Completed
Push — master ( cc5ba4...c4009b )
by Sébastien
03:06
created

WCSS_Shortcodes::get_trial_expiration_date()   B

Complexity

Conditions 5
Paths 6

Size

Total Lines 29
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 29
rs 8.439
cc 5
eloc 15
nc 6
nop 2
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 ) ) {
68
			$product = wc_get_product( $product_id );
69
		}
70
71
		if ( in_array( $product->product_type, self::get_supported_product_types() ) ) {
72
			if ( class_exists( 'WCS_ATT_Schemes' ) && WCS_ATT_Schemes::get_product_subscription_schemes( $product ) ) {
73
				$is_subscription = true;
74
			}
75
		}
76
77
		return $is_subscription;
78
	} // END force_is_subscription()
79
80
	/**
81
	 * Returns the subscription price string.
82
	 *
83
	 * @param  WC_Product $product
84
	 * @return string
85
	 */
86
	public static function get_price( $product ) {
87
		if ( WC_Subscriptions_Product::get_price( $product->id ) > 0 ) {
88
89
			return ecs_html( WC_Subscriptions_Product::get_price( $product->id, array(
90
				'subscription_period' => false,
91
				'subscription_length' => false,
92
				'sign_up_fee'         => false,
93
				'trial_length'        => false,
94
			) ) );
95
96
		} else {
97
98
			/**
99
			 * This hook enables for other price possibilities.
100
			 *
101
			 * hooked: get_satt_lowest_price - 10
102
			 */
103
			do_action( 'woocommerce_subscriptions_shortcode_get_price', $product );
104
105
		}
106
	} // END get_price()
107
108
	/**
109
	 * Returns the lowest subscription scheme.
110
	 * Only works with WooCommerce Subscribe to All the Things v1.1.0+
111
	 *
112
	 * @param  WC_Product $product
113
	 * @return string
114
	 */
115
	public static function get_satt_lowest_scheme_data( $product ) {
116
		if ( class_exists( 'WCS_ATT_Schemes' ) && class_exists( 'WCS_ATT_Scheme_Prices' ) ) {
117
			$product_level_schemes = WCS_ATT_Schemes::get_product_subscription_schemes( $product );
118
119
			return WCS_ATT_Scheme_Prices::get_lowest_price_subscription_scheme_data( $product, $product_level_schemes );
120
		}
121
	} // END get_satt_lowest_scheme()
122
123
	/**
124
	 * Returns the lowest subscription scheme price string.
125
	 * Only works with WooCommerce Subscribe to All the Things v1.1.0+
126
	 *
127
	 * @param  WC_Product $product
128
	 * @return string
129
	 */
130
	public static function get_satt_lowest_price( $product ) {
131
		$scheme = self::get_satt_lowest_scheme_data( $product );
132
133
		if ( !empty( $scheme ) && is_array( $scheme ) ) {
134
			// Override price?
135
			$override = $scheme['scheme']['subscription_pricing_method'];
136
137
			// Discount?
138
			$discount = $scheme['scheme']['subscription_discount'];
139
140
			// Prices
141
			$prices = array(
142
				'price'                      => $scheme['price'],
143
				'regular_price'              => $scheme['regular_price'],
144
				'sale_price'                 => $scheme['sale_price'],
145
				'subscription_price'         => $scheme['scheme']['subscription_price'],
146
				'subscription_regular_price' => $scheme['scheme']['subscription_regular_price'],
147
				'subscription_sale_price'    => $scheme['scheme']['subscription_sale_price']
148
			);
149
150
			// Prepare the price
151
			$price = '';
152
153
			if ( 'inherit' == $override ) {
154
				$price = empty( $discount ) ? $price : ( empty( $prices[ 'regular_price' ] ) ? $prices[ 'regular_price' ] : round( ( double ) $prices[ 'regular_price' ] * ( 100 - $discount ) / 100, wc_get_price_decimals() ) );
155
			} else if ( 'override' == $override ) {
156
				$price = $prices['subscription_price'];
157
158
				if ( $prices[ 'subscription_price' ] < $prices[ 'subscription_regular_price' ] ) {
159
					$price = $prices[ 'subscription_sale_price' ];
160
				}
161
			}
162
163
			// If the price is returned as an array, return just the first.
164
			if ( is_array( $price ) ) {
165
				$price = $price[0];
166
			}
167
168
			return $price;
169
		}
170
	} // END get_price_satt()
171
172
	/**
173
	 * Displays the price of the subscription product and 
174
	 * returns only the price information you wish to return.
175
	 *
176
	 * @global $wpdb
177
	 * @global WP_Post $post
178
	 * @param  array   $atts
179
	 * @return string
180
	 */
