WC_Stripe_Sepa_Subs_Compat::delete_renewal_meta()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 1
dl 0
loc 6
rs 10
c 0
b 0
f 0
1
<?php
2
if ( ! defined( 'ABSPATH' ) ) {
3
	exit;
4
}
5
6
/**
7
 * Compatibility class for Subscriptions.
8
 *
9
 * @extends WC_Gateway_Stripe_Sepa
10
 */
11
class WC_Stripe_Sepa_Subs_Compat extends WC_Gateway_Stripe_Sepa {
12
	/**
13
	 * Constructor
14
	 */
15
	public function __construct() {
16
		parent::__construct();
17
18
		if ( class_exists( 'WC_Subscriptions_Order' ) ) {
19
			add_action( 'woocommerce_scheduled_subscription_payment_' . $this->id, array( $this, 'scheduled_subscription_payment' ), 10, 2 );
20
			add_action( 'wcs_resubscribe_order_created', array( $this, 'delete_resubscribe_meta' ), 10 );
21
			add_action( 'wcs_renewal_order_created', array( $this, 'delete_renewal_meta' ), 10 );
22
			add_action( 'woocommerce_subscription_failing_payment_method_updated_stripe', array( $this, 'update_failing_payment_method' ), 10, 2 );
23
			add_action( 'wc_stripe_sepa_payment_fields', array( $this, 'display_update_subs_payment_checkout' ) );
24
			add_action( 'wc_stripe_add_payment_method_' . $this->id . '_success', array( $this, 'handle_add_payment_method_success' ), 10, 2 );
25
26
			// Display the credit card used for a subscription in the "My Subscriptions" table.
27
			add_filter( 'woocommerce_my_subscriptions_payment_method', array( $this, 'maybe_render_subscription_payment_method' ), 10, 2 );
28
29
			// Allow store managers to manually set Stripe as the payment method on a subscription.
30
			add_filter( 'woocommerce_subscription_payment_meta', array( $this, 'add_subscription_payment_meta' ), 10, 2 );
31
			add_filter( 'woocommerce_subscription_validate_payment_meta', array( $this, 'validate_subscription_payment_meta' ), 10, 2 );
32
			add_filter( 'wc_stripe_display_save_payment_method_checkbox', array( $this, 'maybe_hide_save_checkbox' ) );
33
		}
34
	}
35
36
	/**
37
	 * Checks to see if we need to hide the save checkbox field.
38
	 * Because when cart contains a subs product, it will save regardless.
39
	 *
40
	 * @since 4.0.0
41
	 * @version 4.0.0
42
	 */
43
	public function maybe_hide_save_checkbox( $display_tokenization ) {
44
		if ( WC_Subscriptions_Cart::cart_contains_subscription() ) {
45
			return false;
46
		}
47
48
		return $display_tokenization;
49
	}
50
51
	/**
52
	 * Is $order_id a subscription?
53
	 * @param  int  $order_id
54
	 * @return boolean
55
	 */
56
	public function has_subscription( $order_id ) {
57
		return ( function_exists( 'wcs_order_contains_subscription' ) && ( wcs_order_contains_subscription( $order_id ) || wcs_is_subscription( $order_id ) || wcs_order_contains_renewal( $order_id ) ) );
58
	}
59
60
	/**
61
	 * Checks if page is pay for order and change subs payment page.
62
	 *
63
	 * @since 4.1.0
64
	 * @return bool
65
	 */
66
	public function is_subs_change_payment() {
67
		return ( isset( $_GET['pay_for_order'] ) && isset( $_GET['change_payment_method'] ) );
68
	}
69
70
	/**
71
	 * Displays a checkbox to allow users to update all subs payments with new
72
	 * payment.
73
	 *
74
	 * @since 4.1.11
75
	 */
76 View Code Duplication
	public function display_update_subs_payment_checkout() {
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...
77
		$subs_statuses = apply_filters( 'wc_stripe_update_subs_payment_method_card_statuses', array( 'active' ) );
78
		if (
79
			apply_filters( 'wc_stripe_display_update_subs_payment_method_card_checkbox', true ) &&
80
			wcs_user_has_subscription( get_current_user_id(), '', $subs_statuses ) &&
81
			is_add_payment_method_page()
82
		) {
83
			$label = esc_html( apply_filters( 'wc_stripe_save_to_subs_text', __( 'Update the Payment Method used for all of my active subscriptions.', 'woocommerce-gateway-stripe' ) ) );
84
			$id    = sprintf( 'wc-%1$s-update-subs-payment-method-card', $this->id );
85
			woocommerce_form_field(
86
				$id,
87
				array(
88
					'type'    => 'checkbox',
89
					'label'   => $label,
90
					'default' => apply_filters( 'wc_stripe_save_to_subs_checked', false ),
91
				)
92
			);
93
		}
94
	}
95
96
	/**
97
	 * Updates all active subscriptions payment method.
98
	 *
99
	 * @since 4.1.11
100
	 * @param string $source_id
101
	 * @param object $source_object
102
	 */
103 View Code Duplication
	public function handle_add_payment_method_success( $source_id, $source_object ) {
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...
104
		if ( isset( $_POST[ 'wc-' . $this->id . '-update-subs-payment-method-card' ] ) ) {
105
			$all_subs        = wcs_get_users_subscriptions();
106
			$subs_statuses   = apply_filters( 'wc_stripe_update_subs_payment_method_card_statuses', array( 'active' ) );
107
			$stripe_customer = new WC_Stripe_Customer( get_current_user_id() );
108
109
			if ( ! empty( $all_subs ) ) {
110
				foreach ( $all_subs as $sub ) {
111
					if ( $sub->has_status( $subs_statuses ) ) {
112
						WC_Subscriptions_Change_Payment_Gateway::update_payment_method(
113
							$sub,
114
							$this->id,
115
							array(
116
								'post_meta' => array(
117
									'_stripe_source_id' => array( 'value' => $source_id ),
118
									'_stripe_customer_id' => array( 'value' => $stripe_customer->get_id() ),
119
								),
120
							)
121
						);
122
					}
123
				}
124
			}
125
		}
126
	}
127
128
	/**
129
	 * Updates other subscription sources.
130
	 *
131
	 * @since 3.1.0
132
	 * @version 4.0.0
133
	 */
134 View Code Duplication
	public function save_source_to_order( $order, $source ) {
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...
135
		parent::save_source_to_order( $order, $source );
136
137
		$order_id = $order->get_id();
138
139
		// Also store it on the subscriptions being purchased or paid for in the order.
140
		if ( function_exists( 'wcs_order_contains_subscription' ) && wcs_order_contains_subscription( $order_id ) ) {
141
			$subscriptions = wcs_get_subscriptions_for_order( $order_id );
142
		} elseif ( function_exists( 'wcs_order_contains_renewal' ) && wcs_order_contains_renewal( $order_id ) ) {
143
			$subscriptions = wcs_get_subscriptions_for_renewal_order( $order_id );
144
		} else {
145
			$subscriptions = array();
146
		}
147
148
		foreach ( $subscriptions as $subscription ) {
149
			$subscription_id = $subscription->get_id();
150
			update_post_meta( $subscription_id, '_stripe_customer_id', $source->customer );
151
			update_post_meta( $subscription_id, '_stripe_source_id', $source->source );
152
		}
153
	}
154
155
	/**
156
	 * Process the payment based on type.
157
	 * @param  int $order_id
158
	 * @return array
159
	 */
160 View Code Duplication
	public function process_payment( $order_id, $retry = true, $force_save_source = false, $previous_error = false ) {
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...
161
		if ( $this->has_subscription( $order_id ) ) {
162
			if ( $this->is_subs_change_payment() ) {
163
				return $this->change_subs_payment_method( $order_id );
164
			}
165
166
			// Regular payment with force customer enabled
167
			return parent::process_payment( $order_id, $retry, true, $previous_error );
168
		} else {
169
			return parent::process_payment( $order_id, $retry, $force_save_source, $previous_error );
170
		}
171
	}
172
173
	/**
174
	 * Process the payment method change for subscriptions.
175
	 *
176
	 * @since 4.0.4
177
	 * @param int $order_id
178
	 */
179
	public function change_subs_payment_method( $order_id ) {
180
		try {
181
			$subscription    = wc_get_order( $order_id );
182
			$prepared_source = $this->prepare_source( get_current_user_id(), true );
183
184 View Code Duplication
			if ( empty( $prepared_source->source ) ) {
0 ignored issues
show
Duplication introduced by
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...
185
				$localized_message = __( 'Payment processing failed. Please retry.', 'woocommerce-gateway-stripe' );
186
				throw new WC_Stripe_Exception( print_r( $prepared_source, true ), $localized_message );
187
			}
188
189
			$this->save_source_to_order( $subscription, $prepared_source );
190
191
			do_action( 'wc_stripe_change_subs_payment_method_success', $prepared_source->source, $prepared_source );
192
193
			return array(
194
				'result'   => 'success',
195
				'redirect' => $this->get_return_url( $subscription ),
196
			);
197
		} catch ( WC_Stripe_Exception $e ) {
198
			wc_add_notice( $e->getLocalizedMessage(), 'error' );
199
			WC_Stripe_Logger::log( 'Error: ' . $e->getMessage() );
200
		}
201
	}
202
203
	/**
204
	 * Scheduled_subscription_payment function.
205
	 *
206
	 * @param $amount_to_charge float The amount to charge.
207
	 * @param $renewal_order WC_Order A WC_Order object created to record the renewal payment.
208
	 */
209
	public function scheduled_subscription_payment( $amount_to_charge, $renewal_order ) {
210
		$this->process_subscription_payment( $amount_to_charge, $renewal_order, true, false );
211
	}
212
213
	/**
214
	 * Process_subscription_payment function.
215
	 *
216
	 * @since 3.0
217
	 * @since 4.0.4 Add third parameter flag to retry.
218
	 * @since 4.1.0 Add fourth parameter to log previous errors.
219
	 * @param float $amount
220
	 * @param mixed $renewal_order
221
	 * @param bool $retry Should we retry the process?
222
	 * @param object $previous_error
223
	 */
224
	public function process_subscription_payment( $amount, $renewal_order, $retry = true, $previous_error = false ) {
225
		try {
226 View Code Duplication
			if ( $amount * 100 < WC_Stripe_Helper::get_minimum_amount() ) {
0 ignored issues
show
Duplication introduced by
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...
227
				/* translators: minimum amount */
228
				$message = sprintf( __( 'Sorry, the minimum allowed order total is %1$s to use this payment method.', 'woocommerce-gateway-stripe' ), wc_price( WC_Stripe_Helper::get_minimum_amount() / 100 ) );
229
				throw new WC_Stripe_Exception(
230
					'Error while processing renewal order ' . $renewal_order->get_id() . ' : ' . $message,
231
					$message
232
				);
233
			}
234
235
			$order_id = $renewal_order->get_id();
236
237
			$this->ensure_subscription_has_customer_id( $order_id );
238
239
			// Get source from order
240
			$prepared_source = $this->prepare_order_source( $renewal_order );
241
			$source_object   = $prepared_source->source_object;
242
243 View Code Duplication
			if ( ! $prepared_source->customer ) {
0 ignored issues
show
Duplication introduced by
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...
244
				throw new WC_Stripe_Exception(
245
					'Failed to process renewal for order ' . $renewal_order->get_id() . '. Stripe customer id is missing in the order',
246
					__( 'Customer not found', 'woocommerce-gateway-stripe' )
247
				);
248
			}
249
250
			WC_Stripe_Logger::log( "Info: Begin processing subscription payment for order {$order_id} for the amount of {$amount}" );
251
252
			/* If we're doing a retry and source is chargeable, we need to pass
253
			 * a different idempotency key and retry for success.
254
			 */
255 View Code Duplication
			if ( is_object( $source_object ) && empty( $source_object->error ) && $this->need_update_idempotency_key( $source_object, $previous_error ) ) {
0 ignored issues
show
Duplication introduced by
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...
256
				add_filter( 'wc_stripe_idempotency_key', array( $this, 'change_idempotency_key' ), 10, 2 );
257
			}
258
259 View Code Duplication
			if ( ( $this->is_no_such_source_error( $previous_error ) || $this->is_no_linked_source_error( $previous_error ) ) && apply_filters( 'wc_stripe_use_default_customer_source', true ) ) {
0 ignored issues
show
Duplication introduced by
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...
260
				// Passing empty source will charge customer default.
261
				$prepared_source->source = '';
262
			}
263
264
			$request            = $this->generate_payment_request( $renewal_order, $prepared_source );
265
			$request['capture'] = 'true';
266
			$request['amount']  = WC_Stripe_Helper::get_stripe_amount( $amount, $request['currency'] );
267
			$response           = WC_Stripe_API::request( $request );
268
269 View Code Duplication
			if ( ! empty( $response->error ) ) {
0 ignored issues
show
Duplication introduced by
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...
270
				// We want to retry.
271
				if ( $this->is_retryable_error( $response->error ) ) {
272
					if ( $retry ) {
273
						// Don't do anymore retries after this.
274
						if ( 5 <= $this->retry_interval ) {
275
							return $this->process_subscription_payment( $amount, $renewal_order, false, $response->error );
276
						}
277
278
						sleep( $this->retry_interval );
279
280
						$this->retry_interval++;
281
282
						return $this->process_subscription_payment( $amount, $renewal_order, true, $response->error );
283
					} else {
284
						$localized_message = __( 'Sorry, we are unable to process your payment at this time. Please retry later.', 'woocommerce-gateway-stripe' );
285
						$renewal_order->add_order_note( $localized_message );
286
						throw new WC_Stripe_Exception( print_r( $response, true ), $localized_message );
287
					}
288
				}
289
290
				$localized_messages = WC_Stripe_Helper::get_localized_messages();
291
292
				if ( 'card_error' === $response->error->type ) {
293
					$localized_message = isset( $localized_messages[ $response->error->code ] ) ? $localized_messages[ $response->error->code ] : $response->error->message;
294
				} else {
295
					$localized_message = isset( $localized_messages[ $response->error->type ] ) ? $localized_messages[ $response->error->type ] : $response->error->message;
296
				}
297
298
				$renewal_order->add_order_note( $localized_message );
299
300
				throw new WC_Stripe_Exception( print_r( $response, true ), $localized_message );
301
			}
302
303
			do_action( 'wc_gateway_stripe_process_payment', $response, $renewal_order );
304
305
			$this->process_response( $response, $renewal_order );
306
		} catch ( WC_Stripe_Exception $e ) {
307
			WC_Stripe_Logger::log( 'Error: ' . $e->getMessage() );
308
309
			do_action( 'wc_gateway_stripe_process_payment_error', $e, $renewal_order );
310
311
			/* translators: error message */
312
			$renewal_order->update_status( 'failed' );
313
		}
314
	}
315
316
	/**
317
	 * Don't transfer Stripe customer/token meta to resubscribe orders.
318
	 * @param int $resubscribe_order The order created for the customer to resubscribe to the old expired/cancelled subscription
319
	 */
320 View Code Duplication
	public function delete_resubscribe_meta( $resubscribe_order ) {
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...
321
		delete_post_meta( $resubscribe_order->get_id(), '_stripe_customer_id' );
0 ignored issues
show
Bug introduced by
The method get_id cannot be called on $resubscribe_order (of type integer).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
322
		delete_post_meta( $resubscribe_order->get_id(), '_stripe_source_id' );
0 ignored issues
show
Bug introduced by
The method get_id cannot be called on $resubscribe_order (of type integer).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
323
		// For BW compat will remove in future
324
		delete_post_meta( $resubscribe_order->get_id(), '_stripe_card_id' );
0 ignored issues
show
Bug introduced by
The method get_id cannot be called on $resubscribe_order (of type integer).

Methods can only be called on objects. This check looks for methods being called on variables that have been inferred to never be objects.

Loading history...
325
		$this->delete_renewal_meta( $resubscribe_order );
326
	}
327
328
	/**
329
	 * Don't transfer Stripe fee/ID meta to renewal orders.
330
	 * @param int $resubscribe_order The order created for the customer to resubscribe to the old expired/cancelled subscription
0 ignored issues
show
Bug introduced by
There is no parameter named $resubscribe_order. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
331
	 */
332
	public function delete_renewal_meta( $renewal_order ) {
333
		WC_Stripe_Helper::delete_stripe_fee( $renewal_order );
334
		WC_Stripe_Helper::delete_stripe_net( $renewal_order );
335
336
		return $renewal_order;
337
	}
338
339
	/**
340
	 * Update the customer_id for a subscription after using Stripe to complete a payment to make up for
341
	 * an automatic renewal payment which previously failed.
342
	 *
343
	 * @access public
344
	 * @param WC_Subscription $subscription The subscription for which the failing payment method relates.
345
	 * @param WC_Order $renewal_order The order which recorded the successful payment (to make up for the failed automatic payment).
346
	 * @return void
347
	 */
348
	public function update_failing_payment_method( $subscription, $renewal_order ) {
349
		update_post_meta( $subscription->get_id(), '_stripe_customer_id', $renewal_order->get_meta( '_stripe_customer_id', true ) );
350
		update_post_meta( $subscription->get_id(), '_stripe_source_id', $renewal_order->get_meta( '_stripe_source_id', true ) );
351
	}
352
353
	/**
354
	 * Include the payment meta data required to process automatic recurring payments so that store managers can
355
	 * manually set up automatic recurring payments for a customer via the Edit Subscriptions screen in 2.0+.
356
	 *
357
	 * @since 2.5
358
	 * @param array $payment_meta associative array of meta data required for automatic payments
359
	 * @param WC_Subscription $subscription An instance of a subscription object
360
	 * @return array
361
	 */
362
	public function add_subscription_payment_meta( $payment_meta, $subscription ) {
363
		$source_id = get_post_meta( $subscription->get_id(), '_stripe_source_id', true );
364
365
		// For BW compat will remove in future.
366
		if ( empty( $source_id ) ) {
367
			$source_id = get_post_meta( $subscription->get_id(), '_stripe_card_id', true );
368
369
			// Take this opportunity to update the key name.
370
			update_post_meta( $subscription->get_id(), '_stripe_source_id', $source_id );
371
		}
372
373
		$payment_meta[ $this->id ] = array(
374
			'post_meta' => array(
375
				'_stripe_customer_id' => array(
376
					'value' => get_post_meta( $subscription->get_id(), '_stripe_customer_id', true ),
377
					'label' => 'Stripe Customer ID',
378
				),
379
				'_stripe_source_id'   => array(
380
					'value' => $source_id,
381
					'label' => 'Stripe Source ID',
382
				),
383
			),
384
		);
385
		return $payment_meta;
386
	}
387
388
	/**
389
	 * Validate the payment meta data required to process automatic recurring payments so that store managers can
390
	 * manually set up automatic recurring payments for a customer via the Edit Subscriptions screen in 2.0+.
391
	 *
392
	 * @since 2.5
393
	 * @param string $payment_method_id The ID of the payment method to validate
394
	 * @param array $payment_meta associative array of meta data required for automatic payments
395
	 * @return array
396
	 */
397 View Code Duplication
	public function validate_subscription_payment_meta( $payment_method_id, $payment_meta ) {
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...
398
		if ( $this->id === $payment_method_id ) {
399
400
			if ( ! isset( $payment_meta['post_meta']['_stripe_customer_id']['value'] ) || empty( $payment_meta['post_meta']['_stripe_customer_id']['value'] ) ) {
401
402
				// Allow empty stripe customer id during subscription renewal. It will be added when processing payment if required.
403
				if ( ! isset( $_POST['wc_order_action'] ) || 'wcs_process_renewal' !== $_POST['wc_order_action'] ) {
404
					throw new Exception( __( 'A "Stripe Customer ID" value is required.', 'woocommerce-gateway-stripe' ) );
405
				}
406
			} elseif ( 0 !== strpos( $payment_meta['post_meta']['_stripe_customer_id']['value'], 'cus_' ) ) {
407
				throw new Exception( __( 'Invalid customer ID. A valid "Stripe Customer ID" must begin with "cus_".', 'woocommerce-gateway-stripe' ) );
408
			}
409
410
			if (
411
				( ! empty( $payment_meta['post_meta']['_stripe_source_id']['value'] )
412
				&& 0 !== strpos( $payment_meta['post_meta']['_stripe_source_id']['value'], 'card_' ) )
413
				&& ( ! empty( $payment_meta['post_meta']['_stripe_source_id']['value'] )
414
				&& 0 !== strpos( $payment_meta['post_meta']['_stripe_source_id']['value'], 'src_' ) ) ) {
415
416
				throw new Exception( __( 'Invalid source ID. A valid source "Stripe Source ID" must begin with "src_" or "card_".', 'woocommerce-gateway-stripe' ) );
417
			}
418
		}
419
	}
420
421
	/**
422
	 * Render the payment method used for a subscription in the "My Subscriptions" table
423
	 *
424
	 * @since 1.7.5
425
	 * @param string $payment_method_to_display the default payment method text to display
426
	 * @param WC_Subscription $subscription the subscription details
427
	 * @return string the subscription payment method
428
	 */
429
	public function maybe_render_subscription_payment_method( $payment_method_to_display, $subscription ) {
430
		$customer_user = $subscription->get_customer_id();
431
432
		// bail for other payment methods
433
		if ( $subscription->get_payment_method() !== $this->id || ! $customer_user ) {
434
			return $payment_method_to_display;
435
		}
436
437
		$stripe_source_id = get_post_meta( $subscription->get_id(), '_stripe_source_id', true );
438
439
		// For BW compat will remove in future.
440
		if ( empty( $stripe_source_id ) ) {
441
			$stripe_source_id = get_post_meta( $subscription->get_id(), '_stripe_card_id', true );
442
443
			// Take this opportunity to update the key name.
444
			update_post_meta( $subscription->get_id(), '_stripe_source_id', $stripe_source_id );
445
		}
446
447
		$stripe_customer    = new WC_Stripe_Customer();
448
		$stripe_customer_id = get_post_meta( $subscription->get_id(), '_stripe_customer_id', true );
449
450
		// If we couldn't find a Stripe customer linked to the subscription, fallback to the user meta data.
451 View Code Duplication
		if ( ! $stripe_customer_id || ! is_string( $stripe_customer_id ) ) {
0 ignored issues
show
Duplication introduced by
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...
452
			$user_id            = $customer_user;
453
			$stripe_customer_id = get_user_option( '_stripe_customer_id', $user_id );
454
			$stripe_source_id   = get_user_option( '_stripe_source_id', $user_id );
455
456
			// For BW compat will remove in future.
457
			if ( empty( $stripe_source_id ) ) {
458
				$stripe_source_id = get_user_option( '_stripe_card_id', $user_id );
459
460
				// Take this opportunity to update the key name.
461
				update_user_option( $user_id, '_stripe_source_id', $stripe_source_id, false );
462
			}
463
		}
464
465
		// If we couldn't find a Stripe customer linked to the account, fallback to the order meta data.
466 View Code Duplication
		if ( ( ! $stripe_customer_id || ! is_string( $stripe_customer_id ) ) && false !== $subscription->order ) {
0 ignored issues
show
Duplication introduced by
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...
467
			$stripe_customer_id = get_post_meta( $subscription->get_parent_id(), '_stripe_customer_id', true );
468
			$stripe_source_id   = get_post_meta( $subscription->get_parent_id(), '_stripe_source_id', true );
469
470
			// For BW compat will remove in future.
471
			if ( empty( $stripe_source_id ) ) {
472
				$stripe_source_id = get_post_meta( $subscription->get_parent_id(), '_stripe_card_id', true );
473
474
				// Take this opportunity to update the key name.
475
				update_post_meta( $subscription->get_parent_id(), '_stripe_source_id', $stripe_source_id );
476
			}
477
		}
478
479
		$stripe_customer->set_id( $stripe_customer_id );
480
481
		$sources                   = $stripe_customer->get_sources();
482
		$payment_method_to_display = __( 'N/A', 'woocommerce-gateway-stripe' );
483
484
		if ( $sources ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $sources 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...
485
			foreach ( $sources as $source ) {
486
				if ( $source->id === $stripe_source_id ) {
487
					if ( $source->sepa_debit ) {
488
						/* translators: 1) last 4 digits of SEPA Direct Debit */
489
						$payment_method_to_display = sprintf( __( 'Via SEPA Direct Debit ending in %1$s', 'woocommerce-gateway-stripe' ), $source->sepa_debit->last4 );
490
					}
491
492
					break;
493
				}
494
			}
495
		}
496
497
		return $payment_method_to_display;
498
	}
499
}
500