Completed
Push — master ( deec93...29d630 )
by Claudio
31:19 queued 22:42
created

get_wizard_in_cart_payment_gateways()   D

Complexity

Conditions 14
Paths 290

Size

Total Lines 62

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 35
CRAP Score 14.031

Importance

Changes 0
Metric Value
cc 14
nc 290
nop 0
dl 0
loc 62
ccs 35
cts 37
cp 0.9459
crap 14.031
rs 4.3083
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * Setup Wizard Class
4
 *
5
 * Takes new users through some basic steps to setup their store.
6
 *
7
 * @package     WooCommerce/Admin
8
 * @version     2.6.0
9
 */
10
11 1
if ( ! defined( 'ABSPATH' ) ) {
12
	exit;
13
}
14
15
/**
16
 * WC_Admin_Setup_Wizard class.
17
 */
18
class WC_Admin_Setup_Wizard {
19
20
	/**
21
	 * Current step
22
	 *
23
	 * @var string
24
	 */
25
	private $step = '';
26
27
	/**
28
	 * Steps for the setup wizard
29
	 *
30
	 * @var array
31
	 */
32
	private $steps = array();
33
34
	/**
35
	 * Actions to be executed after the HTTP response has completed
36
	 *
37
	 * @var array
38
	 */
39
	private $deferred_actions = array();
40
41
	/**
42
	 * Tweets user can optionally send after install
43
	 *
44
	 * @var array
45
	 */
46
	private $tweets = array(
47
		'Someone give me woo-t, I just set up a new store with #WordPress and @WooCommerce!',
48
		'Someone give me high five, I just set up a new store with #WordPress and @WooCommerce!',
49
	);
50
51
	/**
52
	 * Hook in tabs.
53
	 */
54 1
	public function __construct() {
55 1
		if ( apply_filters( 'woocommerce_enable_setup_wizard', true ) && current_user_can( 'manage_woocommerce' ) ) {
56
			add_action( 'admin_menu', array( $this, 'admin_menus' ) );
57
			add_action( 'admin_init', array( $this, 'setup_wizard' ) );
58
			add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_scripts' ) );
59
		}
60
	}
61
62
	/**
63
	 * Add admin menus/screens.
64
	 */
65
	public function admin_menus() {
66
		add_dashboard_page( '', '', 'manage_options', 'wc-setup', '' );
67
	}
68
69
	/**
70
	 * The theme "extra" should only be shown if the current user can modify themes
71
	 * and the store doesn't already have a WooCommerce theme.
72
	 *
73
	 * @return boolean
74
	 */
75
	protected function should_show_theme() {
76
		$support_woocommerce = current_theme_supports( 'woocommerce' ) && ! $this->is_default_theme();
77
78
		return (
79
			current_user_can( 'install_themes' ) &&
80
			current_user_can( 'switch_themes' ) &&
81
			! is_multisite() &&
82
			! $support_woocommerce
83
		);
84
	}
85
86
	/**
87
	 * Is the user using a default WP theme?
88
	 *
89
	 * @return boolean
90
	 */
91
	protected function is_default_theme() {
92
		return wc_is_active_theme(
93
			array(
94
				'twentynineteen',
95
				'twentyseventeen',
96
				'twentysixteen',
97
				'twentyfifteen',
98
				'twentyfourteen',
99
				'twentythirteen',
100
				'twentyeleven',
101
				'twentytwelve',
102
				'twentyten',
103
			)
104
		);
105
	}
106
107
	/**
108
	 * The "automated tax" extra should only be shown if the current user can
109
	 * install plugins and the store is in a supported country.
110
	 */
111
	protected function should_show_automated_tax() {
112
		if ( ! current_user_can( 'install_plugins' ) ) {
113
			return false;
114
		}
115
116
		$country_code = WC()->countries->get_base_country();
117
		// https://developers.taxjar.com/api/reference/#countries .
118
		$tax_supported_countries = array_merge(
119
			array( 'US', 'CA', 'AU' ),
120
			WC()->countries->get_european_union_countries()
121
		);
122
123
		return in_array( $country_code, $tax_supported_countries, true );
124
	}
125
126
	/**
127
	 * Should we show the MailChimp install option?
128
	 * True only if the user can install plugins.
129
	 *
130
	 * @return boolean
131
	 */
132
	protected function should_show_mailchimp() {
133
		return current_user_can( 'install_plugins' );
134
	}
135
136
	/**
137
	 * Should we show the Facebook install option?
138
	 * True only if the user can install plugins,
139
	 * and up until the end date of the recommendation.
140
	 *
141
	 * @return boolean
142
	 */
143
	protected function should_show_facebook() {
144
		return current_user_can( 'install_plugins' );
145
	}
146
147
	/**
148
	 * Should we display the 'Recommended' step?
149
	 * True if at least one of the recommendations will be displayed.
150
	 *
151
	 * @return boolean
152
	 */
153
	protected function should_show_recommended_step() {
154
		return $this->should_show_theme()
155
			|| $this->should_show_automated_tax()
156
			|| $this->should_show_mailchimp()
157
			|| $this->should_show_facebook();
158
	}
159
160
	/**
161
	 * Register/enqueue scripts and styles for the Setup Wizard.
162
	 *
163
	 * Hooked onto 'admin_enqueue_scripts'.
164
	 */
165
	public function enqueue_scripts() {
166
		// Whether or not there is a pending background install of Jetpack.
167
		$pending_jetpack = ! class_exists( 'Jetpack' ) && get_option( 'woocommerce_setup_background_installing_jetpack' );
168
		$suffix          = defined( 'SCRIPT_DEBUG' ) && SCRIPT_DEBUG ? '' : '.min';
169
170
		wp_register_script( 'jquery-blockui', WC()->plugin_url() . '/assets/js/jquery-blockui/jquery.blockUI' . $suffix . '.js', array( 'jquery' ), '2.70', true );
171
		wp_register_script( 'selectWoo', WC()->plugin_url() . '/assets/js/selectWoo/selectWoo.full' . $suffix . '.js', array( 'jquery' ), '1.0.6' );
172
		wp_register_script( 'wc-enhanced-select', WC()->plugin_url() . '/assets/js/admin/wc-enhanced-select' . $suffix . '.js', array( 'jquery', 'selectWoo' ), WC_VERSION );
173
		wp_localize_script(
174
			'wc-enhanced-select',
175
			'wc_enhanced_select_params',
176
			array(
177
				'i18n_no_matches'           => _x( 'No matches found', 'enhanced select', 'woocommerce' ),
178
				'i18n_ajax_error'           => _x( 'Loading failed', 'enhanced select', 'woocommerce' ),
179
				'i18n_input_too_short_1'    => _x( 'Please enter 1 or more characters', 'enhanced select', 'woocommerce' ),
180
				'i18n_input_too_short_n'    => _x( 'Please enter %qty% or more characters', 'enhanced select', 'woocommerce' ),
181
				'i18n_input_too_long_1'     => _x( 'Please delete 1 character', 'enhanced select', 'woocommerce' ),
182
				'i18n_input_too_long_n'     => _x( 'Please delete %qty% characters', 'enhanced select', 'woocommerce' ),
183
				'i18n_selection_too_long_1' => _x( 'You can only select 1 item', 'enhanced select', 'woocommerce' ),
184
				'i18n_selection_too_long_n' => _x( 'You can only select %qty% items', 'enhanced select', 'woocommerce' ),
185
				'i18n_load_more'            => _x( 'Loading more results&hellip;', 'enhanced select', 'woocommerce' ),
186
				'i18n_searching'            => _x( 'Searching&hellip;', 'enhanced select', 'woocommerce' ),
187
				'ajax_url'                  => admin_url( 'admin-ajax.php' ),
188
				'search_products_nonce'     => wp_create_nonce( 'search-products' ),
189
				'search_customers_nonce'    => wp_create_nonce( 'search-customers' ),
190
			)
191
		);
192
		wp_enqueue_style( 'woocommerce_admin_styles', WC()->plugin_url() . '/assets/css/admin.css', array(), WC_VERSION );
193
		wp_enqueue_style( 'wc-setup', WC()->plugin_url() . '/assets/css/wc-setup.css', array( 'dashicons', 'install' ), WC_VERSION );
194
195
		wp_register_script( 'wc-setup', WC()->plugin_url() . '/assets/js/admin/wc-setup' . $suffix . '.js', array( 'jquery', 'wc-enhanced-select', 'jquery-blockui', 'wp-util', 'jquery-tiptip' ), WC_VERSION );
196
		wp_localize_script(
197
			'wc-setup',
198
			'wc_setup_params',
199
			array(
200
				'pending_jetpack_install' => $pending_jetpack ? 'yes' : 'no',
201
				'states'                  => WC()->countries->get_states(),
202
				'current_step'            => isset( $this->steps[ $this->step ] ) ? $this->step : false,
203
				'i18n'                    => array(
204
					'extra_plugins' => array(
205
						'payment' => array(
206
							'stripe_create_account'        => __( 'Stripe setup is powered by Jetpack and WooCommerce Services.', 'woocommerce' ),
207
							'ppec_paypal_reroute_requests' => __( 'PayPal setup is powered by Jetpack and WooCommerce Services.', 'woocommerce' ),
208
							'stripe_create_account,ppec_paypal_reroute_requests' => __( 'Stripe and PayPal setup are powered by Jetpack and WooCommerce Services.', 'woocommerce' ),
209
						),
210
					),
211
				),
212
			)
213
		);
214
	}
215
216
	/**
217
	 * Show the setup wizard.
218
	 */
219
	public function setup_wizard() {
220
		if ( empty( $_GET['page'] ) || 'wc-setup' !== $_GET['page'] ) { // WPCS: CSRF ok, input var ok.
0 ignored issues
show
introduced by
Detected usage of a non-sanitized input variable: $_GET
Loading history...
221
			return;
222
		}
223
		$default_steps = array(
224
			'store_setup' => array(
225
				'name'    => __( 'Store setup', 'woocommerce' ),
226
				'view'    => array( $this, 'wc_setup_store_setup' ),
227
				'handler' => array( $this, 'wc_setup_store_setup_save' ),
228
			),
229
			'payment'     => array(
230
				'name'    => __( 'Payment', 'woocommerce' ),
231
				'view'    => array( $this, 'wc_setup_payment' ),
232
				'handler' => array( $this, 'wc_setup_payment_save' ),
233
			),
234
			'shipping'    => array(
235
				'name'    => __( 'Shipping', 'woocommerce' ),
236
				'view'    => array( $this, 'wc_setup_shipping' ),
237
				'handler' => array( $this, 'wc_setup_shipping_save' ),
238
			),
239
			'recommended' => array(
240
				'name'    => __( 'Recommended', 'woocommerce' ),
241
				'view'    => array( $this, 'wc_setup_recommended' ),
242
				'handler' => array( $this, 'wc_setup_recommended_save' ),
243
			),
244
			'activate'    => array(
245
				'name'    => __( 'Activate', 'woocommerce' ),
246
				'view'    => array( $this, 'wc_setup_activate' ),
247
				'handler' => array( $this, 'wc_setup_activate_save' ),
248
			),
249
			'next_steps'  => array(
250
				'name'    => __( 'Ready!', 'woocommerce' ),
251
				'view'    => array( $this, 'wc_setup_ready' ),
252
				'handler' => '',
253
			),
254
		);
255
256
		// Hide recommended step if nothing is going to be shown there.
257
		if ( ! $this->should_show_recommended_step() ) {
258
			unset( $default_steps['recommended'] );
259
		}
260
261
		// Hide shipping step if the store is selling digital products only.
262
		if ( 'virtual' === get_option( 'woocommerce_product_type' ) ) {
263
			unset( $default_steps['shipping'] );
264
		}
265
266
		// Hide activate section when the user does not have capabilities to install plugins, think multiside admins not being a super admin.
267
		if ( ! current_user_can( 'install_plugins' ) ) {
268
			unset( $default_steps['activate'] );
269
		}
270
271
		$this->steps = apply_filters( 'woocommerce_setup_wizard_steps', $default_steps );
272
		$this->step  = isset( $_GET['step'] ) ? sanitize_key( $_GET['step'] ) : current( array_keys( $this->steps ) ); // WPCS: CSRF ok, input var ok.
273
274
		// @codingStandardsIgnoreStart
275 View Code Duplication
		if ( ! empty( $_POST['save_step'] ) && isset( $this->steps[ $this->step ]['handler'] ) ) {
276
			call_user_func( $this->steps[ $this->step ]['handler'], $this );
277
		}
278
		// @codingStandardsIgnoreEnd
279
280
		ob_start();
281
		$this->setup_wizard_header();
282
		$this->setup_wizard_steps();
283
		$this->setup_wizard_content();
284
		$this->setup_wizard_footer();
285
		exit;
286
	}
287
288
	/**
289
	 * Get the URL for the next step's screen.
290
	 *
291
	 * @param string $step  slug (default: current step).
292
	 * @return string       URL for next step if a next step exists.
293
	 *                      Admin URL if it's the last step.
294
	 *                      Empty string on failure.
295
	 * @since 3.0.0
296
	 */
297
	public function get_next_step_link( $step = '' ) {
298
		if ( ! $step ) {
299
			$step = $this->step;
300
		}
301
302
		$keys = array_keys( $this->steps );
303
		if ( end( $keys ) === $step ) {
304
			return admin_url();
305
		}
306
307
		$step_index = array_search( $step, $keys, true );
308
		if ( false === $step_index ) {
309
			return '';
310
		}
311
312
		return add_query_arg( 'step', $keys[ $step_index + 1 ], remove_query_arg( 'activate_error' ) );
313
	}
314
315
	/**
316
	 * Setup Wizard Header.
317
	 */
318
	public function setup_wizard_header() {
319
		set_current_screen();
320
		?>
321
		<!DOCTYPE html>
322
		<html <?php language_attributes(); ?>>
323
		<head>
324
			<meta name="viewport" content="width=device-width" />
325
			<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
326
			<title><?php esc_html_e( 'WooCommerce &rsaquo; Setup Wizard', 'woocommerce' ); ?></title>
327
			<?php do_action( 'admin_enqueue_scripts' ); ?>
328
			<?php wp_print_scripts( 'wc-setup' ); ?>
329
			<?php do_action( 'admin_print_styles' ); ?>
330
			<?php do_action( 'admin_head' ); ?>
331
		</head>
332
		<body class="wc-setup wp-core-ui">
333
			<h1 id="wc-logo"><a href="https://woocommerce.com/"><img src="<?php echo esc_url( WC()->plugin_url() ); ?>/assets/images/woocommerce_logo.png" alt="WooCommerce" /></a></h1>
334
		<?php
335
	}
336
337
	/**
338
	 * Setup Wizard Footer.
339
	 */
340
	public function setup_wizard_footer() {
341
		?>
342
			<?php if ( 'store_setup' === $this->step ) : ?>
343
				<a class="wc-setup-footer-links" href="<?php echo esc_url( admin_url() ); ?>"><?php esc_html_e( 'Not right now', 'woocommerce' ); ?></a>
344
			<?php elseif ( 'recommended' === $this->step || 'activate' === $this->step ) : ?>
345
				<a class="wc-setup-footer-links" href="<?php echo esc_url( $this->get_next_step_link() ); ?>"><?php esc_html_e( 'Skip this step', 'woocommerce' ); ?></a>
346
			<?php endif; ?>
347
			<?php do_action( 'woocommerce_setup_footer' ); ?>
348
			</body>
349
		</html>
350
		<?php
351
	}
352
353
	/**
354
	 * Output the steps.
355
	 */
356
	public function setup_wizard_steps() {
357
		$output_steps      = $this->steps;
358
		$selected_features = array_filter( $this->wc_setup_activate_get_feature_list() );
359
360
		// Hide the activate step if Jetpack is already active, unless WooCommerce Services
361
		// features are selected, or unless the Activate step was already taken.
362
		if ( class_exists( 'Jetpack' ) && Jetpack::is_active() && empty( $selected_features ) && 'yes' !== get_transient( 'wc_setup_activated' ) ) {
363
			unset( $output_steps['activate'] );
364
		}
365
366
		?>
367
		<ol class="wc-setup-steps">
368
			<?php
369
			foreach ( $output_steps as $step_key => $step ) {
370
				$is_completed = array_search( $this->step, array_keys( $this->steps ), true ) > array_search( $step_key, array_keys( $this->steps ), true );
371
372
				if ( $step_key === $this->step ) {
373
					?>
374
					<li class="active"><?php echo esc_html( $step['name'] ); ?></li>
375
					<?php
376
				} elseif ( $is_completed ) {
377
					?>
378
					<li class="done">
379
						<a href="<?php echo esc_url( add_query_arg( 'step', $step_key, remove_query_arg( 'activate_error' ) ) ); ?>"><?php echo esc_html( $step['name'] ); ?></a>
380
					</li>
381
					<?php
382
				} else {
383
					?>
384
					<li><?php echo esc_html( $step['name'] ); ?></li>
385
					<?php
386
				}
387
			}
388
			?>
389
		</ol>
390
		<?php
391
	}
392
393
	/**
394
	 * Output the content for the current step.
395
	 */
396
	public function setup_wizard_content() {
397
		echo '<div class="wc-setup-content">';
398
		if ( ! empty( $this->steps[ $this->step ]['view'] ) ) {
399
			call_user_func( $this->steps[ $this->step ]['view'], $this );
400
		}
401
		echo '</div>';
402
	}
403
404
	/**
405
	 * Initial "store setup" step.
406
	 * Location, product type, page setup, and tracking opt-in.
407
	 */
408
	public function wc_setup_store_setup() {
409
		$address        = WC()->countries->get_base_address();
410
		$address_2      = WC()->countries->get_base_address_2();
411
		$city           = WC()->countries->get_base_city();
412
		$state          = WC()->countries->get_base_state();
413
		$country        = WC()->countries->get_base_country();
414
		$postcode       = WC()->countries->get_base_postcode();
415
		$currency       = get_option( 'woocommerce_currency', 'GBP' );
416
		$product_type   = get_option( 'woocommerce_product_type', 'both' );
417
		$sell_in_person = get_option( 'woocommerce_sell_in_person', 'none_selected' );
418
419
		if ( empty( $country ) ) {
420
			$user_location = WC_Geolocation::geolocate_ip();
421
			$country       = $user_location['country'];
422
			$state         = $user_location['state'];
423
		}
424
425
		$locale_info         = include WC()->plugin_path() . '/i18n/locale-info.php';
426
		$currency_by_country = wp_list_pluck( $locale_info, 'currency_code' );
427
		?>
428
		<form method="post" class="address-step">
429
			<?php wp_nonce_field( 'wc-setup' ); ?>
430
			<p class="store-setup"><?php esc_html_e( 'The following wizard will help you configure your store and get you started quickly.', 'woocommerce' ); ?></p>
431
432
			<div class="store-address-container">
433
434
				<label for="store_country" class="location-prompt"><?php esc_html_e( 'Where is your store based?', 'woocommerce' ); ?></label>
435
				<select id="store_country" name="store_country" required data-placeholder="<?php esc_attr_e( 'Choose a country&hellip;', 'woocommerce' ); ?>" aria-label="<?php esc_attr_e( 'Country', 'woocommerce' ); ?>" class="location-input wc-enhanced-select dropdown">
436
					<?php foreach ( WC()->countries->get_countries() as $code => $label ) : ?>
437
						<option <?php selected( $code, $country ); ?> value="<?php echo esc_attr( $code ); ?>"><?php echo esc_html( $label ); ?></option>
438
					<?php endforeach; ?>
439
				</select>
440
441
				<label class="location-prompt" for="store_address"><?php esc_html_e( 'Address', 'woocommerce' ); ?></label>
442
				<input type="text" id="store_address" class="location-input" name="store_address" required value="<?php echo esc_attr( $address ); ?>" />
443
444
				<label class="location-prompt" for="store_address_2"><?php esc_html_e( 'Address line 2', 'woocommerce' ); ?></label>
445
				<input type="text" id="store_address_2" class="location-input" name="store_address_2" value="<?php echo esc_attr( $address_2 ); ?>" />
446
447
				<div class="city-and-postcode">
448
					<div>
449
						<label class="location-prompt" for="store_city"><?php esc_html_e( 'City', 'woocommerce' ); ?></label>
450
						<input type="text" id="store_city" class="location-input" name="store_city" required value="<?php echo esc_attr( $city ); ?>" />
451
					</div>
452
					<div class="store-state-container hidden">
453
						<label for="store_state" class="location-prompt">
454
							<?php esc_html_e( 'State', 'woocommerce' ); ?>
455
						</label>
456
						<select id="store_state" name="store_state" data-placeholder="<?php esc_attr_e( 'Choose a state&hellip;', 'woocommerce' ); ?>" aria-label="<?php esc_attr_e( 'State', 'woocommerce' ); ?>" class="location-input wc-enhanced-select dropdown"></select>
457
					</div>
458
					<div>
459
						<label class="location-prompt" for="store_postcode"><?php esc_html_e( 'Postcode / ZIP', 'woocommerce' ); ?></label>
460
						<input type="text" id="store_postcode" class="location-input" name="store_postcode" required value="<?php echo esc_attr( $postcode ); ?>" />
461
					</div>
462
				</div>
463
			</div>
464
465
			<div class="store-currency-container">
466
			<label class="location-prompt" for="currency_code">
467
				<?php esc_html_e( 'What currency do you accept payments in?', 'woocommerce' ); ?>
468
			</label>
469
			<select
470
				id="currency_code"
471
				name="currency_code"
472
				required
473
				data-placeholder="<?php esc_attr_e( 'Choose a currency&hellip;', 'woocommerce' ); ?>"
474
				class="location-input wc-enhanced-select dropdown"
475
			>
476
				<option value=""><?php esc_html_e( 'Choose a currency&hellip;', 'woocommerce' ); ?></option>
477
				<?php foreach ( get_woocommerce_currencies() as $code => $name ) : ?>
478
					<option value="<?php echo esc_attr( $code ); ?>" <?php selected( $currency, $code ); ?>>
479
						<?php
480
						$symbol = get_woocommerce_currency_symbol( $code );
481
482
						if ( $symbol === $code ) {
483
							/* translators: 1: currency name 2: currency code */
484
							echo esc_html( sprintf( __( '%1$s (%2$s)', 'woocommerce' ), $name, $code ) );
485
						} else {
486
							/* translators: 1: currency name 2: currency symbol, 3: currency code */
487
							echo esc_html( sprintf( __( '%1$s (%2$s %3$s)', 'woocommerce' ), $name, get_woocommerce_currency_symbol( $code ), $code ) );
488
						}
489
						?>
490
					</option>
491
				<?php endforeach; ?>
492
			</select>
493
			<script type="text/javascript">
494
				var wc_setup_currencies = JSON.parse( decodeURIComponent( '<?php echo rawurlencode( wp_json_encode( $currency_by_country ) ); ?>' ) );
495
				var wc_base_state       = "<?php echo esc_js( $state ); ?>";
496
			</script>
497
			</div>
498
499
			<div class="product-type-container">
500
			<label class="location-prompt" for="product_type">
501
				<?php esc_html_e( 'What type of products do you plan to sell?', 'woocommerce' ); ?>
502
			</label>
503
			<select id="product_type" name="product_type" required class="location-input wc-enhanced-select dropdown">
504
				<option value="both" <?php selected( $product_type, 'both' ); ?>><?php esc_html_e( 'I plan to sell both physical and digital products', 'woocommerce' ); ?></option>
505
				<option value="physical" <?php selected( $product_type, 'physical' ); ?>><?php esc_html_e( 'I plan to sell physical products', 'woocommerce' ); ?></option>
506
				<option value="virtual" <?php selected( $product_type, 'virtual' ); ?>><?php esc_html_e( 'I plan to sell digital products', 'woocommerce' ); ?></option>
507
			</select>
508
			</div>
509
510
			<input
511
				type="checkbox"
512
				id="woocommerce_sell_in_person"
513
				name="sell_in_person"
514
				value="yes"
515
				<?php checked( $sell_in_person, true ); ?>
516
			/>
517
			<label class="location-prompt" for="woocommerce_sell_in_person">
518
				<?php esc_html_e( 'I will also be selling products or services in person.', 'woocommerce' ); ?>
519
			</label>
520
521
			<div class="woocommerce-tracker">
522
				<p class="checkbox">
523
					<input type="checkbox" id="wc_tracker_checkbox" name="wc_tracker_checkbox" value="yes" checked />
524
					<label for="wc_tracker_checkbox"><?php esc_html_e( 'Help WooCommerce improve with usage tracking.', 'woocommerce' ); ?></label>
525
				</p>
526
				<p>
527
				<?php
528
				esc_html_e( 'Gathering usage data allows us to make WooCommerce better &mdash; your store will be considered as we evaluate new features, judge the quality of an update, or determine if an improvement makes sense. If you would rather opt-out, and do not check this box, we will not know this store exists and we will not collect any usage data.', 'woocommerce' );
529
				echo ' <a target="_blank" href="https://woocommerce.com/usage-tracking/">' . esc_html__( 'Read more about what we collect.', 'woocommerce' ) . '</a>';
530
				?>
531
				</p>
532
			</div>
533
			<p class="wc-setup-actions step">
534
				<button type="submit" class="button-primary button button-large button-next" value="<?php esc_attr_e( "Let's go!", 'woocommerce' ); ?>" name="save_step"><?php esc_html_e( "Let's go!", 'woocommerce' ); ?></button>
535
			</p>
536
		</form>
537
		<?php
538
	}
539
540
	/**
541
	 * Save initial store settings.
542
	 */
543
	public function wc_setup_store_setup_save() {
544
		check_admin_referer( 'wc-setup' );
545
546
		$address        = isset( $_POST['store_address'] ) ? wc_clean( wp_unslash( $_POST['store_address'] ) ) : '';
0 ignored issues
show
introduced by
Detected usage of a non-sanitized input variable: $_POST
Loading history...
547
		$address_2      = isset( $_POST['store_address_2'] ) ? wc_clean( wp_unslash( $_POST['store_address_2'] ) ) : '';
0 ignored issues
show
introduced by
Detected usage of a non-sanitized input variable: $_POST
Loading history...
548
		$city           = isset( $_POST['store_city'] ) ? wc_clean( wp_unslash( $_POST['store_city'] ) ) : '';
0 ignored issues
show
introduced by
Detected usage of a non-sanitized input variable: $_POST
Loading history...
549
		$country        = isset( $_POST['store_country'] ) ? wc_clean( wp_unslash( $_POST['store_country'] ) ) : '';
0 ignored issues
show
introduced by
Detected usage of a non-sanitized input variable: $_POST
Loading history...
550
		$state          = isset( $_POST['store_state'] ) ? wc_clean( wp_unslash( $_POST['store_state'] ) ) : '*';
0 ignored issues
show
introduced by
Detected usage of a non-sanitized input variable: $_POST
Loading history...
551
		$postcode       = isset( $_POST['store_postcode'] ) ? wc_clean( wp_unslash( $_POST['store_postcode'] ) ) : '';
0 ignored issues
show
introduced by
Detected usage of a non-sanitized input variable: $_POST
Loading history...
552
		$currency_code  = isset( $_POST['currency_code'] ) ? wc_clean( wp_unslash( $_POST['currency_code'] ) ) : '';
0 ignored issues
show
introduced by
Detected usage of a non-sanitized input variable: $_POST
Loading history...
553
		$product_type   = isset( $_POST['product_type'] ) ? wc_clean( wp_unslash( $_POST['product_type'] ) ) : '';
0 ignored issues
show
introduced by
Detected usage of a non-sanitized input variable: $_POST
Loading history...
554
		$sell_in_person = isset( $_POST['sell_in_person'] ) && ( 'yes' === wc_clean( wp_unslash( $_POST['sell_in_person'] ) ) );
0 ignored issues
show
introduced by
Detected usage of a non-sanitized input variable: $_POST
Loading history...
555
		$tracking       = isset( $_POST['wc_tracker_checkbox'] ) && ( 'yes' === wc_clean( wp_unslash( $_POST['wc_tracker_checkbox'] ) ) );
0 ignored issues
show
introduced by
Detected usage of a non-sanitized input variable: $_POST
Loading history...
556
557
		update_option( 'woocommerce_store_address', $address );
558
		update_option( 'woocommerce_store_address_2', $address_2 );
559
		update_option( 'woocommerce_store_city', $city );
560
		update_option( 'woocommerce_default_country', $country . ':' . $state );
561
		update_option( 'woocommerce_store_postcode', $postcode );
562
		update_option( 'woocommerce_currency', $currency_code );
563
		update_option( 'woocommerce_product_type', $product_type );
564
		update_option( 'woocommerce_sell_in_person', $sell_in_person );
565
566
		$locale_info = include WC()->plugin_path() . '/i18n/locale-info.php';
567
568
		if ( isset( $locale_info[ $country ] ) ) {
569
			update_option( 'woocommerce_weight_unit', $locale_info[ $country ]['weight_unit'] );
570
			update_option( 'woocommerce_dimension_unit', $locale_info[ $country ]['dimension_unit'] );
571
572
			// Set currency formatting options based on chosen location and currency.
573
			if ( $locale_info[ $country ]['currency_code'] === $currency_code ) {
574
				update_option( 'woocommerce_currency_pos', $locale_info[ $country ]['currency_pos'] );
575
				update_option( 'woocommerce_price_decimal_sep', $locale_info[ $country ]['decimal_sep'] );
576
				update_option( 'woocommerce_price_num_decimals', $locale_info[ $country ]['num_decimals'] );
577
				update_option( 'woocommerce_price_thousand_sep', $locale_info[ $country ]['thousand_sep'] );
578
			}
579
		}
580
581
		if ( $tracking ) {
582
			update_option( 'woocommerce_allow_tracking', 'yes' );
583
			wp_schedule_single_event( time() + 10, 'woocommerce_tracker_send_event', array( true ) );
584
		} else {
585
			update_option( 'woocommerce_allow_tracking', 'no' );
586
		}
587
588
		WC_Install::create_pages();
589
		wp_safe_redirect( esc_url_raw( $this->get_next_step_link() ) );
590
		exit;
591
	}
592
593
	/**
594
	 * Finishes replying to the client, but keeps the process running for further (async) code execution.
595
	 *
596
	 * @see https://core.trac.wordpress.org/ticket/41358 .
597
	 */
598 View Code Duplication
	protected function close_http_connection() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
599
		// Only 1 PHP process can access a session object at a time, close this so the next request isn't kept waiting.
600
		// @codingStandardsIgnoreStart
601
		if ( session_id() ) {
602
			session_write_close();
603
		}
604
		// @codingStandardsIgnoreEnd
605
606
		wc_set_time_limit( 0 );
607
608
		// fastcgi_finish_request is the cleanest way to send the response and keep the script running, but not every server has it.
609
		if ( is_callable( 'fastcgi_finish_request' ) ) {
610
			fastcgi_finish_request();
611
		} else {
612
			// Fallback: send headers and flush buffers.
613
			if ( ! headers_sent() ) {
614
				header( 'Connection: close' );
615
			}
616
			@ob_end_flush(); // @codingStandardsIgnoreLine.
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
617
			flush();
618
		}
619
	}