181
	public static function get_subscription_price( $atts ) {
182
		global $wpdb, $post;
183
184
		$defaults = shortcode_atts( array(
185
			'id'           => '',
186
			'sku'          => '',
187
			'period'       => false,
188
			'length'       => false,
189
			'sign_up_fee'  => false,
190
			'trial_length' => false,
191
			'before_price' => '<span class="price subscription-price">',
192
			'after_price'  => '</span>',
193
		), $atts );
194
195
		$atts = wp_parse_args( $atts, $defaults );
196
197
		if ( ! empty( $atts['id'] ) && $atts['id'] > 0 ) {
198
			$product_data = wc_get_product( $atts['id'] );
199
		} elseif ( ! empty( $atts['sku'] ) ) {
200
			$product_id   = wc_get_product_id_by_sku( $atts['sku'] );
201
			$product_data = get_post( $product_id );
202
		} else {
203
			$product_data = wc_get_product( $post->ID );
204
		}
205
206
		// Check that the product type is supported. Return blank if not supported.
207
		if ( ! is_object( $product_data ) || ! in_array( $product_data->product_type, self::get_supported_product_types() ) ) {
208
			return '';
209
		}
210
211
		ob_start();
212
213
		$price_html = WC_Subscriptions_Product::get_price_string( $product_data->id, array(
214
			'price'               => self::get_price( $product_data ),
215
			'subscription_period' => isset( $atts['period'] ) ? $atts['period'] : true,
216
			'subscription_length' => isset( $atts['length'] ) ? $atts['length'] : true,
217
			'sign_up_fee'         => isset( $atts['sign_up_fee'] ) ? $atts['sign_up_fee'] : true,
218
			'trial_length'        => isset( $atts['trial_length'] ) ? $atts['trial_length'] : true,
219
		) );
220
221
		// Clean the subscription price wrapper.
222
		$price_html = str_replace('<span class="subscription-details">', '', $price_html);
223
		$price_html = str_replace('</span">', '', $price_html);
224
225
		// Trim the whitespace.
226
		$price_html = trim( $price_html );
227
228
		// Convert to Price Tag.
229
		$price_html = wc_price( $price_html );
230
231
		$price_html = sprintf( __( '%s%s%s', WCSS::TEXT_DOMAIN ), $atts['before_price'], $price_html, $atts['after_price'] );
232
233
		echo html_entity_decode( $price_html );
234
235
		return ob_get_clean();
236
	} // END get_subscription_price()
237
238
	/**
239
	 * Displays the price meta of the subscription product.
240
	 *
241
	 * @global $wpdb
242
	 * @global WP_Post $post
243
	 * @param  array   $atts
244
	 * @return string
245
	 */
246
	public static function get_subscription_price_meta( $atts ) {
247
		global $wpdb, $post;
248
249
		$defaults = shortcode_atts( array(
250
			'id'           => '',
251
			'sku'          => '',
252
			'meta'         => 'both',
253
			'before_price' => '',
254
			'after_price'  => '',
255
		), $atts );
256
257
		$atts = wp_parse_args( $atts, $defaults );
258
259
		if ( ! empty( $atts['id'] ) && $atts['id'] > 0 ) {
260
			$product_data = wc_get_product( $atts['id'] );
261
		} elseif ( ! empty( $atts['sku'] ) ) {
262
			$product_id   = wc_get_product_id_by_sku( $atts['sku'] );
263
			$product_data = get_post( $product_id );
264
		} else {
265
			$product_data = wc_get_product( $post->ID );
266
		}
267
268
		// Check that the product type is supported. Return blank if not supported.
269
		if ( ! is_object( $product_data ) || ! in_array( $product_data->product_type, self::get_supported_product_types() ) ) {
270
			return '';
271
		}
272
273
		ob_start();
274
275
		$price = WC_Subscriptions_Product::get_price( $product_data->id );
276
277
		// Remove the subscription price wrapper.
278
		$price_html = str_replace('<span class="subscription-details">', '', $price);
279
		$price = str_replace('</span">', '', $price_html);
280
281
		// If the subscription product has no price, then look for alternative.
282
		if ( empty( $price ) ) {
283
			$scheme = self::get_satt_lowest_scheme_data( $product_data );
284
285
			if ( !empty( $scheme ) && is_array( $scheme ) ) {
286
287
				// These values will be overridden. They are defined here to acknowledge their existence.
288
				$price = '';
289
				$regular_price = '';
290
				$sale_price = '';
291
292
				$prices = array(
293
					'price'                      => $scheme['price'],
294
					'regular_price'              => $scheme['regular_price'],
295
					'sale_price'                 => $scheme['sale_price'],
296
					'method'                     => $scheme['scheme']['subscription_pricing_method'],
297
					'subscription_price'         => $scheme['scheme']['subscription_price'],
298
					'subscription_regular_price' => $scheme['scheme']['subscription_regular_price'],
299
					'subscription_sale_price'    => $scheme['scheme']['subscription_sale_price']
300
				);
301
302
				// Return the subscription price based on the pricing method.
303
				switch( $prices['method'] ) {
304
					case 'override':
305
						$price         = $prices['subscription_price'];
306
						$regular_price = $prices['subscription_regular_price'];
307
						$sale_price    = $prices['subscription_sale_price'];
308
						break;
309
					case 'inherit':
310
						$discount      = $scheme['scheme']['subscription_discount'];
311
						$price         = $prices['price'];
312
						$regular_price = $prices['regular_price'];
313
						$sale_price    = $prices['sale_price'];
314
315
						if ( !empty( $discount ) && $discount > 0 ) {
316
							$sale_price = round( ( double ) $regular_price * ( 100 - $discount ) / 100, wc_get_price_decimals() );
317
						}
318
319
						break;
320
				}
321
322
				// Display both the regular price striked out and the sale price 
323
				// should the active price be less than the regular price.
324
				if ( $atts['meta'] != 'active' && !empty( $sale_price ) && $price < $regular_price ) {
325
					$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>';
326
327
					// Trim the whitespace.
328
					$price = trim( $price );
329
				}
330
331
				// Override the value should only one value be returned.
332
				if ( $atts['meta'] != 'both' ) {
333
					if ( $atts['meta'] == 'active' ) {
334
						$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...
335
					}
336
337
					if ( $atts['meta'] == 'regular' ) {
338
						$price = $regular_price;
339
					}
340
341
					if ( $atts['meta'] == 'sale' ) {
342
						$price = $sale_price;
343
					}
344
				}
345
346
				if ( is_numeric( $price ) ) {
347
					$price = wc_price( $price );
348
				}
349
350
				// Clean the price tag.
351
				$price = self::clean_wc_price( $price );
352
353
			}
354
355
		}
356
357
		$price_html = sprintf( __( '%s%s%s', WCSS::TEXT_DOMAIN ), $atts['before_price'], $price, $atts['after_price'] );
358
359
		echo html_entity_decode( $price_html );
360
361
		return ob_get_clean();
362
	} // END get_subscription_price_meta()
