Completed
Push — master ( bf7249...8ab9d7 )
by Matty
02:35
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.0
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.0' );
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
			add_filter( 'woocommerce_payment_gateways', array( $this, 'add_gateways' ) );
127
			add_filter( 'plugin_action_links_' . plugin_basename( __FILE__ ), array( $this, 'plugin_action_links' ) );
128
			add_filter( 'woocommerce_get_sections_checkout', array( $this, 'filter_gateway_order_admin' ) );
129
		}
130
131
		/**
132
		 * Hides any admin notices.
133
		 *
134
		 * @since 4.0.0
135
		 * @version 4.0.0
136
		 */
137
		public function hide_notices() {
138
			if ( isset( $_GET['wc-stripe-hide-notice'] ) && isset( $_GET['_wc_stripe_notice_nonce'] ) ) {
139
				if ( ! wp_verify_nonce( $_GET['_wc_stripe_notice_nonce'], 'wc_stripe_hide_notices_nonce' ) ) {
140
					wp_die( __( 'Action failed. Please refresh the page and retry.', 'woocommerce-gateway-stripe' ) );
141
				}
142
143
				if ( ! current_user_can( 'manage_woocommerce' ) ) {
144
					wp_die( __( 'Cheatin&#8217; huh?', 'woocommerce-gateway-stripe' ) );
145
				}
146
147
				$notice = wc_clean( $_GET['wc-stripe-hide-notice'] );
148
149
				switch ( $notice ) {
150
					case 'ssl':
151
						update_option( 'wc_stripe_show_ssl_notice', 'no' );
152
						break;
153
					case 'keys':
154
						update_option( 'wc_stripe_show_keys_notice', 'no' );
155
						break;
156
				}
157
			}
158
		}
159
160
		/**
161
		 * Allow this class and other classes to add slug keyed notices (to avoid duplication).
162
		 *
163
		 * @since 1.0.0
164
		 * @version 4.0.0
165
		 */
166
		public function add_admin_notice( $slug, $class, $message, $dismissible = false ) {
167
			$this->notices[ $slug ] = array(
168
				'class'       => $class,
169
				'message'     => $message,
170
				'dismissible' => $dismissible,
171
			);
172
		}
173
174
		/**
175
		 * Display any notices we've collected thus far (e.g. for connection, disconnection).
176
		 *
177
		 * @since 1.0.0
178
		 * @version 4.0.0
179
		 */
180
		public function admin_notices() {
181
			if ( ! current_user_can( 'manage_woocommerce' ) ) {
182
				return;
183
			}
184
185
			foreach ( (array) $this->notices as $notice_key => $notice ) {
186
				echo '<div class="' . esc_attr( $notice['class'] ) . '" style="position:relative;">';
187
188
				if ( $notice['dismissible'] ) {
189
				?>
190
					<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>
191
				<?php
192
				}
193
194
				echo '<p>';
195
				echo wp_kses( $notice['message'], array( 'a' => array( 'href' => array() ) ) );
196
				echo '</p></div>';
197
			}
198
		}
199
200
		/**
201
		 * Checks the environment for compatibility problems.  Returns a string with the first incompatibility
202
		 * found or false if the environment has no problems.
203
		 *
204
		 * @since 1.0.0
205
		 * @version 4.0.0
206
		 */
207
		public function get_environment_warning() {
208 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...
209
				/* translators: 1) int version 2) int version */
210
				$message = __( 'WooCommerce Stripe - The minimum PHP version required for this plugin is %1$s. You are running %2$s.', 'woocommerce-gateway-stripe' );
211
212
				return sprintf( $message, WC_STRIPE_MIN_PHP_VER, phpversion() );
213
			}
214
215
			if ( ! defined( 'WC_VERSION' ) ) {
216
				return __( 'WooCommerce Stripe requires WooCommerce to be activated to work.', 'woocommerce-gateway-stripe' );
217
			}
218
219 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...
220
				/* translators: 1) int version 2) int version */