620
621
	/**
622
	 * Function called after the HTTP request is finished, so it's executed without the client having to wait for it.
623
	 *
624
	 * @see WC_Admin_Setup_Wizard::install_plugin
625
	 * @see WC_Admin_Setup_Wizard::install_theme
626
	 */
627
	public function run_deferred_actions() {
628
		$this->close_http_connection();
629
		foreach ( $this->deferred_actions as $action ) {
630
			call_user_func_array( $action['func'], $action['args'] );
631
632
			// Clear the background installation flag if this is a plugin.
633
			if (
634
				isset( $action['func'][1] ) &&
635
				'background_installer' === $action['func'][1] &&
636
				isset( $action['args'][0] )
637
			) {
638
				delete_option( 'woocommerce_setup_background_installing_' . $action['args'][0] );
639
			}
640
		}
641
	}
642
643
	/**
644
	 * Helper method to queue the background install of a plugin.
645
	 *
646
	 * @param string $plugin_id  Plugin id used for background install.
647
	 * @param array  $plugin_info Plugin info array containing name and repo-slug, and optionally file if different from [repo-slug].php.
648
	 */
649
	protected function install_plugin( $plugin_id, $plugin_info ) {
650
		// Make sure we don't trigger multiple simultaneous installs.
651
		if ( get_option( 'woocommerce_setup_background_installing_' . $plugin_id ) ) {
652
			return;
653
		}
654
655
		$plugin_file = isset( $plugin_info['file'] ) ? $plugin_info['file'] : $plugin_info['repo-slug'] . '.php';
656
		if ( is_plugin_active( $plugin_info['repo-slug'] . '/' . $plugin_file ) ) {
657
			return;
658
		}
659
660
		if ( empty( $this->deferred_actions ) ) {
661
			add_action( 'shutdown', array( $this, 'run_deferred_actions' ) );
662
		}
663
664
		array_push(
665
			$this->deferred_actions,
666
			array(
667
				'func' => array( 'WC_Install', 'background_installer' ),
668
				'args' => array( $plugin_id, $plugin_info ),
669
			)
670
		);
671
672
		// Set the background installation flag for this plugin.
673
		update_option( 'woocommerce_setup_background_installing_' . $plugin_id, true );
674
	}
