Test Failed
Push — develop ( c4272a...fda107 )
by Remco
13:02
created

Client::send_request()   B

Complexity

Conditions 6
Paths 9

Size

Total Lines 60
Code Lines 29

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 16
CRAP Score 6.73

Importance

Changes 3
Bugs 0 Features 0
Metric Value
eloc 29
c 3
b 0
f 0
dl 0
loc 60
ccs 16
cts 22
cp 0.7272
rs 8.8337
cc 6
nc 9
nop 4
crap 6.73

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 client.
4
 *
5
 * @author    Pronamic <[email protected]>
6
 * @copyright 2005-2019 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\XML\Security;
15
use WP_Error;
16
17
/**
18
 * Title: Mollie
19
 * Description:
20
 * Copyright: 2005-2019 Pronamic
21
 * Company: Pronamic
22
 *
23
 * @author  Remco Tolsma
24
 * @version 2.1.0
25
 * @since   1.0.0
26
 */
27
class Client {
28
	/**
29
	 * Mollie API endpoint URL
30
	 *
31
	 * @var string
32
	 */
33
	const API_URL = 'https://api.mollie.com/v2/';
34
35
	/**
36
	 * Mollie API Key ID
37
	 *
38
	 * @var string
39
	 */
40
	private $api_key;
41
42
	/**
43
	 * Mode
44
	 *
45
	 * @since 1.1.9
46
	 * @var string
47
	 */
48
	private $mode;
49
50
	/**
51
	 * Error
52
	 *
53
	 * @var WP_Error
54
	 */
55
	private $error;
56
57
	/**
58
	 * Constructs and initializes an Mollie client object
59
	 *
60
	 * @param string $api_key Mollie API key.
61
	 */
62 40
	public function __construct( $api_key ) {
63 40
		$this->api_key = $api_key;
64 40
	}
65
66
	/**
67
	 * Set mode
68
	 *
69
	 * @since 1.1.9
70
	 * @param string $mode Mode (test or live).
71
	 */
72 40
	public function set_mode( $mode ) {
73 40
		$this->mode = $mode;
74 40
	}
75
76
	/**
77
	 * Error
78
	 *
79
	 * @return WP_Error
80
	 */
81 5
	public function get_error() {
82 5
		return $this->error;
83
	}
84
85
	/**
86
	 * Send request with the specified action and parameters
87
	 *
88
	 * @param string $end_point              Requested endpoint.
89
	 * @param string $method                 HTTP method to use.
90
	 * @param array  $data                   Request data.
91
	 * @param int    $expected_response_code Expected response code.
92
	 * @return bool|object
93
	 * @throws \Exception Throws exception when error occurs.
94
	 */
95 10
	private function send_request( $end_point, $method = 'GET', array $data = array(), $expected_response_code = 200 ) {
96
		// Request.
97 10
		$url = self::API_URL . $end_point;
98
99 10
		$response = wp_remote_request(
100 10
			$url,
101
			array(
102 10
				'method'  => $method,
103
				'headers' => array(
104 10
					'Authorization' => 'Bearer ' . $this->api_key,
105
				),
106 10
				'body'    => $data,
107
			)
108
		);
109
110
		if ( $response instanceof \WP_Error ) {
111 10
			throw new \Exception( $response->get_error_message() );
112
		}
113 10
114 10
		// Response code.
115
		$response_code = wp_remote_retrieve_response_code( $response );
116
117
		// phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison
118 10
		if ( $expected_response_code != $response_code ) {
119
			$this->error = new WP_Error( 'mollie_error', 'Unexpected response code.' );
120 10
		}
121
122 10
		// Body.
123
		$body = wp_remote_retrieve_body( $response );
124
125
		$data = json_decode( $body );
126
127
		// JSON error.
128
		$json_error = \json_last_error();
129 10
130 10
		if ( \JSON_ERROR_NONE !== $json_error ) {
131
			throw new \Exception(
132 10
				\sprintf( 'JSON: %s', \json_last_error_msg() ),
133
				$json_error
134
			);
135
		}
136
137
		// Object.
138
		if ( ! \is_object( $data ) ) {
139
			$code = \wp_remote_retrieve_response_code( $response );
140
141
			throw new \Exception(
142
				\sprintf( 'Could not JSON decode Mollie response to an object (HTTP Status Code: %s).', $code ),
143
				\intval( $code )
144
			);
145
		}
146
147
		// Mollie error.
148
		if ( isset( $data->status, $data->title, $data->detail ) ) {
149
			$this->error = new \WP_Error( 'mollie_error', $data->detail, $data );
150
151
			return false;
152
		}
153
154
		return $data;
155
	}
156
157
	/**
158
	 * Create payment.
159
	 *
160
	 * @param PaymentRequest $request Payment request.
161
	 *
162
	 * @return bool|object
163
	 */
164
	public function create_payment( PaymentRequest $request ) {
165
		return $this->send_request( 'payments', 'POST', $request->get_array(), 201 );
166
	}
167
168
	/**
169
	 * Get payments.
170
	 *
171
	 * @return bool|object
172
	 */
173
	public function get_payments() {
174
		return $this->send_request( 'payments', 'GET' );
175
	}
176
177
	/**
178 3
	 * Get payment.
179 3
	 *
180
	 * @param string $payment_id Payment ID.
181 3
	 *
182 3
	 * @return bool|object
183
	 */
184
	public function get_payment( $payment_id ) {
185
		if ( empty( $payment_id ) ) {
186
			return false;
187
		}
188
189
		return $this->send_request( 'payments/' . $payment_id, 'GET' );
190
	}
191
192
	/**
193
	 * Get issuers
194
	 *
195
	 * @return array|bool
196
	 */
197
	public function get_issuers() {
198
		$response = $this->send_request( 'methods/ideal?include=issuers', 'GET' );
199
200
		if ( false === $response ) {
201
			return false;
202
		}
203
204
		$issuers = array();
205
206 2
		if ( isset( $response->issuers ) ) {
207 2
			foreach ( $response->issuers as $issuer ) {
208
				$id   = Security::filter( $issuer->id );
209 2
				$name = Security::filter( $issuer->name );
210 2
211
				$issuers[ $id ] = $name;
212
			}
213 2
		}
214
215 2
		return $issuers;
216 2
	}
217
218
	/**
219
	 * Get payment methods
220
	 *
221
	 * @param string $sequence_type Sequence type.
222
	 *
223
	 * @return array|bool
224
	 */
225
	public function get_payment_methods( $sequence_type = '' ) {
226
		$data = array();
227
228
		if ( '' !== $sequence_type ) {
229
			$data['sequenceType'] = $sequence_type;
230
		}
231
232
		$response = $this->send_request( 'methods', 'GET', $data );
233
234
		if ( false === $response ) {
235
			return false;
236
		}
237
238
		$payment_methods = array();
239
240
		if ( isset( $response->_embedded->methods ) ) {
241
			foreach ( $response->_embedded->methods as $payment_method ) {
242
				$id   = Security::filter( $payment_method->id );
243
				$name = Security::filter( $payment_method->description );
244
245
				$payment_methods[ $id ] = $name;
246
			}
247
		}
248
249
		return $payment_methods;
250
	}
251
252
	/**
253
	 * Create customer.
254
	 *
255
	 * @since 1.1.6
256
	 *
257
	 * @param string $email Customer email address.
258
	 * @param string $name  Customer name.
259
	 *
260
	 * @return string|bool
261
	 */
262
	public function create_customer( $email, $name ) {
263
		if ( empty( $email ) ) {
264
			return false;
265
		}
266
267
		$response = $this->send_request(
268
			'customers',
269
			'POST',
270
			array(
271
				'name'  => $name,
272
				'email' => $email,
273
			),
274
			201
275
		);
276
277
		if ( false === $response ) {
278 5
			return false;
279 5
		}
280
281
		if ( ! isset( $response->id ) ) {
282
			return false;
283 5
		}
284
285 5
		return $response->id;
286 5
	}
287
288
	/**
289
	 * Get customer.
290
	 *
291
	 * @param string $customer_id Mollie customer ID.
292
	 *
293
	 * @since unreleased
294
	 *
295
	 * @return object|bool
296
	 */
297
	public function get_customer( $customer_id ) {
298
		if ( empty( $customer_id ) ) {
299
			return false;
300
		}
301
302
		$response = $this->send_request( 'customers/' . $customer_id, 'GET', array(), 200 );
303
304
		if ( false === $response ) {
305
			return false;
306
		}
307
308
		if ( is_wp_error( $this->error ) ) {
309
			return false;
310
		}
311
312
		return $response;
313
	}
314
315
	/**
316
	 * Get mandates for customer.
317
	 *
318
	 * @param string $customer_id Mollie customer ID.
319
	 *
320
	 * @return object|bool
321
	 */
322
	public function get_mandates( $customer_id ) {
323
		if ( '' === $customer_id ) {
324
			return false;
325
		}
326
327
		return $this->send_request( 'customers/' . $customer_id . '/mandates?limit=250', 'GET' );
328
	}
329
330
	/**
331
	 * Is there a valid mandate for customer?
332
	 *
333
	 * @param string      $customer_id    Mollie customer ID.
334
	 * @param string|null $payment_method Payment method to find mandates for.
335
	 *
336
	 * @return boolean
337
	 */
338
	public function has_valid_mandate( $customer_id, $payment_method = null ) {
339
		$mandates = $this->get_mandates( $customer_id );
340
341
		if ( ! $mandates ) {
342
			return false;
343
		}
344
345
		$mollie_method = Methods::transform( $payment_method );
346
347
		foreach ( $mandates->_embedded as $mandate ) {
348
			if ( $mollie_method !== $mandate->method ) {
349
				continue;
350
			}
351
352
			if ( 'valid' === $mandate->status ) {
353
				return true;
354
			}
355
		}
356
357
		return false;
358
	}
359
360
	/**
361
	 * Get formatted date and time of first valid mandate.
362
	 *
363
	 * @param string $customer_id    Mollie customer ID.
364
	 * @param string $payment_method Payment method.
365
	 *
366
	 * @return null|DateTime
367
	 */
368
	public function get_first_valid_mandate_datetime( $customer_id, $payment_method = null ) {
369
		$mandates = $this->get_mandates( $customer_id );
370
371
		if ( ! $mandates ) {
372
			return null;
373
		}
374
375
		$mollie_method = Methods::transform( $payment_method );
376
377
		foreach ( $mandates->_embedded as $mandate ) {
378
			if ( $mollie_method !== $mandate->method ) {
379
				continue;
380
			}
381
382
			if ( 'valid' !== $mandate->status ) {
383
				continue;
384
			}
385
386
			if ( ! isset( $valid_mandates ) ) {
387
				$valid_mandates = array();
388
			}
389
390
			// @codingStandardsIgnoreStart
391
			$valid_mandates[ $mandate->createdAt ] = $mandate;
392
			// @codingStandardsIgnoreEnd
393
		}
394
395
		if ( isset( $valid_mandates ) ) {
396
			ksort( $valid_mandates );
397
398
			$mandate = array_shift( $valid_mandates );
399
400
			// @codingStandardsIgnoreStart
401
			$create_date = new DateTime( $mandate->createdAt );
402
			// @codingStandardsIgnoreEnd
403
404
			return $create_date;
405
		}
406
407
		return null;
408
	}
409
}
410