363
364
	/**
365
	 * Displays the subscription discount of the subscription product.
366
	 * This shortcode only work with products using the mini-extension
367
	 * "WooCommerce Subscribe to All the Things".
368
	 *
369
	 * @param  array $atts
370
	 * @return string
371
	 */
372
	public static function get_subscription_discount( $atts ) {
373
		global $wpdb, $post;
374
375
		$defaults = shortcode_atts( array(
376
			'id'  => '',
377
			'sku' => '',
378
		), $atts );
379
380
		$atts = wp_parse_args( $atts, $defaults );
381
382
		if ( ! empty( $atts['id'] ) && $atts['id'] > 0 ) {
383
			$product_data = wc_get_product( $atts['id'] );
384
		} elseif ( ! empty( $atts['sku'] ) ) {
385
			$product_id   = wc_get_product_id_by_sku( $atts['sku'] );
386
			$product_data = get_post( $product_id );
387
		} else {
388
			$product_data = wc_get_product( $post->ID );
389
		}
390
391
		// Check that the product type is supported. Return blank if not supported.
392
		if ( ! is_object( $product_data ) || ! in_array( $product_data->product_type, self::get_supported_product_types() ) ) {
393
			return '';
394
		}
395
396
		ob_start();
397
398
		$override = 'inherit'; // Returns inherit by default. Will be overridden later.
399
		$discount = ''; // Returns empty by default.
400
401
		// Get Subscription Discount - Only available with the WooCommerce extension "Subscribe to All the Things".
402
		$scheme = self::get_satt_lowest_scheme_data( $product_data );
403
404 View Code Duplication
		if ( !empty( $scheme ) && is_array( $scheme ) ) {
405
			// Override price?
406
			$override = $scheme['scheme']['subscription_pricing_method'];
407
408
			// Discount ?
409
			$discount = $scheme['scheme']['subscription_discount'];
410
		}
411
412
		if ( ! empty( $discount ) && is_numeric( $discount ) && $override == 'inherit' ) {
413
			$discount = sprintf( __( '%s%s %s', WCSS::TEXT_DOMAIN ), $discount, '%', apply_filters( 'wcs_shortcodes_sub_discount_string', __( 'discount', WCSS::TEXT_DOMAIN ) ) );
414
		}
415
416
		echo $discount;
417
418
		return ob_get_clean();
419
	} // END get_subscription_discount()
420
421
	/**
422
	 * Displays the subscription period of the subscription product.
423
	 *
424
	 * @param  array $atts
425
	 * @return string
426
	 */