675
676
677
	/**
678
	 * Helper method to queue the background install of a theme.
679
	 *
680
	 * @param string $theme_id  Theme id used for background install.
681
	 */
682
	protected function install_theme( $theme_id ) {
683
		if ( empty( $this->deferred_actions ) ) {
684
			add_action( 'shutdown', array( $this, 'run_deferred_actions' ) );
685
		}
686
		array_push(
687
			$this->deferred_actions,
688
			array(
689
				'func' => array( 'WC_Install', 'theme_background_installer' ),
690
				'args' => array( $theme_id ),
691
			)
692
		);
693
	}
694
695
	/**
696
	 * Helper method to install Jetpack.
697
	 */
698
	protected function install_jetpack() {
699
		$this->install_plugin(
700
			'jetpack',
701
			array(
702
				'name'      => __( 'Jetpack', 'woocommerce' ),
703
				'repo-slug' => 'jetpack',
704
			)
705
		);
706
	}
707
708
	/**
709
	 * Helper method to install WooCommerce Services and its Jetpack dependency.
710
	 */
711
	protected function install_woocommerce_services() {
712
		$this->install_jetpack();
713
		$this->install_plugin(
714
			'woocommerce-services',
715
			array(
716
				'name'      => __( 'WooCommerce Services', 'woocommerce' ),
717
				'repo-slug' => 'woocommerce-services',
718
			)
719
		);
720
	}
721
722
	/**
723
	 * Retrieve info for missing WooCommerce Services and/or Jetpack plugin.
724
	 *
725
	 * @return array
726
	 */
727 1
	protected function get_wcs_requisite_plugins() {
728 1
		$plugins = array();
729 1 View Code Duplication
		if ( ! is_plugin_active( 'woocommerce-services/woocommerce-services.php' ) && ! get_option( 'woocommerce_setup_background_installing_woocommerce-services' ) ) {
730 1
			$plugins[] = array(
731 1
				'name' => __( 'WooCommerce Services', 'woocommerce' ),
732 1
				'slug' => 'woocommerce-services',
733
			);
734
		}
735 1 View Code Duplication
		if ( ! is_plugin_active( 'jetpack/jetpack.php' ) && ! get_option( 'woocommerce_setup_background_installing_jetpack' ) ) {
736 1
			$plugins[] = array(
737 1
				'name' => __( 'Jetpack', 'woocommerce' ),
738 1
				'slug' => 'jetpack',
739
			);
740
		}
741 1
		return $plugins;
742
	}
743
744
	/**
745
	 * Plugin install info message markup with heading.
746
	 */
747
	public function plugin_install_info() {
748
		?>
749
		<span class="plugin-install-info">
750
			<span class="plugin-install-info-label"><?php esc_html_e( 'The following plugins will be installed and activated for you:', 'woocommerce' ); ?></span>
751
			<span class="plugin-install-info-list"></span>
752
		</span>
753
		<?php
754
	}
755
756
	/**
757
	 * Get shipping methods based on country code.
758
	 *
759
	 * @param string $country_code Country code.
760
	 * @param string $currency_code Currency code.
761
	 * @return array
762
	 */
763
	protected function get_wizard_shipping_methods( $country_code, $currency_code ) {
0 ignored issues
show
Unused Code introduced by
The parameter $country_code 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...
Unused Code introduced by
The parameter $currency_code 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...
764
		$shipping_methods = array(
765
			'flat_rate'     => array(
766
				'name'        => __( 'Flat Rate', 'woocommerce' ),
767
				'description' => __( 'Set a fixed price to cover shipping costs.', 'woocommerce' ),
768
				'settings'    => array(
769
					'cost' => array(
770
						'type'          => 'text',
771
						'default_value' => __( 'Cost', 'woocommerce' ),
772
						'description'   => __( 'What would you like to charge for flat rate shipping?', 'woocommerce' ),
773
						'required'      => true,
774
					),
775
				),
776
			),
777
			'free_shipping' => array(
778
				'name'        => __( 'Free Shipping', 'woocommerce' ),
779
				'description' => __( "Don't charge for shipping.", 'woocommerce' ),
780
			),
781
		);
782
783
		return $shipping_methods;
784
	}
785
786
	/**
787
	 * Render the available shipping methods for a given country code.
788
	 *
789
	 * @param string $country_code Country code.
790
	 * @param string $currency_code Currency code.
791
	 * @param string $input_prefix Input prefix.
792
	 */
793
	protected function shipping_method_selection_form( $country_code, $currency_code, $input_prefix ) {
794
		$selected         = 'flat_rate';
795
		$shipping_methods = $this->get_wizard_shipping_methods( $country_code, $currency_code );
796
		?>
797
		<div class="wc-wizard-shipping-method-select">
798
			<div class="wc-wizard-shipping-method-dropdown">
799
				<select
800
					id="<?php echo esc_attr( "{$input_prefix}[method]" ); ?>"
801
					name="<?php echo esc_attr( "{$input_prefix}[method]" ); ?>"
802
					class="method wc-enhanced-select"
803
					data-plugins="<?php echo wc_esc_json( wp_json_encode( $this->get_wcs_requisite_plugins() ) ); ?>"
804
				>
805 View Code Duplication
				<?php foreach ( $shipping_methods as $method_id => $method ) : ?>
806
					<option value="<?php echo esc_attr( $method_id ); ?>" <?php selected( $selected, $method_id ); ?>><?php echo esc_html( $method['name'] ); ?></option>
807
				<?php endforeach; ?>
808
				</select>
809
			</div>
810
			<div class="shipping-method-descriptions">
811 View Code Duplication
				<?php foreach ( $shipping_methods as $method_id => $method ) : ?>
812
					<p class="shipping-method-description <?php echo esc_attr( $method_id ); ?> <?php echo $method_id !== $selected ? 'hide' : ''; ?>">
813
						<?php echo esc_html( $method['description'] ); ?>
814
					</p>
815
				<?php endforeach; ?>
816
			</div>
817
		</div>
818
819
		<div class="shipping-method-settings">
820
		<?php foreach ( $shipping_methods as $method_id => $method ) : ?>
821
			<?php
822
			if ( empty( $method['settings'] ) ) {
823
				continue;
824
			}
825
			?>
826
			<div class="shipping-method-setting <?php echo esc_attr( $method_id ); ?> <?php echo $method_id !== $selected ? 'hide' : ''; ?>">
827
			<?php foreach ( $method['settings'] as $setting_id => $setting ) : ?>
828
				<?php $method_setting_id = "{$input_prefix}[{$method_id}][{$setting_id}]"; ?>
829
				<input
830
					type="<?php echo esc_attr( $setting['type'] ); ?>"
831
					placeholder="<?php echo esc_attr( $setting['default_value'] ); ?>"
832
					id="<?php echo esc_attr( $method_setting_id ); ?>"
833
					name="<?php echo esc_attr( $method_setting_id ); ?>"
834
					class="<?php echo esc_attr( $setting['required'] ? 'shipping-method-required-field' : '' ); ?>"
835
					<?php echo ( $method_id === $selected && $setting['required'] ) ? 'required' : ''; ?>
836
				/>
837
				<p class="description">
838
					<?php echo esc_html( $setting['description'] ); ?>
839
				</p>
840
			<?php endforeach; ?>
841
			</div>
842
		<?php endforeach; ?>
843
		</div>
844
		<?php
845
	}
846
847
	/**
848
	 * Render a product weight unit dropdown.
849
	 *
850
	 * @return string
851
	 */
852
	protected function get_product_weight_selection() {
853
		$weight_unit = get_option( 'woocommerce_weight_unit' );
854
		ob_start();
855
		?>
856
		<span class="wc-setup-shipping-unit">
857
			<select id="weight_unit" name="weight_unit" class="wc-enhanced-select">
858
				<option value="kg" <?php selected( $weight_unit, 'kg' ); ?>><?php esc_html_e( 'Kilograms', 'woocommerce' ); ?></option>
859
				<option value="g" <?php selected( $weight_unit, 'g' ); ?>><?php esc_html_e( 'Grams', 'woocommerce' ); ?></option>
860
				<option value="lbs" <?php selected( $weight_unit, 'lbs' ); ?>><?php esc_html_e( 'Pounds', 'woocommerce' ); ?></option>
861
				<option value="oz" <?php selected( $weight_unit, 'oz' ); ?>><?php esc_html_e( 'Ounces', 'woocommerce' ); ?></option>
862
			</select>
863
		</span>
864
		<?php
865
866
		return ob_get_clean();
867
	}
868
869
	/**
870
	 * Render a product dimension unit dropdown.
871
	 *
872
	 * @return string
873
	 */
874
	protected function get_product_dimension_selection() {
875
		$dimension_unit = get_option( 'woocommerce_dimension_unit' );
876
		ob_start();
877
		?>
878
		<span class="wc-setup-shipping-unit">
879
			<select id="dimension_unit" name="dimension_unit" class="wc-enhanced-select">
880
				<option value="m" <?php selected( $dimension_unit, 'm' ); ?>><?php esc_html_e( 'Meters', 'woocommerce' ); ?></option>
881
				<option value="cm" <?php selected( $dimension_unit, 'cm' ); ?>><?php esc_html_e( 'Centimeters', 'woocommerce' ); ?></option>
882
				<option value="mm" <?php selected( $dimension_unit, 'mm' ); ?>><?php esc_html_e( 'Millimeters', 'woocommerce' ); ?></option>
883
				<option value="in" <?php selected( $dimension_unit, 'in' ); ?>><?php esc_html_e( 'Inches', 'woocommerce' ); ?></option>
884
				<option value="yd" <?php selected( $dimension_unit, 'yd' ); ?>><?php esc_html_e( 'Yards', 'woocommerce' ); ?></option>
885
			</select>
886
		</span>
887
		<?php
888
889
		return ob_get_clean();
890
	}
