Passed
Push — master ( d4ad7c...cc3467 )
by Reüel
07:39 queued 12s
created

get_http_authorization_test()   B

Complexity

Conditions 6
Paths 6

Size

Total Lines 106
Code Lines 60

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 42

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 6
eloc 60
c 1
b 0
f 0
nc 6
nop 0
dl 0
loc 106
ccs 0
cts 57
cp 0
crap 42
rs 8.2505

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
 * Site Health controller
4
 *
5
 * @author    Pronamic <[email protected]>
6
 * @copyright 2005-2019 Pronamic
7
 * @license   GPL-3.0-or-later
8
 * @package   Pronamic\WordPress\Pay\Gateways\Adyen
9
 */
10
11
namespace Pronamic\WordPress\Pay\Gateways\Adyen;
12
13
use WP_Error;
14
use WP_REST_Request;
15
16
/**
17
 * Site Health controller
18
 *
19
 * @author  Remco Tolsma
20
 * @version 1.0.5
21
 * @since   1.0.5
22
 */
23
class SiteHealthController {
24
	/**
25
	 * HTTP Basic authentication test username.
26
	 *
27
	 * @var string
28
	 */
29
	const HTTP_BASIC_AUTHENTICATION_TEST_USERNAME = 'test';
30
31
	/**
32
	 * HTTP Basic authentication test password.
33
	 *
34
	 * @var string
35
	 */
36
	const HTTP_BASIC_AUTHENTICATION_TEST_PASSWORD = '1234';
37
38
	/**
39
	 * Setup.
40
	 *
41
	 * @return void
42
	 */
43 5
	public function setup() {
44 5
		add_filter( 'site_status_tests', array( $this, 'site_status_tests' ) );
45
46 5
		$prefix = 'health-check-';
47 5
		$action = 'pronamic-pay-adyen-http-authorization-test';
48
49 5
		add_action( 'wp_ajax_' . $prefix . $action, array( $this, 'wp_ajax_health_check_http_authorization_test' ) );
50
51 5
		add_action( 'rest_api_init', array( $this, 'rest_api_init' ) );
52 5
	}
53
54
	/**
55
	 * Site status tests.
56
	 *
57
	 * @link https://make.wordpress.org/core/2019/04/25/site-health-check-in-5-2/
58
	 * @param array<string, array<string, array<string, string>>> $tests Tests.
59
	 * @return array<string, array<string, array<string, string>>>
60
	 */
61
	public function site_status_tests( $tests ) {
62
		$tests['async']['pronamic_pay_adyen_http_authorization_test'] = array(
63
			'label' => __( 'HTTP Authorization header test', 'pronamic_ideal' ),
64
			'test'  => 'pronamic-pay-adyen-http-authorization-test',
65
		);
66
67
		return $tests;
68
	}
69
70
	/**
71
	 * Get HTTP authorization header.
72
	 *
73
	 * @return string
74
	 */
75
	private function get_http_authorization_header() {
76
		// phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode -- Benign reason.
77
		return 'Basic ' . base64_encode( self::HTTP_BASIC_AUTHENTICATION_TEST_USERNAME . ':' . self::HTTP_BASIC_AUTHENTICATION_TEST_PASSWORD );
78
	}
79
80
	/**
81
	 * Get HTTP authorization test.
82
	 *
83
	 * @return array<string, string|array<string, string>>
84
	 */
85
	private function get_http_authorization_test() {
86
		$result = array(
87
			'label'       => __( 'HTTP Basic authentication is working' ),
88
			'status'      => 'good',
89
			'badge'       => array(
90
				'label' => __( 'Payments', 'pronamic_ideal' ),
91
				'color' => 'blue',
92
			),
93
			'description' => sprintf(
94
				'<p>%s</p>',
95
				__( 'HTTP Basic authentication is required to securely receive Adyen notifications.', 'pronamic_ideal' )
96
			),
97
			'actions'     => '',
98
			'test'        => 'pronamic-pay-adyen-http-authorization-test',
99
		);
100
101
		$rest_url = \rest_url( Integration::REST_ROUTE_NAMESPACE . '/http-authorization-test' );
102
103
		$request_authorization = $this->get_http_authorization_header();
104
105
		$response = wp_remote_get(
106
			$rest_url,
107
			array(
108
				'headers' => array(
109
					'Authorization' => $request_authorization,
110
				),
111
			)
112
		);
113
114
		if ( $response instanceof \WP_Error ) {
115
			$result['status'] = 'critical';
116
117
			$result['label'] = __( 'Could not reach HTTP Authorization header test endpoint.', 'pronamic_ideal' );
118
119
			$result['description'] .= sprintf(
120
				'<p>%s</p>',
121
				sprintf(
122
					'<span class="error"><span class="screen-reader-text">%s</span></span> %s',
123
					__( 'Error', 'pronamic_ideal' ),
124
					sprintf(
125
						/* translators: %s: The error returned by the lookup. */
126
						__( 'Your site is unable to test the HTTP Authorization header, and returned the error: %s' ),
127
						$response->get_error_message()
128
					)
129
				)
130
			);
131
132
			return $result;
133
		}
134
135
		// Body.
136
		$body = \wp_remote_retrieve_body( $response );
137
138
		// Response.
139
		$response_code    = \wp_remote_retrieve_response_code( $response );
140
		$response_message = \wp_remote_retrieve_response_message( $response );
141
142
		// Data.
143
		$data = json_decode( $body );
144
145
		// JSON error.
146
		$json_error = json_last_error();
147
148
		if ( \JSON_ERROR_NONE !== $json_error ) {
149
			$result['status'] = 'critical';
150
151
			$result['description'] .= \sprintf(
152
				'Could not JSON decode response, HTTP response: "%s %s", HTTP body length: "%d", JSON error: "%s".',
153
				$response_code,
154
				$response_message,
155
				\strlen( $body ),
156
				\json_last_error_msg()
157
			);
158
159
			return $result;
160
		}
161
162
		// Object.
163
		if ( ! \is_object( $data ) ) {
164
			$result['status'] = 'critical';
165
166
			$result['description'] .= \sprintf(
167
				'Could not JSON decode response to an object, HTTP response: "%s %s", HTTP body: "%s".',
168
				$response_code,
169
				$response_message,
170
				$body
171
			);
172
173
			return $result;
174
		}
175
176
		if ( ! property_exists( $data, 'authorization' ) ) {
177
			$result['status'] = 'critical';
178
179
			return $result;
180
		}
181
182
		if ( $data->authorization !== $request_authorization ) {
183
			$result['status'] = 'critical';
184
185
			return $result;
186
		}
187
188
		$result['status'] = 'good';
189
190
		return $result;
191
	}
192
193
	/**
194
	 * WordPress AJAX health check HTTP authorization test.
195
	 *
196
	 * @link https://github.com/WordPress/WordPress/blob/5.2.4/wp-admin/includes/class-wp-site-health.php#L1128-L1189
197
	 * @link https://github.com/WordPress/WordPress/blob/5.2.4/wp-admin/includes/ajax-actions.php#L4865-L4883
198
	 * @return void
199
	 */
200
	public function wp_ajax_health_check_http_authorization_test() {
201
		check_ajax_referer( 'health-check-site-status' );
202
203
		if ( ! current_user_can( 'view_site_health_checks' ) ) {
204
			wp_send_json_error();
205
		}
206
207
		$result = $this->get_http_authorization_test();
208
209
		wp_send_json_success( $result );
210
	}
211
212
	/**
213
	 * REST API init.
214
	 *
215
	 * @link https://developer.wordpress.org/rest-api/extending-the-rest-api/adding-custom-endpoints/
216
	 * @link https://developer.wordpress.org/reference/hooks/rest_api_init/
217
	 * @return void
218
	 */
219 10
	public function rest_api_init() {
220 10
		register_rest_route(
221 10
			Integration::REST_ROUTE_NAMESPACE,
222 10
			'/http-authorization-test',
223
			array(
224 10
				'methods'  => 'GET',
225 10
				'callback' => array( $this, 'rest_api_http_authorization_test' ),
226
			)
227
		);
228 10
	}
229
230
	/**
231
	 * REST API Adyen notifications handler.
232
	 *
233
	 * @link https://www.php.net/manual/en/features.http-auth.php
234
	 * @param WP_REST_Request $request Request.
235
	 * @return object
236
	 */
237
	public function rest_api_http_authorization_test( WP_REST_Request $request ) {
238
		$data = array(
239
			'authorization' => $request->get_header( 'Authorization' ),
240
		);
241
242
		$server_keys = array(
243
			'HTTP_AUTHORIZATION',
244
			'PHP_AUTH_USER',
245
			'PHP_AUTH_PW',
246
			'AUTH_TYPE',
247
		);
248
249
		foreach ( $server_keys as $key ) {
250
			if ( array_key_exists( $key, $_SERVER ) ) {
251
				// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
252
				$data[ $key ] = wp_unslash( $_SERVER[ $key ] );
253
			}
254
		}
255
256
		return (object) $data;
257
	}
258
}
259