427
	public static function get_subscription_period( $atts ) {
428
		global $wpdb, $post;
429
430
		$defaults = shortcode_atts( array(
431
			'id'  => '',
432
			'sku' => '',
433
			'raw' => false
434
		), $atts );
435
436
		$atts = wp_parse_args( $atts, $defaults );
437
438
		if ( ! empty( $atts['id'] ) && $atts['id'] > 0 ) {
439
			$product_data = wc_get_product( $atts['id'] );
440
		} elseif ( ! empty( $atts['sku'] ) ) {
441
			$product_id   = wc_get_product_id_by_sku( $atts['sku'] );
442
			$product_data = get_post( $product_id );
443
		} else {
444
			$product_data = wc_get_product( $post->ID );
445
		}
446
447
		// Check that the product type is supported. Return blank if not supported.
448
		if ( ! is_object( $product_data ) || ! in_array( $product_data->product_type, self::get_supported_product_types() ) ) {
449
			return '';
450
		}
451
452
		ob_start();
453
454
		// Get Subscription Period
455
		$period = WC_Subscriptions_Product::get_period( $product_data );
456
457
		// If the period is empty, look for alternative.
458
		if ( empty( $period ) ) {
459
			$scheme = self::get_satt_lowest_scheme_data( $product_data );
460
461
			if ( !empty( $scheme ) && is_array( $scheme ) ) {
462
				$period = $scheme['scheme']['subscription_period'];
463
			}
464
		}
465
466
		if ( ! $atts['raw'] ) {
467
			$period = sprintf( __( 'Per %s', WCSS::TEXT_DOMAIN ), $period );
468
			$period = ucwords($period);
469
		}
470
471
		echo $period;
472
473
		return ob_get_clean();
474
	} // END get_subscription_period()
475
476
	/**
477
	 * Displays the subscription period interval of the subscription product.
478
	 *
479
	 * @param  array $atts
480
	 * @return string
481
	 */
482 View Code Duplication
	public static function get_subscription_period_interval( $atts ) {
483
		global $wpdb, $post;
484
485
		$defaults = shortcode_atts( array(
486
			'id'  => '',
487
			'sku' => '',
488
		), $atts );
489
490
		$atts = wp_parse_args( $atts, $defaults );
491
492
		if ( ! empty( $atts['id'] ) && $atts['id'] > 0 ) {
493
			$product_data = wc_get_product( $atts['id'] );
494
		} elseif ( ! empty( $atts['sku'] ) ) {
495
			$product_id   = wc_get_product_id_by_sku( $atts['sku'] );
496
			$product_data = get_post( $product_id );
497
		} else {
498
			$product_data = wc_get_product( $post->ID );
499
		}
500
501
		// Check that the product type is supported. Return blank if not supported.
502
		if ( ! is_object( $product_data ) || ! in_array( $product_data->product_type, self::get_supported_product_types() ) ) {
503
			return '';
504
		}
505
506
		ob_start();
507
508
		// Get Subscription Period Interval
509
		$period_interval = WC_Subscriptions_Product::get_interval( $product_data );
510
511
		// If the period is empty, look for alternative.
512
		if ( empty( $period_interval ) ) {
513
			$scheme = self::get_satt_lowest_scheme_data( $product_data );
514
515
			if ( !empty( $scheme ) && is_array( $scheme ) ) {
516
				$period_interval = $scheme['scheme']['subscription_period_interval'];
517
			}
518
		}
519
520
		echo $period_interval;
521
522
		return ob_get_clean();
523
	} // END get_subscription_period_interval()
524
525
	/**
526
	 * Displays the subscription length of the subscription product.
527
	 *
528
	 * @param  array $atts
529
	 * @return string
530
	 */
531
	public static function get_subscription_length( $atts ) {
532
		global $wpdb, $post;
533
534
		$defaults = shortcode_atts( array(
535
			'id'  => '',
536
			'sku' => '',
537
			'raw' => false,
538
		), $atts );
539
540
		$atts = wp_parse_args( $atts, $defaults );
541
542
		if ( ! empty( $atts['id'] ) && $atts['id'] > 0 ) {
543
			$product_data = wc_get_product( $atts['id'] );
544
		} elseif ( ! empty( $atts['sku'] ) ) {
545
			$product_id   = wc_get_product_id_by_sku( $atts['sku'] );
546
			$product_data = get_post( $product_id );
547
		} else {
548
			$product_data = wc_get_product( $post->ID );
549
		}
550
551
		// Check that the product type is supported. Return blank if not supported.
552
		if ( ! is_object( $product_data ) || ! in_array( $product_data->product_type, self::get_supported_product_types() ) ) {
553
			return '';
554
		}
555
556
		ob_start();
557
558
		// Get Subscription Length
559
		$length = WC_Subscriptions_Product::get_length( $product_data );
560
561
		// If the length is empty, look for alternative.
562
		if ( empty( $length ) ) {
563
			$scheme = self::get_satt_lowest_scheme_data( $product_data );
564
565
			if ( !empty( $scheme ) && is_array( $scheme ) ) {
566
567
				$period = self::get_subscription_period( array( 'id' => $product_data->id, 'raw' => true ) );
568
				$length = $scheme['scheme']['subscription_length'];
569
570
				// If we are not returning raw data then making it readable for humans.
571
				if ( ! $atts['raw'] ) {
572
573
					if ( $length > 0 ) {
574
						$length = sprintf( '%s %s', $length, $period );
575
					} else {
576
						$length = sprintf( __( 'Every %s', WCSS::TEXT_DOMAIN ), $period );
577
					}
578
579
					$length = ucfirst($length);
580
581
				}
582
583
			}
584
585
		}
586
587
		echo $length;
588
589
		return ob_get_clean();
590
	} // END get_subscription_length()