221
				$message = __( 'WooCommerce Stripe - The minimum WooCommerce version required for this plugin is %1$s. You are running %2$s.', 'woocommerce-gateway-stripe' );
222
223
				return sprintf( $message, WC_STRIPE_MIN_WC_VER, WC_VERSION );
224
			}
225
226
			if ( ! function_exists( 'curl_init' ) ) {
227
				return __( 'WooCommerce Stripe - cURL is not installed.', 'woocommerce-gateway-stripe' );
228
			}
229
230
			return false;
231
		}
232
233
		/**
234
		 * Get setting link.
235
		 *
236
		 * @since 1.0.0
237
		 *
238
		 * @return string Setting link
239
		 */
240
		public function get_setting_link() {
241
			$use_id_as_section = function_exists( 'WC' ) ? version_compare( WC()->version, '2.6', '>=' ) : false;
242
243
			$section_slug = $use_id_as_section ? 'stripe' : strtolower( 'WC_Gateway_Stripe' );
244
245
			return admin_url( 'admin.php?page=wc-settings&tab=checkout&section=' . $section_slug );
246
		}
247
248
		/**
249
		 * The backup sanity check, in case the plugin is activated in a weird way,
250
		 * or the environment changes after activation. Also handles upgrade routines.
251
		 *
252
		 * @since 1.0.0
253
		 * @version 4.0.0
254
		 */
255
		public function check_environment() {
256
			if ( ! defined( 'IFRAME_REQUEST' ) && ( WC_STRIPE_VERSION !== get_option( 'wc_stripe_version' ) ) ) {
257
				$this->install();
258
259
				do_action( 'woocommerce_stripe_updated' );
260
			}
261
262
			$environment_warning = $this->get_environment_warning();
263
264
			if ( $environment_warning && is_plugin_active( plugin_basename( __FILE__ ) ) ) {
265
				$this->add_admin_notice( 'bad_environment', 'error', $environment_warning );
266
			}
267
268
			$show_ssl_notice  = get_option( 'wc_stripe_show_ssl_notice' );
269
			$show_keys_notice = get_option( 'wc_stripe_show_keys_notice' );
270
			$options          = get_option( 'woocommerce_stripe_settings' );
271
272
			if ( isset( $options['enabled'] ) && 'yes' === $options['enabled'] && empty( $show_keys_notice ) ) {
273
				$secret  = WC_Stripe_API::get_secret_key();
274
275
				if ( empty( $secret ) && ! ( isset( $_GET['page'], $_GET['section'] ) && 'wc-settings' === $_GET['page'] && 'stripe' === $_GET['section'] ) ) {
276
					$setting_link = $this->get_setting_link();
277
					/* translators: 1) link */
278
					$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 );
279
				}
280
			}
281
282
			if ( empty( $show_ssl_notice ) && isset( $options['enabled'] ) && 'yes' === $options['enabled'] ) {
283
				// Show message if enabled and FORCE SSL is disabled and WordpressHTTPS plugin is not detected.
284
				if ( ( function_exists( 'wc_site_is_https' ) && ! wc_site_is_https() ) && ( 'no' === get_option( 'woocommerce_force_ssl_checkout' ) && ! class_exists( 'WordPressHTTPS' ) ) ) {
285
					/* translators: 1) link 2) link */
286
					$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 );
287
				}
288
			}
289
		}
290
291
		/**
292
		 * Updates the plugin version in db
293
		 *
294
		 * @since 3.1.0
295
		 * @version 4.0.0
296
		 */
297
		public function update_plugin_version() {
298
			delete_option( 'wc_stripe_version' );
299
			update_option( 'wc_stripe_version', WC_STRIPE_VERSION );
300
		}
301
302
		/**
303
		 * Handles upgrade routines.
304
		 *
305
		 * @since 3.1.0
306
		 * @version 3.1.0
307
		 */
308
		public function install() {
309
			if ( ! defined( 'WC_STRIPE_INSTALLING' ) ) {
310
				define( 'WC_STRIPE_INSTALLING', true );
311
			}
312
313
			$this->update_plugin_version();
314
		}
