Completed
Push — master ( 9cba74...cc5ba4 )
by Sébastien
02:22
created

WCSS_Shortcodes::clean_wc_price()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 19
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
c 1
b 0
f 1
dl 0
loc 19
rs 9.4285
cc 3
eloc 10
nc 2
nop 1
1
<?php
2
/**
3
 * Subscription Shortcodes
4
 *
5
 * @class WCSS_Shortcodes
6
 * @since 1.0.0
7
 */
8
9
class WCSS_Shortcodes {
10
11
	/**
12
	 * Initialize the shortcodes.
13
	 */
14
	public static function init() {
15
		$shortcodes = array(
16
			'subscription_price'           => 'get_subscription_price',
17
			'subscription_price_meta'      => 'get_subscription_price_meta',
18
			'subscription_discount'        => 'get_subscription_discount',
19
			'subscription_period'          => 'get_subscription_period',
20
			'subscription_period_interval' => 'get_subscription_period_interval',
21
			'subscription_length'          => 'get_subscription_length',
22
			'subscription_sign_up_fee'     => 'get_subscription_sign_up_fee',
23
			'subscription_trial'           => 'get_subscription_trial_string',
24
			'subscription_trial_length'    => 'get_subscription_trial_length',
25
			'subscription_trial_period'    => 'get_subscription_trial_period',
26
			'subscription_first_payment'   => 'get_subscription_first_payment',
27
			'subscription_initial_payment' => 'get_subscription_initial',
28
		);
29
30
		foreach ( $shortcodes as $shortcode => $function ) {
31
			add_shortcode( apply_filters( "{$shortcode}_shortcode_tag", $shortcode ), array( __CLASS__, $function ) );
32
		} // END foreach()
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
33
34
		// Adds support for product types that have subscription scheme options.
35
		add_filter( 'woocommerce_is_subscription', array( __CLASS__, 'force_is_subscription' ), 10, 3 );
36
37
		// Adds alternative subscription price from the WooCommerce extension "Subscribe to All the Things" and returns the lowest scheme price.
38
		add_action( 'woocommerce_subscriptions_shortcode_get_price', array( __CLASS__, 'get_satt_lowest_price' ), 10, 1 );
39
40
		// Adds the product types supported from the WooCommerce extension "Subscribe to All the Things".
41
		add_filter( 'wcss_product_types', array( __CLASS__, 'support_product_types_for_wc_satt' ), 10, 1 );
42
	} // END init()
43
44
	/**
45
	 * Get the supported product types.
46
	 * By default, this is only the subscription product types.
47
	 * However, it can be filtered to allow other product types should you need to.
48
	 *
49
	 * @return array
50
	 */
51
	public static function get_supported_product_types() {
52
		return apply_filters( 'wcss_product_types', array(
53
			'subscription', 
54
			'subscription-variation', 
55
		) );
56
	} // END get_supported_product_types()
57
58
	/**
59
	 * Adds support for product types that have subscription scheme options.
60
	 *
61
	 * @param  bool   $is_subscription
62
	 * @param  int    $product_id
63
	 * @param  object $product
64
	 * @return bool
65
	 */
66
	public static function force_is_subscription( $is_subscription, $product_id, $product ) {
67
		/*if ( is_object( $product ) ) {
0 ignored issues
show
Unused Code Comprehensibility introduced by
47% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
68
			$product = $product;
69
		} elseif ( is_numeric( $product_id ) ) {
70
			$product = wc_get_product( $product_id );
71
		}*/
72
73
		if ( in_array( $product->product_type, self::get_supported_product_types() ) ) {
74
			if ( class_exists( 'WCS_ATT_Schemes' ) && WCS_ATT_Schemes::get_product_subscription_schemes( $product ) ) {
75
				$is_subscription = true;
76
			}
77
		}
78
79
		return $is_subscription;
80
	} // END force_is_subscription()
81
82
	/**
83
	 * Returns the subscription price string.
84
	 *
85
	 * @param  WC_Product $product
86
	 * @return string
87
	 */
88
	public static function get_price( $product ) {
89
		if ( WC_Subscriptions_Product::get_price( $product->id ) > 0 ) {
90
91
			return ecs_html( WC_Subscriptions_Product::get_price( $product->id, array(
92
				'subscription_period' => false,
93
				'subscription_length' => false,
94
				'sign_up_fee'         => false,
95
				'trial_length'        => false,
96
			) ) );
97
98
		} else {
99
100
			/**
101
			 * This hook enables for other price possibilities.
102
			 *
103
			 * hooked: get_satt_lowest_price - 10
104
			 */
105
			do_action( 'woocommerce_subscriptions_shortcode_get_price', $product );
106
107
		}
108
	} // END get_price()
109
110
	/**
111
	 * Returns the lowest subscription scheme.
112
	 * Only works with WooCommerce Subscribe to All the Things v1.1.0+
113
	 *
114
	 * @param  WC_Product $product
115
	 * @return string
116
	 */
117
	public static function get_satt_lowest_scheme_data( $product ) {
118
		if ( class_exists( 'WCS_ATT_Schemes' ) && class_exists( 'WCS_ATT_Scheme_Prices' ) ) {
119
			$product_level_schemes = WCS_ATT_Schemes::get_product_subscription_schemes( $product );
120
121
			return WCS_ATT_Scheme_Prices::get_lowest_price_subscription_scheme_data( $product, $product_level_schemes );
122
		}
123
	} // END get_satt_lowest_scheme()
124
125
	/**
126
	 * Returns the lowest subscription scheme price string.
127
	 * Only works with WooCommerce Subscribe to All the Things v1.1.0+
128
	 *
129
	 * @param  WC_Product $product
130
	 * @return string
131
	 */
132
	public static function get_satt_lowest_price( $product ) {
133
		$scheme = self::get_satt_lowest_scheme_data( $product );
134
135
		if ( !empty( $scheme ) && is_array( $scheme ) ) {
136
			// Override price?
137
			$override = $scheme['scheme']['subscription_pricing_method'];
138
139
			// Discount?
140
			$discount = $scheme['scheme']['subscription_discount'];
141
142
			// Prices
143
			$prices = array(
144
				'price'                      => $scheme['price'],
145
				'regular_price'              => $scheme['regular_price'],
146
				'sale_price'                 => $scheme['sale_price'],
147
				'subscription_price'         => $scheme['scheme']['subscription_price'],
148
				'subscription_regular_price' => $scheme['scheme']['subscription_regular_price'],
149
				'subscription_sale_price'    => $scheme['scheme']['subscription_sale_price']
150
			);
151
152
			// Prepare the price
153
			$price = '';
154
155
			if ( 'inherit' == $override ) {
156
				$price = empty( $discount ) ? $price : ( empty( $prices[ 'regular_price' ] ) ? $prices[ 'regular_price' ] : round( ( double ) $prices[ 'regular_price' ] * ( 100 - $discount ) / 100, wc_get_price_decimals() ) );
157
			} else if ( 'override' == $override ) {
158
				$price = $prices['subscription_price'];
159
160
				if ( $prices[ 'subscription_price' ] < $prices[ 'subscription_regular_price' ] ) {
161
					$price = $prices[ 'subscription_sale_price' ];
162
				}
163
			}
164
165
			// If the price is returned as an array, return just the first.
166
			if ( is_array( $price ) ) {
167
				$price = $price[0];
168
			}
169
170
			return $price;
171
		}
172
	} // END get_price_satt()
173
174
	/**
175
	 * Displays the price of the subscription product and 
176
	 * returns only the price information you wish to return.
177
	 *
178
	 * @global $wpdb
179
	 * @global WP_Post $post
180
	 * @param  array   $atts
181
	 * @return string
182
	 */
183
	public static function get_subscription_price( $atts ) {
184
		global $wpdb, $post;
185
186
		$defaults = shortcode_atts( array(
187
			'id'           => '',
188
			'sku'          => '',
189
			'period'       => false,
190
			'length'       => false,
191
			'sign_up_fee'  => false,
192
			'trial_length' => false,
193
			'before_price' => '<span class="price subscription-price">',
194
			'after_price'  => '</span>',
195
		), $atts );
196
197
		$atts = wp_parse_args( $atts, $defaults );
198
199
		if ( ! empty( $atts['id'] ) && $atts['id'] > 0 ) {
200
			$product_data = wc_get_product( $atts['id'] );
201
		} elseif ( ! empty( $atts['sku'] ) ) {
202
			$product_id   = wc_get_product_id_by_sku( $atts['sku'] );
203
			$product_data = get_post( $product_id );
204
		} else {
205
			$product_data = wc_get_product( $post->ID );
206
		}
207
208
		// Check that the product type is supported. Return blank if not supported.
209
		if ( ! is_object( $product_data ) || ! in_array( $product_data->product_type, self::get_supported_product_types() ) ) {
210
			return '';
211
		}
212
213
		ob_start();
214
215
		$price_html = WC_Subscriptions_Product::get_price_string( $product_data->id, array(
216
			'price'               => self::get_price( $product_data ),
217
			'subscription_period' => isset( $atts['period'] ) ? $atts['period'] : true,
218
			'subscription_length' => isset( $atts['length'] ) ? $atts['length'] : true,
219
			'sign_up_fee'         => isset( $atts['sign_up_fee'] ) ? $atts['sign_up_fee'] : true,
220
			'trial_length'        => isset( $atts['trial_length'] ) ? $atts['trial_length'] : true,
221
		) );
222
223
		// Clean the subscription price wrapper.
224
		$price_html = str_replace('<span class="subscription-details">', '', $price_html);
225
		$price_html = str_replace('</span">', '', $price_html);
226
227
		// Trim the whitespace.
228
		$price_html = trim( $price_html );
229
230
		// Convert to Price Tag.
231
		$price_html = wc_price( $price_html );
232
233
		$price_html = sprintf( __( '%s%s%s', WCSS::TEXT_DOMAIN ), $atts['before_price'], $price_html, $atts['after_price'] );
234
235
		echo html_entity_decode( $price_html );
236
237
		return ob_get_clean();
238
	} // END get_subscription_price()
239
240
	/**
241
	 * Displays the price meta of the subscription product.
242
	 *
243
	 * @global $wpdb
244
	 * @global WP_Post $post
245
	 * @param  array   $atts
246
	 * @return string
247
	 */
248
	public static function get_subscription_price_meta( $atts ) {
249
		global $wpdb, $post;
250
251
		$defaults = shortcode_atts( array(
252
			'id'           => '',
253
			'sku'          => '',
254
			'meta'         => 'both',
255
			'before_price' => '',
256
			'after_price'  => '',
257
		), $atts );
258
259
		$atts = wp_parse_args( $atts, $defaults );
260
261
		if ( ! empty( $atts['id'] ) && $atts['id'] > 0 ) {
262
			$product_data = wc_get_product( $atts['id'] );
263
		} elseif ( ! empty( $atts['sku'] ) ) {
264
			$product_id   = wc_get_product_id_by_sku( $atts['sku'] );
265
			$product_data = get_post( $product_id );
266
		} else {
267
			$product_data = wc_get_product( $post->ID );
268
		}
269
270
		// Check that the product type is supported. Return blank if not supported.
271
		if ( ! is_object( $product_data ) || ! in_array( $product_data->product_type, self::get_supported_product_types() ) ) {
272
			return '';
273
		}
274
275
		ob_start();
276
277
		$price = WC_Subscriptions_Product::get_price( $product_data->id );
278
279
		// Remove the subscription price wrapper.
280
		$price_html = str_replace('<span class="subscription-details">', '', $price);
281
		$price = str_replace('</span">', '', $price_html);
282
283
		// If the subscription product has no price, then look for alternative.
284
		if ( empty( $price ) ) {
285
			$scheme = self::get_satt_lowest_scheme_data( $product_data );
286
287
			if ( !empty( $scheme ) && is_array( $scheme ) ) {
288
289
				// These values will be overridden. They are defined here to acknowledge their existence.
290
				$price = '';
291
				$regular_price = '';
292
				$sale_price = '';
293
294
				$prices = array(
295
					'price'                      => $scheme['price'],
296
					'regular_price'              => $scheme['regular_price'],
297
					'sale_price'                 => $scheme['sale_price'],
298
					'method'                     => $scheme['scheme']['subscription_pricing_method'],
299
					'subscription_price'         => $scheme['scheme']['subscription_price'],
300
					'subscription_regular_price' => $scheme['scheme']['subscription_regular_price'],
301
					'subscription_sale_price'    => $scheme['scheme']['subscription_sale_price']
302
				);
303
304
				// Return the subscription price based on the pricing method.
305
				switch( $prices['method'] ) {
306
					case 'override':
307
						$price         = $prices['subscription_price'];
308
						$regular_price = $prices['subscription_regular_price'];
309
						$sale_price    = $prices['subscription_sale_price'];
310
						break;
311
					case 'inherit':
312
						$discount      = $scheme['scheme']['subscription_discount'];
313
						$price         = $prices['price'];
314
						$regular_price = $prices['regular_price'];
315
						$sale_price    = $prices['sale_price'];
316
317
						if ( !empty( $discount ) && $discount > 0 ) {
318
							$sale_price = round( ( double ) $regular_price * ( 100 - $discount ) / 100, wc_get_price_decimals() );
319
						}
320
321
						break;
322
				}
323
324
				// Display both the regular price striked out and the sale price 
325
				// should the active price be less than the regular price.
326
				if ( $atts['meta'] != 'active' && !empty( $sale_price ) && $price < $regular_price ) {
327
					$price = '<del>' . ( ( is_numeric( $regular_price ) ) ? wc_price( $regular_price ) : $regular_price ) . '</del> <ins>' . ( ( is_numeric( $sale_price ) ) ? wc_price( $sale_price ) : $sale_price ) . '</ins>';
328
329
					// Trim the whitespace.
330
					$price = trim( $price );
331
				}
332
333
				// Override the value should only one value be returned.
334
				if ( $atts['meta'] != 'both' ) {
335
					if ( $atts['meta'] == 'active' ) {
336
						$price = $price;
0 ignored issues
show
Bug introduced by
Why assign $price to itself?

This checks looks for cases where a variable has been assigned to itself.

This assignement can be removed without consequences.

Loading history...
337
					}
338
339
					if ( $atts['meta'] == 'regular' ) {
340
						$price = $regular_price;
341
					}
342
343
					if ( $atts['meta'] == 'sale' ) {
344
						$price = $sale_price;
345
					}
346
				}
347
348
				if ( is_numeric( $price ) ) {
349
					$price = wc_price( $price );
350
				}
351
352
				// Clean the price tag.
353
				$price = self::clean_wc_price( $price );
354
355
			}
356
357
		}
358
359
		$price_html = sprintf( __( '%s%s%s', WCSS::TEXT_DOMAIN ), $atts['before_price'], $price, $atts['after_price'] );
360
361
		echo html_entity_decode( $price_html );
362
363
		return ob_get_clean();
364
	} // END get_subscription_price_meta()
365
366
	/**
367
	 * Displays the subscription discount of the subscription product.
368
	 * This shortcode only work with products using the mini-extension
369
	 * "WooCommerce Subscribe to All the Things".
370
	 *
371
	 * @param  array $atts
372
	 * @return string
373
	 */
374
	public static function get_subscription_discount( $atts ) {
375
		global $wpdb, $post;
376
377
		$defaults = shortcode_atts( array(
378
			'id'  => '',
379
			'sku' => '',
380
		), $atts );
381
382
		$atts = wp_parse_args( $atts, $defaults );
383
384
		if ( ! empty( $atts['id'] ) && $atts['id'] > 0 ) {
385
			$product_data = wc_get_product( $atts['id'] );
386
		} elseif ( ! empty( $atts['sku'] ) ) {
387
			$product_id   = wc_get_product_id_by_sku( $atts['sku'] );
388
			$product_data = get_post( $product_id );
389
		} else {
390
			$product_data = wc_get_product( $post->ID );
391
		}
392
393
		// Check that the product type is supported. Return blank if not supported.
394
		if ( ! is_object( $product_data ) || ! in_array( $product_data->product_type, self::get_supported_product_types() ) ) {
395
			return '';
396
		}
397
398
		ob_start();
399
400
		$override = 'inherit'; // Returns inherit by default. Will be overridden later.
401
		$discount = ''; // Returns empty by default.
402
403
		// Get Subscription Discount - Only available with the WooCommerce extension "Subscribe to All the Things".
404
		$scheme = self::get_satt_lowest_scheme_data( $product_data );
405
406 View Code Duplication
		if ( !empty( $scheme ) && is_array( $scheme ) ) {
407
			// Override price?
408
			$override = $scheme['scheme']['subscription_pricing_method'];
409
410
			// Discount ?
411
			$discount = $scheme['scheme']['subscription_discount'];
412
		}
413
414
		if ( ! empty( $discount ) && is_numeric( $discount ) && $override == 'inherit' ) {
415
			$discount = sprintf( __( '%s%s %s', WCSS::TEXT_DOMAIN ), $discount, '%', apply_filters( 'wcs_shortcodes_sub_discount_string', __( 'discount', WCSS::TEXT_DOMAIN ) ) );
416
		}
417
418
		echo $discount;
419
420
		return ob_get_clean();
421
	} // END get_subscription_discount()
422
423
	/**
424
	 * Displays the subscription period of the subscription product.
425
	 *
426
	 * @param  array $atts
427
	 * @return string
428
	 */
429
	public static function get_subscription_period( $atts ) {
430
		global $wpdb, $post;
431
432
		$defaults = shortcode_atts( array(
433
			'id'  => '',
434
			'sku' => '',
435
			'raw' => false
436
		), $atts );
437
438
		$atts = wp_parse_args( $atts, $defaults );
439
440
		if ( ! empty( $atts['id'] ) && $atts['id'] > 0 ) {
441
			$product_data = wc_get_product( $atts['id'] );
442
		} elseif ( ! empty( $atts['sku'] ) ) {
443
			$product_id   = wc_get_product_id_by_sku( $atts['sku'] );
444
			$product_data = get_post( $product_id );
445
		} else {
446
			$product_data = wc_get_product( $post->ID );
447
		}
448
449
		// Check that the product type is supported. Return blank if not supported.
450
		if ( ! is_object( $product_data ) || ! in_array( $product_data->product_type, self::get_supported_product_types() ) ) {
451
			return '';
452
		}
453
454
		ob_start();
455
456
		// Get Subscription Period
457
		$period = WC_Subscriptions_Product::get_period( $product_data );
458
459
		// If the period is empty, look for alternative.
460
		if ( empty( $period ) ) {
461
			$scheme = self::get_satt_lowest_scheme_data( $product_data );
462
463
			if ( !empty( $scheme ) && is_array( $scheme ) ) {
464
				$period = $scheme['scheme']['subscription_period'];
465
			}
466
		}
467
468
		if ( ! $atts['raw'] ) {
469
			$period = sprintf( __( 'Per %s', WCSS::TEXT_DOMAIN ), $period );
470
			$period = ucwords($period);
471
		}
472
473
		echo $period;
474
475
		return ob_get_clean();
476
	} // END get_subscription_period()
477
478
	/**
479
	 * Displays the subscription period interval of the subscription product.
480
	 *
481
	 * @param  array $atts
482
	 * @return string
483
	 */
484 View Code Duplication
	public static function get_subscription_period_interval( $atts ) {
485
		global $wpdb, $post;
486
487
		$defaults = shortcode_atts( array(
488
			'id'  => '',
489
			'sku' => '',
490
		), $atts );
491
492
		$atts = wp_parse_args( $atts, $defaults );
493
494
		if ( ! empty( $atts['id'] ) && $atts['id'] > 0 ) {
495
			$product_data = wc_get_product( $atts['id'] );
496
		} elseif ( ! empty( $atts['sku'] ) ) {
497
			$product_id   = wc_get_product_id_by_sku( $atts['sku'] );
498
			$product_data = get_post( $product_id );
499
		} else {
500
			$product_data = wc_get_product( $post->ID );
501
		}
502
503
		// Check that the product type is supported. Return blank if not supported.
504
		if ( ! is_object( $product_data ) || ! in_array( $product_data->product_type, self::get_supported_product_types() ) ) {
505
			return '';
506
		}
507
508
		ob_start();
509
510
		// Get Subscription Period Interval
511
		$period_interval = WC_Subscriptions_Product::get_interval( $product_data );
512
513
		// If the period is empty, look for alternative.
514
		if ( empty( $period_interval ) ) {
515
			$scheme = self::get_satt_lowest_scheme_data( $product_data );
516
517
			if ( !empty( $scheme ) && is_array( $scheme ) ) {
518
				$period_interval = $scheme['scheme']['subscription_period_interval'];
519
			}
520
		}
521
522
		echo $period_interval;
523
524
		return ob_get_clean();
525
	} // END get_subscription_period_interval()
526
527
	/**
528
	 * Displays the subscription length of the subscription product.
529
	 *
530
	 * @param  array $atts
531
	 * @return string
532
	 */
533
	public static function get_subscription_length( $atts ) {
534
		global $wpdb, $post;
535
536
		$defaults = shortcode_atts( array(
537
			'id'  => '',
538
			'sku' => '',
539
			'raw' => false,
540
		), $atts );
541
542
		$atts = wp_parse_args( $atts, $defaults );
543
544
		if ( ! empty( $atts['id'] ) && $atts['id'] > 0 ) {
545
			$product_data = wc_get_product( $atts['id'] );
546
		} elseif ( ! empty( $atts['sku'] ) ) {
547
			$product_id   = wc_get_product_id_by_sku( $atts['sku'] );
548
			$product_data = get_post( $product_id );
549
		} else {
550
			$product_data = wc_get_product( $post->ID );
551
		}
552
553
		// Check that the product type is supported. Return blank if not supported.
554
		if ( ! is_object( $product_data ) || ! in_array( $product_data->product_type, self::get_supported_product_types() ) ) {
555
			return '';
556
		}
557
558
		ob_start();
559
560
		// Get Subscription Length
561
		$length = WC_Subscriptions_Product::get_length( $product_data );
562
563
		// If the length is empty, look for alternative.
564
		if ( empty( $length ) ) {
565
			$scheme = self::get_satt_lowest_scheme_data( $product_data );
566
567
			if ( !empty( $scheme ) && is_array( $scheme ) ) {
568
569
				$period = self::get_subscription_period( array( 'id' => $product_data->id, 'raw' => true ) );
570
				$length = $scheme['scheme']['subscription_length'];
571
572
				// If we are not returning raw data then making it readable for humans.
573
				if ( ! $atts['raw'] ) {
574
575
					if ( $length > 0 ) {
576
						$length = sprintf( '%s %s', $length, $period );
577
					} else {
578
						$length = sprintf( __( 'Every %s', WCSS::TEXT_DOMAIN ), $period );
579
					}
580
581
					$length = ucfirst($length);
582
583
				}
584
585
			}
586
587
		}
588
589
		echo $length;
590
591
		return ob_get_clean();
592
	} // END get_subscription_length()
593
594
	/**
595
	 * Displays the subscription sign-up fee of the subscription product.
596
	 *
597
	 * @param  array $atts
598
	 * @return string
599
	 */
600
	public static function get_subscription_sign_up_fee( $atts ) {
601
		global $wpdb, $post;
602
603
		$defaults = shortcode_atts( array(
604
			'id'           => '',
605
			'sku'          => '',
606
			'raw'          => false,
607
			'before_price' => '',
608
			'after_price'  => '',
609
		), $atts );
610
611
		$atts = wp_parse_args( $atts, $defaults );
612
613
		if ( ! empty( $atts['id'] ) && $atts['id'] > 0 ) {
614
			$product_data = wc_get_product( $atts['id'] );
615
		} elseif ( ! empty( $atts['sku'] ) ) {
616
			$product_id   = wc_get_product_id_by_sku( $atts['sku'] );
617
			$product_data = get_post( $product_id );
618
		} else {
619
			$product_data = wc_get_product( $post->ID );
620
		}
621
622
		// Check that the product type is supported. Return blank if not supported.
623
		if ( ! is_object( $product_data ) || ! in_array( $product_data->product_type, self::get_supported_product_types() ) ) {
624
			return '';
625
		}
626
627
		ob_start();
628
629
		// Get Subscription Sign Up Fee
630
		$sign_up_fee = WC_Subscriptions_Product::get_sign_up_fee( $product_data );
631
632
		// If the sign up fee is empty, look for alternative.
633
		if ( empty( $sign_up_fee ) ) {
634
			$scheme = self::get_satt_lowest_scheme_data( $product_data );
635
636
			if ( !empty( $scheme ) && is_array( $scheme ) ) {
637
				$sign_up_fee = $scheme['scheme']['subscription_sign_up_fee'];
638
			}
639
		}
640
641
		if ( ! $atts['raw'] ) {
642
			// Convert number into a price tag.
643
			if ( is_numeric( $sign_up_fee ) ) {
644
				$sign_up_fee = wc_price( $sign_up_fee );
645
			}
646
647
			// Clean the price tag.
648
			$sign_up_fee = self::clean_wc_price( $sign_up_fee );
649
650
			$price_html = sprintf( __( '%s%s%s', WCSS::TEXT_DOMAIN ), $atts['before_price'], $sign_up_fee, $atts['after_price'] );
651
652
			$sign_up_fee = html_entity_decode( $price_html );
653
		}
654
655
		echo $sign_up_fee;
656
657
		return ob_get_clean();
658
	} // END get_subscription_sign_up_fee()
659
660
	/**
661
	 * Displays the subscription trial details of the subscription product.
662
	 *
663
	 * @param  array $atts
664
	 * @return string
665
	 */
666
	public static function get_subscription_trial_string( $atts ) {
667
		global $wpdb, $post;
668
669
		$defaults = shortcode_atts( array(
670
			'id'  => '',
671
			'sku' => '',
672
		), $atts );
673
674
		$atts = wp_parse_args( $atts, $defaults );
675
676
		if ( ! empty( $atts['id'] ) && $atts['id'] > 0 ) {
677
			$product_data = wc_get_product( $atts['id'] );
678
		} elseif ( ! empty( $atts['sku'] ) ) {
679
			$product_id   = wc_get_product_id_by_sku( $atts['sku'] );
680
			$product_data = get_post( $product_id );
681
		} else {
682
			$product_data = wc_get_product( $post->ID );
683
		}
684
685
		// Check that the product type is supported. Return blank if not supported.
686
		if ( ! is_object( $product_data ) || ! in_array( $product_data->product_type, self::get_supported_product_types() ) ) {
687
			return '';
688
		}
689
690
		ob_start();
691
692
		// Get Subscription Trial Length
693
		$trial_length = self::get_subscription_trial_length( array( 'id' => $product_data->id ) );
694
695
		// Get Subscription Trial Period
696
		$trial_period = self::get_subscription_trial_period( array( 'id' => $product_data->id, 'raw' => true ) );
697
698
		if ( ! empty( $trial_length ) && $trial_length > 0 ) {
699
700
			switch ( $trial_period ) {
701
				case 'day':
702
					echo sprintf( _n( '%s day', '%s days', $trial_length, WCSS::TEXT_DOMAIN ), $trial_length );
703
					break;
704
705
				case 'week':
706
					echo sprintf( _n( '%s week', '%s weeks', $trial_length, WCSS::TEXT_DOMAIN ), $trial_length );
707
					break;
708
709
				case 'month':
710
					echo sprintf( _n( '%s month', '%s months', $trial_length, WCSS::TEXT_DOMAIN ), $trial_length );
711
					break;
712
713
				case 'year':
714
					echo sprintf( _n( '%s year', '%s years', $trial_length, WCSS::TEXT_DOMAIN ), $trial_length );
715
					break;
716
			}
717
718
		}
719
720
		return ob_get_clean();
721
	} // END get_subscription_trial_string()
722
723
	/**
724
	 * Displays the subscription trial length of the subscription product.
725
	 *
726
	 * @param  array $atts
727
	 * @return string
728
	 */
729 View Code Duplication
	public static function get_subscription_trial_length( $atts ) {
730
		global $wpdb, $post;
731
732
		$defaults = shortcode_atts( array(
733
			'id'  => '',
734
			'sku' => '',
735
		), $atts );
736
737
		$atts = wp_parse_args( $atts, $defaults );
738
739
		if ( ! empty( $atts['id'] ) && $atts['id'] > 0 ) {
740
			$product_data = wc_get_product( $atts['id'] );
741
		} elseif ( ! empty( $atts['sku'] ) ) {
742
			$product_id   = wc_get_product_id_by_sku( $atts['sku'] );
743
			$product_data = get_post( $product_id );
744
		} else {
745
			$product_data = wc_get_product( $post->ID );
746
		}
747
748
		// Check that the product type is supported. Return blank if not supported.
749
		if ( ! is_object( $product_data ) || ! in_array( $product_data->product_type, self::get_supported_product_types() ) ) {
750
			return '';
751
		}
752
753
		ob_start();
754
755
		// Get Subscription Trial Length
756
		$trial_length = WC_Subscriptions_Product::get_trial_length( $product_data );
757
758
		// If the trial length is empty, look for alternative.
759
		if ( empty( $trial_length ) ) {
760
			$scheme = self::get_satt_lowest_scheme_data( $product_data );
761
762
			if ( !empty( $scheme ) && is_array( $scheme ) ) {
763
				$trial_length = $scheme['scheme']['subscription_trial_length'];
764
			}
765
		}
766
767
		echo $trial_length;
768
769
		return ob_get_clean();
770
	} // END get_subscription_trial_length()
771
772
	/**
773
	 * Displays the subscription trial period of the subscription product.
774
	 *
775
	 * @param  array $atts
776
	 * @return string
777
	 */
778
	public static function get_subscription_trial_period( $atts ) {
779
		global $wpdb, $post;
780
781
		$defaults = shortcode_atts( array(
782
			'id'  => '',
783
			'sku' => '',
784
			'raw' => false,
785
		), $atts );
786
787
		$atts = wp_parse_args( $atts, $defaults );
788
789
		if ( ! empty( $atts['id'] ) && $atts['id'] > 0 ) {
790
			$product_data = wc_get_product( $atts['id'] );
791
		} elseif ( ! empty( $atts['sku'] ) ) {
792
			$product_id   = wc_get_product_id_by_sku( $atts['sku'] );
793
			$product_data = get_post( $product_id );
794
		} else {
795
			$product_data = wc_get_product( $post->ID );
796
		}
797
798
		// Check that the product type is supported. Return blank if not supported.
799
		if ( ! is_object( $product_data ) || ! in_array( $product_data->product_type, self::get_supported_product_types() ) ) {
800
			return '';
801
		}
802
803
		ob_start();
804
805
		// Get Subscription Trial Length
806
		$trial_length = self::get_subscription_trial_length( array( 'id' => $product_data->id ) );
807
808
		// Get Subscription Trial Period
809
		$trial_period = WC_Subscriptions_Product::get_trial_period( $product_data );
810
811
		// If the trial length is empty or is not zero, look for alternative.
812
		if ( empty( $trial_length ) || $trial_length != 0 ) {
813
			$scheme = self::get_satt_lowest_scheme_data( $product_data );
814
815 View Code Duplication
			if ( !empty( $scheme ) && is_array( $scheme ) ) {
816
				$trial_length = $scheme['scheme']['subscription_trial_length'];
817
				$trial_period = $scheme['scheme']['subscription_trial_period'];
818
			}
819
		}
820
821
		if ( ! empty( $trial_length ) && $trial_length > 0 ) {
822
823
			if ( ! $atts['raw'] ) {
824
				$trial_period = ucfirst($trial_period);
825
			}
826
827
		}
828
829
		echo $trial_period;
830
831
		return ob_get_clean();
832
	} // END get_subscription_trial_period()
833
834
	/**
835
	 * Displays the date and/or time of the first payment of the subscription.
836
	 *
837
	 * @param  array $atts
838
	 * @return string
839
	 */
840
	public static function get_subscription_first_payment( $atts ) {
841
		global $wpdb, $post;
842
843
		$defaults = shortcode_atts( array(
844
			'id'        => '',
845
			'sku'       => '',
846
			'show_time' => false,
847
			'from_date' => '',
848
			'timezone'  => 'gmt',
849
			'format'    => 'timestamp'
850
		), $atts );
851
852
		$atts = wp_parse_args( $atts, $defaults );
853
854
		if ( ! empty( $atts['id'] ) && $atts['id'] > 0 ) {
855
			$product_data = wc_get_product( $atts['id'] );
856
		} elseif ( ! empty( $atts['sku'] ) ) {
857
			$product_id   = wc_get_product_id_by_sku( $atts['sku'] );
858
			$product_data = get_post( $product_id );
859
		} else {
860
			$product_data = wc_get_product( $post->ID );
861
		}
862
863
		// Check that the product type is supported. Return blank if not supported.
864
		if ( ! is_object( $product_data ) || ! in_array( $product_data->product_type, self::get_supported_product_types() ) ) {
865
			return '';
866
		}
867
868
		ob_start();
869
870
		$billing_interval = self::get_subscription_period_interval( array( 'id' => $product_data->id ) );
871
		$billing_length   = self::get_subscription_length( array( 'id' => $product_data->id, 'raw' => true ) );
872
		$trial_length     = self::get_subscription_trial_length( array( 'id' => $product_data->id ) );
873
874
		$from_date = $atts['from_date'];
875
876
		if ( $billing_interval != $billing_length || $trial_length > 0 ) {
877
			if ( empty( $from_date ) ) {
878
				$from_date = gmdate( 'Y-m-d H:i:s' );
879
			}
880
881
			// If the subscription has a free trial period, the first renewal is the same as the expiration of the free trial
882
			if ( $trial_length > 0 ) {
883
				$first_renewal_timestamp = strtotime( WC_Subscriptions_Product::get_trial_expiration_date( $product_data->id, $from_date ) );
884
			} else {
885
				$from_timestamp = strtotime( $from_date );
886
				$billing_period = self::get_subscription_period( array( 'id' => $product_data->id, 'raw' => true ) );
887
888
				if ( 'month' == $billing_period ) {
889
					$first_renewal_timestamp = wcs_add_months( $from_timestamp, $billing_interval );
890
				} else {
891
					$first_renewal_timestamp = strtotime( "+ $billing_interval {$billing_period}s", $from_timestamp );
892
				}
893
894
				if ( 'site' == $atts['timezone'] ) {
895
					$first_renewal_timestamp += ( get_option( 'gmt_offset' ) * HOUR_IN_SECONDS );
896
				}
897
			}
898
		} else {
899
			$first_renewal_timestamp = 0;
900
		}
901
902
		$date_format = ''; // Will be overridden later on.
903
904
		if ( $first_renewal_timestamp > 0 ) {
905
			if ( $atts['show_time'] ) {
906 View Code Duplication
				if ( 'timestamp' == $atts['format'] ) {
907
					$date_format = 'Y-m-d H:i:s';
908
				} else if ( 'string' == $atts['format'] ) {
909
					$date_format = 'D jS M Y H:i A';
910
				}
911 View Code Duplication
			} else {
912
				if ( 'timestamp' == $atts['format'] ) {
913
					$date_format = 'Y-m-d';
914
				} else if ( 'string' == $atts['format'] ) {
915
					$date_format = 'D jS M Y';
916
				}
917
			}
918
919
			$first_payment = date( $date_format, $first_renewal_timestamp );
920
		} else {
921
			$first_payment = '';
922
		}
923
924
		echo $first_payment;
925
926
		return ob_get_clean();
927
	} // END get_subscription_first_payment()
928
929
	/**
930
	 * Displays the price of the initial payment of the subscription.
931
	 *
932
	 * @param  array $atts
933
	 * @return string
934
	 */
935
	public static function get_subscription_initial( $atts ) {
936
		global $wpdb, $post;
937
938
		$defaults = shortcode_atts( array(
939
			'id'        => '',
940
			'sku'       => '',
941
			'total'     => false
942
		), $atts );
943
944
		$atts = wp_parse_args( $atts, $defaults );
945
946
		if ( ! empty( $atts['id'] ) && $atts['id'] > 0 ) {
947
			$product_data = wc_get_product( $atts['id'] );
948
		} elseif ( ! empty( $atts['sku'] ) ) {
949
			$product_id   = wc_get_product_id_by_sku( $atts['sku'] );
950
			$product_data = get_post( $product_id );
951
		} else {
952
			$product_data = wc_get_product( $post->ID );
953
		}
954
955
		// Check that the product type is supported. Return blank if not supported.
956
		if ( ! is_object( $product_data ) || ! in_array( $product_data->product_type, self::get_supported_product_types() ) ) {
957
			return '';
958
		}
959
960
		ob_start();
961
962
		// Subscription Active Price
963
		$initial_payment = self::get_subscription_price_meta( array( 'id' => $product_data->id, 'meta' => 'active' ) );
964
965
		// Free Trial ?
966
		$trial_length = self::get_subscription_trial_length( array( 'id' => $product_data->id ) );
967
968
		// If there is a free trial then the initial payment is Zero.
969
		if ( $trial_length > 0 ) {
970
			$initial_payment = 0;
971
		}
972
973
		// Sign up fee ?
974
		$sign_up_fee = self::get_subscription_sign_up_fee( array( 'id' => $product_data->id, 'raw' => true ) );
975
976
		// Apply the sign up fee if it exists.
977
		if ( !empty( $sign_up_fee ) && $sign_up_fee > 0 ) {
978
979
			if ( ! $atts['total'] ) {
980
				$initial_payment = sprintf( __( '%s with a %s sign up fee.', WCSS::TEXT_DOMAIN ), wc_price( $initial_payment ), wc_price( $sign_up_fee ) );
981
			} else {
982
				$initial_payment = round( ( double ) $initial_payment+$sign_up_fee, wc_get_price_decimals() );
983
			}
984
985
		}
986
987
		// Convert number into a price tag.
988
		if ( is_numeric( $initial_payment ) ) {
989
			$initial_payment = wc_price( $initial_payment );
990
		}
991
992
		// Clean the price tag.
993
		$initial_payment = self::clean_wc_price( $initial_payment );
994
995
		echo $initial_payment;
996
997
		return ob_get_clean();
998
	} // END get_subscription_initial()
999
1000
	/**
1001
	 * Adds the product types supported from the WooCommerce extension "Subscribe to All the Things".
1002
	 *
1003
	 * @param  $product_types
1004
	 * @return array
1005
	 */
1006
	public static function support_product_types_for_wc_satt( $product_types ) {
1007
		// Only add the product types from the WooCommerce extension "Subscribe to All the Things" if it is active.
1008
		if ( class_exists( 'WCS_ATT' ) ) {
1009
			$satt_product_types = WCS_ATT()->get_supported_product_types();
1010
			$product_types = array_merge( $satt_product_types, $product_types );
1011
		}
1012
1013
		return $product_types;
1014
	} // support_product_types_for_wc_satt()
1015
1016
	/**
1017
	 * This function returns the formatted price tag clean without
1018
	 * WooCommerce price span wrapper which was added in version 2.6
1019
	 *
1020
	 * @param  string $price
1021
	 * @global $woocommerce
1022
	 * @return string
1023
	 */
1024
	public static function clean_wc_price( $price ) {
1025
		global $woocommerce;
1026
1027
		if ( version_compare( $woocommerce->version, '2.6.0' ) >= 0 ) {
1028
1029
			$find = array(
1030
				'<span class="woocommerce-Price-amount amount">', 
1031
				'<span class="woocommerce-Price-currencySymbol">', 
1032
				'</span>'
1033
			);
1034
1035
			foreach( $find as $remove ) {
1036
				$price = str_replace( $remove, '', $price );
1037
			}
1038
1039
		}
1040
1041
		return $price;
1042
	} // END clean_wc_price
1043
1044
} // END WCSS_Shortcodes
1045
1046
WCSS_Shortcodes::init();