591
592
	/**
593
	 * Displays the subscription sign-up fee of the subscription product.
594
	 *
595
	 * @param  array $atts
596
	 * @return string
597
	 */
598
	public static function get_subscription_sign_up_fee( $atts ) {
599
		global $wpdb, $post;
600
601
		$defaults = shortcode_atts( array(
602
			'id'           => '',
603
			'sku'          => '',
604
			'raw'          => false,
605
			'before_price' => '',
606
			'after_price'  => '',
607
		), $atts );
608
609
		$atts = wp_parse_args( $atts, $defaults );
610
611
		if ( ! empty( $atts['id'] ) && $atts['id'] > 0 ) {
612
			$product_data = wc_get_product( $atts['id'] );
613
		} elseif ( ! empty( $atts['sku'] ) ) {
614
			$product_id   = wc_get_product_id_by_sku( $atts['sku'] );
615
			$product_data = get_post( $product_id );
616
		} else {
617
			$product_data = wc_get_product( $post->ID );
618
		}
619
620
		// Check that the product type is supported. Return blank if not supported.
621
		if ( ! is_object( $product_data ) || ! in_array( $product_data->product_type, self::get_supported_product_types() ) ) {
622
			return '';
623
		}
624
625
		ob_start();
626
627
		// Get Subscription Sign Up Fee
628
		$sign_up_fee = WC_Subscriptions_Product::get_sign_up_fee( $product_data );
629
630
		// If the sign up fee is empty, look for alternative.
631
		if ( empty( $sign_up_fee ) ) {
632
			$scheme = self::get_satt_lowest_scheme_data( $product_data );
633
634
			if ( !empty( $scheme ) && is_array( $scheme ) ) {
635
				$sign_up_fee = $scheme['scheme']['subscription_sign_up_fee'];
636
			}
637
		}
638
639
		if ( ! $atts['raw'] ) {
640
			// Convert number into a price tag.
641
			if ( is_numeric( $sign_up_fee ) ) {
642
				$sign_up_fee = wc_price( $sign_up_fee );
643
			}
644
645
			// Clean the price tag.
646
			$sign_up_fee = self::clean_wc_price( $sign_up_fee );
647
648
			$price_html = sprintf( __( '%s%s%s', WCSS::TEXT_DOMAIN ), $atts['before_price'], $sign_up_fee, $atts['after_price'] );
649
650
			$sign_up_fee = html_entity_decode( $price_html );
651
		}
652
653
		echo $sign_up_fee;
654
655
		return ob_get_clean();
656
	} // END get_subscription_sign_up_fee()
657
658
	/**
659
	 * Displays the subscription trial details of the subscription product.
660
	 *
661
	 * @param  array $atts
662
	 * @return string
663
	 */
664
	public static function get_subscription_trial_string( $atts ) {
665
		global $wpdb, $post;
666
667
		$defaults = shortcode_atts( array(
668
			'id'  => '',
669
			'sku' => '',
670
		), $atts );
671
672
		$atts = wp_parse_args( $atts, $defaults );
673
674
		if ( ! empty( $atts['id'] ) && $atts['id'] > 0 ) {
675
			$product_data = wc_get_product( $atts['id'] );
676
		} elseif ( ! empty( $atts['sku'] ) ) {
677
			$product_id   = wc_get_product_id_by_sku( $atts['sku'] );
678
			$product_data = get_post( $product_id );
679
		} else {
680
			$product_data = wc_get_product( $post->ID );
681
		}
682
683
		// Check that the product type is supported. Return blank if not supported.
684
		if ( ! is_object( $product_data ) || ! in_array( $product_data->product_type, self::get_supported_product_types() ) ) {
685
			return '';
686
		}
687
688
		ob_start();
689
690
		// Get Subscription Trial Length
691
		$trial_length = self::get_subscription_trial_length( array( 'id' => $product_data->id ) );
692
693
		// Get Subscription Trial Period
694
		$trial_period = self::get_subscription_trial_period( array( 'id' => $product_data->id, 'raw' => true ) );
695
696
		if ( ! empty( $trial_length ) && $trial_length > 0 ) {
697
698
			switch ( $trial_period ) {
699
				case 'day':
700
					echo sprintf( _n( '%s day', '%s days', $trial_length, WCSS::TEXT_DOMAIN ), $trial_length );
701
					break;
702
703
				case 'week':
704
					echo sprintf( _n( '%s week', '%s weeks', $trial_length, WCSS::TEXT_DOMAIN ), $trial_length );
705
					break;
706
707
				case 'month':
708
					echo sprintf( _n( '%s month', '%s months', $trial_length, WCSS::TEXT_DOMAIN ), $trial_length );
709
					break;
710
711
				case 'year':
712
					echo sprintf( _n( '%s year', '%s years', $trial_length, WCSS::TEXT_DOMAIN ), $trial_length );
713
					break;
714
			}
715
716
		}
717
718
		return ob_get_clean();
719
	} // END get_subscription_trial_string()