891
892
	/**
893
	 * Shipping.
894
	 */
895
	public function wc_setup_shipping() {
896
		$country_code          = WC()->countries->get_base_country();
897
		$country_name          = WC()->countries->countries[ $country_code ];
898
		$prefixed_country_name = WC()->countries->estimated_for_prefix( $country_code ) . $country_name;
899
		$currency_code         = get_woocommerce_currency();
900
		$existing_zones        = WC_Shipping_Zones::get_zones();
901
		$intro_text            = '';
902
903
		if ( empty( $existing_zones ) ) {
904
			$intro_text = sprintf(
905
				/* translators: %s: country name including the 'the' prefix if needed */
906
				__( "We've created two Shipping Zones - for %s and for the rest of the world. Below you can set Flat Rate shipping costs for these Zones or offer Free Shipping.", 'woocommerce' ),
907
				$prefixed_country_name
908
			);
909
		}
910
911
		$is_wcs_labels_supported  = $this->is_wcs_shipping_labels_supported_country( $country_code );
912
		$is_shipstation_supported = $this->is_shipstation_supported_country( $country_code );
913
914
		?>
915
		<h1><?php esc_html_e( 'Shipping', 'woocommerce' ); ?></h1>
916
		<?php if ( $intro_text ) : ?>
917
			<p><?php echo wp_kses_post( $intro_text ); ?></p>
918
		<?php endif; ?>
919
		<form method="post">
920
			<?php if ( empty( $existing_zones ) ) : ?>
921
				<ul class="wc-wizard-services shipping">
922
					<li class="wc-wizard-service-item">
923
						<div class="wc-wizard-service-name">
924
							<p><?php echo esc_html_e( 'Shipping Zone', 'woocommerce' ); ?></p>
925
						</div>
926
						<div class="wc-wizard-service-description">
927
							<p><?php echo esc_html_e( 'Shipping Method', 'woocommerce' ); ?></p>
928
						</div>
929
					</li>
930
					<li class="wc-wizard-service-item">
931
						<div class="wc-wizard-service-name">
932
							<p><?php echo esc_html( $country_name ); ?></p>
933
						</div>
934
						<div class="wc-wizard-service-description">
935
							<?php $this->shipping_method_selection_form( $country_code, $currency_code, 'shipping_zones[domestic]' ); ?>
936
						</div>
937
						<div class="wc-wizard-service-enable">
938
							<span class="wc-wizard-service-toggle">
939
								<input id="shipping_zones[domestic][enabled]" type="checkbox" name="shipping_zones[domestic][enabled]" value="yes" checked="checked" class="wc-wizard-shipping-method-enable" data-plugins="true" />
940
								<label for="shipping_zones[domestic][enabled]">
941
							</span>
942
						</div>
943
					</li>
944
					<li class="wc-wizard-service-item">
945
						<div class="wc-wizard-service-name">
946
							<p><?php echo esc_html_e( 'Locations not covered by your other zones', 'woocommerce' ); ?></p>
947
						</div>
948
						<div class="wc-wizard-service-description">
949
							<?php $this->shipping_method_selection_form( $country_code, $currency_code, 'shipping_zones[intl]' ); ?>
950
						</div>
951
						<div class="wc-wizard-service-enable">
952
							<span class="wc-wizard-service-toggle">
953
								<input id="shipping_zones[intl][enabled]" type="checkbox" name="shipping_zones[intl][enabled]" value="yes" checked="checked" class="wc-wizard-shipping-method-enable" data-plugins="true" />
954
								<label for="shipping_zones[intl][enabled]">
955
							</span>
956
						</div>
957
					</li>
958
					<li class="wc-wizard-service-info">
959
						<p>
960
						<?php
961
						printf(
962
							wp_kses(
963
								/* translators: %1$s: live rates tooltip text, %2$s: shipping extensions URL */
964
								__( 'If you\'d like to offer <span class="help_tip" data-tip="%1$s">live rates</span> from a specific carrier (e.g. UPS) you can find a variety of extensions available for WooCommerce <a href="%2$s" target="_blank">here</a>.', 'woocommerce' ),
965
								array(
966
									'span' => array(
967
										'class'    => array(),
968
										'data-tip' => array(),
969
									),
970
									'a'    => array(
971
										'href'   => array(),
972
										'target' => array(),
973
									),
974
								)
975
							),
976
							esc_attr__( 'A live rate is the exact cost to ship an order, quoted directly from the shipping carrier.', 'woocommerce' ),
977
							'https://woocommerce.com/product-category/woocommerce-extensions/shipping-methods/shipping-carriers/'
978
						);
979
						?>
980
						</p>
981
					</li>
982
				</ul>
983
			<?php endif; ?>
984
985
		<?php if ( $is_wcs_labels_supported || $is_shipstation_supported ) : ?>
986
			<ul class="wc-setup-shipping-recommended">
987
			<?php
988
			if ( $is_wcs_labels_supported ) :
989
				$this->display_recommended_item(
990
					array(
991
						'type'        => 'woocommerce_services',
992
						'title'       => __( 'Print shipping labels at home', 'woocommerce' ),
993
						'description' => __( 'We recommend WooCommerce Services & Jetpack. These plugins will save you time at the Post Office by enabling you to print your shipping labels at home.', 'woocommerce' ),
994
						'img_url'     => WC()->plugin_url() . '/assets/images/obw-woocommerce-services-icon.png',
995
						'img_alt'     => __( 'WooCommerce Services icon', 'woocommerce' ),
996
						'plugins'     => $this->get_wcs_requisite_plugins(),
997
					)
998
				);
999 View Code Duplication
			elseif ( $is_shipstation_supported ) :
1000
				$this->display_recommended_item(
1001
					array(
1002
						'type'        => 'shipstation',
1003
						'title'       => __( 'Print shipping labels at home', 'woocommerce' ),
1004
						'description' => __( 'We recommend using ShipStation to save time at the Post Office by printing your shipping labels at home. Try ShipStation free for 30 days.', 'woocommerce' ),
1005
						'img_url'     => WC()->plugin_url() . '/assets/images/obw-shipstation-icon.png',
1006
						'img_alt'     => __( 'ShipStation icon', 'woocommerce' ),
1007
						'plugins'     => array(
1008
							array(
1009
								'name' => __( 'ShipStation', 'woocommerce' ),
1010
								'slug' => 'woocommerce-shipstation-integration',
1011
							),
1012
						),
1013
					)
1014
				);
1015
			endif;
1016
		endif;
1017
		?>
1018
			</ul>
1019
1020
			<div class="wc-setup-shipping-units">
1021
				<p>
1022
					<?php
1023
						echo wp_kses(
1024
							sprintf(
1025
								/* translators: %1$s: weight unit dropdown, %2$s: dimension unit dropdown */
1026
								esc_html__( 'We\'ll use %1$s for product weight and %2$s for product dimensions.', 'woocommerce' ),
1027
								$this->get_product_weight_selection(),
1028
								$this->get_product_dimension_selection()
1029
							),
1030
							array(
1031
								'span'   => array(
1032
									'class' => array(),
1033
								),
1034
								'select' => array(
1035
									'id'    => array(),
1036
									'name'  => array(),
1037
									'class' => array(),
1038
								),
1039
								'option' => array(
1040
									'value'    => array(),
1041
									'selected' => array(),
1042
								),
1043
							)
1044
						);
1045
					?>
1046
				</p>
1047
			</div>
1048
1049
			<p class="wc-setup-actions step">
1050
				<?php $this->plugin_install_info(); ?>
1051
				<button type="submit" class="button-primary button button-large button-next" value="<?php esc_attr_e( 'Continue', 'woocommerce' ); ?>" name="save_step"><?php esc_html_e( 'Continue', 'woocommerce' ); ?></button>
1052
				<?php wp_nonce_field( 'wc-setup' ); ?>
1053
			</p>
1054
		</form>
1055
		<?php
1056
	}
1057
1058
	/**
1059
	 * Save shipping options.
1060
	 */
1061
	public function wc_setup_shipping_save() {
1062
		check_admin_referer( 'wc-setup' );
1063
1064
		if ( ! did_action( 'rest_api_init' ) ) {
1065
			WC()->api->rest_api_includes();
1066
		}
1067
1068
		// @codingStandardsIgnoreStart
1069
		$setup_domestic   = isset( $_POST['shipping_zones']['domestic']['enabled'] ) && ( 'yes' === $_POST['shipping_zones']['domestic']['enabled'] );
1070
		$domestic_method  = isset( $_POST['shipping_zones']['domestic']['method'] ) ? sanitize_text_field( wp_unslash( $_POST['shipping_zones']['domestic']['method'] ) ) : '';
1071
		$setup_intl       = isset( $_POST['shipping_zones']['intl']['enabled'] ) && ( 'yes' === $_POST['shipping_zones']['intl']['enabled'] );
1072
		$intl_method      = isset( $_POST['shipping_zones']['intl']['method'] ) ? sanitize_text_field( wp_unslash( $_POST['shipping_zones']['intl']['method'] ) ) : '';
1073
		$weight_unit      = sanitize_text_field( wp_unslash( $_POST['weight_unit'] ) );
1074
		$dimension_unit   = sanitize_text_field( wp_unslash( $_POST['dimension_unit'] ) );
1075
		$existing_zones   = WC_Shipping_Zones::get_zones();
1076
		// @codingStandardsIgnoreEnd
1077
1078
		update_option( 'woocommerce_ship_to_countries', '' );
1079
		update_option( 'woocommerce_weight_unit', $weight_unit );
1080
		update_option( 'woocommerce_dimension_unit', $dimension_unit );
1081
1082
		$setup_wcs_labels  = isset( $_POST['setup_woocommerce_services'] ) && 'yes' === $_POST['setup_woocommerce_services'];
0 ignored issues
show
introduced by
Detected usage of a non-sanitized input variable: $_POST
Loading history...
1083
		$setup_shipstation = isset( $_POST['setup_shipstation'] ) && 'yes' === $_POST['setup_shipstation'];
0 ignored issues
show
introduced by
Detected usage of a non-sanitized input variable: $_POST
Loading history...
1084
1085
		update_option( 'woocommerce_setup_shipping_labels', $setup_wcs_labels );
1086
1087
		if ( $setup_wcs_labels ) {
1088
			$this->install_woocommerce_services();
1089
		}
1090
1091
		if ( $setup_shipstation ) {
1092
			$this->install_plugin(
1093
				'woocommerce-shipstation-integration',
1094
				array(
1095
					'name'      => __( 'ShipStation', 'woocommerce' ),
1096
					'repo-slug' => 'woocommerce-shipstation-integration',
1097
					'file'      => 'woocommerce-shipstation.php',
1098
				)
1099
			);
1100
		}
1101
1102
		// For now, limit this setup to the first run.
1103
		if ( ! empty( $existing_zones ) ) {
1104
			wp_safe_redirect( esc_url_raw( $this->get_next_step_link() ) );
1105
			exit;
1106
		}
1107
1108
		/*
1109
		 * If enabled, create a shipping zone containing the country the
1110
		 * store is located in, with the selected method preconfigured.
1111
		 */
1112
		if ( $setup_domestic ) {
1113
			$country = WC()->countries->get_base_country();
1114
1115
			$zone = new WC_Shipping_Zone( null );
1116
			$zone->set_zone_order( 0 );
1117
			$zone->add_location( $country, 'country' );
1118
			$instance_id = $zone->add_shipping_method( $domestic_method );
1119
			$zone->save();
1120
1121
			// Save chosen shipping method settings (using REST controller for convenience).
1122 View Code Duplication
			if ( isset( $instance_id ) && ! empty( $_POST['shipping_zones']['domestic'][ $domestic_method ] ) ) { // WPCS: input var ok.
1123
				$method_controller = new WC_REST_Shipping_Zone_Methods_Controller();
1124
				// @codingStandardsIgnoreStart
1125
				$method_controller->update_item( array(
1126
					'zone_id'     => $zone->get_id(),
1127
					'instance_id' => $instance_id,
1128
					'settings'    => wp_unslash( $_POST['shipping_zones']['domestic'][ $domestic_method ] ),
1129
				) );
1130
				// @codingStandardsIgnoreEnd
1131
			}
1132
		}
1133
1134
		// If enabled, set the selected method for the "rest of world" zone.
1135
		if ( $setup_intl ) {
1136
			$zone        = new WC_Shipping_Zone( 0 );
1137
			$instance_id = $zone->add_shipping_method( $intl_method );
1138
1139
			$zone->save();
1140
1141
			// Save chosen shipping method settings (using REST controller for convenience).
1142 View Code Duplication
			if ( isset( $instance_id ) && ! empty( $_POST['shipping_zones']['intl'][ $intl_method ] ) ) { // WPCS: input var ok.
1143
				$method_controller = new WC_REST_Shipping_Zone_Methods_Controller();
1144
				// @codingStandardsIgnoreStart
1145
				$method_controller->update_item( array(
1146
					'zone_id'     => $zone->get_id(),
1147
					'instance_id' => $instance_id,
1148
					'settings'    => wp_unslash( $_POST['shipping_zones']['intl'][ $intl_method ] ),
1149
				) );
1150
				// @codingStandardsIgnoreEnd
1151
			}
1152
		}
1153
1154
		// Notify the user that no shipping methods are configured.
1155
		if ( ! $setup_domestic && ! $setup_intl ) {
1156
			WC_Admin_Notices::add_notice( 'no_shipping_methods' );
1157
		}
1158
1159
		wp_safe_redirect( esc_url_raw( $this->get_next_step_link() ) );
1160
		exit;
1161
	}
1162
1163
	/**
1164
	 * Is Stripe country supported
1165
	 * https://stripe.com/global .
1166
	 *
1167
	 * @param string $country_code Country code.
1168
	 */
