Completed
Push — master ( 402a3d...7d5f77 )
by Sébastien
02:39
created

wc-satt-stt.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/*
3
 * Plugin Name: WooCommerce Subscribe to All the Things - Sign up and Trial Addon
4
 * Plugin URI:  https://github.com/seb86/woocommerce-subscribe-to-all-the-things-signup-trial-add-on
5
 * Version:     1.0.0 Beta
6
 * Description: Add a sign up fee and free trial for each subscription scheme. Requires WooCommerce Subscribe to All the Things extension v1.1.1+.
7
 * Author:      Sébastien Dumont
8
 * Author URI:  https://sebastiendumont.com
9
 *
10
 * Text Domain: wc-satt-stt
11
 * Domain Path: /languages/
12
 *
13
 * Requires at least: 4.1
14
 * Tested up to: 4.5.3
15
 *
16
 * Copyright: © 2016 Sébastien Dumont
17
 * License: GNU General Public License v3.0
18
 * License URI: http://www.gnu.org/licenses/gpl-3.0.html
19
 */
20
if ( ! defined('ABSPATH') ) exit; // Exit if accessed directly.
21
22
if ( ! class_exists( 'WCSATT_STT' ) ) {
23
	class WCSATT_STT {
24
25
		/* Plugin version. */
26
		const VERSION = '1.0.0';
27
28
		/* Required WC version. */
29
		const REQ_WC_VERSION = '2.3.0';
30
31
		/* Required WCSATT version */
32
		const REQ_WCSATT_VERSION = '1.1.1';
33
34
		/* Text domain. */
35
		const TEXT_DOMAIN = 'wc-satt-stt';
36
37
		/**
38
		 * @var WCSATT_STT - the single instance of the class.
39
		 *
40
		 * @since 1.0.0
41
		 */
42
		protected static $_instance = null;
43
44
		/**
45
		 * Main WCSATT_STT Instance.
46
		 *
47
		 * Ensures only one instance of WCSATT_STT is loaded or can be loaded.
48
		 *
49
		 * @static
50
		 * @see WCSATT_STT()
51
		 * @return WCSATT_STT - Main instance
52
		 * @since 1.0.0
53
		 */
54
		public static function instance() {
55
			if ( is_null( self::$_instance ) ) {
56
				self::$_instance = new self();
57
			}
58
			return self::$_instance;
59
		}
60
61
		/**
62
		 * Cloning is forbidden.
63
		 *
64
		 * @since 1.0.0
65
		 */
66
		public function __clone() {
67
			_doing_it_wrong( __FUNCTION__, __( 'Foul!' ), '1.0.0' );
68
		}
69
70
		/**
71
		 * Unserializing instances of this class is forbidden.
72
		 *
73
		 * @since 1.0.0
74
		 */
75
		public function __wakeup() {
76
			_doing_it_wrong( __FUNCTION__, __( 'Foul!' ), '1.0.0' );
77
		}
78
79
		/**
80
		 * Load the plugin.
81
		 */
82
		public function __construct() {
83
			add_action( 'plugins_loaded', array( $this, 'load_plugin' ) );
84
			add_action( 'init', array( $this, 'init_plugin' ) );
85
			add_action( 'admin_init', array( $this, 'admin_wcsatt_stt_product_meta' ) );
86
			add_filter( 'plugin_row_meta', array( $this, 'plugin_meta_links' ), 10, 4 );
87
		}
88
89
		public function plugin_path() {
90
			return untrailingslashit( plugin_dir_path( __FILE__ ) );
91
		} // END plugin_path()
92
93
		/*
94
		 * Check requirements on activation.
95
		 */
96
		public function load_plugin() {
97
			global $woocommerce;
98
99
			// Check that the required WooCommerce is running.
100
			if ( version_compare( $woocommerce->version, self::REQ_WC_VERSION, '<' ) ) {
101
				add_action( 'admin_notices', array( $this, 'wcsatt_stt_wc_admin_notice' ) );
102
				return false;
103
			}
104
105
			// Checks that WooCommerce Subscribe All the Things is running or is less than the required version.
106
			if ( ! class_exists( 'WCS_ATT' ) || version_compare( WCS_ATT::VERSION, self::REQ_WCSATT_VERSION, '<' ) ) {
107
				add_action( 'admin_notices', array( $this, 'wcsatt_stt_admin_notice' ) );
108
				return false;
109
			}
110
		} // END load_plugin()
111
112
		/**
113
		 * Display a warning message if minimum version of WooCommerce check fails.
114
		 *
115
		 * @return void
116
		 */
117
		public function wcsatt_stt_wc_admin_notice() {
118
			echo '<div class="error"><p>' . sprintf( __( '%1$s requires at least %2$s v%3$s in order to function. Please upgrade %2$s.', 'wc-satt-stt' ), 'Sign up and Trial Options Add-on for WCSATT', 'WooCommerce', self::REQ_WC_VERSION ) . '</p></div>';
119
		} // END wcsatt_stt_wc_admin_notice()
120
121
		/**
122
		 * Display a warning message if minimum version of WooCommerce Subscribe to All the Things check fails.
123
		 *
124
		 * @return void
125
		 */
126
		public function wcsatt_stt_admin_notice() {
127
			echo '<div class="error"><p>' . sprintf( __( '%1$s requires at least %2$s v%3$s in order to function. Please upgrade %2$s.', 'wc-satt-stt' ), 'Sign up and Trial Options Add-on', 'WooCommerce Subscribe to All the Things', self::REQ_WCSATT_VERSION ) . '</p></div>';
128
		} // END wcsatt_stt_admin_notice()
129
130
		/**
131
		 * Initialize the plugin if ready.
132
		 *
133
		 * @return void
134
		 */
135
		public function init_plugin() {
136
			// Load text domain.
137
			load_plugin_textdomain( 'wc-satt-stt', false, dirname( plugin_basename( __FILE__ ) ) . '/languages/' );
138
139
			// Adds the sign up fee and trial data to the price html on the 'wcsatt_overridden_subscription_prices_product' filter.
140
			add_filter( 'wcsatt_overridden_subscription_prices_product', array( $this, 'add_sub_scheme_data_price_html' ), 10, 3 );
141
142
			// Adds the extra subscription scheme data to the product object on the 'wcsatt_converted_product_for_scheme_option' filter.
143
			add_filter( 'wcsatt_converted_product_for_scheme_option', array( $this, 'sub_product_scheme_option' ), 10, 2 );
144
145
			// Filters the price string to include the sign up fee and/or trial to pass per scheme option on the 'wcsatt_single_product_subscription_scheme_price_html' filter.
146
			add_filter( 'wcsatt_single_product_subscription_scheme_price_html', array( $this, 'get_price_string' ), 10, 2 );
147
148
			// Filters the lowest price string to include the sign up fee on the 'wcsatt_get_single_product_lowest_price_string' filter.
149
			add_filter( 'wcsatt_get_single_product_lowest_price_string', array( $this, 'get_lowest_price_string' ), 10, 2 );
150
151
			// Filters the lowest price subscription scheme data on the 'wcsatt_get_lowest_price_sub_scheme_data' filter.
152
			add_filter( 'wcsatt_get_lowest_price_sub_scheme_data', array( $this, 'get_lowest_price_sub_scheme_data' ), 10, 2 );
153
154
			// Adds the sign-up and/or trial data to the subscription scheme prices on the 'wcsatt_subscription_scheme_prices' filter.
155
			add_filter( 'wcsatt_subscription_scheme_prices', array( $this, 'add_subscription_scheme_prices' ), 10, 2 );
156
157
			// Overrides the price of the subscription for sign up fee and/or trial on the 'wcsatt_cart_item' filter.
158
			add_filter( 'wcsatt_cart_item', array( $this, 'update_cart_item_sub_data' ), 10, 1 );
159
		} // END init_plugin()
160
161
		/**
162
		 * Register the product meta data fields.
163
		 *
164
		 * @return void
165
		 */
166
		public function admin_wcsatt_stt_product_meta() {
167
			// Subscription scheme options displayed on the 'wcsatt_subscription_scheme_product_content' action.
168
			add_action( 'wcsatt_subscription_scheme_product_content', array( $this, 'wcsatt_stt_fields' ), 15, 3 );
169
170
			// Filter the subscription scheme data to process the sign up and trial options on the ''wcsatt_subscription_scheme_process_scheme_data' filter.
171
			add_filter( 'wcsatt_subscription_scheme_process_scheme_data', array( $this, 'wcsatt_stt_process_scheme_data' ), 10, 2 );
172
		} // END admin_wcsatt_stt_product_meta()
173
174
		/**
175
		 * Show row meta on the plugin screen.
176
		 *
177
		 * @param mixed $links Plugin Row Meta
178
		 * @param mixed $file  Plugin Base file
179
		 * @return array
180
		 */
181
		public function plugin_meta_links( $links, $file, $data, $status ) {
182
			if ( $file == plugin_basename( __FILE__ ) ) {
183
				$author1 = '<a href="' . $data[ 'AuthorURI' ] . '">' . $data[ 'Author' ] . '</a>';
184
				$author2 = '<a href="http://www.subscriptiongroup.co.uk/">Subscription Group Limited</a>';
185
				$links[ 1 ] = sprintf( __( 'By %s', self::TEXT_DOMAIN ), sprintf( __( '%s and %s', self::TEXT_DOMAIN ), $author1, $author2 ) );
186
			}
187
188
			return $links;
189
		} // END plugin_meta_links()
190
191
		/**
192
		 * Adds the default values for subscriptions schemes content.
193
		 *
194
		 * @param  array $defaults
195
		 * @return void
196
		 */
197
		public static function add_default_subscription_schemes_content( $defaults ) {
198
			$new_defaults = array(
199
				'subscription_sign_up_fee'  => '',
200
				'subscription_trial_length' => '',
201
				'subscription_trial_period' => ''
202
			);
203
204
			return array_merge( $new_defaults, $defaults );
205
		} // END add_default_subscription_schemes_content()
206
207
		/**
208
		 * Adds the trial and sign up fields under the subscription section.
209
		 *
210
		 * @param  int   $index
211
		 * @param  array $scheme_data
212
		 * @param  int   $post_id
213
		 * @return void
214
		 */
215
		public function wcsatt_stt_fields( $index, $scheme_data, $post_id ) {
216
			if ( ! empty( $scheme_data ) ) {
217
				$subscription_sign_up_fee = ! empty( $scheme_data[ 'subscription_sign_up_fee' ] ) ? $scheme_data[ 'subscription_sign_up_fee' ] : '';
218
				$subscription_trial_length = isset( $scheme_data[ 'subscription_trial_length' ] ) ? $scheme_data[ 'subscription_trial_length' ] : 0;
219
				$subscription_trial_period = isset( $scheme_data[ 'subscription_trial_period' ] ) ? $scheme_data[ 'subscription_trial_period' ] : '';
220
			} else {
221
				$subscription_sign_up_fee = '';
222
				$subscription_trial_length = 0;
223
				$subscription_trial_period = '';
224
			}
225
226
			// Sign-up Fee
227
			woocommerce_wp_text_input( array(
228
				'id'          => '_subscription_sign_up_fee',
229
				'class'       => 'wc_input_subscription_intial_price',
230
				// translators: %s is a currency symbol / code
231
				'label'       => sprintf( __( 'Sign-up Fee (%s)', WCSATT_STT::TEXT_DOMAIN ), get_woocommerce_currency_symbol() ),
232
				'placeholder' => _x( 'e.g. 9.90', 'example price', WCSATT_STT::TEXT_DOMAIN ),
233
				'description' => __( 'Optionally include an amount to be charged at the outset of the subscription. The sign-up fee will be charged immediately, even if the product has a free trial or the payment dates are synced.', WCSATT_STT::TEXT_DOMAIN ),
234
				'desc_tip'    => true,
235
				'type'        => 'text',
236
				'custom_attributes' => array(
237
					'step' => 'any',
238
					'min'  => '0',
239
				),
240
				'name'        => 'wcsatt_schemes[' . $index . '][subscription_sign_up_fee]',
241
				'value'       => $subscription_sign_up_fee
242
			) );
243
244
			// Trial Length
245
			woocommerce_wp_text_input( array(
246
				'id'          => '_subscription_trial_length',
247
				'class'       => 'wc_input_subscription_trial_length',
248
				'label'       => __( 'Free Trial', WCSATT_STT::TEXT_DOMAIN ),
249
				'name'        => 'wcsatt_schemes[' . $index . '][subscription_trial_length]',
250
				'value'       => $subscription_trial_length
251
			) );
252
253
			// Trial Period
254
			woocommerce_wp_select( array(
255
				'id'          => '_subscription_trial_period',
256
				'class'       => 'wc_input_subscription_trial_period',
257
				'label'       => __( 'Subscription Trial Period', WCSATT_STT::TEXT_DOMAIN ),
258
				'options'     => wcs_get_available_time_periods(),
259
				// translators: placeholder is trial period validation message if passed an invalid value (e.g. "Trial period can not exceed 4 weeks")
260
				'description' => sprintf( _x( 'An optional period of time to wait before charging the first recurring payment. Any sign up fee will still be charged at the outset of the subscription. %s', 'Trial period dropdown\'s description in pricing fields', WCSATT_STT::TEXT_DOMAIN ), WC_Subscriptions_Admin::get_trial_period_validation_message() ),
261
				'desc_tip'    => true,
262
				'value'       => WC_Subscriptions_Product::get_trial_period( $post_id ), // Explicitly set value in to ensure backward compatibility
263
				'name'        => 'wcsatt_schemes[' . $index . '][subscription_trial_period]',
264
				'value'       => $subscription_trial_period
265
		) );
266
		} // END wcsatt_stt_fields()
267
268
		/**
269
		 * Filters the subscription scheme data to pass the 
270
		 * sign up and trial options when saving.
271
		 *
272
		 * @param  ini $posted_scheme
273
		 * @param  string $product_type
274
		 * @return void
275
		 */
276
		public function wcsatt_stt_process_scheme_data( $posted_scheme, $product_type ) {
277
			// Copy variable type fields.
278
			if ( 'variable' == $product_type ) {
279
				if ( isset( $posted_scheme[ 'subscription_sign_up_fee_variable' ] ) ) {
280
					$posted_scheme[ 'subscription_sign_up_fee' ] = $posted_scheme[ 'subscription_sign_up_fee_variable' ];
281
				}
282
				if ( isset( $posted_scheme[ 'subscription_trial_length_variable' ] ) ) {
283
					$posted_scheme[ 'subscription_trial_length' ] = $posted_scheme[ 'subscription_trial_length_variable' ];
284
				}
285
				if ( isset( $posted_scheme[ 'subscription_trial_period_variable' ] ) ) {
286
					$posted_scheme[ 'subscription_trial_period' ] = $posted_scheme[ 'subscription_trial_period_variable'];
287
				}
288
			}
289
290
			// Format subscription sign up fee.
291
			if ( isset( $posted_scheme[ 'subscription_sign_up_fee' ] ) ) {
292
				$posted_scheme[ 'subscription_sign_up_fee' ] = ( $posted_scheme[ 'subscription_sign_up_fee' ] === '' ) ? '' : wc_format_decimal( $posted_scheme[ 'subscription_sign_up_fee' ] );
293
			}
294
295
			// Make sure trial period is within allowable range.
296
			$subscription_ranges = wcs_get_subscription_ranges();
297
			$max_trial_length = count( $subscription_ranges[ $posted_scheme[ 'subscription_trial_period' ] ] ) - 1;
298
299
			// Format subscription trial length.
300
			if ( isset( $posted_scheme[ 'subscription_trial_length' ] ) && $posted_scheme[ 'subscription_trial_length' ] > $max_trial_length ) {
301
				$posted_scheme[ 'subscription_trial_length' ] = ( $posted_scheme[ 'subscription_trial_length' ] === '' ) ? '' : absint( $posted_scheme[ 'subscription_trial_length' ] );
302
			}
303
304
			// Format subscription trial period.
305
			$trial_periods = apply_filters( 'wcsatt_stt_trial_periods', array( 'day', 'week', 'month', 'year' ) );
306
			if ( isset( $posted_scheme[ 'subscription_trial_period' ] ) && in_array( $posted_scheme[ 'subscription_trial_period' ], $trial_periods ) ) {
307
				$posted_scheme[ 'subscription_trial_period' ] = trim( $posted_scheme[ 'subscription_trial_period' ] );
308
			}
309
310
			return $posted_scheme;
311
		} // END wcsatt_stt_process_scheme_data()
312
313
		/**
314
		 * Adds the additional subscription scheme data for products with attached subscription schemes.
315
		 *
316
		 * @param  object     $_product
317
		 * @param  array      $subscription_scheme
318
		 * @param  WC_Product $product
319
		 * @return string
320
		 */
321
		public function add_sub_scheme_data_price_html( $_product, $subscription_scheme, $product ) {
322
			if ( isset( $subscription_scheme[ 'subscription_sign_up_fee' ] ) ) {
323
				$_product->subscription_sign_up_fee = $subscription_scheme[ 'subscription_sign_up_fee' ];
324
			}
325
326
			if ( isset( $subscription_scheme[ 'subscription_trial_length' ] ) ) {
327
				$_product->subscription_trial_length = $subscription_scheme[ 'subscription_trial_length' ];
328
			}
329
330
			if ( isset( $subscription_scheme[ 'subscription_trial_period' ] ) ) {
331
				$_product->subscription_trial_period = $subscription_scheme[ 'subscription_trial_period' ];
332
			}
333
334
			return $_product;
335
		} // END add_sub_scheme_data_price_html()
336
337
		/**
338
		 * Adds the extra subscription scheme data to the product object.
339
		 * This allows the subscription price to change the initial and
340
		 * recurring subscriptions.
341
		 *
342
		 * @param  object $_cloned
343
		 * @param  array  $subscription_scheme
344
		 * @return object
345
		 */
346
		public function sub_product_scheme_option( $_cloned, $subscription_scheme ) {
347
			if ( isset( $subscription_scheme[ 'subscription_sign_up_fee' ] ) && $subscription_scheme[ 'subscription_sign_up_fee' ] > 0 ) {
348
				$_cloned->subscription_sign_up_fee = $subscription_scheme[ 'subscription_sign_up_fee' ];
349
			}
350
351
			if ( isset( $subscription_scheme[ 'subscription_trial_length' ] ) && 0 != $subscription_scheme[ 'subscription_trial_length' ] ) {
352
				$_cloned->subscription_trial_length = $subscription_scheme[ 'subscription_trial_length' ];
353
				$_cloned->subscription_trial_period = $subscription_scheme[ 'subscription_trial_period' ];
354
			}
355
356
			return $_cloned;
357
		} // END sub_product_scheme_option()
358
359
		/**
360
		 * Filters the price string to include the sign up fee and/or trial 
361
		 * to pass per subscription scheme option.
362
		 *
363
		 * @param  array $prices
364
		 * @param  array $subscription_scheme
365
		 * @return array
366
		 */
367
		public function get_price_string( $prices, $subscription_scheme ) {
368
			if ( isset( $subscription_scheme[ 'subscription_sign_up_fee' ] ) && $subscription_scheme[ 'subscription_sign_up_fee' ] > 0 ) {
369
				$prices[ 'sign_up_fee' ] = $subscription_scheme[ 'subscription_sign_up_fee' ];
370
			}
371
372
			if ( isset( $subscription_scheme[ 'subscription_trial_length' ] ) && 0 != $subscription_scheme[ 'subscription_trial_length' ] ) {
373
				$prices[ 'trial_length' ] = true;
374
			}
375
376
			return $prices;
377
		} // END get_price_string()
378
379
		/**
380
		 * Filters the price string to include the sign up 
381
		 * fee on the lowest subscription scheme.
382
		 *
383
		 * @param  array $prices
384
		 * @param  array $lowest_subscription_scheme
385
		 * @return array
386
		 */
387
		public function get_lowest_price_string( $prices,  $lowest_subscription_scheme ) {
388
			if ( isset( $lowest_subscription_scheme[ 'sign_up_fee' ] ) && $lowest_subscription_scheme[ 'sign_up_fee' ] > 0 ) {
389
				$prices[ 'sign_up_fee' ] = $lowest_subscription_scheme[ 'sign_up_fee' ];
390
			}
391
392
			return $prices;
393
		} // END get_lowest_price_string()
394
395
		/**
396
		 * Adds the sign-up fee to the lowest subscription scheme option.
397
		 *
398
		 * @param array $data
399
		 * @param array $lowest_scheme
400
		 * @return array
401
		 */
402
		public function get_lowest_price_sub_scheme_data( $data, $lowest_scheme ) {
403
			if ( isset( $lowest_scheme['subscription_sign_up_fee'] ) && $lowest_scheme['subscription_sign_up_fee'] > 0 ) {
404
				$data['sign_up_fee'] = $lowest_scheme['subscription_sign_up_fee'];
405
			}
406
407
			return $data;
408
		} // END get_lowest_price_sub_scheme_data()
409
410
		/**
411
		 * Adds the sign-up and/or trial data to the subscription scheme prices.
412
		 *
413
		 * @param  array $prices
414
		 * @param  array $subscription_scheme
415
		 * @return array
416
		 */
417
		public function add_subscription_scheme_prices( $prices, $subscription_scheme ) {
418
			if ( isset( $subscription_scheme[ 'subscription_sign_up_fee' ] ) ) {
419
				$prices[ 'sign_up_fee' ] = $subscription_scheme[ 'subscription_sign_up_fee' ];
420
			}
421
422
			if ( isset( $subscription_scheme[ 'subscription_trial_length' ] ) ) {
423
				$prices[ 'trial_length' ] = $subscription_scheme[ 'subscription_trial_length' ];
424
			}
425
426
			if ( isset( $subscription_scheme[ 'subscription_trial_period' ] ) ) {
427
				$prices[ 'trial_period' ] = $subscription_scheme[ 'subscription_trial_period' ];
428
			}
429
430
			return $prices;
431
		} // END add_subscription_scheme_prices()
432
433
		/**
434
		 * Updates the cart item data for a subscription product that
435
		 * has a sign-up fee and/or trial period applied.
436
		 *
437
		 * @param  array $cart_item
438
		 * @return array
439
		 */
440
		public function update_cart_item_sub_data( $cart_item ) {
441
			$active_scheme = WCS_ATT_Schemes::get_active_subscription_scheme( $cart_item );
442
443
			$subscription_prices = WCS_ATT_Scheme_Prices::get_active_subscription_scheme_prices( $cart_item, $active_scheme );
444
445
			if ( $active_scheme && $cart_item['data']->is_converted_to_sub == 'yes' ) {
446
447
				// Subscription Price
448
				$price = $cart_item['data']->subscription_price;
449
450
				// Is there a sign up fee?
451
				$sign_up_fee = isset( $subscription_prices['sign_up_fee'] ) ? $subscription_prices['sign_up_fee'] : '';
452
453
				// Put them both together.
454
				$new_price = $price + $sign_up_fee;
455
456
				if ( $sign_up_fee > 0 ) {
457
					$cart_item['data']->initial_amount = $new_price;
458
					$cart_item['data']->subscription_sign_up_fee = $sign_up_fee;
459
				}
460
461
				$trial_length = isset( $subscription_prices['trial_length'] ) ? $subscription_prices['trial_length'] : 0;
462
				$trial_period = isset( $subscription_prices['trial_period'] ) ? $subscription_prices['trial_period'] : '';
463
464
				// If a trial length is more than zero then re-adjust the price.
465
				if ( $trial_length > 0 ) {
466
467
					/*$cart_item['data']->price = $new_price;
0 ignored issues
show
Unused Code Comprehensibility introduced by
60% 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...
468
					$cart_item['data']->subscription_price = $new_price;
469
					$cart_item['data']->sale_price = $new_price;
470
					$cart_item['data']->regular_price = $new_price;*/
471
472
					$cart_item['data']->subscription_trial_length = $trial_length;
473
					$cart_item['data']->subscription_trial_period = $trial_period;
474
				} else {
475
					$cart_item['data']->subscription_trial_length = 0;
476
					$cart_item['data']->subscription_trial_period = '';
477
				}
478
479
			}
480
481
			return $cart_item;
482
		} // END update_cart_item_sub_data()
483
484
	} // END class
485
486
} // END if class exists
487
488
return WCSATT_STT::instance();