Failed Conditions
Push — master ( a58383...417a33 )
by Reüel
10:40 queued 04:17
created

Gateway::get_available_payment_methods()   B

Complexity

Conditions 11
Paths 35

Size

Total Lines 66
Code Lines 34

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 21
CRAP Score 16.8164

Importance

Changes 6
Bugs 0 Features 0
Metric Value
cc 11
eloc 34
c 6
b 0
f 0
nc 35
nop 0
dl 0
loc 66
ccs 21
cts 33
cp 0.6364
crap 16.8164
rs 7.3166

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
 * Mollie gateway.
4
 *
5
 * @author    Pronamic <[email protected]>
6
 * @copyright 2005-2020 Pronamic
7
 * @license   GPL-3.0-or-later
8
 * @package   Pronamic\WordPress\Pay
9
 */
10
11
namespace Pronamic\WordPress\Pay\Gateways\Mollie;
12
13
use Pronamic\WordPress\DateTime\DateTime;
14
use Pronamic\WordPress\Pay\Banks\BankAccountDetails;
15
use Pronamic\WordPress\Pay\Banks\BankTransferDetails;
16
use Pronamic\WordPress\Pay\Core\Gateway as Core_Gateway;
17
use Pronamic\WordPress\Pay\Core\PaymentMethods;
18
use Pronamic\WordPress\Pay\Payments\FailureReason;
19
use Pronamic\WordPress\Pay\Payments\Payment;
20
use Pronamic\WordPress\Pay\Subscriptions\Subscription;
21
22
/**
23
 * Title: Mollie
24
 * Description:
25
 * Copyright: 2005-2020 Pronamic
26
 * Company: Pronamic
27
 *
28
 * @author  Remco Tolsma
29
 * @version 2.1.3
30
 * @since   1.1.0
31
 */
