Completed
Push — master ( c63b04...a7bcfb )
by Sébastien
02:23
created

wc-satt-stt.php (6 issues)

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://sebastiendumont.com
5
 * Version:     1.0.0 Alpha
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:      Sebastien 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.2
15
 *
16
 * Copyright: © 2016 Sebastien 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 ) < 0 ) {
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 ) < '1.1.1' ) {
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 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 Addon', '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
			// Filters the suffix price html on the 'wcsatt_suffix_price_html' filter.
143
			add_filter( 'wcsatt_suffix_price_html', array( $this, 'filter_suffix_price_html' ), 10, 1 );
144
145
			// Overrides the price of the subscription for sign up fee and/or trial on the 'woocommerce_add_cart_item' filter.
146
			add_filter( 'woocommerce_add_cart_item', array( $this, 'add_cart_item' ), 15, 1 );
147
		} // END init_plugin()
148
149
		/**
150
		 * Register the product meta data fields.
151
		 *
152
		 * @return void
153
		 */
154
		public function admin_wcsatt_stt_product_meta() {
155
			// Subscription scheme options displayed on the 'wcsatt_subscription_scheme_content' action.
156
			//add_action( 'wcsatt_subscription_scheme_content', array( $this, 'wcsatt_stt_fields' ), 15, 3 );
157
158
			// Subscription scheme options displayed on the 'wcsatt_subscription_scheme_product_content' action.
159
			add_action( 'wcsatt_subscription_scheme_product_content', array( $this, 'wcsatt_stt_fields' ), 15, 3 );
160
161
			// Filter the subscription scheme data to process the sign up and trial options on the ''wcsatt_subscription_scheme_process_scheme_data' filter.
162
			add_filter( 'wcsatt_subscription_scheme_process_scheme_data', array( $this, 'wcsatt_stt_process_scheme_data' ), 10, 2 );
163
		} // END admin_wcsatt_stt_product_meta()
164
165
		/**
166
		 * Show row meta on the plugin screen.
167
		 *
168
		 * @param mixed $links Plugin Row Meta
169
		 * @param mixed $file  Plugin Base file
170
		 * @return array
171
		 */
172
		public function plugin_meta_links( $links, $file, $data, $status ) {
173
			if ( $file == plugin_basename( __FILE__ ) ) {
174
				$author1 = '<a href="' . $data[ 'AuthorURI' ] . '">' . $data[ 'Author' ] . '</a>';
175
				$links[ 1 ] = sprintf( __( 'By %s', WCSATT_STT::TEXT_DOMAIN ), $author1 );
176
			}
177
178
			return $links;
179
		} // END plugin_meta_links()
180
181
		/**
182
		 * Subscriptions schemes admin metaboxes.
183
		 *
184
		 * @param  array $values
185
		 * @return void
186
		 */
187
		public static function add_default_subscription_schemes_content( $defaults ) {
188
			$new_defaults = array(
189
				'subscription_sign_up_fee' => '',
190
				'subscription_trial_length' => 0,
191
				'subscription_trial_period' => ''
192
			);
193
194
			return array_merge( $new_defaults, $defaults );
195
		} // END add_default_subscription_schemes_content()
196
197
		/**
198
		 * Adds the trial and sign up fields under the subscription section.
199
		 *
200
		 * @param  int   $index
201
		 * @param  array $scheme_data
202
		 * @param  int   $post_id
203
		 * @return void
204
		 */
