Completed
Push — master ( 69d170...2515df )
by Roy
03:07 queued 01:09
created

woocommerce-gateway-stripe.php (5 issues)

Upgrade to new PHP Analysis Engine

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

1
<?php
2
/**
3
 * Plugin Name: WooCommerce Stripe Gateway
4
 * Plugin URI: https://wordpress.org/plugins/woocommerce-gateway-stripe/
5
 * Description: Take credit card payments on your store using Stripe.
6
 * Author: WooCommerce
7
 * Author URI: https://woocommerce.com/
8
 * Version: 4.0.1
9
 * Requires at least: 4.4
10
 * Tested up to: 4.9
11
 * WC requires at least: 2.6
12
 * WC tested up to: 3.3
13
 * Text Domain: woocommerce-gateway-stripe
14
 *
15
 */
16
17
if ( ! defined( 'ABSPATH' ) ) {
18
	exit;
19
}
20
21
if ( ! class_exists( 'WC_Stripe' ) ) :
22
	/**
23
	 * Required minimums and constants
24
	 */
25
	define( 'WC_STRIPE_VERSION', '4.0.1' );
26
	define( 'WC_STRIPE_MIN_PHP_VER', '5.6.0' );
27
	define( 'WC_STRIPE_MIN_WC_VER', '2.6.0' );
28
	define( 'WC_STRIPE_MAIN_FILE', __FILE__ );
29
	define( 'WC_STRIPE_PLUGIN_URL', untrailingslashit( plugins_url( basename( plugin_dir_path( __FILE__ ) ), basename( __FILE__ ) ) ) );
30
	define( 'WC_STRIPE_PLUGIN_PATH', untrailingslashit( plugin_dir_path( __FILE__ ) ) );