32
class Gateway extends Core_Gateway {
33
	/**
34
	 * Client.
35
	 *
36
	 * @var Client
37
	 */
38
	protected $client;
39
40
	/**
41
	 * Profile data store.
42
	 *
43
	 * @var ProfileDataStore
44
	 */
45
	private $profile_data_store;
46
47
	/**
48
	 * Customer data store.
49
	 *
50
	 * @var CustomerDataStore
51
	 */
52
	private $customer_data_store;
53
54
	/**
55
	 * Constructs and initializes an Mollie gateway
56
	 *
57
	 * @param Config $config Config.
58
	 */
59 39
	public function __construct( Config $config ) {
60 39
		parent::__construct( $config );
61
62 39
		$this->set_method( self::METHOD_HTTP_REDIRECT );
63
64
		// Supported features.
65 39
		$this->supports = array(
66
			'payment_status_request',
67
			'recurring_direct_debit',
68
			'recurring_credit_card',
69
			'recurring',
70
			'webhook',
71
			'webhook_log',
72
			'webhook_no_config',
73
		);
74
75
		// Client.
76 39
		$this->client = new Client( \strval( $config->api_key ) );
77
78
		// Data Stores.
79 39
		$this->profile_data_store  = new ProfileDataStore();
80 39
		$this->customer_data_store = new CustomerDataStore();
81
82
		// Actions.
83 39
		add_action( 'pronamic_payment_status_update', array( $this, 'copy_customer_id_to_wp_user' ), 99, 1 );
84 39
	}
85
86
	/**
87
	 * Get issuers
88
	 *
89
	 * @see Core_Gateway::get_issuers()
90
	 * @return array<int, array<string, array<string>>>
91
	 */
92 3
	public function get_issuers() {
93 3
		$groups = array();
94
95
		try {
96 3
			$result = $this->client->get_issuers();
97
98
			$groups[] = array(
99
				'options' => $result,
100
			);
101 3
		} catch ( Error $e ) {
102
			// Catch Mollie error.
103 3
			$error = new \WP_Error(
104 3
				'mollie_error',
105 3
				sprintf( '%1$s (%2$s) - %3$s', $e->get_title(), $e->getCode(), $e->get_detail() )
106
			);
107
108 3
			$this->set_error( $error );
109
		} catch ( \Exception $e ) {
110
			// Catch exceptions.
111
			$error = new \WP_Error( 'mollie_error', $e->getMessage() );
112
113
			$this->set_error( $error );
114
		}
115
116 3
		return $groups;
117
	}
118
119
	/**
120
	 * Get available payment methods.
121
	 *
122
	 * @see Core_Gateway::get_available_payment_methods()
123
	 * @return array<string>
124
	 */
125 2
	public function get_available_payment_methods() {
126 2
		$payment_methods = array();
127
128
		// Set sequence types to get payment methods for.
129 2
		$sequence_types = array( Sequence::ONE_OFF, Sequence::RECURRING, Sequence::FIRST );
130
131 2
		$results = array();
132
133 2
		foreach ( $sequence_types as $sequence_type ) {
134
			// Get active payment methods for Mollie account.
135
			try {
136 2
				$result = $this->client->get_payment_methods( $sequence_type );
137 2
			} catch ( Error $e ) {
138
				// Catch Mollie error.
139
				$error = new \WP_Error(
140
					'mollie_error',
141
					sprintf( '%1$s (%2$s) - %3$s', $e->get_title(), $e->getCode(), $e->get_detail() )
142
				);
143
144
				$this->set_error( $error );
145
146
				break;
147 2
			} catch ( \Exception $e ) {
148
				// Catch exceptions.
149 2
				$error = new \WP_Error( 'mollie_error', $e->getMessage() );
150
151 2
				$this->set_error( $error );
152
153 2
				break;
154
			}
155
156 2
			if ( Sequence::FIRST === $sequence_type ) {
157
				foreach ( $result as $method => $title ) {
158
					unset( $result[ $method ] );
159
160
					// Get WordPress payment method for direct debit method.
161
					$method         = Methods::transform_gateway_method( $method );
162
					$payment_method = array_search( $method, PaymentMethods::get_recurring_methods(), true );
163
164
					if ( $payment_method ) {
165
						$results[ $payment_method ] = $title;
166
					}
167
				}
168
			}
169
170 2
			if ( is_array( $result ) ) {
171 2
				$results = array_merge( $results, $result );
172
			}
173
		}
174
175
		// Transform to WordPress payment methods.
176 2
		foreach ( $results as $method => $title ) {
177 2
			if ( PaymentMethods::is_recurring_method( $method ) ) {
178
				$payment_method = $method;
179
			} else {
180 2
				$payment_method = Methods::transform_gateway_method( $method );
181
			}
182
183 2
			if ( $payment_method ) {
184 2
				$payment_methods[] = $payment_method;
185
			}
186
		}
187
188 2
		$payment_methods = array_unique( $payment_methods );
189
190 2
		return $payment_methods;
191
	}
192
193
	/**
194
	 * Get supported payment methods
195
	 *
196
	 * @see Pronamic_WP_Pay_Gateway::get_supported_payment_methods()
197
	 * @return array<string>
198
	 */
199 2
	public function get_supported_payment_methods() {
200
		return array(
201 2
			PaymentMethods::APPLE_PAY,
202
			PaymentMethods::BANCONTACT,
203
			PaymentMethods::BANK_TRANSFER,
204
			PaymentMethods::BELFIUS,
205
			PaymentMethods::CREDIT_CARD,
206
			PaymentMethods::DIRECT_DEBIT,
207
			PaymentMethods::DIRECT_DEBIT_BANCONTACT,
208
			PaymentMethods::DIRECT_DEBIT_IDEAL,
209
			PaymentMethods::DIRECT_DEBIT_SOFORT,
210
			PaymentMethods::EPS,
211
			PaymentMethods::GIROPAY,
212
			PaymentMethods::IDEAL,
213
			PaymentMethods::KBC,
214
			PaymentMethods::PAYPAL,
215
			PaymentMethods::SOFORT,
216
		);
217
	}
218
219
	/**
220
	 * Get webhook URL for Mollie.
221
	 *
222
	 * @return string|null
223
	 */
224 4
	public function get_webhook_url() {
225 4
		$url = \rest_url( Integration::REST_ROUTE_NAMESPACE . '/webhook' );
226
227 4
		$host = wp_parse_url( $url, PHP_URL_HOST );
228
229 4
		if ( is_array( $host ) ) {
230
			// Parsing failure.
231
			$host = '';
232
		}
233
234 4
		if ( 'localhost' === $host ) {
235
			// Mollie doesn't allow localhost.
236 1
			return null;
237 3
		} elseif ( '.dev' === substr( $host, -4 ) ) {
238
			// Mollie doesn't allow the .dev TLD.
239 1
			return null;
240 2
		} elseif ( '.local' === substr( $host, -6 ) ) {
241
			// Mollie doesn't allow the .local TLD.
242 1
			return null;
243 1
		} elseif ( '.test' === substr( $host, -5 ) ) {
244
			// Mollie doesn't allow the .test TLD.
245
			return null;
246
		}
247
248 1
		return $url;
249
	}
250
251
	/**
252
	 * Start
253
	 *
254
	 * @see Pronamic_WP_Pay_Gateway::start()
255
	 * @param Payment $payment Payment.
256
	 * @return void
257
	 */
258
	public function start( Payment $payment ) {
259
		$request = new PaymentRequest(
260
			AmountTransformer::transform( $payment->get_total_amount() ),
261
			\strval( $payment->get_description() )
262
		);
263
264
		$request->redirect_url = $payment->get_return_url();
265
		$request->webhook_url  = $this->get_webhook_url();
266
267
		// Locale.
268
		$customer = $payment->get_customer();
269
270
		if ( null !== $customer ) {
271
			$request->locale = LocaleHelper::transform( $customer->get_locale() );
272
		}
273
274
		// Customer ID.
275
		$customer_id = $this->get_customer_id_for_payment( $payment );
276
277
		if ( null === $customer_id ) {
278
			$customer_id = $this->create_customer_for_payment( $payment );
279
		}
280
281
		if ( null !== $customer_id ) {
282
			$request->customer_id = $customer_id;
283
		}
284
285
		// Payment method.
286
		$payment_method = $payment->get_method();
287
288
		// Recurring payment method.
289
		$is_recurring_method = ( $payment->get_subscription() && PaymentMethods::is_recurring_method( $payment_method ) );
290
291
		// Consumer bank details.
292
		$consumer_bank_details = $payment->get_consumer_bank_details();
293
294
		if ( PaymentMethods::DIRECT_DEBIT === $payment_method && null !== $consumer_bank_details ) {
295
			$consumer_name = $consumer_bank_details->get_name();
296
			$consumer_iban = $consumer_bank_details->get_iban();
297
298
			$request->consumer_name    = $consumer_name;
299
			$request->consumer_account = $consumer_iban;
300
301
			// Check if one-off SEPA Direct Debit can be used, otherwise short circuit payment.
302
			if ( null !== $customer_id ) {
303
				// Find or create mandate.
304
				$mandate_id = $this->client->has_valid_mandate( $customer_id, PaymentMethods::DIRECT_DEBIT, $consumer_iban );
305
306
				if ( false === $mandate_id ) {
307
					$mandate = $this->client->create_mandate( $customer_id, $consumer_bank_details );
308
309
					$mandate_id = $mandate->id;
310
				}
311
312
				// Charge immediately on-demand.
313
				$request->sequence_type = Sequence::RECURRING;
314
				$request->mandate_id    = $mandate_id;
315
316
				$is_recurring_method = true;
317
318
				$payment->recurring = true;
319
			}
320
		}
321
322
		if ( false === $is_recurring_method ) {
323
			// Always use 'direct debit mandate via iDEAL/Bancontact/Sofort' payment methods as recurring method.
324
			$is_recurring_method = PaymentMethods::is_direct_debit_method( $payment_method );
325
		}
326
327
		if ( $is_recurring_method ) {
328
			$request->sequence_type = $payment->get_recurring() ? Sequence::RECURRING : Sequence::FIRST;
329
330
			if ( Sequence::FIRST === $request->sequence_type ) {
331
				$payment_method = PaymentMethods::get_first_payment_method( $payment_method );
332
			}
333
334
			if ( Sequence::RECURRING === $request->sequence_type ) {
335
				$payment->set_action_url( $payment->get_return_url() );
336
			}
337
		}
338
339
		// Leap of faith if the WordPress payment method could not transform to a Mollie method?
340
		$request->method = Methods::transform( $payment_method, $payment_method );
341
342
		// Issuer.
343
		if ( Methods::IDEAL === $request->method ) {
344
			$request->issuer = $payment->get_issuer();
345
		}
346
347
		// Billing email.
348
		$billing_email = $payment->get_email();
349
350
		/**
351
		 * Filters the Mollie payment billing email used for bank transfer payment instructions.
352
		 *
353
		 * @since 2.2.0
354
		 *
355
		 * @param string|null $billing_email Billing email.
356
		 * @param Payment     $payment       Payment.
357
		 */
358
		$billing_email = \apply_filters( 'pronamic_pay_mollie_payment_billing_email', $billing_email, $payment );
359
360
		$request->set_billing_email( $billing_email );
361
362
		// Due date.
363
		try {
364
			$due_date = new DateTime( sprintf( '+%s days', $this->config->due_date_days ) );
365
		} catch ( \Exception $e ) {
366
			$due_date = null;
367
		}
368
369
		$request->set_due_date( $due_date );
370
371
		// Create payment.
372
		$result = $this->client->create_payment( $request );
373
374
		// Set transaction ID.
375
		if ( isset( $result->id ) ) {
376
			$payment->set_transaction_id( $result->id );
377
		}
378
379
		// Set expiry date.
380
		/* phpcs:disable WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase */
381
		if ( isset( $result->expiresAt ) ) {
382
			try {
383
				$expires_at = new DateTime( $result->expiresAt );
384
			} catch ( \Exception $e ) {
385
				$expires_at = null;
386
			}
387
388
			$payment->set_expiry_date( $expires_at );
389
		}
390
		/* phpcs:enable WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase */
391
392
		// Set status.
393
		if ( isset( $result->status ) ) {
394
			$payment->set_status( Statuses::transform( $result->status ) );
395
		}
396
397
		// Set bank transfer recipient details.
398
		if ( isset( $result->details ) ) {
399
			$bank_transfer_recipient_details = $payment->get_bank_transfer_recipient_details();
400
401
			if ( null === $bank_transfer_recipient_details ) {
402
				$bank_transfer_recipient_details = new BankTransferDetails();
403
404
				$payment->set_bank_transfer_recipient_details( $bank_transfer_recipient_details );
405
			}
406
407
			$bank_details = $bank_transfer_recipient_details->get_bank_account();
408
409
			if ( null === $bank_details ) {
410
				$bank_details = new BankAccountDetails();
411
412
				$bank_transfer_recipient_details->set_bank_account( $bank_details );
413
			}
414
415
			$details = $result->details;
416
417
			/*
418
			 * @codingStandardsIgnoreStart
419
			 *
420
			 * Ignore coding standards because of sniff WordPress.NamingConventions.ValidVariableName.NotSnakeCaseMemberVar
421
			 */
422
			if ( isset( $details->bankName ) ) {
423
				/**
424
				 * Set `bankName` as bank details name, as result "Stichting Mollie Payments"
425
				 * is not the name of a bank, but the account holder name.
426
				 */
427
				$bank_details->set_name( $details->bankName );
428
			}
429
430
			if ( isset( $details->bankAccount ) ) {
431
				$bank_details->set_iban( $details->bankAccount );
432
			}
433
434
			if ( isset( $details->bankBic ) ) {
435
				$bank_details->set_bic( $details->bankBic );
436
			}
437
438
			if ( isset( $details->transferReference ) ) {
439
				$bank_transfer_recipient_details->set_reference( $details->transferReference );
440
			}
441
			// @codingStandardsIgnoreEnd
442
		}
443
444
		// Set action URL.
445
		if ( isset( $result->_links ) ) {
446
			if ( isset( $result->_links->checkout->href ) ) {
447
				$payment->set_action_url( $result->_links->checkout->href );
448
			}
449
		}
450
	}
451
452
	/**
453
	 * Update status of the specified payment
454
	 *
455
	 * @param Payment $payment Payment.
456
	 * @return void
457
	 */
458
	public function update_status( Payment $payment ) {
459
		$transaction_id = $payment->get_transaction_id();
460
461
		if ( null === $transaction_id ) {
462
			return;
463
		}
464
465
		$mollie_payment = $this->client->get_payment( $transaction_id );
466
467
		if ( isset( $mollie_payment->status ) ) {
468
			$payment->set_status( Statuses::transform( $mollie_payment->status ) );
469
		}
470
471
		/**
472
		 * Mollie profile.
473
		 */
474
		$mollie_profile = new Profile();
475
476
		// phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase -- Mollie.
477
		$mollie_profile->set_id( $mollie_payment->profileId );
478
479
		$profile_internal_id = $this->profile_data_store->get_or_insert_profile( $mollie_profile );
480
481
		/**
482
		 * If the Mollie payment contains a customer ID we will try to connect
483
		 * this Mollie customer ID the WordPress user and subscription.
484
		 * This can be usefull in case when a WordPress user is created after
485
		 * a succesfull payment.
486
		 *
487
		 * @link https://www.gravityforms.com/add-ons/user-registration/
488
		 */
489
490
		// phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase -- Mollie.
491
		if ( isset( $mollie_payment->customerId ) ) {
492
			// phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase -- Mollie.
493
			$mollie_customer = new Customer( $mollie_payment->customerId );
494
495
			$customer_internal_id = $this->customer_data_store->get_or_insert_customer(
0 ignored issues
show
Unused Code introduced by
The assignment to $customer_internal_id is dead and can be removed.
Loading history...
496
				$mollie_customer,
497
				array(
498
					'profile_id' => $profile_internal_id,
499
				),
500
				array(
501
					'profile_id' => '%s',
502
				)
503
			);
504
505
			// Meta.
506
			$customer_id = $payment->get_meta( 'mollie_customer_id' );
507
508
			if ( empty( $customer_id ) ) {
509
				$payment->set_meta( 'mollie_customer_id', $mollie_customer->get_id() );
510
			}
511
512
			// Customer.
513
			$customer = $payment->get_customer();
514
515
			if ( null !== $customer ) {
516
				// Connect to user.
517
				$user_id = $customer->get_user_id();
518
519
				if ( null !== $user_id ) {
520
					$user = \get_user_by( 'id', $user_id );
521
522
					if ( false !== $user ) {
523
						$this->customer_data_store->connect_mollie_customer_to_wp_user( $mollie_customer, $user );
524
					}
525
				}
526
			}
527
528
			// Subscription.
529
			$subscription = $payment->get_subscription();
530
531
			if ( null !== $subscription ) {
532
				$customer_id = $subscription->get_meta( 'mollie_customer_id' );
533
534
				if ( empty( $customer_id ) ) {
535
					$subscription->set_meta( 'mollie_customer_id', $mollie_customer->get_id() );
536
				}
537
			}
538
		}
539
540
		if ( isset( $mollie_payment->details ) ) {
541
			$consumer_bank_details = $payment->get_consumer_bank_details();
542
543
			if ( null === $consumer_bank_details ) {
544
				$consumer_bank_details = new BankAccountDetails();
545
546
				$payment->set_consumer_bank_details( $consumer_bank_details );
547
			}
548
549
			$details = $mollie_payment->details;
550
551
			/*
552
			 * @codingStandardsIgnoreStart
553
			 *
554
			 * Ignore coding standards because of sniff WordPress.NamingConventions.ValidVariableName.NotSnakeCaseMemberVar
555
			 */
556
			if ( isset( $details->consumerName ) ) {
557
				$consumer_bank_details->set_name( $details->consumerName );
558
			}
559
560
			if ( isset( $details->cardHolder ) ) {
561
				$consumer_bank_details->set_name( $details->cardHolder );
562
			}
563
564
			if ( isset( $details->cardNumber ) ) {
565
				// The last four digits of the card number.
566
				$consumer_bank_details->set_account_number( $details->cardNumber );
567
			}
568
569
			if ( isset( $details->cardCountryCode ) ) {
570
				// The ISO 3166-1 alpha-2 country code of the country the card was issued in.
571
				$consumer_bank_details->set_country( $details->cardCountryCode );
572
			}
573
574
			if ( isset( $details->consumerAccount ) ) {
575
				switch ( $mollie_payment->method ) {
576
					case Methods::BELFIUS:
577
					case Methods::DIRECT_DEBIT:
578
					case Methods::IDEAL:
579
					case Methods::KBC:
580
					case Methods::SOFORT:
581
						$consumer_bank_details->set_iban( $details->consumerAccount );
582
583
						break;
584
					case Methods::BANCONTACT:
585
					case Methods::BANKTRANSFER:
586
					case Methods::PAYPAL:
587
					default:
588
						$consumer_bank_details->set_account_number( $details->consumerAccount );
589
590
						break;
591
				}
592
			}
593
594
			if ( isset( $details->consumerBic ) ) {
595
				$consumer_bank_details->set_bic( $details->consumerBic );
596
			}
597
598
			/*
599
			 * Failure reason.
600
			 */
601
			$failure_reason = $payment->get_failure_reason();
602
603
			if ( null === $failure_reason ) {
604
				$failure_reason = new FailureReason();
605
606
				$payment->set_failure_reason( $failure_reason );
607
			}
608
609
			// SEPA Direct Debit.
610
			if ( isset( $details->bankReasonCode ) ) {
611
				$failure_reason->set_code( $details->bankReasonCode );
612
			}
613
614
			if ( isset( $details->bankReasonCode ) ) {
615
				$failure_reason->set_message( $details->bankReason );
616
			}
617
618
			// Credit card.
619
			if ( isset( $details->failureReason ) ) {
620
				$failure_reason->set_code( $details->failureReason );
621
			}
622
623
			if ( isset( $details->failureMessage ) ) {
624
				$failure_reason->set_message( $details->failureMessage );
625
			}
626
			// @codingStandardsIgnoreEnd
627
		}
628
	}
629
630
	/**
631
	 * Get Mollie customer ID for payment.
632
	 *
633
	 * @param Payment $payment Payment.
634
	 * @return string|null
635
	 */
636 10
	public function get_customer_id_for_payment( Payment $payment ) {
637 10
		$customer_ids = $this->get_customer_ids_for_payment( $payment );
638
639 10
		$customer_id = $this->get_first_existing_customer_id( $customer_ids );
640
641 10
		return $customer_id;
642
	}
643
644
	/**
645
	 * Get Mollie customers for the specified payment.
646
	 *
647
	 * @param Payment $payment Payment.
648
	 * @return array<string>
649
	 */
650 10
	private function get_customer_ids_for_payment( Payment $payment ) {
651 10
		$customer_ids = array();
652
653
		// Customer ID from subscription meta.
654 10
		$subscription = $payment->get_subscription();
655
656 10
		if ( null !== $subscription ) {
657 10
			$customer_id = $this->get_customer_id_for_subscription( $subscription );
658
659 10
			if ( null !== $customer_id ) {
660 4
				$customer_ids[] = $customer_id;
661
			}
662
		}
663
664
		// Customer ID from WordPress user.
665 10
		$customer = $payment->get_customer();
666
667 10
		if ( null !== $customer ) {
668 9
			$user_id = $customer->get_user_id();
669
670 9
			if ( ! empty( $user_id ) ) {
671 7
				$user_customer_ids = $this->get_customer_ids_for_user( $user_id );
672
673 7
				$customer_ids = \array_merge( $customer_ids, $user_customer_ids );
674
			}
675
		}
676
677 10
		return $customer_ids;
678
	}
679
680
	/**
681
	 * Get Mollie customers for the specified WordPress user ID.
682
	 *
683
	 * @param int $user_id WordPress user ID.
684
	 * @return array<string>
685
	 */
686 24
	public function get_customer_ids_for_user( $user_id ) {
687 24
		$customer_query = new CustomerQuery(
688
			array(
689 24
				'user_id' => $user_id,
690
			)
691
		);
692
693 24
		$customers = $customer_query->get_customers();
694
695 24
		$customer_ids = wp_list_pluck( $customers, 'mollie_id' );
696
697 24
		return $customer_ids;
698
	}
699
700
	/**
701
	 * Get customer ID for subscription.
702
	 *
703
	 * @param Subscription $subscription Subscription.
704
	 * @return string|null
705
	 */
706 10
	private function get_customer_id_for_subscription( Subscription $subscription ) {
707 10
		$customer_id = $subscription->get_meta( 'mollie_customer_id' );
708
709 10
		if ( empty( $customer_id ) ) {
710
			// Try to get (legacy) customer ID from first payment.
711 7
			$first_payment = $subscription->get_first_payment();
712
713 7
			if ( null !== $first_payment ) {
714 7
				$customer_id = $first_payment->get_meta( 'mollie_customer_id' );
715
			}
716
		}
717
718 10
		if ( empty( $customer_id ) ) {
719 6
			return null;
720
		}
721
722 4
		return $customer_id;
723
	}
724
725
	/**
726
	 * Get first existing customer from customers list.
727
	 *
728
	 * @param array<string> $customer_ids Customers.
729
	 * @return string|null
730
	 */
731 10
	private function get_first_existing_customer_id( $customer_ids ) {
732 10
		$customer_ids = \array_filter( $customer_ids );
733
734 10
		$customer_ids = \array_unique( $customer_ids );
735
736 10
		foreach ( $customer_ids as $customer_id ) {
737 4
			$customer = $this->client->get_customer( $customer_id );
738
739 4
			if ( null !== $customer ) {
740 4
				return $customer_id;
741
			}
742
		}
743
744 6
		return null;
745
	}
746
747
	/**
748
	 * Create customer for payment.
749
	 *
750
	 * @param Payment $payment Payment.
751
	 * @return string|null
752
	 * @throws Error Throws Error when Mollie error occurs.
753
	 */
754
	private function create_customer_for_payment( Payment $payment ) {
755
		$mollie_customer = new Customer();
756
		$mollie_customer->set_mode( $this->config->is_test_mode() ? 'test' : 'live' );
757
		$mollie_customer->set_email( $payment->get_email() );
758
759
		$pronamic_customer = $payment->get_customer();
760
761
		if ( null !== $pronamic_customer ) {
762
			// Name.
763
			$name = \strval( $pronamic_customer->get_name() );
764
765
			if ( '' !== $name ) {
766
				$mollie_customer->set_name( $name );
767
			}
768
769
			// Locale.
770
			$locale = $pronamic_customer->get_locale();
771
772
			if ( null !== $locale ) {
773
				$mollie_customer->set_locale( LocaleHelper::transform( $locale ) );
774
			}
775
		}
776
777
		// Try to get name from consumer bank details.
778
		$consumer_bank_details = $payment->get_consumer_bank_details();
779
780
		if ( null === $mollie_customer->get_name() && null !== $consumer_bank_details ) {
781
			$name = $consumer_bank_details->get_name();
782
783
			if ( null !== $name ) {
784
				$mollie_customer->set_name( $name );
785
			}
786
		}
787
788
		// Create customer.
789
		$mollie_customer = $this->client->create_customer( $mollie_customer );
790
791
		$customer_id = $this->customer_data_store->insert_customer( $mollie_customer );
0 ignored issues
show
Unused Code introduced by
The assignment to $customer_id is dead and can be removed.
Loading history...
792
793
		// Connect to user.
794
		if ( null !== $pronamic_customer ) {
795
			$user_id = $pronamic_customer->get_user_id();
796
797
			if ( null !== $user_id ) {
798
				$user = \get_user_by( 'id', $user_id );
799
800
				if ( false !== $user ) {
801
					$this->customer_data_store->connect_mollie_customer_to_wp_user( $mollie_customer, $user );
802
				}
803
			}
804
		}
805
806
		// Store customer ID in subscription meta.
807
		$subscription = $payment->get_subscription();
808
809
		if ( null !== $subscription ) {
810
			$subscription->set_meta( 'mollie_customer_id', $mollie_customer->get_id() );
811
		}
812
813
		return $mollie_customer->get_id();
814
	}
815
816
	/**
817
	 * Copy Mollie customer ID from subscription meta to WordPress user meta.
818
	 *
819
	 * @param Payment $payment Payment.
820
	 * @return void
821
	 */
822 27
	public function copy_customer_id_to_wp_user( Payment $payment ) {
823 27
		if ( $this->config->id !== $payment->config_id ) {
824 1
			return;
825
		}
826
827
		// Subscription.
828 26
		$subscription = $payment->get_subscription();
829
830
		// Customer.
831 26
		$customer = $payment->get_customer();
832
833 26
		if ( null === $customer && null !== $subscription ) {
834 17
			$customer = $subscription->get_customer();
835
		}
836
837 26
		if ( null === $customer ) {
838 1
			return;
839
		}
840
841
		// WordPress user.
842 25
		$user_id = $customer->get_user_id();
843
844 25
		if ( null === $user_id ) {
845 2
			return;
846
		}
847
848 23
		$user = \get_user_by( 'id', $user_id );
849
850 23
		if ( false === $user ) {
851 12
			return;
852
		}
853
854
		// Customer IDs.
855 11
		$customer_ids = array();
856
857
		// Payment.
858 11
		$customer_ids[] = $payment->get_meta( 'mollie_customer_id' );
859
860
		// Subscription.
861 11
		if ( null !== $subscription ) {
862 11
			$customer_ids[] = $subscription->get_meta( 'mollie_customer_id' );
863
		}
864
865
		// Connect.
866 11
		$customer_ids = \array_filter( $customer_ids );
867 11
		$customer_ids = \array_unique( $customer_ids );
868
869 11
		foreach ( $customer_ids as $customer_id ) {
870 2
			$customer = new Customer( $customer_id );
871
872 2
			$this->customer_data_store->get_or_insert_customer( $customer );
873
874 2
			$this->customer_data_store->connect_mollie_customer_to_wp_user( $customer, $user );
875
		}
876 11
	}
877
}
878