205
		public function wcsatt_stt_fields( $index, $scheme_data, $post_id ) {
206
			if ( ! empty( $scheme_data ) ) {
207
				$subscription_sign_up_fee = ! empty( $scheme_data[ 'subscription_sign_up_fee' ] ) ? $scheme_data[ 'subscription_sign_up_fee' ] : 'inherit';
0 ignored issues
show
$subscription_sign_up_fee is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
208
				$subscription_trial_length = isset( $scheme_data[ 'subscription_trial_length' ] ) ? $scheme_data[ 'subscription_trial_length' ] : '';
0 ignored issues
show
$subscription_trial_length is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
209
				$subscription_trial_period = isset( $scheme_data[ 'subscription_trial_period' ] ) ? $scheme_data[ 'subscription_trial_period' ] : '';
0 ignored issues
show
$subscription_trial_period is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
210
			} else {
211
				$subscription_sign_up_fee = '';
0 ignored issues
show
$subscription_sign_up_fee is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
212
				$subscription_trial_length = 0;
0 ignored issues
show
$subscription_trial_length is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
213
				$subscription_trial_period = '';
0 ignored issues
show
$subscription_trial_period is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
214
			}
215
216
			// Sign-up Fee
217
			woocommerce_wp_text_input( array(
218
				'id'          => '_subscription_sign_up_fee',
219
				'class'       => 'wc_input_subscription_intial_price',
220
				// translators: %s is a currency symbol / code
221
				'label'       => sprintf( __( 'Sign-up Fee (%s)', WCSATT_STT::TEXT_DOMAIN ), get_woocommerce_currency_symbol() ),
222
				'placeholder' => _x( 'e.g. 9.90', 'example price', WCSATT_STT::TEXT_DOMAIN ),
223
				'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 ),
224
				'desc_tip'    => true,
225
				'type'        => 'text',
226
				'custom_attributes' => array(
227
					'step' => 'any',
228
					'min'  => '0',
229
				),
230
				'name'        => 'wcsatt_schemes[' . $index . '][subscription_sign_up_fee]'
231
			) );
232
233
			// Trial Length
234
			woocommerce_wp_text_input( array(
235
				'id'          => '_subscription_trial_length',
236
				'class'       => 'wc_input_subscription_trial_length',
237
				'label'       => __( 'Free Trial', WCSATT_STT::TEXT_DOMAIN ),
238
				'name'        => 'wcsatt_schemes[' . $index . '][subscription_trial_length]'
239
			) );
240
241
			// Trial Period
242
			woocommerce_wp_select( array(
243
				'id'          => '_subscription_trial_period',
244
				'class'       => 'wc_input_subscription_trial_period',
245
				'label'       => __( 'Subscription Trial Period', WCSATT_STT::TEXT_DOMAIN ),
246
				'options'     => wcs_get_available_time_periods(),
247
				// translators: placeholder is trial period validation message if passed an invalid value (e.g. "Trial period can not exceed 4 weeks")
248
				'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 ), self::get_trial_period_validation_message() ),
249
				'desc_tip'    => true,
250
				'value'       => WC_Subscriptions_Product::get_trial_period( $post_id ), // Explicitly set value in to ensure backward compatibility
251
				'name'        => 'wcsatt_schemes[' . $index . '][subscription_trial_period]'
252
		) );
253
		} // END wcsatt_stt_fields()
254
255
		/**
256
		 * Filters the subscription scheme data to pass the 
257
		 * sign up and trial options when saving.
258
		 *
259
		 * @param  ini $posted_scheme
260
		 * @param  string $product_type
261
		 * @return void
262
		 */
