Completed
Push — fix/typo-pro-promo ( e5832e...fc698e )
by
unknown
29:20
created

Jetpack_ReCaptcha::verify()   D

Complexity

Conditions 10
Paths 12

Size

Total Lines 38
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 10
eloc 20
nc 12
nop 2
dl 0
loc 38
rs 4.8196
c 0
b 0
f 0

How to fix   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
/**
4
 * Class that handles reCAPTCHA.
5
 */
6
class Jetpack_ReCaptcha {
7
8
	/**
9
	 * URL to which requests are POSTed.
10
	 *
11
	 * @const string
12
	 */
13
	const VERIFY_URL = 'https://www.google.com/recaptcha/api/siteverify';
14
15
	/**
16
	 * Site key to use in HTML code.
17
	 *
18
	 * @var string
19
	 */
20
	private $site_key;
21
22
	/**
23
	 * Shared secret for the site.
24
	 *
25
	 * @var string
26
	 */
27
	private $secret_key;
28
29
	/**
30
	 * Config for reCAPTCHA instance.
31
	 *
32
	 * @var array
33
	 */
34
	private $config;
35
36
	/**
37
	 * Error codes returned from reCAPTCHA API.
38
	 *
39
	 * @see https://developers.google.com/recaptcha/docs/verify
40
	 *
41
	 * @var array
42
	 */
43
	private $error_codes;
44
45
	/**
46
	 * Create a configured instance to use the reCAPTCHA service.
47
	 *
48
	 * @param string $site_key   Site key to use in HTML code.
49
	 * @param string $secret_key Shared secret between site and reCAPTCHA server.
50
	 * @param array  $config     Config array to optionally configure reCAPTCHA instance.
51
	 */
52
	public function __construct( $site_key, $secret_key, $config = array() ) {
53
		$this->site_key   = $site_key;
54
		$this->secret_key = $secret_key;
55
		$this->config     = wp_parse_args( $config, $this->get_default_config() );
56
57
		$this->error_codes = array(
58
			'missing-input-secret'   => __( 'The secret parameter is missing', 'jetpack' ),
59
			'invalid-input-secret'   => __( 'The secret parameter is invalid or malformed', 'jetpack' ),
60
			'missing-input-response' => __( 'The response parameter is missing', 'jetpack' ),
61
			'invalid-input-response' => __( 'The response parameter is invalid or malformed', 'jetpack' ),
62
			'invalid-json'           => __( 'Invalid JSON', 'jetpack' ),
63
			'unexpected-response'    => __( 'Unexpected response', 'jetpack' ),
64
		);
65
	}
66
67
	/**
68
	 * Get default config for this reCAPTCHA instance.
69
	 *
70
	 * @return array Default config
71
	 */
72
	public function get_default_config() {
73
		return array(
74
			'language'       => get_locale(),
75
			'script_async'   => true,
76
			'tag_class'      => 'g-recaptcha',
77
			'tag_attributes' => array(
78
				'theme'    => 'light',
79
				'type'     => 'image',
80
				'tabindex' => 0,
81
			),
82
		);
83
	}
84
85
	/**
86
	 * Calls the reCAPTCHA siteverify API to verify whether the user passes
87
	 * CAPTCHA test.
88
	 *
89
	 * @param string $response  The value of 'g-recaptcha-response' in the submitted
90
	 *                          form.
91
	 * @param string $remote_ip The end user's IP address.
92
	 *
93
	 * @return bool|WP_Error Returns true if verified. Otherwise WP_Error is returned.
94
	 */
95
	public function verify( $response, $remote_ip ) {
96
		// No need make a request if response is empty.
97
		if ( empty( $response ) ) {
98
			return new WP_Error( 'missing-input-response', $this->error_codes['missing-input-response'], 400 );
99
		}
100
101
		$resp = wp_remote_post( self::VERIFY_URL, $this->get_verify_request_params( $response, $remote_ip ) );
102
		if ( is_wp_error( $resp ) ) {
103
			return $resp;
104
		}
105
106
		$resp_decoded = json_decode( wp_remote_retrieve_body( $resp ), true );
107
		if ( ! $resp_decoded ) {
108
			return new WP_Error( 'invalid-json', $this->error_codes['invalid-json'], 400 );
109
		}
110
111
		// Default error code and message.
112
		$error_code    = 'unexpected-response';
113
		$error_message = $this->error_codes['unexpected-response'];
114
115
		// Use the first error code if exists.
116
		if ( isset( $resp_decoded['error-codes'] ) && is_array( $resp_decoded['error-codes'] ) ) {
117
			if ( isset( $resp_decoded['error-codes'][0] ) && isset( $this->error_codes[ $resp_decoded['error-codes'][0] ] ) ) {
118
				$error_message = $this->error_codes[ $resp_decoded['error-codes'][0] ];
119
				$error_code    = $resp_decoded['error-codes'][0];
120
			}
121
		}
122
123
		if ( ! isset( $resp_decoded['success'] ) ) {
124
			return new WP_Error( $error_code, $error_message );
125
		}
126
127
		if ( true !== $resp_decoded['success'] ) {
128
			return new WP_Error( $error_code, $error_message );
129
		}
130
131
		return true;
132
	}
133
134
	/**
135
	 * Get siteverify request parameters.
136
	 *
137
	 * @param string $response  The value of 'g-recaptcha-response' in the submitted
138
	 *                          form.
139
	 * @param string $remote_ip The end user's IP address.
140
	 *
141
	 * @return array
142
	 */
143
	public function get_verify_request_params( $response, $remote_ip ) {
144
		return array(
145
			'body' => array(
146
				'secret'   => $this->secret_key,
147
				'response' => $response,
148
				'remoteip' => $remote_ip,
149
			),
150
			'sslverify' => true,
151
		);
152
	}
153
154
	/**
155
	 * Get reCAPTCHA HTML to render.
156
	 *
157
	 * @return string
158
	 */
159
	public function get_recaptcha_html() {
160
		return sprintf(
161
			'
162
			<div
163
				class="%s"
164
				data-sitekey="%s"
165
				data-theme="%s"
166
				data-type="%s"
167
				data-tabindex="%s"></div>
168
			<script type="text/javascript" src="https://www.google.com/recaptcha/api.js?hl=%s"%s></script>
169
			',
170
			esc_attr( $this->config['tag_class'] ),
171
			esc_attr( $this->site_key ),
172
			esc_attr( $this->config['tag_attributes']['theme'] ),
173
			esc_attr( $this->config['tag_attributes']['type'] ),
174
			esc_attr( $this->config['tag_attributes']['tabindex'] ),
175
			rawurlencode( $this->config['language'] ),
176
			$this->config['script_async'] ? ' async' : ''
177
		);
178
	}
179
}
180