720
721
	/**
722
	 * Displays the subscription trial length of the subscription product.
723
	 *
724
	 * @param  array $atts
725
	 * @return string
726
	 */
727 View Code Duplication
	public static function get_subscription_trial_length( $atts ) {
728
		global $wpdb, $post;
729
730
		$defaults = shortcode_atts( array(
731
			'id'  => '',
732
			'sku' => '',
733
		), $atts );
734
735
		$atts = wp_parse_args( $atts, $defaults );
736
737
		if ( ! empty( $atts['id'] ) && $atts['id'] > 0 ) {
738
			$product_data = wc_get_product( $atts['id'] );
739
		} elseif ( ! empty( $atts['sku'] ) ) {
740
			$product_id   = wc_get_product_id_by_sku( $atts['sku'] );
741
			$product_data = get_post( $product_id );
742
		} else {
743
			$product_data = wc_get_product( $post->ID );
744
		}
745
746
		// Check that the product type is supported. Return blank if not supported.
747
		if ( ! is_object( $product_data ) || ! in_array( $product_data->product_type, self::get_supported_product_types() ) ) {
748
			return '';
749
		}
750
751
		ob_start();
752
753
		// Get Subscription Trial Length
754
		$trial_length = WC_Subscriptions_Product::get_trial_length( $product_data );
755
756
		// If the trial length is empty, look for alternative.
757
		if ( empty( $trial_length ) ) {
758
			$scheme = self::get_satt_lowest_scheme_data( $product_data );
759
760
			if ( !empty( $scheme ) && is_array( $scheme ) ) {
761
				$trial_length = $scheme['scheme']['subscription_trial_length'];
762
			}
763
		}
764
765
		echo $trial_length;
766
767
		return ob_get_clean();
768
	} // END get_subscription_trial_length()
769
770
	/**
771
	 * Displays the subscription trial period of the subscription product.
772
	 *
773
	 * @param  array $atts
774
	 * @return string
775
	 */
776
	public static function get_subscription_trial_period( $atts ) {
777
		global $wpdb, $post;
778
779
		$defaults = shortcode_atts( array(
780
			'id'  => '',
781
			'sku' => '',
782
			'raw' => false,
783
		), $atts );
784
785
		$atts = wp_parse_args( $atts, $defaults );
786
787
		if ( ! empty( $atts['id'] ) && $atts['id'] > 0 ) {
788
			$product_data = wc_get_product( $atts['id'] );
789
		} elseif ( ! empty( $atts['sku'] ) ) {
790
			$product_id   = wc_get_product_id_by_sku( $atts['sku'] );
791
			$product_data = get_post( $product_id );
792
		} else {
793
			$product_data = wc_get_product( $post->ID );
794
		}
795
796
		// Check that the product type is supported. Return blank if not supported.
797
		if ( ! is_object( $product_data ) || ! in_array( $product_data->product_type, self::get_supported_product_types() ) ) {
798
			return '';
799
		}
800
801
		ob_start();
802
803
		// Get Subscription Trial Length
804
		$trial_length = self::get_subscription_trial_length( array( 'id' => $product_data->id ) );
805
806
		// Get Subscription Trial Period
807
		$trial_period = WC_Subscriptions_Product::get_trial_period( $product_data );
808
809
		// If the trial length is empty or is not zero, look for alternative.
810
		if ( empty( $trial_length ) || $trial_length != 0 ) {
811
			$scheme = self::get_satt_lowest_scheme_data( $product_data );
812
813 View Code Duplication
			if ( !empty( $scheme ) && is_array( $scheme ) ) {
814
				$trial_length = $scheme['scheme']['subscription_trial_length'];
815
				$trial_period = $scheme['scheme']['subscription_trial_period'];
816
			}
817
		}
818
819
		if ( ! empty( $trial_length ) && $trial_length > 0 ) {
820
821
			if ( ! $atts['raw'] ) {
822
				$trial_period = ucfirst($trial_period);
823
			}
824
825
		}
826
827
		echo $trial_period;
828
829
		return ob_get_clean();
830
	} // END get_subscription_trial_period()
831
832
	/**
833
	 * Displays the date and/or time of the first payment of the subscription.
834
	 *
835
	 * @param  array $atts
836
	 * @return string
837
	 */
