Passed
Push — master ( 63237f...7c0386 )
by Reüel
06:18 queued 10s
created

Client::send_request()   A

Complexity

Conditions 5
Paths 5

Size

Total Lines 54
Code Lines 28

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 21
CRAP Score 5.1777

Importance

Changes 4
Bugs 0 Features 0
Metric Value
cc 5
eloc 28
c 4
b 0
f 0
nc 5
nop 3
dl 0
loc 54
ccs 21
cts 26
cp 0.8077
crap 5.1777
rs 9.1608

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