263
		public function wcsatt_stt_process_scheme_data( $posted_scheme, $product_type ) {
264
			// Copy variable type fields.
265
			if ( 'variable' == $product_type ) {
266
				if ( isset( $posted_scheme[ 'subscription_sign_up_fee_variable' ] ) ) {
267
					$posted_scheme[ 'subscription_sign_up_fee' ] = $posted_scheme[ 'subscription_sign_up_fee_variable' ];
268
				}
269
				if ( isset( $posted_scheme[ 'subscription_trial_length_variable' ] ) ) {
270
					$posted_scheme[ 'subscription_trial_length' ] = $posted_scheme[ 'subscription_trial_length_variable' ];
271
				}
272
				if ( isset( $posted_scheme[ 'subscription_trial_period_variable' ] ) ) {
273
					$posted_scheme[ 'subscription_trial_period' ] = $posted_scheme[ 'subscription_trial_period_variable'];
274
				}
275
			}
276
277
			// Format subscription sign up fee.
278 View Code Duplication
			if ( isset( $posted_scheme[ 'subscription_sign_up_fee' ] ) ) {
279
				$posted_scheme[ 'subscription_sign_up_fee' ] = ( $posted_scheme[ 'subscription_sign_up_fee' ] === '' ) ? '' : wc_format_decimal( $posted_scheme[ 'subscription_sign_up_fee' ] );
280
			}
281
282
			// Format subscription trial length.
283 View Code Duplication
			if ( isset( $posted_scheme[ 'subscription_trial_length' ] ) ) {
284
				$posted_scheme[ 'subscription_trial_length' ] = ( $posted_scheme[ 'subscription_trial_length' ] === '' ) ? '' : wc_format_decimal( $posted_scheme[ 'subscription_trial_length' ] );
285
			}
286
287
			// Format subscription trial period.
288
			$trial_periods = apply_filters( 'wcsatt_stt_trial_periods', array( 'day', 'week', 'month', 'year' ) );
289
			if ( isset( $posted_scheme[ 'subscription_trial_period' ] ) && in_array( $posted_scheme[ 'subscription_trial_period' ], $trial_periods ) ) {
290
				$posted_scheme[ 'subscription_trial_period' ] = $posted_scheme[ 'subscription_trial_period' ];
291
			}
292
293
			return $posted_scheme;
294
		} // END wcsatt_stt_process_scheme_data()
295
296
		/**
297
		 * Adds the additional subscription scheme data for products with attached subscription schemes.
298
		 *
299
		 * @param  object     $_product
300
		 * @param  array      $subscription_scheme
301
		 * @param  WC_Product $product
302
		 * @return string
303
		 */
304
		public function add_sub_scheme_data_price_html( $_product, $subscription_scheme, $product ) {
305
			if ( isset( $subscription_scheme[ 'subscription_sign_up_fee' ] ) ) {
306
				$_product->subscription_sign_up_fee = $subscription_scheme[ 'subscription_sign_up_fee' ];
307
			}
308
309
			if ( isset( $subscription_scheme[ 'subscription_trial_length' ] ) ) {
310
				$_product->subscription_trial_length = $subscription_scheme[ 'subscription_trial_length' ];
311
			}
312
313
			if ( isset( $subscription_scheme[ 'subscription_trial_period' ] ) ) {
314
				$_product->subscription_trial_period = $subscription_scheme[ 'subscription_trial_period' ];
315
			}
316
317
			return $_product;
318
		}
319
320
		/**
321
		 * Filter the suffix price string.
322
		 *
323
		 * @param object     $_product
324
		 * @param array      $subscription_scheme
325
		 * @param WC_Product $product
326
		 * @return string
327
		 */
328
		public function filter_suffix_price_html( $_product, $subscription_scheme, $product ) {
329
			if ( isset( $_product->subscription_trial_length ) && 0 != $_product->subscription_trial_length ) {
330
				$trial_string = wcs_get_subscription_trial_period_strings( $_product->subscription_trial_length, $_product->subscription_trial_period );
331
				// translators: 1$: subscription string (e.g. "$15 on March 15th every 3 years for 6 years"), 2$: trial length (e.g.: "with 4 months free trial")
332
				$subscription_string = sprintf( __( '%1$s with %2$s free trial', WCSATT_STT::TEXT_DOMAIN ), $subscription_string, $trial_string );
333
			}
334
335
			$sign_up_fee = $_product->subscription_sign_up_fee;
336
337
			if ( is_numeric( $sign_up_fee ) ) {
338
				$sign_up_fee = wc_price( $sign_up_fee );
339
			}
340
341
			if ( isset( $_product->subscription_sign_up_fee ) && $_product->subscription_sign_up_fee > 0 ) {
342
				// translators: 1$: subscription string (e.g. "$15 on March 15th every 3 years for 6 years with 2 months free trial"), 2$: signup fee price (e.g. "and a $30 sign-up fee")
343
				$subscription_string = sprintf( __( '%1$s and a %2$s sign-up fee', WCSATT_STT::TEXT_DOMAIN ), $subscription_string, $sign_up_fee );
344
			}
345
346
			return $subscription_string;
347
		}