1169 1
	protected function is_stripe_supported_country( $country_code ) {
1170
		$stripe_supported_countries = array(
1171 1
			'AU',
1172
			'AT',
1173
			'BE',
1174
			'CA',
1175
			'DK',
1176
			'FI',
1177
			'FR',
1178
			'DE',
1179
			'HK',
1180
			'IE',
1181
			'JP',
1182
			'LU',
1183
			'NL',
1184
			'NZ',
1185
			'NO',
1186
			'SG',
1187
			'ES',
1188
			'SE',
1189
			'CH',
1190
			'GB',
1191
			'US',
1192
		);
1193
1194 1
		return in_array( $country_code, $stripe_supported_countries, true );
1195
	}
1196
1197
	/**
1198
	 * Is PayPal currency supported.
1199
	 *
1200
	 * @param string $currency Currency code.
1201
	 * @return boolean
1202
	 */
1203 1
	protected function is_paypal_supported_currency( $currency ) {
1204
		$supported_currencies = array(
1205 1
			'AUD',
1206
			'BRL',
1207
			'CAD',
1208
			'MXN',
1209
			'NZD',
1210
			'HKD',
1211
			'SGD',
1212
			'USD',
1213
			'EUR',
1214
			'JPY',
1215
			'TRY',
1216
			'NOK',
1217
			'CZK',
1218
			'DKK',
1219
			'HUF',
1220
			'ILS',
1221
			'MYR',
1222
			'PHP',
1223
			'PLN',
1224
			'SEK',
1225
			'CHF',
1226
			'TWD',
1227
			'THB',
1228
			'GBP',
1229
			'RMB',
1230
			'RUB',
1231
			'INR',
1232
		);
1233 1
		return in_array( $currency, $supported_currencies, true );
1234
	}
1235
1236
	/**
1237
	 * Is Klarna Checkout country supported.
1238
	 *
1239
	 * @param string $country_code Country code.
1240
	 */
1241 1
	protected function is_klarna_checkout_supported_country( $country_code ) {
1242
		$supported_countries = array(
1243 1
			'SE', // Sweden.
1244
			'FI', // Finland.
1245
			'NO', // Norway.
1246
			'NL', // Netherlands.
1247
		);
1248 1
		return in_array( $country_code, $supported_countries, true );
1249
	}
1250
1251
	/**
1252
	 * Is Klarna Payments country supported.
1253
	 *
1254
	 * @param string $country_code Country code.
1255
	 */
1256 1
	protected function is_klarna_payments_supported_country( $country_code ) {
1257
		$supported_countries = array(
1258 1
			'DK', // Denmark.
1259
			'DE', // Germany.
1260
			'AT', // Austria.
1261
		);
1262 1
		return in_array( $country_code, $supported_countries, true );
1263
	}
1264
1265
	/**
1266
	 * Is Square country supported
1267
	 *
1268
	 * @param string $country_code Country code.
1269
	 */
1270 1
	protected function is_square_supported_country( $country_code ) {
1271
		$square_supported_countries = array(
1272 1
			'US',
1273
			'CA',
1274
			'JP',
1275
			'GB',
1276
			'AU',
1277
		);
1278 1
		return in_array( $country_code, $square_supported_countries, true );
1279
	}
1280
1281
	/**
1282
	 * Is eWAY Payments country supported
1283
	 *
1284
	 * @param string $country_code Country code.
1285
	 */
1286 1
	protected function is_eway_payments_supported_country( $country_code ) {
1287
		$supported_countries = array(
1288 1
			'AU', // Australia.
1289
			'NZ', // New Zealand.
1290
		);
1291 1
		return in_array( $country_code, $supported_countries, true );
1292
	}
1293
1294
	/**
1295
	 * Is ShipStation country supported
1296
	 *
1297
	 * @param string $country_code Country code.
1298
	 */
1299
	protected function is_shipstation_supported_country( $country_code ) {
1300
		$supported_countries = array(
1301
			'AU', // Australia.
1302
			'CA', // Canada.
1303
			'GB', // United Kingdom.
1304
		);
1305
		return in_array( $country_code, $supported_countries, true );
1306
	}
1307
1308
	/**
1309
	 * Is WooCommerce Services shipping label country supported
1310
	 *
1311
	 * @param string $country_code Country code.
1312
	 */
1313
	protected function is_wcs_shipping_labels_supported_country( $country_code ) {
1314
		$supported_countries = array(
1315
			'US', // United States.
1316
		);
1317
		return in_array( $country_code, $supported_countries, true );
1318
	}
1319
1320
	/**
1321
	 * Helper method to retrieve the current user's email address.
1322
	 *
1323
	 * @return string Email address
1324
	 */
1325 1
	protected function get_current_user_email() {
1326 1
		$current_user = wp_get_current_user();
1327 1
		$user_email   = $current_user->user_email;
1328
1329 1
		return $user_email;
1330
	}
1331
1332
	/**
1333
	 * Array of all possible "in cart" gateways that can be offered.
1334
	 *
1335
	 * @return array
1336
	 */
1337 1
	protected function get_wizard_available_in_cart_payment_gateways() {
1338 1
		$user_email = $this->get_current_user_email();
1339
1340 1
		$stripe_description = '<p>' . sprintf(
1341
			/* translators: %s: URL */
1342 1
			__( 'Accept debit and credit cards in 135+ currencies, methods such as Alipay, and one-touch checkout with Apple Pay. <a href="%s" target="_blank">Learn more</a>.', 'woocommerce' ),
1343 1
			'https://woocommerce.com/products/stripe/'
1344 1
		) . '</p>';
1345 1
		$paypal_checkout_description = '<p>' . sprintf(
1346
			/* translators: %s: URL */
1347 1
			__( 'Safe and secure payments using credit cards or your customer\'s PayPal account. <a href="%s" target="_blank">Learn more</a>.', 'woocommerce' ),
1348 1
			'https://woocommerce.com/products/woocommerce-gateway-paypal-checkout/'
1349 1
		) . '</p>';
1350 1
		$klarna_checkout_description = '<p>' . sprintf(
1351
			/* translators: %s: URL */
1352 1
			__( 'Full checkout experience with pay now, pay later and slice it. No credit card numbers, no passwords, no worries. <a href="%s" target="_blank">Learn more about Klarna</a>.', 'woocommerce' ),
1353 1
			'https://woocommerce.com/products/klarna-checkout/'
1354 1
		) . '</p>';
1355 1
		$klarna_payments_description = '<p>' . sprintf(
1356
			/* translators: %s: URL */
1357 1
			__( 'Choose the payment that you want, pay now, pay later or slice it. No credit card numbers, no passwords, no worries. <a href="%s" target="_blank">Learn more about Klarna</a>.', 'woocommerce' ),
1358 1
			'https://woocommerce.com/products/klarna-payments/ '
1359 1
		) . '</p>';
1360 1
		$square_description = '<p>' . sprintf(
1361
			/* translators: %s: URL */
1362 1
			__( 'Securely accept credit and debit cards with one low rate, no surprise fees (custom rates available). Sell online and in store and track sales and inventory in one place. <a href="%s" target="_blank">Learn more about Square</a>.', 'woocommerce' ),
1363 1
			'https://woocommerce.com/products/square/'
1364 1
		) . '</p>';
1365
1366
		return array(
1367
			'stripe'          => array(
1368 1
				'name'        => __( 'WooCommerce Stripe Gateway', 'woocommerce' ),
1369 1
				'image'       => WC()->plugin_url() . '/assets/images/stripe.png',
1370 1
				'description' => $stripe_description,
1371 1
				'class'       => 'checked stripe-logo',
1372 1
				'repo-slug'   => 'woocommerce-gateway-stripe',
1373
				'settings'    => array(
1374
					'create_account' => array(
1375 1
						'label'       => __( 'Set up Stripe for me using this email:', 'woocommerce' ),
1376 1
						'type'        => 'checkbox',
1377 1
						'value'       => 'yes',
1378 1
						'default'     => 'yes',
1379 1
						'placeholder' => '',
1380
						'required'    => false,
1381 1
						'plugins'     => $this->get_wcs_requisite_plugins(),
1382
					),
1383
					'email'          => array(
1384 1
						'label'       => __( 'Stripe email address:', 'woocommerce' ),
1385 1
						'type'        => 'email',
1386 1
						'value'       => $user_email,
1387 1
						'placeholder' => __( 'Stripe email address', 'woocommerce' ),
1388
						'required'    => true,
1389
					),
1390
				),
1391
			),
1392
			'ppec_paypal'     => array(
1393 1
				'name'        => __( 'WooCommerce PayPal Checkout Gateway', 'woocommerce' ),
1394 1
				'image'       => WC()->plugin_url() . '/assets/images/paypal.png',
1395 1
				'description' => $paypal_checkout_description,
1396
				'enabled'     => false,
1397 1
				'class'       => 'checked paypal-logo',
1398 1
				'repo-slug'   => 'woocommerce-gateway-paypal-express-checkout',
1399
				'settings'    => array(
1400
					'reroute_requests' => array(
1401 1
						'label'       => __( 'Set up PayPal for me using this email:', 'woocommerce' ),
1402 1
						'type'        => 'checkbox',
1403 1
						'value'       => 'yes',
1404 1
						'default'     => 'yes',
1405 1
						'placeholder' => '',
1406
						'required'    => false,
1407 1
						'plugins'     => $this->get_wcs_requisite_plugins(),
1408
					),
1409
					'email'            => array(
1410 1
						'label'       => __( 'Direct payments to email address:', 'woocommerce' ),
1411 1
						'type'        => 'email',
1412 1
						'value'       => $user_email,
1413 1
						'placeholder' => __( 'Email address to receive payments', 'woocommerce' ),
1414
						'required'    => true,
1415
					),
1416
				),
1417
			),
1418
			'paypal'          => array(
1419 1
				'name'        => __( 'PayPal Standard', 'woocommerce' ),
1420 1
				'description' => __( 'Accept payments via PayPal using account balance or credit card.', 'woocommerce' ),
1421 1
				'image'       => '',
1422
				'settings'    => array(
1423
					'email' => array(
1424 1
						'label'       => __( 'PayPal email address:', 'woocommerce' ),
1425 1
						'type'        => 'email',
1426 1
						'value'       => $user_email,
1427 1
						'placeholder' => __( 'PayPal email address', 'woocommerce' ),
1428
						'required'    => true,
1429
					),
1430
				),
1431
			),
1432
			'klarna_checkout' => array(
1433 1
				'name'        => __( 'Klarna Checkout for WooCommerce', 'woocommerce' ),
1434 1
				'description' => $klarna_checkout_description,
1435 1
				'image'       => WC()->plugin_url() . '/assets/images/klarna-black.png',
1436
				'enabled'     => true,
1437 1
				'class'       => 'klarna-logo',
1438 1
				'repo-slug'   => 'klarna-checkout-for-woocommerce',
1439
			),
1440
			'klarna_payments' => array(
1441 1
				'name'        => __( 'Klarna Payments for WooCommerce', 'woocommerce' ),
1442 1
				'description' => $klarna_payments_description,
1443 1
				'image'       => WC()->plugin_url() . '/assets/images/klarna-black.png',
1444
				'enabled'     => true,
1445 1
				'class'       => 'klarna-logo',
1446 1
				'repo-slug'   => 'klarna-payments-for-woocommerce',
1447
			),
1448
			'square'          => array(
1449 1
				'name'        => __( 'WooCommerce Square', 'woocommerce' ),
1450 1
				'description' => $square_description,
1451 1
				'image'       => WC()->plugin_url() . '/assets/images/square-black.png',
1452 1
				'class'       => 'square-logo',
1453
				'enabled'     => false,
1454 1
				'repo-slug'   => 'woocommerce-square',
1455
			),
1456
			'eway'            => array(
1457 1
				'name'        => __( 'WooCommerce eWAY Gateway', 'woocommerce' ),
1458 1
				'description' => __( 'The eWAY extension for WooCommerce allows you to take credit card payments directly on your store without redirecting your customers to a third party site to make payment.', 'woocommerce' ),
1459 1
				'image'       => WC()->plugin_url() . '/assets/images/eway-logo.jpg',
1460
				'enabled'     => false,
1461 1
				'class'       => 'eway-logo',
1462 1
				'repo-slug'   => 'woocommerce-gateway-eway',
1463
			),
1464
			'payfast'         => array(
1465 1
				'name'        => __( 'WooCommerce PayFast Gateway', 'woocommerce' ),
1466 1
				'description' => __( 'The PayFast extension for WooCommerce enables you to accept payments by Credit Card and EFT via one of South Africa’s most popular payment gateways. No setup fees or monthly subscription costs.', 'woocommerce' ),
1467 1
				'image'       => WC()->plugin_url() . '/assets/images/payfast.png',
1468 1
				'class'       => 'payfast-logo',
1469
				'enabled'     => false,
1470 1
				'repo-slug'   => 'woocommerce-payfast-gateway',
1471 1
				'file'        => 'gateway-payfast.php',
1472
			),
1473
		);
1474
	}
1475
1476
	/**
1477
	 * Simple array of "in cart" gateways to show in wizard.
1478
	 *
1479
	 * @return array
1480
	 */
