Completed
Branch issue-6 (9081e8)
by Sébastien
14:48
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 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 All the Things extension v1.1.0+.
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.0';
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 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' ), 'WooCommerce Subscribe All the Things - Sign up and Trial Add-on', 'WooCommerce Subscribe 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 ) {
0 ignored issues
show
The parameter $product is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
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
					$cart_item['data']->subscription_trial_length = $trial_length;
467
					$cart_item['data']->subscription_trial_period = $trial_period;
468
				} else {
469
					$cart_item['data']->subscription_trial_length = 0;
470
					$cart_item['data']->subscription_trial_period = '';
471
				}
472
473
			}
474
475
			return $cart_item;
476
		} // END update_cart_item_sub_data()
477
478
	} // END class
479
480
} // END if class exists
481
482
return WCSATT_STT::instance();