348
349
		/**
350
		 * Converts a cart item if it's a subscription with 
351
		 * a trial subscription or/and has a sign-up fee.
352
		 *
353
		 * @param  array $cart_item
354
		 * @return array
355
		 */
356
		public function add_cart_item( $cart_item ) {
357
			$active_scheme = WCS_ATT_Schemes::get_active_subscription_scheme( $cart_item );
358
359
			if ( $active_scheme && $cart_item['data']->is_converted_to_sub == 'yes' ) {
360
361
				$sign_up_fee  = $this->get_item_signup_fee( $cart_item[ 'product_id' ], $active_scheme );
362
				$trial_length = $this->get_item_trial_length( $cart_item[ 'product_id' ], $active_scheme );
363
				$trial_period = $this->get_item_trial_period( $cart_item[ 'product_id' ], $active_scheme );
364
365
				// Subscription Price
366
				$price = $cart_item['data']->subscription_price;
367
368
				// Is there a sign up fee?
369
				$sign_up_fee = ! empty( $sign_up_fee ) ? $sign_up_fee : '';
370
371
				// If a trial length is more than zero then re-adjust the price.
372
				if ( $trial_length > 0 ) {
373
					$cart_item['data']->price = $sign_up_fee;
374
					$cart_item['data']->subscription_price = $sign_up_fee;
375
					$cart_item['data']->sale_price = $sign_up_fee;
376
					$cart_item['data']->regular_price = $sign_up_fee;
377
					$cart_item['data']->initial_amount = $sign_up_fee;
378
					$cart_item['data']->subscription_sign_up_fee = $sign_up_fee;
379
					$cart_item['data']->subscription_trial_length = $trial_length;
380
					$cart_item['data']->subscription_trial_period = $trial_period;
381
				} else {
382
					$cart_item['data']->price = $price + $sign_up_fee;
383
					$cart_item['data']->subscription_price = $price + $sign_up_fee;
384
					$cart_item['data']->sale_price = $price + $sign_up_fee;
385
					$cart_item['data']->regular_price = $price + $sign_up_fee;
386
					$cart_item['data']->initial_amount = $price + $sign_up_fee;
387
					$cart_item['data']->subscription_sign_up_fee = $sign_up_fee;
388
					$cart_item['data']->subscription_trial_length = 0;
389
					$cart_item['data']->subscription_trial_period = '';
390
				}
391
392
			}
393
394
			return $cart_item;
395
		} // END add_cart_item()
396
397
		/**
398
		 * Get the item signup fee from the subscription scheme.
399
		 *
400
		 * @param int  $product_id
401
		 * @param int  $scheme_id
402
		 * @return int
403
		 */
404
		public function get_item_signup_fee( $product_id, $scheme_id ) {
405
			$product_schemes = get_post_meta( $product_id, '_wcsatt_schemes', true );
406
			$thescheme = $product_schemes[$scheme_id];
407
408
			return $thescheme['subscription_sign_up_fee'];
409
		} // END get_item_signup_fee()
410
411
		/**
412
		 * Get the item trial length from the subscription scheme.
413
		 *
414
		 * @param int  $product_id
415
		 * @param int  $scheme_id
416
		 * @return int
417
		 */
418
		public function get_item_trial_length( $product_id, $scheme_id ) {
419
			$product_schemes = get_post_meta( $product_id, '_wcsatt_schemes', true );
420
			$thescheme = $product_schemes[$scheme_id];
421
422
			return $thescheme['subscription_trial_length'];
423
		} // END get_item_trial_length()
424
425
		/**
426
		 * Get the item trial period from the subscription scheme.
427
		 *
428
		 * @param  int    $product_id
429
		 * @param  int    $scheme_id
430
		 * @return string
431
		 */
432
		public function get_item_trial_period( $product_id, $scheme_id ) {
433
			$product_schemes = get_post_meta( $product_id, '_wcsatt_schemes', true );
434
			$thescheme = $product_schemes[$scheme_id];
435
436
			return $thescheme['subscription_trial_period'];
437
		} // END get_item_trial_period()
438
439
	} // END class
440
441
} // END if class exists
442
443
return WCSATT_STT::instance();