1481 1
	public function get_wizard_in_cart_payment_gateways() {
1482 1
		$gateways = $this->get_wizard_available_in_cart_payment_gateways();
1483 1
		$country  = WC()->countries->get_base_country();
1484 1
		$currency = get_woocommerce_currency();
1485
1486 1
		$can_stripe  = $this->is_stripe_supported_country( $country );
1487 1
		$can_eway    = $this->is_eway_payments_supported_country( $country );
1488 1
		$can_payfast = ( 'ZA' === $country ); // South Africa.
1489 1
		$can_paypal  = $this->is_paypal_supported_currency( $currency );
1490
1491 1
		if ( ! current_user_can( 'install_plugins' ) ) {
1492 1
			return $can_paypal ? array( 'paypal' => $gateways['paypal'] ) : array();
1493
		}
1494
1495 1
		$klarna_or_square = false;
1496
1497 1
		if ( $this->is_klarna_checkout_supported_country( $country ) ) {
1498 1
			$klarna_or_square = 'klarna_checkout';
1499 1
		} elseif ( $this->is_klarna_payments_supported_country( $country ) ) {
1500 1
			$klarna_or_square = 'klarna_payments';
1501 1
		} elseif ( $this->is_square_supported_country( $country ) && get_option( 'woocommerce_sell_in_person' ) ) {
1502 1
			$klarna_or_square = 'square';
1503
		}
1504
1505 1
		$offered_gateways = array();
1506
1507 1
		if ( $can_stripe ) {
1508 1
			$gateways['stripe']['enabled']  = true;
1509 1
			$gateways['stripe']['featured'] = true;
1510 1
			$offered_gateways              += array( 'stripe' => $gateways['stripe'] );
1511 1
		} elseif ( $can_paypal ) {
1512 1
			$gateways['ppec_paypal']['enabled'] = true;
1513
		}
1514
1515 1
		if ( $klarna_or_square ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $klarna_or_square of type string|false is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
1516 1
			if ( in_array( $klarna_or_square, array( 'klarna_checkout', 'klarna_payments' ), true ) ) {
1517 1
				$gateways[ $klarna_or_square ]['enabled']  = true;
1518 1
				$gateways[ $klarna_or_square ]['featured'] = false;
1519
				$offered_gateways                          += array(
1520 1
					$klarna_or_square => $gateways[ $klarna_or_square ],
1521
				);
1522
			} else {
1523
				$offered_gateways += array(
1524 1
					$klarna_or_square => $gateways[ $klarna_or_square ],
1525
				);
1526
			}
1527
		}
1528
1529 1
		if ( $can_paypal ) {
1530 1
			$offered_gateways += array( 'ppec_paypal' => $gateways['ppec_paypal'] );
1531
		}
1532
1533 1
		if ( $can_eway ) {
1534
			$offered_gateways += array( 'eway' => $gateways['eway'] );
1535
		}
1536
1537 1
		if ( $can_payfast ) {
1538
			$offered_gateways += array( 'payfast' => $gateways['payfast'] );
1539
		}
1540
1541 1
		return $offered_gateways;
1542
	}
1543
1544
	/**
1545
	 * Simple array of "manual" gateways to show in wizard.
1546
	 *
1547
	 * @return array
1548
	 */
1549
	public function get_wizard_manual_payment_gateways() {
1550
		$gateways = array(
1551
			'cheque' => array(
1552
				'name'        => _x( 'Check payments', 'Check payment method', 'woocommerce' ),
1553
				'description' => __( 'A simple offline gateway that lets you accept a check as method of payment.', 'woocommerce' ),
1554
				'image'       => '',
1555
				'class'       => '',
1556
			),
1557
			'bacs'   => array(
1558
				'name'        => __( 'Bank transfer (BACS) payments', 'woocommerce' ),
1559
				'description' => __( 'A simple offline gateway that lets you accept BACS payment.', 'woocommerce' ),
1560
				'image'       => '',
1561
				'class'       => '',
1562
			),
1563
			'cod'    => array(
1564
				'name'        => __( 'Cash on delivery', 'woocommerce' ),
1565
				'description' => __( 'A simple offline gateway that lets you accept cash on delivery.', 'woocommerce' ),
1566
				'image'       => '',
1567
				'class'       => '',
1568
			),
1569
		);
1570
1571
		return $gateways;
1572
	}
1573
1574
	/**
1575
	 * Display service item in list.
1576
	 *
1577
	 * @param int   $item_id Item ID.
1578
	 * @param array $item_info Item info array.
1579
	 */
1580
	public function display_service_item( $item_id, $item_info ) {
1581
		$item_class = 'wc-wizard-service-item';
1582
		if ( isset( $item_info['class'] ) ) {
1583
			$item_class .= ' ' . $item_info['class'];
1584
		}
1585
1586
		$previously_saved_settings = get_option( 'woocommerce_' . $item_id . '_settings' );
1587
1588
		// Show the user-saved state if it was previously saved.
1589
		// Otherwise, rely on the item info.
1590
		if ( is_array( $previously_saved_settings ) ) {
1591
			$should_enable_toggle = ( isset( $previously_saved_settings['enabled'] ) && 'yes' === $previously_saved_settings['enabled'] ) ? true : ( isset( $item_info['enabled'] ) && $item_info['enabled'] );
1592
		} else {
1593
			$should_enable_toggle = isset( $item_info['enabled'] ) && $item_info['enabled'];
1594
		}
1595
1596
		$plugins = null;
1597
		if ( isset( $item_info['repo-slug'] ) ) {
1598
			$plugin  = array(
1599
				'slug' => $item_info['repo-slug'],
1600
				'name' => $item_info['name'],
1601
			);
1602
			$plugins = array( $plugin );
1603
		}
1604
1605
		?>
1606
		<li class="<?php echo esc_attr( $item_class ); ?>">
1607
			<div class="wc-wizard-service-name">
1608 View Code Duplication
				<?php if ( ! empty( $item_info['image'] ) ) : ?>
1609
					<img src="<?php echo esc_attr( $item_info['image'] ); ?>" alt="<?php echo esc_attr( $item_info['name'] ); ?>" />
1610
				<?php else : ?>
1611
					<p><?php echo esc_html( $item_info['name'] ); ?></p>
1612
				<?php endif; ?>
1613
			</div>
1614
			<div class="wc-wizard-service-enable">
1615
				<span class="wc-wizard-service-toggle <?php echo esc_attr( $should_enable_toggle ? '' : 'disabled' ); ?>" tabindex="0">
1616
					<input
1617
						id="wc-wizard-service-<?php echo esc_attr( $item_id ); ?>"
1618
						type="checkbox"
1619
						name="wc-wizard-service-<?php echo esc_attr( $item_id ); ?>-enabled"
1620
						value="yes" <?php checked( $should_enable_toggle ); ?>
1621
						data-plugins="<?php echo wc_esc_json( wp_json_encode( $plugins ) ); ?>"
1622
					/>
1623
					<label for="wc-wizard-service-<?php echo esc_attr( $item_id ); ?>">
1624
				</span>
1625
			</div>
1626
			<div class="wc-wizard-service-description">
1627
				<?php echo wp_kses_post( wpautop( $item_info['description'] ) ); ?>
1628
				<?php if ( ! empty( $item_info['settings'] ) ) : ?>
1629
					<div class="wc-wizard-service-settings <?php echo $should_enable_toggle ? '' : 'hide'; ?>">
1630
						<?php foreach ( $item_info['settings'] as $setting_id => $setting ) : ?>
1631
							<?php
1632
							$is_checkbox = 'checkbox' === $setting['type'];
1633
1634
							if ( $is_checkbox ) {
1635
								$checked = false;
1636
								if ( isset( $previously_saved_settings[ $setting_id ] ) ) {
1637
									$checked = 'yes' === $previously_saved_settings[ $setting_id ];
1638
								} elseif ( false === $previously_saved_settings && isset( $setting['default'] ) ) {
1639
									$checked = 'yes' === $setting['default'];
1640
								}
1641
							}
1642
							if ( 'email' === $setting['type'] ) {
1643
								$value = empty( $previously_saved_settings[ $setting_id ] )
1644
									? $setting['value']
1645
									: $previously_saved_settings[ $setting_id ];
1646
							}
1647
							?>
1648
							<?php $input_id = $item_id . '_' . $setting_id; ?>
1649
							<div class="<?php echo esc_attr( 'wc-wizard-service-setting-' . $input_id ); ?>">
1650
								<label
1651
									for="<?php echo esc_attr( $input_id ); ?>"
1652
									class="<?php echo esc_attr( $input_id ); ?>"
1653
								>
1654
									<?php echo esc_html( $setting['label'] ); ?>
1655
								</label>
1656
								<input
1657
									type="<?php echo esc_attr( $setting['type'] ); ?>"
1658
									id="<?php echo esc_attr( $input_id ); ?>"
1659
									class="<?php echo esc_attr( 'payment-' . $setting['type'] . '-input' ); ?>"
1660
									name="<?php echo esc_attr( $input_id ); ?>"
1661
									value="<?php echo esc_attr( isset( $value ) ? $value : $setting['value'] ); ?>"
1662
									placeholder="<?php echo esc_attr( $setting['placeholder'] ); ?>"
1663
									<?php echo ( $setting['required'] ) ? 'required' : ''; ?>
1664
									<?php echo $is_checkbox ? checked( isset( $checked ) && $checked, true, false ) : ''; ?>
1665
									data-plugins="<?php echo wc_esc_json( wp_json_encode( isset( $setting['plugins'] ) ? $setting['plugins'] : null ) ); ?>"
1666
								/>
1667
								<?php if ( ! empty( $setting['description'] ) ) : ?>
1668
									<span class="wc-wizard-service-settings-description"><?php echo esc_html( $setting['description'] ); ?></span>
1669
								<?php endif; ?>
1670
							</div>
1671
						<?php endforeach; ?>
1672
					</div>
1673
				<?php endif; ?>
1674
			</div>
1675
		</li>
1676
		<?php
1677
	}
1678
1679
	/**
1680
	 * Is it a featured service?
1681
	 *
1682
	 * @param array $service Service info array.
1683
	 * @return boolean
1684
	 */
1685
	public function is_featured_service( $service ) {
1686
		return ! empty( $service['featured'] );
1687
	}
1688
1689
	/**
1690
	 * Is this a non featured service?
1691
	 *
1692
	 * @param array $service Service info array.
1693
	 * @return boolean
1694
	 */
1695
	public function is_not_featured_service( $service ) {
1696
		return ! $this->is_featured_service( $service );
1697
	}
1698
1699
	/**
1700
	 * Payment Step.
1701
	 */
1702
	public function wc_setup_payment() {
1703
		$featured_gateways = array_filter( $this->get_wizard_in_cart_payment_gateways(), array( $this, 'is_featured_service' ) );
1704
		$in_cart_gateways  = array_filter( $this->get_wizard_in_cart_payment_gateways(), array( $this, 'is_not_featured_service' ) );
1705
		$manual_gateways   = $this->get_wizard_manual_payment_gateways();
1706
		?>
1707
		<h1><?php esc_html_e( 'Payment', 'woocommerce' ); ?></h1>
1708
		<form method="post" class="wc-wizard-payment-gateway-form">
1709
			<p>
1710
				<?php
1711
				printf(
1712
					wp_kses(
1713
						/* translators: %s: Link */
1714
						__( 'WooCommerce can accept both online and offline payments. <a href="%s" target="_blank">Additional payment methods</a> can be installed later.', 'woocommerce' ),
1715
						array(
1716
							'a' => array(
1717
								'href'   => array(),
1718
								'target' => array(),
1719
							),
1720
						)
1721
					),
1722
					esc_url( admin_url( 'admin.php?page=wc-addons&section=payment-gateways' ) )
1723
				);
1724
				?>
1725
			</p>
1726
			<?php if ( $featured_gateways ) : ?>
0 ignored issues
show
Bug Best Practice introduced by
The expression $featured_gateways of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
1727
			<ul class="wc-wizard-services featured">
1728
				<?php
1729
				foreach ( $featured_gateways as $gateway_id => $gateway ) {
1730
					$this->display_service_item( $gateway_id, $gateway );
1731
				}
1732
				?>
1733
			</ul>
1734
			<?php endif; ?>
1735
			<?php if ( $in_cart_gateways ) : ?>
0 ignored issues
show
Bug Best Practice introduced by
The expression $in_cart_gateways of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
1736
			<ul class="wc-wizard-services in-cart">
1737
				<?php
1738
				foreach ( $in_cart_gateways as $gateway_id => $gateway ) {
1739
					$this->display_service_item( $gateway_id, $gateway );
1740
				}
1741
				?>
1742
			</ul>
1743
			<?php endif; ?>
1744
			<ul class="wc-wizard-services manual">
1745
				<li class="wc-wizard-services-list-toggle closed">
1746
					<div class="wc-wizard-service-name">
1747
						<?php esc_html_e( 'Offline Payments', 'woocommerce' ); ?>
1748
					</div>
1749
					<div class="wc-wizard-service-description">
1750
						<?php esc_html_e( 'Collect payments from customers offline.', 'woocommerce' ); ?>
1751
					</div>
1752
					<div class="wc-wizard-service-enable" tabindex="0">
1753
						<input class="wc-wizard-service-list-toggle" id="wc-wizard-service-list-toggle" type="checkbox">
1754
						<label for="wc-wizard-service-list-toggle"></label>
1755
					</div>
1756
				</li>
1757
				<?php
1758
				foreach ( $manual_gateways as $gateway_id => $gateway ) {
1759
					$this->display_service_item( $gateway_id, $gateway );
1760
				}
1761
				?>
1762
			</ul>
1763
			<p class="wc-setup-actions step">
1764
				<?php $this->plugin_install_info(); ?>
1765
				<button type="submit" class="button-primary button button-large button-next" value="<?php esc_attr_e( 'Continue', 'woocommerce' ); ?>" name="save_step"><?php esc_html_e( 'Continue', 'woocommerce' ); ?></button>
1766
				<?php wp_nonce_field( 'wc-setup' ); ?>
1767
			</p>
1768
		</form>
1769
		<?php
1770
	}
1771
1772
	/**
1773
	 * Payment Step save.
1774
	 */
1775
	public function wc_setup_payment_save() {
1776
		check_admin_referer( 'wc-setup' );
1777
1778
		if (
1779
			(
1780
				// Install WooCommerce Services with Stripe to enable deferred account creation.
1781
				! empty( $_POST['wc-wizard-service-stripe-enabled'] ) && // WPCS: CSRF ok, input var ok.
1782
				! empty( $_POST['stripe_create_account'] ) // WPCS: CSRF ok, input var ok.
1783
			) || (
1784
				// Install WooCommerce Services with PayPal EC to enable proxied payments.
1785
				! empty( $_POST['wc-wizard-service-ppec_paypal-enabled'] ) && // WPCS: CSRF ok, input var ok.
1786
				! empty( $_POST['ppec_paypal_reroute_requests'] ) // WPCS: CSRF ok, input var ok.
1787
			)
1788
		) {
1789
			$this->install_woocommerce_services();
1790
		}
1791
1792
		$gateways = array_merge( $this->get_wizard_in_cart_payment_gateways(), $this->get_wizard_manual_payment_gateways() );
1793
1794
		foreach ( $gateways as $gateway_id => $gateway ) {
1795
			// If repo-slug is defined, download and install plugin from .org.
1796
			if ( ! empty( $gateway['repo-slug'] ) && ! empty( $_POST[ 'wc-wizard-service-' . $gateway_id . '-enabled' ] ) ) { // WPCS: CSRF ok, input var ok.
1797
				$this->install_plugin( $gateway_id, $gateway );
1798
			}
1799
1800
			$settings = array( 'enabled' => ! empty( $_POST[ 'wc-wizard-service-' . $gateway_id . '-enabled' ] ) ? 'yes' : 'no' );  // WPCS: CSRF ok, input var ok.
1801
1802
			// @codingStandardsIgnoreStart
1803
			if ( ! empty( $gateway['settings'] ) ) {
1804
				foreach ( $gateway['settings'] as $setting_id => $setting ) {
1805
					$settings[ $setting_id ] = 'yes' === $settings['enabled'] && isset( $_POST[ $gateway_id . '_' . $setting_id ] )
1806
						? wc_clean( wp_unslash( $_POST[ $gateway_id . '_' . $setting_id ] ) )
1807
						: false;
1808
				}
1809
			}
1810
			// @codingStandardsIgnoreSEnd
1811
1812
			if ( 'ppec_paypal' === $gateway_id && empty( $settings['reroute_requests'] ) ) {
1813
				unset( $settings['enabled'] );
1814
			}
1815
1816
			$settings_key = 'woocommerce_' . $gateway_id . '_settings';
1817
			$previously_saved_settings = array_filter( (array) get_option( $settings_key, array() ) );
1818
			update_option( $settings_key, array_merge( $previously_saved_settings, $settings ) );
1819
		}
1820
1821
		wp_redirect( esc_url_raw( $this->get_next_step_link() ) );
1822
		exit;
1823
	}