838
	public static function get_subscription_first_payment( $atts ) {
839
		global $wpdb, $post;
840
841
		$defaults = shortcode_atts( array(
842
			'id'        => '',
843
			'sku'       => '',
844
			'show_time' => false,
845
			'from_date' => '',
846
			'timezone'  => 'gmt',
847
			'format'    => 'timestamp'
848
		), $atts );
849
850
		$atts = wp_parse_args( $atts, $defaults );
851
852
		if ( ! empty( $atts['id'] ) && $atts['id'] > 0 ) {
853
			$product_data = wc_get_product( $atts['id'] );
854
		} elseif ( ! empty( $atts['sku'] ) ) {
855
			$product_id   = wc_get_product_id_by_sku( $atts['sku'] );
856
			$product_data = get_post( $product_id );
857
		} else {
858
			$product_data = wc_get_product( $post->ID );
859
		}
860
861
		// Check that the product type is supported. Return blank if not supported.
862
		if ( ! is_object( $product_data ) || ! in_array( $product_data->product_type, self::get_supported_product_types() ) ) {
863
			return '';
864
		}
865
866
		ob_start();
867
868
		$billing_interval = self::get_subscription_period_interval( array( 'id' => $product_data->id ) );
869
		$billing_length   = self::get_subscription_length( array( 'id' => $product_data->id, 'raw' => true ) );
870
		$trial_length     = self::get_subscription_trial_length( array( 'id' => $product_data->id ) );
871
872
		$from_date = $atts['from_date'];
873
874
		if ( $billing_interval !== $billing_length || $trial_length > 0 ) {
875
			if ( empty( $from_date ) ) {
876
				$from_date = gmdate( 'Y-m-d H:i:s' );
877
			}
878
879
			// If the subscription has a free trial period, the first renewal is the same as the expiration of the free trial.
880
			if ( $trial_length > 0 ) {
881
				$first_renewal_timestamp = strtotime( self::get_trial_expiration_date( $product_data->id, $from_date ) );
882
			} else {
883
				$from_timestamp = strtotime( $from_date );
884
				$billing_period = self::get_subscription_period( array( 'id' => $product_data->id, 'raw' => true ) );
885
886
				if ( 'month' == $billing_period ) {
887
					$first_renewal_timestamp = wcs_add_months( $from_timestamp, $billing_interval );
888
				} else {
889
					$first_renewal_timestamp = strtotime( "+ $billing_interval {$billing_period}s", $from_timestamp );
890
				}
891
892
				if ( 'site' == $atts['timezone'] ) {
893
					$first_renewal_timestamp += ( get_option( 'gmt_offset' ) * HOUR_IN_SECONDS );
894
				}
895
			}
896
		} else {
897
			$first_renewal_timestamp = 0;
898
		}
899
900
		$date_format = ''; // Will be overridden later on.
901
902
		if ( $first_renewal_timestamp > 0 ) {
903
			if ( $atts['show_time'] ) {
904 View Code Duplication
				if ( 'timestamp' == $atts['format'] ) {
905
					$date_format = 'Y-m-d H:i:s';
906
				} else if ( 'string' == $atts['format'] ) {
907
					$date_format = 'D jS M Y H:i A';
908
				}
909 View Code Duplication
			} else {
910
				if ( 'timestamp' == $atts['format'] ) {
911
					$date_format = 'Y-m-d';
912
				} else if ( 'string' == $atts['format'] ) {
913
					$date_format = 'D jS M Y';
914
				}
915
			}
916
917
			$first_payment = date( $date_format, $first_renewal_timestamp );
918
		} else {
919
			$first_payment = '';
920
		}
921
922
		echo $first_payment;
923
924
		return ob_get_clean();
925
	} // END get_subscription_first_payment()
926
927
	/**
928
	 * Displays the price of the initial payment of the subscription.
929
	 *
930
	 * @param  array $atts
931
	 * @return string
932
	 */
