Integration::__construct()   B
last analyzed

Complexity

Conditions 6
Paths 16

Size

Total Lines 67
Code Lines 36

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 22
CRAP Score 6.0208

Importance

Changes 15
Bugs 0 Features 0
Metric Value
cc 6
eloc 36
c 15
b 0
f 0
nc 16
nop 1
dl 0
loc 67
ccs 22
cts 24
cp 0.9167
crap 6.0208
rs 8.7217

How to fix   Long Method   

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 integration.
4
 *
5
 * @author    Pronamic <[email protected]>
6
 * @copyright 2005-2022 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\Core\PaymentMethods;
15
use Pronamic\WordPress\Pay\AbstractGatewayIntegration;
16
use Pronamic\WordPress\Pay\Payments\Payment;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, Pronamic\WordPress\Pay\Gateways\Mollie\Payment. Consider defining an alias.

Let?s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let?s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
17
use Pronamic\WordPress\Pay\Subscriptions\Subscription as CoreSubscription;
18
19
/**
20
 * Title: Mollie integration
21
 * Description:
22
 * Copyright: 2005-2022 Pronamic
23
 * Company: Pronamic
24
 *
25
 * @author  Remco Tolsma
26
 * @version 2.1.4
27
 * @since   1.0.0
28
 */
29
class Integration extends AbstractGatewayIntegration {
30
	/**
31
	 * REST route namespace.
32
	 *
33
	 * @var string
34
	 */
35
	const REST_ROUTE_NAMESPACE = 'pronamic-pay/mollie/v1';
36
37
	/**
38
	 * Register URL.
39
	 *
40
	 * @var string
41
	 */
42
	public $register_url;
43
44
	/**
45
	 * Construct and initialize Mollie integration.
46
	 *
47
	 * @param array<string, array> $args Arguments.
48
	 */
49 7
	public function __construct( $args = array() ) {
50 7
		$args = wp_parse_args(
51 7
			$args,
52
			array(
53 7
				'id'                     => 'mollie',
54 7
				'name'                   => 'Mollie',
55 7
				'version'                => '2.1.0',
56 7
				'url'                    => 'http://www.mollie.com/en/',
57 7
				'product_url'            => \__( 'https://www.mollie.com/en/pricing', 'pronamic_ideal' ),
58 7
				'dashboard_url'          => 'https://www.mollie.com/dashboard/',
59 7
				'provider'               => 'mollie',
60
				'supports'               => array(
61
					'payment_status_request',
62
					'recurring_apple_pay',
63
					'recurring_direct_debit',
64
					'recurring_credit_card',
65
					'recurring',
66
					'refunds',
67
					'webhook',
68
					'webhook_log',
69
					'webhook_no_config',
70 7
				),
71 7
				'version_option_name'    => 'pronamic_pay_mollie_version',
72
				'db_version_option_name' => 'pronamic_pay_mollie_db_version',
73
			)
74
		);
75 7
76
		parent::__construct( $args );
77
78 7
		// Filters.
79
		$function = array( $this, 'next_payment_delivery_date' );
80 7
81 7
		if ( ! \has_filter( 'pronamic_pay_subscription_next_payment_delivery_date', $function ) ) {
82
			\add_filter( 'pronamic_pay_subscription_next_payment_delivery_date', $function, 10, 2 );
83
		}
84 7
85
		add_filter( 'pronamic_payment_provider_url_mollie', array( $this, 'payment_provider_url' ), 10, 2 );
86
87 7
		// Actions.
88
		$function = array( $this, 'scheduled_payment_start' );
89
90
		if ( ! \has_action( 'pronamic_pay_mollie_payment_start', $function ) ) {
91
			\add_action( 'pronamic_pay_mollie_payment_start', $function, 10, 1 );
92 7
		}
93
94
		// Tables.
95
		$this->register_tables();
96
97 7
		/**
98
		 * Install.
99
		 */
100
		new Install( $this );
101
102
		/**
103
		 * Admin
104
		 */
105
		if ( \is_admin() ) {
106 7
			new Admin();
107
		}
108
109 7
		/**
110
		 * CLI.
111
		 *
112
		 * @link https://github.com/woocommerce/woocommerce/blob/3.9.0/includes/class-woocommerce.php#L453-L455
113
		 */
114
		if ( defined( 'WP_CLI' ) && WP_CLI ) {
115
			new CLI();
116
		}
117
	}
118
119
	/**
120
	 * Setup gateway integration.
121
	 *
122
	 * @return void
123
	 */
124
	public function setup() {
125
		// Check if dependencies are met and integration is active.
126
		if ( ! $this->is_active() ) {
127
			return;
128
		}
129
130
		// Webhook controller.
131
		$webhook_controller = new WebhookController();
132
133
		$webhook_controller->setup();
134 7
	}
135 7
136
	/**
137
	 * Register tables.
138
	 *
139
	 * @link https://github.com/WordPress/WordPress/blob/5.3/wp-includes/wp-db.php#L894-L937
140 7
	 * @return void
141 7
	 */
142 7
	private function register_tables() {
143 7
		global $wpdb;
144 7
145
		/**
146
		 * Tables.
147
		 */
148
		$wpdb->pronamic_pay_mollie_organizations  = $wpdb->base_prefix . 'pronamic_pay_mollie_organizations';
149
		$wpdb->pronamic_pay_mollie_profiles       = $wpdb->base_prefix . 'pronamic_pay_mollie_profiles';
150
		$wpdb->pronamic_pay_mollie_customers      = $wpdb->base_prefix . 'pronamic_pay_mollie_customers';
151 1
		$wpdb->pronamic_pay_mollie_customer_users = $wpdb->base_prefix . 'pronamic_pay_mollie_customer_users';
152 1
	}
153
154
	/**
155 1
	 * Get settings fields.
156 1
	 *
157 1
	 * @return array<int, array<string, callable|int|string|bool|array<int|string,int|string>>>
158 1
	 */
159 1
	public function get_settings_fields() {
160 1
		$fields = array();
161
162 1
		// API Key.
163
		$fields[] = array(
164
			'section'  => 'general',
165
			'filter'   => FILTER_SANITIZE_STRING,
166 1
			'meta_key' => '_pronamic_gateway_mollie_api_key',
167 1
			'title'    => _x( 'API Key', 'mollie', 'pronamic_ideal' ),
168
			'type'     => 'text',
169 1
			'classes'  => array( 'regular-text', 'code' ),
170 1
			'tooltip'  => __( 'API key as mentioned in the payment provider dashboard', 'pronamic_ideal' ),
171 1
		);
172 1
173 1
		// Due date days.
174
		$fields[] = array(
175 1
			'section'     => 'advanced',
176 1
			'filter'      => \FILTER_SANITIZE_NUMBER_INT,
177
			'meta_key'    => '_pronamic_gateway_mollie_due_date_days',
178 1
			'title'       => _x( 'Due date days', 'mollie', 'pronamic_ideal' ),
179 1
			'type'        => 'number',
180 1
			'min'         => 1,
181 1
			'max'         => 100,
182
			'classes'     => array( 'regular-text' ),
183
			'tooltip'     => __( 'Number of days after which a bank transfer payment expires.', 'pronamic_ideal' ),
184
			'description' => sprintf(
185
				/* translators: 1: <code>1</code>, 2: <code>100</code>, 3: <code>12</code> */
186 1
				__( 'Minimum %1$s and maximum %2$s days. Default: %3$s days.', 'pronamic_ideal' ),
187 1
				sprintf( '<code>%s</code>', '1' ),
188 1
				sprintf( '<code>%s</code>', '100' ),
189 1
				sprintf( '<code>%s</code>', '12' )
190
			),
191 1
		);
192
193 1
		// Webhook.
194
		$fields[] = array(
195
			'section'  => 'feedback',
196 1
			'title'    => __( 'Webhook URL', 'pronamic_ideal' ),
197
			'type'     => 'text',
198
			'classes'  => array( 'large-text', 'code' ),
199
			'value'    => rest_url( self::REST_ROUTE_NAMESPACE . '/webhook' ),
200
			'readonly' => true,
201
			'tooltip'  => __( 'The Webhook URL as sent with each transaction to receive automatic payment status updates on.', 'pronamic_ideal' ),
202
		);
203
204
		return $fields;
205
	}
206
207
	/**
208
	 * Save post.
209
	 *
210
	 * @link https://developer.wordpress.org/reference/functions/get_post_meta/
211
	 * @param int $post_id Post ID.
212
	 * @return void
213
	 */
214
	public function save_post( $post_id ) {
215
		$api_key = get_post_meta( $post_id, '_pronamic_gateway_mollie_api_key', true );
216
217
		if ( ! is_string( $api_key ) ) {
218
			return;
219
		}
220
221
		$api_key_prefix = substr( $api_key, 0, 4 );
222
223
		switch ( $api_key_prefix ) {
224
			case 'live':
225
				update_post_meta( $post_id, '_pronamic_gateway_mode', Gateway::MODE_LIVE );
226
227
				return;
228
			case 'test':
229
				update_post_meta( $post_id, '_pronamic_gateway_mode', Gateway::MODE_TEST );
230
231
				return;
232
		}
233
	}
234 1
235 1
	/**
236
	 * Payment provider URL.
237 1
	 *
238
	 * @param string|null $url     Payment provider URL.
239
	 * @param Payment     $payment Payment.
240
	 * @return string|null
241 1
	 */
242 1
	public function payment_provider_url( $url, Payment $payment ) {
243
		$transaction_id = $payment->get_transaction_id();
244
245
		if ( null === $transaction_id ) {
246
			return $url;
247
		}
248
249
		return sprintf(
250
			'https://www.mollie.com/dashboard/payments/%s',
251
			$transaction_id
252
		);
253 2
	}
254 2
255
	/**
256 2
	 * Get configuration by post ID.
257 2
	 *
258 2
	 * @param int $post_id Post ID.
259 2
	 * @return Config
260
	 */
261 2
	public function get_config( $post_id ) {
262
		$config = new Config();
263
264
		$config->id            = intval( $post_id );
265
		$config->api_key       = $this->get_meta( $post_id, 'mollie_api_key' );
266
		$config->mode          = $this->get_meta( $post_id, 'mode' );
267
		$config->due_date_days = $this->get_meta( $post_id, 'mollie_due_date_days' );
268
269
		return $config;
270 1
	}
271 1
272
	/**
273
	 * Get gateway.
274
	 *
275
	 * @param int $post_id Post ID.
276
	 * @return Gateway
277
	 */
278
	public function get_gateway( $post_id ) {
279
		return new Gateway( $this->get_config( $post_id ) );
280
	}
281 10
282 10
	/**
283
	 * Start scheduled payment.
284 10
	 *
285
	 * @param int $payment_id Payment ID.
286
	 * @return void
287
	 * @throws \Exception Throws exception after four failed attempts.
288
	 */
289 10
	public function scheduled_payment_start( $payment_id ) {
290
		// Check payment.
291 10
		$payment = \get_pronamic_payment( $payment_id );
292 10
293
		if ( null === $payment ) {
294
			return;
295
		}
296
297
		// Check gateway.
298
		$gateway = $payment->get_gateway();
299
300
		if ( null === $gateway ) {
301
			return;
302
		}
303
304
		// Attempt.
305
		$attempt = (int) $payment->get_meta( 'mollie_create_payment_attempt' );
306
307
		if ( $attempt > 4 ) {
308
			throw new \Exception( \sprintf( 'Could not create Mollie payment for %s after %s attempts.', $payment_id, $attempt ) );
309
		}
310
311
		// Start payment.
312
		$gateway->start( $payment );
313
314
		$payment->save();
315
	}
316
317
	/**
318
	 * Next payment delivery date.
319
	 *
320
	 * @param \DateTimeInterface $next_payment_delivery_date Next payment delivery date.
321
	 * @param CoreSubscription   $subscription               Subscription.
322
	 * @return DateTime
323
	 */
324
	public function next_payment_delivery_date( \DateTimeInterface $next_payment_delivery_date, CoreSubscription $subscription ) {
325
		$config_id = $subscription->get_config_id();
326
327
		if ( null === $config_id ) {
328
			return $next_payment_delivery_date;
329
		}
330
331
		// Check gateway.
332
		$gateway_id = \get_post_meta( $config_id, '_pronamic_gateway_id', true );
333
334
		if ( 'mollie' !== $gateway_id ) {
335
			return $next_payment_delivery_date;
336
		}
337
338
		// Check direct debit payment method.
339
		$payment_method = $subscription->get_payment_method();
340
341
		if ( null === $payment_method ) {
342
			return $next_payment_delivery_date;
343
		}
344
345
		if ( ! PaymentMethods::is_direct_debit_method( $payment_method ) ) {
346
			return $next_payment_delivery_date;
347
		}
348
349
		// Base delivery date on next payment date.
350
		$next_payment_date = $subscription->get_next_payment_date();
351
352
		if ( null === $next_payment_date ) {
353
			return $next_payment_delivery_date;
354
		}
355
356
		$next_payment_delivery_date = clone $next_payment_date;
357
358
		// Textual representation of the day of the week, Sunday through Saturday.
359
		$day_of_week = $next_payment_delivery_date->format( 'l' );
360
361
		/*
362
		 * Subtract days from next payment date for earlier delivery.
363
		 *
364
		 * @link https://help.mollie.com/hc/en-us/articles/115000785649-When-are-direct-debit-payments-processed-and-paid-out-
365
		 * @link https://help.mollie.com/hc/en-us/articles/115002540294-What-are-the-payment-methods-processing-times-
366
		 */
367
		switch ( $day_of_week ) {
368
			case 'Monday':
369
				$next_payment_delivery_date = $next_payment_delivery_date->modify( '-3 days' );
370
371
				break;
372
			case 'Saturday':
373
				$next_payment_delivery_date = $next_payment_delivery_date->modify( '-2 days' );
374
375
				break;
376
			case 'Sunday':
377
				$next_payment_delivery_date = $next_payment_delivery_date->modify( '-3 days' );
378
379
				break;
380
			default:
381
				$next_payment_delivery_date = $next_payment_delivery_date->modify( '-1 day' );
382
383
				break;
384
		}
385
386
		$next_payment_delivery_date = $next_payment_delivery_date->setTime( 0, 0, 0 );
387
388
		return $next_payment_delivery_date;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $next_payment_delivery_date returns the type Pronamic\WordPress\DateTime\DateTimeImmutable which is incompatible with the documented return type Pronamic\WordPress\DateTime\DateTime.
Loading history...
389
	}
390
}
391