31
32
	class WC_Stripe {
33
34
		/**
35
		 * @var Singleton The reference the *Singleton* instance of this class
36
		 */
37
		private static $instance;
38
39
		/**
40
		 * @var Reference to logging class.
41
		 */
42
		private static $log;
0 ignored issues
show
The property $log is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
43
44
		/**
45
		 * Returns the *Singleton* instance of this class.
46
		 *
47
		 * @return Singleton The *Singleton* instance.
48
		 */
49
		public static function get_instance() {
50
			if ( null === self::$instance ) {
51
				self::$instance = new self();
0 ignored issues
show
Documentation Bug introduced by
It seems like new self() of type object<WC_Stripe> is incompatible with the declared type object<Singleton> of property $instance.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
52
			}
53
			return self::$instance;
0 ignored issues
show
Bug Compatibility introduced by
The expression self::$instance; of type WC_Stripe|Singleton adds the type WC_Stripe to the return on line 53 which is incompatible with the return type documented by WC_Stripe::get_instance of type Singleton.
Loading history...
54
		}
55
56
		/**
57
		 * Private clone method to prevent cloning of the instance of the
58
		 * *Singleton* instance.
59
		 *
60
		 * @return void
61
		 */
62
		private function __clone() {}
63
64
		/**
65
		 * Private unserialize method to prevent unserializing of the *Singleton*
66
		 * instance.
67
		 *
68
		 * @return void
69
		 */
70
		private function __wakeup() {}
71
72
		/**
73
		 * Notices (array)
74
		 * @var array
75
		 */
76
		public $notices = array();
77
78
		/**
79
		 * Protected constructor to prevent creating a new instance of the
80
		 * *Singleton* via the `new` operator from outside of this class.
81
		 */
82
		private function __construct() {
83
			add_action( 'admin_init', array( $this, 'check_environment' ) );
84
			add_action( 'admin_notices', array( $this, 'admin_notices' ), 15 );
85
			add_action( 'plugins_loaded', array( $this, 'init' ) );
86
			add_action( 'wp_loaded', array( $this, 'hide_notices' ) );
87
		}
88
89
		/**
90
		 * Init the plugin after plugins_loaded so environment variables are set.
91
		 *
92
		 * @since 1.0.0
93
		 * @version 4.0.0
94
		 */
95
		public function init() {
96
			require_once( dirname( __FILE__ ) . '/includes/class-wc-stripe-logger.php' );
97
			require_once( dirname( __FILE__ ) . '/includes/class-wc-stripe-helper.php' );
98
			include_once( dirname( __FILE__ ) . '/includes/class-wc-stripe-api.php' );
99
100
			// Don't hook anything else in the plugin if we're in an incompatible environment
101
			if ( self::get_environment_warning() ) {
102
				return;
103
			}
104
105
			load_plugin_textdomain( 'woocommerce-gateway-stripe', false, plugin_basename( dirname( __FILE__ ) ) . '/languages' );
106
107
			require_once( dirname( __FILE__ ) . '/includes/abstracts/abstract-wc-stripe-payment-gateway.php' );
108
			require_once( dirname( __FILE__ ) . '/includes/class-wc-stripe-webhook-handler.php' );
109
			require_once( dirname( __FILE__ ) . '/includes/class-wc-stripe-sepa-payment-token.php' );
110
			require_once( dirname( __FILE__ ) . '/includes/class-wc-gateway-stripe.php' );
111
			require_once( dirname( __FILE__ ) . '/includes/payment-methods/class-wc-gateway-stripe-bancontact.php' );
112
			require_once( dirname( __FILE__ ) . '/includes/payment-methods/class-wc-gateway-stripe-sofort.php' );
113
			require_once( dirname( __FILE__ ) . '/includes/payment-methods/class-wc-gateway-stripe-giropay.php' );
114
			require_once( dirname( __FILE__ ) . '/includes/payment-methods/class-wc-gateway-stripe-ideal.php' );
115
			require_once( dirname( __FILE__ ) . '/includes/payment-methods/class-wc-gateway-stripe-p24.php' );
116
			require_once( dirname( __FILE__ ) . '/includes/payment-methods/class-wc-gateway-stripe-alipay.php' );
117
			require_once( dirname( __FILE__ ) . '/includes/payment-methods/class-wc-gateway-stripe-sepa.php' );
118
			require_once( dirname( __FILE__ ) . '/includes/payment-methods/class-wc-gateway-stripe-bitcoin.php' );
119
			require_once( dirname( __FILE__ ) . '/includes/payment-methods/class-wc-stripe-payment-request.php' );
120
			require_once( dirname( __FILE__ ) . '/includes/compat/class-wc-stripe-compat.php' );
121
			require_once( dirname( __FILE__ ) . '/includes/compat/class-wc-stripe-sepa-compat.php' );
122
			require_once( dirname( __FILE__ ) . '/includes/class-wc-stripe-order-handler.php' );
123
			require_once( dirname( __FILE__ ) . '/includes/class-wc-stripe-payment-tokens.php' );
124
			require_once( dirname( __FILE__ ) . '/includes/class-wc-stripe-customer.php' );
125
126
			// REMOVE IN THE FUTURE.
127
			require_once( dirname( __FILE__ ) . '/includes/deprecated/class-wc-stripe-apple-pay.php' );
128
129
			add_filter( 'woocommerce_payment_gateways', array( $this, 'add_gateways' ) );
130
			add_filter( 'plugin_action_links_' . plugin_basename( __FILE__ ), array( $this, 'plugin_action_links' ) );
131
			add_filter( 'woocommerce_get_sections_checkout', array( $this, 'filter_gateway_order_admin' ) );
132
		}
133
134
		/**
135
		 * Hides any admin notices.
136
		 *
137
		 * @since 4.0.0
138
		 * @version 4.0.0
139
		 */
140
		public function hide_notices() {
141
			if ( isset( $_GET['wc-stripe-hide-notice'] ) && isset( $_GET['_wc_stripe_notice_nonce'] ) ) {
142
				if ( ! wp_verify_nonce( $_GET['_wc_stripe_notice_nonce'], 'wc_stripe_hide_notices_nonce' ) ) {
143
					wp_die( __( 'Action failed. Please refresh the page and retry.', 'woocommerce-gateway-stripe' ) );
144
				}
145
146
				if ( ! current_user_can( 'manage_woocommerce' ) ) {
147
					wp_die( __( 'Cheatin&#8217; huh?', 'woocommerce-gateway-stripe' ) );
148
				}
149
150
				$notice = wc_clean( $_GET['wc-stripe-hide-notice'] );
151
152
				switch ( $notice ) {
153
					case 'ssl':
154
						update_option( 'wc_stripe_show_ssl_notice', 'no' );
155
						break;
156
					case 'keys':
157
						update_option( 'wc_stripe_show_keys_notice', 'no' );
158
						break;
159
				}
160
			}
161
		}
162
163
		/**
164
		 * Allow this class and other classes to add slug keyed notices (to avoid duplication).
165
		 *
166
		 * @since 1.0.0
167
		 * @version 4.0.0
168
		 */
169
		public function add_admin_notice( $slug, $class, $message, $dismissible = false ) {
170
			$this->notices[ $slug ] = array(
171
				'class'       => $class,
172
				'message'     => $message,
173
				'dismissible' => $dismissible,
174
			);
175
		}
176
177
		/**
178
		 * Display any notices we've collected thus far (e.g. for connection, disconnection).
179
		 *
180
		 * @since 1.0.0
181
		 * @version 4.0.0
182
		 */
183
		public function admin_notices() {
184
			if ( ! current_user_can( 'manage_woocommerce' ) ) {
185
				return;
186
			}
187
188
			foreach ( (array) $this->notices as $notice_key => $notice ) {
189
				echo '<div class="' . esc_attr( $notice['class'] ) . '" style="position:relative;">';
190
191
				if ( $notice['dismissible'] ) {
192
				?>
193
					<a href="<?php echo esc_url( wp_nonce_url( add_query_arg( 'wc-stripe-hide-notice', $notice_key ), 'wc_stripe_hide_notices_nonce', '_wc_stripe_notice_nonce' ) ); ?>" class="woocommerce-message-close notice-dismiss" style="position:absolute;right:1px;padding:9px;text-decoration:none;"></a>
194
				<?php
195
				}
196
197
				echo '<p>';
198
				echo wp_kses( $notice['message'], array( 'a' => array( 'href' => array() ) ) );
199
				echo '</p></div>';
200
			}
201
		}
202
203
		/**
204
		 * Checks the environment for compatibility problems.  Returns a string with the first incompatibility
205
		 * found or false if the environment has no problems.
206
		 *
207
		 * @since 1.0.0
208
		 * @version 4.0.0
209
		 */
210
		public function get_environment_warning() {
211 View Code Duplication
			if ( version_compare( phpversion(), WC_STRIPE_MIN_PHP_VER, '<' ) ) {
0 ignored issues
show
This code seems to be duplicated across 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...
212
				/* translators: 1) int version 2) int version */
213
				$message = __( 'WooCommerce Stripe - The minimum PHP version required for this plugin is %1$s. You are running %2$s.', 'woocommerce-gateway-stripe' );
214
215
				return sprintf( $message, WC_STRIPE_MIN_PHP_VER, phpversion() );
216
			}
217
218
			if ( ! defined( 'WC_VERSION' ) ) {
219
				return __( 'WooCommerce Stripe requires WooCommerce to be activated to work.', 'woocommerce-gateway-stripe' );
220
			}
221
222 View Code Duplication
			if ( version_compare( WC_VERSION, WC_STRIPE_MIN_WC_VER, '<' ) ) {
0 ignored issues
show
This code seems to be duplicated across 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...
223
				/* translators: 1) int version 2) int version */
224
				$message = __( 'WooCommerce Stripe - The minimum WooCommerce version required for this plugin is %1$s. You are running %2$s.', 'woocommerce-gateway-stripe' );
225
226
				return sprintf( $message, WC_STRIPE_MIN_WC_VER, WC_VERSION );
227
			}
228
229
			if ( ! function_exists( 'curl_init' ) ) {
230
				return __( 'WooCommerce Stripe - cURL is not installed.', 'woocommerce-gateway-stripe' );
231
			}
232
233
			return false;
234
		}
235
236
		/**
237
		 * Get setting link.
238
		 *
239
		 * @since 1.0.0
240
		 *
241
		 * @return string Setting link
242
		 */
243
		public function get_setting_link() {
244
			$use_id_as_section = function_exists( 'WC' ) ? version_compare( WC()->version, '2.6', '>=' ) : false;
245
246
			$section_slug = $use_id_as_section ? 'stripe' : strtolower( 'WC_Gateway_Stripe' );
247
248
			return admin_url( 'admin.php?page=wc-settings&tab=checkout&section=' . $section_slug );
249
		}
250
251
		/**
252
		 * The backup sanity check, in case the plugin is activated in a weird way,
253
		 * or the environment changes after activation. Also handles upgrade routines.
254
		 *
255
		 * @since 1.0.0
256
		 * @version 4.0.0
257
		 */
258
		public function check_environment() {
259
			if ( ! defined( 'IFRAME_REQUEST' ) && ( WC_STRIPE_VERSION !== get_option( 'wc_stripe_version' ) ) ) {
260
				$this->install();
261
262
				do_action( 'woocommerce_stripe_updated' );
263
			}
264
265
			$environment_warning = $this->get_environment_warning();
266
267
			if ( $environment_warning && is_plugin_active( plugin_basename( __FILE__ ) ) ) {
268
				$this->add_admin_notice( 'bad_environment', 'error', $environment_warning );
269
			}
270
271
			$show_ssl_notice  = get_option( 'wc_stripe_show_ssl_notice' );
272
			$show_keys_notice = get_option( 'wc_stripe_show_keys_notice' );
273
			$options          = get_option( 'woocommerce_stripe_settings' );
274
275
			if ( isset( $options['enabled'] ) && 'yes' === $options['enabled'] && empty( $show_keys_notice ) ) {
276
				$secret  = WC_Stripe_API::get_secret_key();
277
278
				if ( empty( $secret ) && ! ( isset( $_GET['page'], $_GET['section'] ) && 'wc-settings' === $_GET['page'] && 'stripe' === $_GET['section'] ) ) {
279
					$setting_link = $this->get_setting_link();
280
					/* translators: 1) link */
281
					$this->add_admin_notice( 'keys', 'notice notice-warning', sprintf( __( 'Stripe is almost ready. To get started, <a href="%s">set your Stripe account keys</a>.', 'woocommerce-gateway-stripe' ), $setting_link ), true );
282
				}
283
			}
284
285
			if ( empty( $show_ssl_notice ) && isset( $options['enabled'] ) && 'yes' === $options['enabled'] ) {
286
				// Show message if enabled and FORCE SSL is disabled and WordpressHTTPS plugin is not detected.
287
				if ( ( function_exists( 'wc_site_is_https' ) && ! wc_site_is_https() ) && ( 'no' === get_option( 'woocommerce_force_ssl_checkout' ) && ! class_exists( 'WordPressHTTPS' ) ) ) {
288
					/* translators: 1) link 2) link */
289
					$this->add_admin_notice( 'ssl', 'notice notice-warning', sprintf( __( 'Stripe is enabled, but the <a href="%1$s">force SSL option</a> is disabled; your checkout may not be secure! Please enable SSL and ensure your server has a valid <a href="%2$s" target="_blank">SSL certificate</a> - Stripe will only work in test mode.', 'woocommerce-gateway-stripe' ), admin_url( 'admin.php?page=wc-settings&tab=checkout' ), 'https://en.wikipedia.org/wiki/Transport_Layer_Security' ), true );
290
				}
291
			}
292
		}
293
294
		/**
295
		 * Updates the plugin version in db
296
		 *
297
		 * @since 3.1.0
298
		 * @version 4.0.0
299
		 */
300
		public function update_plugin_version() {
301
			delete_option( 'wc_stripe_version' );
302
			update_option( 'wc_stripe_version', WC_STRIPE_VERSION );
303
		}
304
305
		/**
306
		 * Handles upgrade routines.
307
		 *
308
		 * @since 3.1.0
309
		 * @version 3.1.0
310
		 */
311
		public function install() {
312
			if ( ! defined( 'WC_STRIPE_INSTALLING' ) ) {
313
				define( 'WC_STRIPE_INSTALLING', true );
314
			}
315
316
			$this->update_plugin_version();
317
		}
318
319
		/**
320
		 * Adds plugin action links.
321
		 *
322
		 * @since 1.0.0
323
		 * @version 4.0.0
324
		 */
325
		public function plugin_action_links( $links ) {
326
			$plugin_links = array(
327
				'<a href="admin.php?page=wc-settings&tab=checkout&section=stripe">' . esc_html__( 'Settings', 'woocommerce-gateway-stripe' ) . '</a>',
328
				'<a href="https://docs.woocommerce.com/document/stripe/">' . esc_html__( 'Docs', 'woocommerce-gateway-stripe' ) . '</a>',
329
				'<a href="https://woocommerce.com/contact-us/">' . esc_html__( 'Support', 'woocommerce-gateway-stripe' ) . '</a>',
330
			);
331
			return array_merge( $plugin_links, $links );
332
		}
333
334
		/**
335
		 * Add the gateways to WooCommerce.
336
		 *
337
		 * @since 1.0.0
338
		 * @version 4.0.0
339
		 */
340
		public function add_gateways( $methods ) {
341
			if ( class_exists( 'WC_Subscriptions_Order' ) && function_exists( 'wcs_create_renewal_order' ) || class_exists( 'WC_Pre_Orders_Order' ) ) {
342
				$methods[] = 'WC_Stripe_Compat';
343
				$methods[] = 'WC_Stripe_Sepa_Compat';
344
			} else {
345
				$methods[] = 'WC_Gateway_Stripe';
346
				$methods[] = 'WC_Gateway_Stripe_Sepa';
347
			}
348
349
			$methods[] = 'WC_Gateway_Stripe_Bancontact';
350
			$methods[] = 'WC_Gateway_Stripe_Sofort';
351
			$methods[] = 'WC_Gateway_Stripe_Giropay';
352
			$methods[] = 'WC_Gateway_Stripe_Ideal';
353
			$methods[] = 'WC_Gateway_Stripe_P24';
354
			$methods[] = 'WC_Gateway_Stripe_Alipay';
355
			$methods[] = 'WC_Gateway_Stripe_Bitcoin';
356
357
			return $methods;
358
		}
359
360
		/**
361
		 * Modifies the order of the gateways displayed in admin.
362
		 *
363
		 * @since 4.0.0
364
		 * @version 4.0.0
365
		 */
366
		public function filter_gateway_order_admin( $sections ) {
367
			unset( $sections['stripe'] );
368
			unset( $sections['stripe_bancontact'] );
369
			unset( $sections['stripe_sofort'] );
370
			unset( $sections['stripe_giropay'] );
371
			unset( $sections['stripe_ideal'] );
372
			unset( $sections['stripe_p24'] );
373
			unset( $sections['stripe_alipay'] );
374
			unset( $sections['stripe_sepa'] );
375
			unset( $sections['stripe_bitcoin'] );
376
377
			$sections['stripe']            = 'Stripe';
378
			$sections['stripe_bancontact'] = __( 'Stripe Bancontact', 'woocommerce-gateway-stripe' );
379
			$sections['stripe_sofort']     = __( 'Stripe SOFORT', 'woocommerce-gateway-stripe' );
380
			$sections['stripe_giropay']    = __( 'Stripe Giropay', 'woocommerce-gateway-stripe' );
381
			$sections['stripe_ideal']      = __( 'Stripe iDeal', 'woocommerce-gateway-stripe' );
382
			$sections['stripe_p24']        = __( 'Stripe P24', 'woocommerce-gateway-stripe' );
383
			$sections['stripe_alipay']     = __( 'Stripe Alipay', 'woocommerce-gateway-stripe' );
384
			$sections['stripe_sepa']       = __( 'Stripe SEPA Direct Debit', 'woocommerce-gateway-stripe' );
385
			$sections['stripe_bitcoin']    = __( 'Stripe Bitcoin', 'woocommerce-gateway-stripe' );
386
387
			return $sections;
388
		}
389
	}
390
391
	WC_Stripe::get_instance();
392
393
endif;
394