933
	public static function get_subscription_initial( $atts ) {
934
		global $wpdb, $post;
935
936
		$defaults = shortcode_atts( array(
937
			'id'        => '',
938
			'sku'       => '',
939
			'total'     => false
940
		), $atts );
941
942
		$atts = wp_parse_args( $atts, $defaults );
943
944
		if ( ! empty( $atts['id'] ) && $atts['id'] > 0 ) {
945
			$product_data = wc_get_product( $atts['id'] );
946
		} elseif ( ! empty( $atts['sku'] ) ) {
947
			$product_id   = wc_get_product_id_by_sku( $atts['sku'] );
948
			$product_data = get_post( $product_id );
949
		} else {
950
			$product_data = wc_get_product( $post->ID );
951
		}
952
953
		// Check that the product type is supported. Return blank if not supported.
954
		if ( ! is_object( $product_data ) || ! in_array( $product_data->product_type, self::get_supported_product_types() ) ) {
955
			return '';
956
		}
957
958
		ob_start();
959
960
		// Subscription Active Price
961
		$initial_payment = self::get_subscription_price_meta( array( 'id' => $product_data->id, 'meta' => 'active' ) );
962
963
		// Free Trial ?
964
		$trial_length = self::get_subscription_trial_length( array( 'id' => $product_data->id ) );
965
966
		// If there is a free trial then the initial payment is Zero.
967
		if ( $trial_length > 0 ) {
968
			$initial_payment = 0;
969
		}
970
971
		// Sign up fee ?
972
		$sign_up_fee = self::get_subscription_sign_up_fee( array( 'id' => $product_data->id, 'raw' => true ) );
973
974
		// Apply the sign up fee if it exists.
975
		if ( !empty( $sign_up_fee ) && $sign_up_fee > 0 ) {
976
977
			if ( ! $atts['total'] ) {
978
				$initial_payment = sprintf( __( '%s with a %s sign up fee.', WCSS::TEXT_DOMAIN ), wc_price( $initial_payment ), wc_price( $sign_up_fee ) );
979
			} else {
980
				$initial_payment = round( ( double ) $initial_payment+$sign_up_fee, wc_get_price_decimals() );
981
			}
982
983
		}
984
985
		// Convert number into a price tag.
986
		if ( is_numeric( $initial_payment ) ) {
987
			$initial_payment = wc_price( $initial_payment );
988
		}
989
990
		// Clean the price tag.
991
		$initial_payment = self::clean_wc_price( $initial_payment );
992
993
		echo $initial_payment;
994
995
		return ob_get_clean();
996
	} // END get_subscription_initial()
997
998
	/**
999
	 * Adds the product types supported from the WooCommerce extension "Subscribe to All the Things".
1000
	 *
1001
	 * @param  $product_types
1002
	 * @return array
1003
	 */
1004
	public static function support_product_types_for_wc_satt( $product_types ) {
1005
		// Only add the product types from the WooCommerce extension "Subscribe to All the Things" if it is active.
1006
		if ( class_exists( 'WCS_ATT' ) ) {
1007
			$satt_product_types = WCS_ATT()->get_supported_product_types();
1008
			$product_types = array_merge( $satt_product_types, $product_types );
1009
		}
1010
1011
		return $product_types;
1012
	} // support_product_types_for_wc_satt()
1013
1014
	/**
1015
	 * This function returns the formatted price tag clean without
1016
	 * WooCommerce price span wrapper which was added in version 2.6
1017
	 *
1018
	 * @param  string $price
1019
	 * @global $woocommerce
1020
	 * @return string
1021
	 */
1022
	public static function clean_wc_price( $price ) {
1023
		global $woocommerce;
1024
1025
		if ( version_compare( $woocommerce->version, '2.6.0' ) >= 0 ) {
1026
1027
			$find = array(
1028
				'<span class="woocommerce-Price-amount amount">', 
1029
				'<span class="woocommerce-Price-currencySymbol">', 
1030
				'</span>'
1031
			);
1032
1033
			foreach( $find as $remove ) {
1034
				$price = str_replace( $remove, '', $price );
1035
			}
1036
1037
		}
1038
1039
		return $price;
1040
	} // END clean_wc_price
1041
1042
	/**
1043
	 * Takes a subscription product's ID and returns the date on which the subscription trial will expire,
1044
	 * based on the subscription's trial length and calculated from either the $from_date if specified,
1045
	 * or the current date/time.
1046
	 *
1047
	 * @param int $product_id The product/post ID of the subscription
1048
	 * @param mixed $from_date A MySQL formatted date/time string from which to calculate the expiration date (in UTC timezone), or empty (default), which will use today's date/time (in UTC timezone).
1049
	 */
1050
	public static function get_trial_expiration_date( $product_id, $from_date = '' ) {
1051
		$trial_expiration_date = WC_Subscriptions_Product::get_trial_expiration_date( $product_id, $from_date );
1052
1053
		// If returned empty then try alternative.
1054
		if ( empty( $trial_expiration_date ) ) {
1055
1056
			$trial_period = self::get_subscription_trial_period( array( 'id' => $product_id, 'raw' => true ) );
1057
			$trial_length = self::get_subscription_trial_length( array( 'id' => $product_id ) );
1058
1059
			if ( $trial_length > 0 ) {
1060
1061
				if ( empty( $from_date ) ) {
1062
					$from_date = gmdate( 'Y-m-d H:i:s' );
1063
				}
1064
1065
				if ( 'month' == $trial_period ) {
1066
					$trial_expiration_date = date( 'Y-m-d H:i:s', wcs_add_months( strtotime( $from_date ), $trial_length ) );
1067
				} else { // Safe to just add the billing periods
1068
					$trial_expiration_date = date( 'Y-m-d H:i:s', strtotime( "+ {$trial_length} {$trial_period}s", strtotime( $from_date ) ) );
1069
				}
1070
1071
			} else {
1072
				$trial_expiration_date = 0;
1073
			}
1074
1075
		}
1076
1077
		return $trial_expiration_date;
1078
	} // END get_trial_expiration_date()
1079
1080
} // END WCSS_Shortcodes
1081
1082
WCSS_Shortcodes::init();