1824
1825
	protected function display_recommended_item( $item_info ) {
1826
		$type        = $item_info['type'];
1827
		$title       = $item_info['title'];
1828
		$description = $item_info['description'];
1829
		$img_url     = $item_info['img_url'];
1830
		$img_alt     = $item_info['img_alt'];
1831
		?>
1832
		<li class="recommended-item checkbox">
1833
			<input
1834
				id="<?php echo esc_attr( 'wc_recommended_' . $type ); ?>"
1835
				type="checkbox"
1836
				name="<?php echo esc_attr( 'setup_' . $type ); ?>"
1837
				value="yes"
1838
				checked
1839
				data-plugins="<?php echo wc_esc_json( wp_json_encode( isset( $item_info['plugins'] ) ? $item_info['plugins'] : null ) ); ?>"
1840
			/>
1841
			<label for="<?php echo esc_attr( 'wc_recommended_' . $type ); ?>">
1842
				<img
1843
					src="<?php echo esc_url( $img_url ); ?>"
1844
					class="<?php echo esc_attr( 'recommended-item-icon-' . $type ); ?> recommended-item-icon"
1845
					alt="<?php echo esc_attr( $img_alt ); ?>" />
1846
				<div class="recommended-item-description-container">
1847
					<h3><?php echo esc_html( $title ); ?></h3>
1848
					<p><?php echo wp_kses( $description, array(
1849
						'a' => array(
1850
							'href'   => array(),
1851
							'target' => array(),
1852
							'rel'    => array(),
1853
						),
1854
						'em' => array(),
1855
					) ); ?></p>
1856
				</div>
1857
			</label>
1858
		</li>
1859
		<?php
1860
	}
1861
1862
	/**
1863
	 * Recommended step
1864
	 */
1865
	public function wc_setup_recommended() {
1866
		?>
1867
		<h1><?php esc_html_e( 'Recommended for All WooCommerce Stores', 'woocommerce' ); ?></h1>
1868
		<p>
1869
			<?php esc_html_e( 'Enhance your store with these recommended features.', 'woocommerce' ); ?>
1870
		</p>
1871
		<form method="post">
1872
			<ul class="recommended-step">
1873
				<?php
1874
				if ( $this->should_show_theme() ) :
1875
					$theme      = wp_get_theme();
1876
					$theme_name = $theme['Name'];
1877
					$this->display_recommended_item( array(
1878
						'type'        => 'storefront_theme',
1879
						'title'       => __( 'Storefront Theme', 'woocommerce' ),
1880
						'description' => sprintf( __(
1881
								'Design your store with deep WooCommerce integration. If toggled on, we’ll install <a href="https://woocommerce.com/storefront/" target="_blank" rel="noopener noreferrer">Storefront</a>, and your current theme <em>%s</em> will be deactivated.', 'woocommerce' ),
1882
								$theme_name
1883
						),
1884
						'img_url'     => WC()->plugin_url() . '/assets/images/obw-storefront-icon.svg',
1885
						'img_alt'     => __( 'Storefront icon', 'woocommerce' ),
1886
					) );
1887
				endif;
1888
1889
				if ( $this->should_show_automated_tax() ) :
1890
					$this->display_recommended_item( array(
1891
						'type'        => 'automated_taxes',
1892
						'title'       => __( 'Automated Taxes', 'woocommerce' ),
1893
						'description' => __( 'Save time and errors with automated tax calculation and collection at checkout. Powered by WooCommerce Services and Jetpack.', 'woocommerce' ),
1894
						'img_url'     => WC()->plugin_url() . '/assets/images/obw-taxes-icon.svg',
1895
						'img_alt'     => __( 'automated taxes icon', 'woocommerce' ),
1896
						'plugins'     => $this->get_wcs_requisite_plugins(),
1897
					) );
1898
				endif;
1899
1900 View Code Duplication
				if ( $this->should_show_mailchimp() ) :
1901
					$this->display_recommended_item( array(
1902
						'type'        => 'mailchimp',
1903
						'title'       => __( 'Mailchimp', 'woocommerce' ),
1904
						'description' => __( 'Join the 16 million customers who use Mailchimp. Sync list and store data to send automated emails, and targeted campaigns.', 'woocommerce' ),
1905
						'img_url'     => WC()->plugin_url() . '/assets/images/obw-mailchimp-icon.svg',
1906
						'img_alt'     => __( 'Mailchimp icon', 'woocommerce' ),
1907
						'plugins'     => array( array( 'name' => __( 'Mailchimp for WooCommerce', 'woocommerce' ), 'slug' => 'mailchimp-for-woocommerce' ) ),
1908
					) );
1909
				endif;
1910
1911 View Code Duplication
				if ( $this->should_show_facebook() ) :
1912
					$this->display_recommended_item( array(
1913
						'type'        => 'facebook',
1914
						'title'       => __( 'Facebook', 'woocommerce' ),
1915
						'description' => __( 'Enjoy all Facebook products combined in one extension: pixel tracking, catalog sync, messenger chat, shop functionality and Instagram shopping (coming soon)!', 'woocommerce' ),
1916
						'img_url'     => WC()->plugin_url() . '/assets/images/obw-facebook-icon.svg',
1917
						'img_alt'     => __( 'Facebook icon', 'woocommerce' ),
1918
						'plugins'     => array( array( 'name' => __( 'Facebook for WooCommerce', 'woocommerce' ), 'slug' => 'facebook-for-woocommerce' ) ),
1919
					) );
1920
				endif;
1921
			?>
1922
		</ul>
1923
			<p class="wc-setup-actions step">
1924
				<?php $this->plugin_install_info(); ?>
1925
				<button type="submit" class="button-primary button button-large button-next" value="<?php esc_attr_e( 'Continue', 'woocommerce' ); ?>" name="save_step"><?php esc_html_e( 'Continue', 'woocommerce' ); ?></button>
1926
				<?php wp_nonce_field( 'wc-setup' ); ?>
1927
			</p>
1928
		</form>
1929
		<?php
1930
	}
1931
1932
	/**
1933
	 * Recommended step save.
1934
	 */
1935
	public function wc_setup_recommended_save() {
1936
		check_admin_referer( 'wc-setup' );
1937
1938
		$setup_storefront       = isset( $_POST['setup_storefront_theme'] ) && 'yes' === $_POST['setup_storefront_theme'];
1939
		$setup_automated_tax    = isset( $_POST['setup_automated_taxes'] ) && 'yes' === $_POST['setup_automated_taxes'];
1940
		$setup_mailchimp        = isset( $_POST['setup_mailchimp'] ) && 'yes' === $_POST['setup_mailchimp'];
1941
		$setup_facebook         = isset( $_POST['setup_facebook'] ) && 'yes' === $_POST['setup_facebook'];
1942
1943
		update_option( 'woocommerce_calc_taxes', $setup_automated_tax ? 'yes' : 'no' );
1944
		update_option( 'woocommerce_setup_automated_taxes', $setup_automated_tax );
1945
1946
		if ( $setup_storefront ) {
1947
			$this->install_theme( 'storefront' );
1948
		}
1949
1950
		if ( $setup_automated_tax ) {
1951
			$this->install_woocommerce_services();
1952
		}
1953
1954
		if ( $setup_mailchimp ) {
1955
			// Prevent MailChimp from redirecting to its settings page during the OBW flow.
1956
			add_option( 'mailchimp_woocommerce_plugin_do_activation_redirect', false );
1957
1958
			$this->install_plugin(
1959
				'mailchimp-for-woocommerce',
1960
				array(
1961
					'name'      => __( 'MailChimp for WooCommerce', 'woocommerce' ),
1962
					'repo-slug' => 'mailchimp-for-woocommerce',
1963
					'file'      => 'mailchimp-woocommerce.php',
1964
				)
1965
			);
1966
		}
1967
1968
		if ( $setup_facebook ) {
1969
			$this->install_plugin(
1970
				'facebook-for-woocommerce',
1971
				array(
1972
					'name'      => __( 'Facebook for WooCommerce', 'woocommerce' ),
1973
					'repo-slug' => 'facebook-for-woocommerce',
1974
				)
1975
			);
1976
		}
1977
1978
		wp_redirect( esc_url_raw( $this->get_next_step_link() ) );
1979
		exit;
1980
	}
1981
1982
	/**
1983
	 * Go to the next step if Jetpack was connected.
1984
	 */
1985
	protected function wc_setup_activate_actions() {
1986
		if (
1987
			isset( $_GET['from'] ) &&
1988
			'wpcom' === $_GET['from'] &&
1989
			class_exists( 'Jetpack' ) &&
1990
			Jetpack::is_active()
1991
		) {
1992
			wp_redirect( esc_url_raw( remove_query_arg( 'from', $this->get_next_step_link() ) ) );
1993
			exit;
1994
		}
1995
	}
1996
1997
	protected function wc_setup_activate_get_feature_list() {
1998
		$features = array();
1999
2000
		$stripe_settings = get_option( 'woocommerce_stripe_settings', false );
2001
		$stripe_enabled  = is_array( $stripe_settings )
2002
			&& isset( $stripe_settings['create_account'] ) && 'yes' === $stripe_settings['create_account']
2003
			&& isset( $stripe_settings['enabled'] ) && 'yes' === $stripe_settings['enabled'];
2004
		$ppec_settings   = get_option( 'woocommerce_ppec_paypal_settings', false );
2005
		$ppec_enabled    = is_array( $ppec_settings )
2006
			&& isset( $ppec_settings['reroute_requests'] ) && 'yes' === $ppec_settings['reroute_requests']
2007
			&& isset( $ppec_settings['enabled'] ) && 'yes' === $ppec_settings['enabled'];
2008
2009
		$features['payment'] = $stripe_enabled || $ppec_enabled;
2010
		$features['taxes']   = (bool) get_option( 'woocommerce_setup_automated_taxes', false );
2011
		$features['labels']  = (bool) get_option( 'woocommerce_setup_shipping_labels', false );
2012
2013
		return $features;
2014
	}
2015
2016
	protected function wc_setup_activate_get_feature_list_str() {
2017
		$features = $this->wc_setup_activate_get_feature_list();
2018
		if ( $features['payment'] && $features['taxes'] && $features['labels'] ) {
2019
			return __( 'payment setup, automated taxes and discounted shipping labels', 'woocommerce' );
2020
		} else if ( $features['payment'] && $features['taxes'] ) {
2021
			return __( 'payment setup and automated taxes', 'woocommerce' );
2022
		} else if ( $features['payment'] && $features['labels'] ) {
2023
			return __( 'payment setup and discounted shipping labels', 'woocommerce' );
2024
		} else if ( $features['payment'] ) {
2025
			return __( 'payment setup', 'woocommerce' );
2026
		} else if ( $features['taxes'] && $features['labels'] ) {
2027
			return __( 'automated taxes and discounted shipping labels', 'woocommerce' );
2028
		} else if ( $features['taxes'] ) {
2029
			return __( 'automated taxes', 'woocommerce' );
2030
		} else if ( $features['labels'] ) {
2031
			return __( 'discounted shipping labels', 'woocommerce' );
2032
		}
2033
		return false;
2034
	}
2035
2036
	/**
2037
	 * Activate step.
2038
	 */