315
316
		/**
317
		 * Adds plugin action links.
318
		 *
319
		 * @since 1.0.0
320
		 * @version 4.0.0
321
		 */
322
		public function plugin_action_links( $links ) {
323
			$plugin_links = array(
324
				'<a href="admin.php?page=wc-settings&tab=checkout&section=stripe">' . esc_html__( 'Settings', 'woocommerce-gateway-stripe' ) . '</a>',
325
				'<a href="https://docs.woocommerce.com/document/stripe/">' . esc_html__( 'Docs', 'woocommerce-gateway-stripe' ) . '</a>',
326
				'<a href="https://woocommerce.com/contact-us/">' . esc_html__( 'Support', 'woocommerce-gateway-stripe' ) . '</a>',
327
			);
328
			return array_merge( $plugin_links, $links );
329
		}
330
331
		/**
332
		 * Add the gateways to WooCommerce.
333
		 *
334
		 * @since 1.0.0
335
		 * @version 4.0.0
336
		 */
337
		public function add_gateways( $methods ) {
338
			if ( class_exists( 'WC_Subscriptions_Order' ) && function_exists( 'wcs_create_renewal_order' ) || class_exists( 'WC_Pre_Orders_Order' ) ) {
339
				$methods[] = 'WC_Stripe_Compat';
340
				$methods[] = 'WC_Stripe_Sepa_Compat';
341
			} else {
342
				$methods[] = 'WC_Gateway_Stripe';
343
				$methods[] = 'WC_Gateway_Stripe_Sepa';
344
			}
345
346
			$methods[] = 'WC_Gateway_Stripe_Bancontact';
347
			$methods[] = 'WC_Gateway_Stripe_Sofort';
348
			$methods[] = 'WC_Gateway_Stripe_Giropay';
349
			$methods[] = 'WC_Gateway_Stripe_Ideal';
350
			$methods[] = 'WC_Gateway_Stripe_P24';
351
			$methods[] = 'WC_Gateway_Stripe_Alipay';
352
			$methods[] = 'WC_Gateway_Stripe_Bitcoin';
353
354
			return $methods;
355
		}
356
357
		/**
358
		 * Modifies the order of the gateways displayed in admin.
359
		 *
360
		 * @since 4.0.0
361
		 * @version 4.0.0
362
		 */
363
		public function filter_gateway_order_admin( $sections ) {
364
			unset( $sections['stripe'] );
365
			unset( $sections['stripe_bancontact'] );
366
			unset( $sections['stripe_sofort'] );
367
			unset( $sections['stripe_giropay'] );
368
			unset( $sections['stripe_ideal'] );
369
			unset( $sections['stripe_p24'] );
370
			unset( $sections['stripe_alipay'] );
371
			unset( $sections['stripe_sepa'] );
372
			unset( $sections['stripe_bitcoin'] );
373
374
			$sections['stripe']            = 'Stripe';
375
			$sections['stripe_bancontact'] = __( 'Stripe Bancontact', 'woocommerce-gateway-stripe' );
376
			$sections['stripe_sofort']     = __( 'Stripe SOFORT', 'woocommerce-gateway-stripe' );
377
			$sections['stripe_giropay']    = __( 'Stripe Giropay', 'woocommerce-gateway-stripe' );
378
			$sections['stripe_ideal']      = __( 'Stripe iDeal', 'woocommerce-gateway-stripe' );
379
			$sections['stripe_p24']        = __( 'Stripe P24', 'woocommerce-gateway-stripe' );
380
			$sections['stripe_alipay']     = __( 'Stripe Alipay', 'woocommerce-gateway-stripe' );
381
			$sections['stripe_sepa']       = __( 'Stripe SEPA Direct Debit', 'woocommerce-gateway-stripe' );
382
			$sections['stripe_bitcoin']    = __( 'Stripe Bitcoin', 'woocommerce-gateway-stripe' );
383
384
			return $sections;
385
		}
386
	}
387
388
	WC_Stripe::get_instance();
389
390
endif;
391