2039
	public function wc_setup_activate() {
2040
		$this->wc_setup_activate_actions();
2041
2042
		$jetpack_connected = class_exists( 'Jetpack' ) && Jetpack::is_active();
2043
2044
		$has_jetpack_error = false;
2045
		if ( isset( $_GET['activate_error'] ) ) {
2046
			$has_jetpack_error = true;
2047
2048
			$title = __( "Sorry, we couldn't connect your store to Jetpack", 'woocommerce' );
2049
2050
			$error_message = $this->get_activate_error_message( sanitize_text_field( wp_unslash( $_GET['activate_error'] ) ) );
2051
			$description = $error_message;
2052
		} else {
2053
			$feature_list = $this->wc_setup_activate_get_feature_list_str();
2054
2055
			$description = false;
2056
2057
			if ( $feature_list ) {
2058
				if ( ! $jetpack_connected ) {
2059
					/* translators: %s: list of features, potentially comma separated */
2060
					$description_base = __( 'Your store is almost ready! To activate services like %s, just connect with Jetpack.', 'woocommerce' );
2061
				} else {
2062
					$description_base = __( 'Thanks for using Jetpack! Your store is almost ready: to activate services like %s, just connect your store.', 'woocommerce' );
2063
				}
2064
				$description = sprintf( $description_base, $feature_list );
2065
			}
2066
2067
			if ( ! $jetpack_connected ) {
2068
				$title = $feature_list ?
2069
					__( 'Connect your store to Jetpack', 'woocommerce' ) :
2070
					__( 'Connect your store to Jetpack to enable extra features', 'woocommerce' );
2071
				$button_text = __( 'Continue with Jetpack', 'woocommerce' );
2072
			} elseif ( $feature_list ) {
2073
				$title = __( 'Connect your store to activate WooCommerce Services', 'woocommerce' );
2074
				$button_text = __( 'Continue with WooCommerce Services', 'woocommerce' );
2075
			} else {
2076
				wp_redirect( esc_url_raw( $this->get_next_step_link() ) );
2077
				exit;
2078
			}
2079
		}
2080
		?>
2081
		<h1><?php echo esc_html( $title ); ?></h1>
2082
		<p><?php echo esc_html( $description ); ?></p>
2083
2084
		<?php if ( $jetpack_connected ) : ?>
2085
			<div class="activate-splash">
2086
				<img
2087
					class="jetpack-logo"
2088
					src="<?php echo esc_url( WC()->plugin_url() . '/assets/images/jetpack_horizontal_logo.png' ); ?>"
2089
					alt="Jetpack logo"
2090
				/>
2091
				<img
2092
					class="wcs-notice"
2093
					src="<?php echo esc_url( WC()->plugin_url() . '/assets/images/wcs-notice.png' ); ?>"
2094
				/>
2095
			</div>
2096
		<?php else : ?>
2097
			<img
2098
				class="jetpack-logo"
2099
				src="<?php echo esc_url( WC()->plugin_url() . '/assets/images/jetpack_vertical_logo.png' ); ?>"
2100
				alt="Jetpack logo"
2101
			/>
2102
		<?php endif; ?>
2103
2104
		<?php if ( $has_jetpack_error ) : ?>
2105
			<p class="wc-setup-actions step">
2106
				<a
2107
					href="<?php echo esc_url( $this->get_next_step_link() ); ?>"
2108
					class="button-primary button button-large"
2109
				>
2110
					<?php esc_html_e( 'Finish setting up your store', 'woocommerce' ); ?>
2111
				</a>
2112
			</p>
2113
		<?php else : ?>
2114
			<p class="jetpack-terms">
2115
				<?php
2116
					printf(
2117
						wp_kses_post( __( 'By connecting your site you agree to our fascinating <a href="%1$s" target="_blank">Terms of Service</a> and to <a href="%2$s" target="_blank">share details</a> with WordPress.com', 'woocommerce' ) ),
2118
						'https://wordpress.com/tos',
2119
						'https://jetpack.com/support/what-data-does-jetpack-sync'
2120
					);
2121
				?>
2122
			</p>
2123
			<form method="post" class="activate-jetpack">
2124
				<p class="wc-setup-actions step">
2125
					<button type="submit" class="button-primary button button-large" value="<?php echo esc_attr( $button_text ); ?>"><?php echo esc_html( $button_text ); ?></button>
2126
				</p>
2127
				<input type="hidden" name="save_step" value="activate" />
2128
				<?php wp_nonce_field( 'wc-setup' ); ?>
2129
			</form>
2130
			<?php if ( ! $jetpack_connected ) : ?>
2131
				<h3 class="jetpack-reasons">
2132
					<?php
2133
						echo esc_html( $description ?
2134
							__( "Bonus reasons you'll love Jetpack", 'woocommerce' ) :
2135
							__( "Reasons you'll love Jetpack", 'woocommerce' )
2136
						);
2137
					?>
2138
				</h3>
2139
				<ul class="wc-wizard-features">
2140
					<li class="wc-wizard-feature-item">
2141
						<p class="wc-wizard-feature-name">
2142
							<strong><?php esc_html_e( 'Better security', 'woocommerce' ); ?></strong>
2143
						</p>
2144
						<p class="wc-wizard-feature-description">
2145
							<?php esc_html_e( 'Protect your store from unauthorized access.', 'woocommerce' ); ?>
2146
						</p>
2147
					</li>
2148
					<li class="wc-wizard-feature-item">
2149
						<p class="wc-wizard-feature-name">
2150
							<strong><?php esc_html_e( 'Store stats', 'woocommerce' ); ?></strong>
2151
						</p>
2152
						<p class="wc-wizard-feature-description">
2153
							<?php esc_html_e( 'Get insights on how your store is doing, including total sales, top products, and more.', 'woocommerce' ); ?>
2154
						</p>
2155
					</li>
2156
					<li class="wc-wizard-feature-item">
2157
						<p class="wc-wizard-feature-name">
2158
							<strong><?php esc_html_e( 'Store monitoring', 'woocommerce' ); ?></strong>
2159
						</p>
2160
						<p class="wc-wizard-feature-description">
2161
							<?php esc_html_e( 'Get an alert if your store is down for even a few minutes.', 'woocommerce' ); ?>
2162
						</p>
2163
					</li>
2164
					<li class="wc-wizard-feature-item">
2165
						<p class="wc-wizard-feature-name">
2166
							<strong><?php esc_html_e( 'Product promotion', 'woocommerce' ); ?></strong>
2167
						</p>
2168
						<p class="wc-wizard-feature-description">
2169
							<?php esc_html_e( "Share new items on social media the moment they're live in your store.", 'woocommerce' ); ?>
2170
						</p>
2171
					</li>
2172
				</ul>
2173
			<?php endif; ?>
2174
		<?php endif; ?>
2175
	<?php
2176
	}
2177
2178
	protected function get_all_activate_errors() {
2179
		return array(
2180
			'default' => __( "Sorry! We tried, but we couldn't connect Jetpack just now 😭. Please go to the Plugins tab to connect Jetpack, so that you can finish setting up your store.", 'woocommerce' ),
2181
			'jetpack_cant_be_installed' => __( "Sorry! We tried, but we couldn't install Jetpack for you 😭. Please go to the Plugins tab to install it, and finish setting up your store.", 'woocommerce' ),
2182
			'register_http_request_failed' => __( "Sorry! We couldn't contact Jetpack just now 😭. Please make sure that your site is visible over the internet, and that it accepts incoming and outgoing requests via curl. You can also try to connect to Jetpack again, and if you run into any more issues, please contact support.", 'woocommerce' ),
2183
			'siteurl_private_ip_dev' => __( "Your site might be on a private network. Jetpack can only connect to public sites. Please make sure your site is visible over the internet, and then try connecting again 🙏." , 'woocommerce' ),
2184
		);
2185
	}
2186
2187
	protected function get_activate_error_message( $code = '' ) {
2188
		$errors = $this->get_all_activate_errors();
2189
		return array_key_exists( $code, $errors ) ? $errors[ $code ] : $errors['default'];
2190
	}
2191
2192
	/**
2193
	 * Activate step save.
2194
	 *
2195
	 * Install, activate, and launch connection flow for Jetpack.
2196
	 */
2197
	public function wc_setup_activate_save() {
2198
		check_admin_referer( 'wc-setup' );
2199
2200
		set_transient( 'wc_setup_activated', 'yes', MINUTE_IN_SECONDS * 10 );
2201
2202
		// Leave a note for WooCommerce Services that Jetpack has been opted into.
2203
		update_option( 'woocommerce_setup_jetpack_opted_in', true );
2204
2205
		if ( class_exists( 'Jetpack' ) && Jetpack::is_active() ) {
2206
			wp_safe_redirect( esc_url_raw( $this->get_next_step_link() ) );
2207
			exit;
2208
		}
2209
2210
		WC_Install::background_installer( 'jetpack', array(
2211
			'name'      => __( 'Jetpack', 'woocommerce' ),
2212
			'repo-slug' => 'jetpack',
2213
		) );
2214
2215
		// Did Jetpack get successfully installed?
2216
		if ( ! class_exists( 'Jetpack' ) ) {
2217
			wp_redirect( esc_url_raw( add_query_arg( 'activate_error', 'jetpack_cant_be_installed' ) ) );
2218
			exit;
2219
		}
2220
2221
		Jetpack::maybe_set_version_option();
2222
		$register_result = Jetpack::try_registration();
2223
2224
		if ( is_wp_error( $register_result ) ) {
2225
			$result_error_code = $register_result->get_error_code();
2226
			$jetpack_error_code = array_key_exists( $result_error_code, $this->get_all_activate_errors() ) ? $result_error_code : 'register';
2227
			wp_redirect( esc_url_raw( add_query_arg( 'activate_error', $jetpack_error_code ) ) );
2228
			exit;
2229
		}
2230
2231
		$redirect_url = esc_url_raw( add_query_arg( array(
2232
			'page'           => 'wc-setup',
2233
			'step'           => 'activate',
2234
			'from'           => 'wpcom',
2235
			'activate_error' => false,
2236
		), admin_url() ) );
2237
		$connection_url = Jetpack::init()->build_connect_url( true, $redirect_url, 'woocommerce-setup-wizard' );
2238
2239
		wp_redirect( esc_url_raw( $connection_url ) );
2240
		exit;
2241
	}
2242
2243
	/**
2244
	 * Final step.
2245
	 */
2246
	public function wc_setup_ready() {
2247
		// We've made it! Don't prompt the user to run the wizard again.
2248
		WC_Admin_Notices::remove_notice( 'install' );
2249
2250
		$user_email   = $this->get_current_user_email();
2251
		$videos_url   = 'https://docs.woocommerce.com/document/woocommerce-guided-tour-videos/?utm_source=setupwizard&utm_medium=product&utm_content=videos&utm_campaign=woocommerceplugin';
2252
		$docs_url     = 'https://docs.woocommerce.com/documentation/plugins/woocommerce/getting-started/?utm_source=setupwizard&utm_medium=product&utm_content=docs&utm_campaign=woocommerceplugin';
2253
		$help_text    = sprintf(
2254
			/* translators: %1$s: link to videos, %2$s: link to docs */
2255
			__( 'Watch our <a href="%1$s" target="_blank">guided tour videos</a> to learn more about WooCommerce, and visit WooCommerce.com to learn more about <a href="%2$s" target="_blank">getting started</a>.', 'woocommerce' ),
2256
			$videos_url,
2257
			$docs_url
2258
		);
2259
		?>
2260
		<h1><?php esc_html_e( "You're ready to start selling!", 'woocommerce' ); ?></h1>
2261
2262
		<div class="woocommerce-message woocommerce-newsletter">
2263
			<p><?php esc_html_e( "We're here for you — get tips, product updates, and inspiration straight to your mailbox.", 'woocommerce' ); ?></p>
2264
			<form action="//woocommerce.us8.list-manage.com/subscribe/post?u=2c1434dc56f9506bf3c3ecd21&amp;id=13860df971&amp;SIGNUPPAGE=plugin" method="post" target="_blank" novalidate>
2265
				<div class="newsletter-form-container">
2266
					<input
2267
						class="newsletter-form-email"
2268
						type="email"
2269
						value="<?php echo esc_attr( $user_email ); ?>"
2270
						name="EMAIL"
2271
						placeholder="<?php esc_attr_e( 'Email address', 'woocommerce' ); ?>"
2272
						required
2273
					>
2274
					<p class="wc-setup-actions step newsletter-form-button-container">
2275
						<button
2276
							type="submit"
2277
							value="<?php esc_html_e( 'Yes please!', 'woocommerce' ); ?>"
2278
							name="subscribe"
2279
							id="mc-embedded-subscribe"
2280
							class="button-primary button newsletter-form-button"
2281
						><?php esc_html_e( 'Yes please!', 'woocommerce' ); ?></button>
2282
					</p>
2283
				</div>
2284
			</form>
2285
		</div>
2286
2287
		<ul class="wc-wizard-next-steps">
2288
			<li class="wc-wizard-next-step-item">
2289
				<div class="wc-wizard-next-step-description">
2290
					<p class="next-step-heading"><?php esc_html_e( 'Next step', 'woocommerce' ); ?></p>
2291
					<h3 class="next-step-description"><?php esc_html_e( 'Create some products', 'woocommerce' ); ?></h3>
2292
					<p class="next-step-extra-info"><?php esc_html_e( "You're ready to add products to your store.", 'woocommerce' ); ?></p>
2293
				</div>
2294
				<div class="wc-wizard-next-step-action">
2295
					<p class="wc-setup-actions step">
2296
						<a class="button button-primary button-large" href="<?php echo esc_url( admin_url( 'post-new.php?post_type=product&tutorial=true' ) ); ?>">
2297
							<?php esc_html_e( 'Create a product', 'woocommerce' ); ?>
2298
						</a>
2299
					</p>
2300
				</div>
2301
			</li>
2302
			<li class="wc-wizard-next-step-item">
2303
				<div class="wc-wizard-next-step-description">
2304
					<p class="next-step-heading"><?php esc_html_e( 'Have an existing store?', 'woocommerce' ); ?></p>
2305
					<h3 class="next-step-description"><?php esc_html_e( 'Import products', 'woocommerce' ); ?></h3>
2306
					<p class="next-step-extra-info"><?php esc_html_e( 'Transfer existing products to your new store — just import a CSV file.', 'woocommerce' ); ?></p>
2307
				</div>
2308
				<div class="wc-wizard-next-step-action">
2309
					<p class="wc-setup-actions step">
2310
						<a class="button button-large" href="<?php echo esc_url( admin_url( 'edit.php?post_type=product&page=product_importer' ) ); ?>">
2311
							<?php esc_html_e( 'Import products', 'woocommerce' ); ?>
2312
						</a>
2313
					</p>
2314
				</div>
2315
			</li>
2316
			<li class="wc-wizard-additional-steps">
2317
				<div class="wc-wizard-next-step-description">
2318
					<p class="next-step-heading"><?php esc_html_e( 'You can also:', 'woocommerce' ); ?></p>
2319
				</div>
2320
				<div class="wc-wizard-next-step-action">
2321
					<p class="wc-setup-actions step">
2322
						<a class="button button-large" href="<?php echo esc_url( admin_url() ); ?>">
2323
							<?php esc_html_e( 'Visit Dashboard', 'woocommerce' ); ?>
2324
						</a>
2325
						<a class="button button-large" href="<?php echo esc_url( admin_url( 'admin.php?page=wc-settings' ) ); ?>">
2326
							<?php esc_html_e( 'Review Settings', 'woocommerce' ); ?>
2327
						</a>
2328
						<a class="button button-large" href="<?php echo esc_url( add_query_arg( array( 'autofocus' => array( 'panel' => 'woocommerce' ), 'url' => wc_get_page_permalink( 'shop' ) ), admin_url( 'customize.php' ) ) ); ?>">
2329
							<?php esc_html_e( 'View &amp; Customize', 'woocommerce' ); ?>
2330
						</a>
2331
					</p>
2332
				</div>
2333
			</li>
2334
		</ul>
2335
		<p class="next-steps-help-text"><?php echo wp_kses_post( $help_text ); ?></p>
2336
		<?php
2337
	}
2338
}
2339
2340
new WC_Admin_Setup_Wizard();
2341