PluginProbe ʕ •ᴥ•ʔ
WP Job Manager / 2.4.7
WP Job Manager v2.4.7
2.4.7 2.4.6 2.4.5 2.4.4 2.4.3 2.4.2 trunk 1.0.0 1.0.1 1.0.2 1.0.3 1.0.4 1.0.5 1.1.0 1.1.1 1.1.2 1.1.3 1.10.0 1.11.0 1.11.1 1.12.0 1.12.1 1.13.0 1.14.0 1.15.0 1.16.0 1.16.1 1.17.0 1.18.0 1.19.0 1.2.0 1.20.0 1.20.1 1.21.0 1.21.1 1.21.2 1.21.3 1.21.4 1.22.0 1.22.1 1.22.2 1.22.3 1.23.0 1.23.1 1.23.10 1.23.11 1.23.12 1.23.13 1.23.2 1.23.3 1.23.4 1.23.5 1.23.6 1.23.7 1.23.8 1.23.9 1.24.0 1.24.0.1 1.25.0 1.25.0.1 1.25.1 1.25.1.1 1.25.2 1.25.2.1 1.25.3 1.25.3.1 1.26.0 1.26.0.1 1.26.1 1.26.1.1 1.26.2 1.26.2.1 1.27.0 1.27.0.1 1.28.0 1.28.0.1 1.29.0 1.29.0.1 1.29.1 1.29.1.1 1.29.2 1.29.2.1 1.29.3 1.29.3.1 1.3.0 1.3.1 1.30.0 1.30.0.1 1.30.1 1.30.1.1 1.30.2 1.30.2.1 1.31.0 1.31.0.1 1.31.1 1.31.1.1 1.31.2 1.31.3 1.32.0 1.32.1 1.32.2 1.32.3 1.33.0 1.33.1 1.33.2 1.33.3 1.33.4 1.33.5 1.34.0 1.34.1 1.34.2 1.34.3 1.34.4 1.34.5 1.35.0 1.35.1 1.35.2 1.35.3 1.36.0 1.36.1 1.36.2 1.37.0 1.38.0 1.38.1 1.39.0 1.4.0 1.40.0 1.40.1 1.40.2 1.41.0 1.42.0 1.5.0 1.5.1 1.5.2 1.6.0 1.7.0 1.7.1 1.7.3 1.8.0 1.8.1 1.8.2 1.9.0 1.9.1 1.9.2 1.9.3 2.0.0 2.1.0 2.1.1 2.2.0 2.2.1 2.2.2 2.3.0 2.4.0 2.4.1
wp-job-manager / includes / class-wp-job-manager-recaptcha.php
wp-job-manager / includes Last commit date
3rd-party 3 days ago abstracts 3 months ago admin 2 weeks ago emails 2 weeks ago forms 3 days ago helper 3 months ago promoted-jobs 3 days ago ui 2 weeks ago widgets 2 weeks ago class-access-token.php 2 years ago class-dev-tools.php 2 years ago class-guest-session.php 2 years ago class-guest-user.php 2 years ago class-job-dashboard-shortcode.php 6 months ago class-job-listing-stats.php 2 years ago class-job-overlay.php 2 years ago class-stats-dashboard.php 2 years ago class-stats-script.php 3 months ago class-stats.php 3 months ago class-wp-job-manager-ajax.php 2 months ago class-wp-job-manager-api.php 6 years ago class-wp-job-manager-blocks.php 2 weeks ago class-wp-job-manager-cache-helper.php 3 months ago class-wp-job-manager-category-walker.php 6 years ago class-wp-job-manager-com-api.php 2 years ago class-wp-job-manager-data-cleaner.php 2 years ago class-wp-job-manager-data-exporter.php 3 months ago class-wp-job-manager-dependency-checker.php 2 years ago class-wp-job-manager-email-notifications.php 2 years ago class-wp-job-manager-forms.php 5 years ago class-wp-job-manager-geocode.php 2 weeks ago class-wp-job-manager-install.php 2 years ago class-wp-job-manager-post-types.php 3 days ago class-wp-job-manager-recaptcha.php 6 months ago class-wp-job-manager-rest-api.php 2 months ago class-wp-job-manager-shortcodes.php 2 weeks ago class-wp-job-manager-usage-tracking-data.php 2 years ago class-wp-job-manager-usage-tracking.php 2 years ago class-wp-job-manager-widget.php 2 weeks ago class-wp-job-manager.php 3 months ago trait-singleton.php 2 years ago
class-wp-job-manager-recaptcha.php
262 lines
1 <?php
2 /**
3 * File containing the WP_Job_Manager_Recaptcha class.
4 *
5 * @package wp-job-manager
6 */
7
8 namespace WP_Job_Manager;
9
10 if ( ! defined( 'ABSPATH' ) ) {
11 exit;
12 }
13
14 /**
15 * WP_Job_Manager_Recaptcha class.
16 *
17 * @since 2.3.0
18 */
19 class WP_Job_Manager_Recaptcha {
20
21 use Singleton;
22
23 /**
24 * Site key.
25 *
26 * @var string
27 */
28 private $site_key;
29
30 /**
31 * Secret key.
32 *
33 * @var string
34 */
35 private $secret_key;
36
37 /**
38 * The reCAPTCHA version.
39 *
40 * @var string
41 */
42 private $recaptcha_version;
43
44 const RECAPTCHA_SITE_KEY = 'job_manager_recaptcha_site_key';
45 const RECAPTCHA_SECRET_KEY = 'job_manager_recaptcha_secret_key';
46 const RECAPTCHA_VERSION = 'job_manager_recaptcha_version';
47
48 /**
49 * Initialize class for landing pages.
50 *
51 * @since 2.0.0
52 */
53 private function __construct() {
54 $this->site_key = get_option( self::RECAPTCHA_SITE_KEY );
55 $this->secret_key = get_option( self::RECAPTCHA_SECRET_KEY );
56 $this->recaptcha_version = get_option( self::RECAPTCHA_VERSION, 'v2' );
57
58 }
59
60 /**
61 * Enables the reCAPTCHA field on the form. To do that, it checks if the provided option is enabled and if it is
62 * it adds the necessary hooks to display and validate the reCAPTCHA field.
63 *
64 * @param string $recaptcha_enabled_option The options name to check if the reCAPTCHA field is enabled.
65 * @param array $display_hooks The hooks to display the reCAPTCHA field.
66 * @param array $validate_hooks The hooks to validate the reCAPTCHA field.
67 *
68 * @return void
69 */
70 public function maybe_enable_recaptcha( string $recaptcha_enabled_option, array $display_hooks, array $validate_hooks ) {
71 if ( $this->use_recaptcha_field( $recaptcha_enabled_option ) ) {
72 foreach ( $display_hooks as $display_hook ) {
73 add_action( $display_hook, [ $this, 'display_recaptcha_field' ] );
74 }
75
76 foreach ( $validate_hooks as $validate_hook ) {
77 add_filter( $validate_hook, [ $this, 'validate_recaptcha_field' ] );
78 }
79
80 if ( did_action( 'wp_enqueue_scripts' ) ) {
81 $this->enqueue_scripts();
82 } else {
83 add_action( 'wp_enqueue_scripts', [ $this, 'enqueue_scripts' ] );
84 }
85 }
86 }
87
88 /**
89 * Use reCAPTCHA field on the form?
90 *
91 * @param string $option_name The options name to check if the reCAPTCHA field is enabled.
92 *
93 * @return bool
94 */
95 private function use_recaptcha_field( $option_name ) {
96 if ( ! $this->is_recaptcha_available() ) {
97 return false;
98 }
99
100 return 1 === absint( get_option( $option_name ) );
101 }
102
103 /**
104 * Enqueue the scripts and add appropriate hooks for the recaptcha to load.
105 *
106 * @access private
107 */
108 public function enqueue_scripts() {
109 $instance = self::instance();
110
111 if ( in_array( $instance->recaptcha_version, [ 'v2', 'v3' ], true ) ) {
112 $recaptcha_version = $instance->recaptcha_version;
113 $recaptcha_url = '';
114
115 if ( 'v2' === $recaptcha_version ) {
116 $recaptcha_url = 'https://www.google.com/recaptcha/api.js';
117 } elseif ( 'v3' === $recaptcha_version ) {
118 $recaptcha_url = 'https://www.google.com/recaptcha/api.js?render=' . $instance->site_key;
119 }
120 wp_enqueue_script( 'recaptcha', $recaptcha_url, [], JOB_MANAGER_VERSION, [ 'strategy' => 'defer' ] );
121 }
122 }
123
124 /**
125 * Checks whether reCAPTCHA has been set up and is available.
126 *
127 * @access private
128 *
129 * @return bool
130 */
131 public function is_recaptcha_available() {
132 $is_recaptcha_available = ! empty( $this->site_key ) && ! empty( $this->secret_key );
133
134 /**
135 * Filter whether reCAPTCHA should be available for this form.
136 *
137 * @since 1.30.0
138 *
139 * @param bool $is_recaptcha_available
140 */
141 return apply_filters( 'job_manager_is_recaptcha_available', $is_recaptcha_available );
142 }
143
144 /**
145 * Display the reCAPTCHA field in the form.
146 *
147 * @access private
148 *
149 * @return void
150 */
151 public function display_recaptcha_field() {
152 $field = [];
153 $field['label'] = get_option( 'job_manager_recaptcha_label' );
154 $field['required'] = true;
155 $field['site_key'] = $this->site_key;
156
157 $template = 'form-fields/recaptcha-' . ( 'v3' === $this->recaptcha_version ? 'v3-' : '' ) . 'field.php';
158
159 get_job_manager_template(
160 $template,
161 [
162 'key' => 'recaptcha',
163 'field' => $field,
164 ]
165 );
166 }
167
168 /**
169 * Validate a reCAPTCHA field.
170 *
171 * @param bool $success
172 *
173 * @access private
174 *
175 * @return bool|\WP_Error
176 */
177 public function validate_recaptcha_field( $success ) {
178 $recaptcha_field_label = get_option( 'job_manager_recaptcha_label' );
179
180 // translators: %s is the name of the form validation that failed.
181 $validation_error = new \WP_Error( 'validation-error', sprintf( esc_html__( '"%s" check failed. Please try again.', 'wp-job-manager' ), $recaptcha_field_label ) );
182
183 // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce check happens earlier (when possible).
184 $input_recaptcha_response = isset( $_POST['g-recaptcha-response'] ) ? sanitize_text_field( wp_unslash( $_POST['g-recaptcha-response'] ) ) : '';
185
186 if ( empty( $input_recaptcha_response ) ) {
187 return $validation_error;
188 }
189
190 if ( 'v2' === $this->recaptcha_version ) {
191 $default_remote_addr = isset( $_SERVER['REMOTE_ADDR'] ) ? sanitize_text_field( wp_unslash( $_SERVER['REMOTE_ADDR'] ) ) : '';
192 $response = wp_remote_get(
193 add_query_arg(
194 [
195 'secret' => $this->secret_key,
196 'response' => $input_recaptcha_response,
197 'remoteip' => isset( $_SERVER['HTTP_X_FORWARDED_FOR'] ) ? sanitize_text_field( wp_unslash( $_SERVER['HTTP_X_FORWARDED_FOR'] ) ) : $default_remote_addr,
198 ],
199 'https://www.google.com/recaptcha/api/siteverify'
200 )
201 );
202 if ( is_wp_error( $response ) || empty( $response['body'] ) ) {
203 return $validation_error;
204 } else {
205 $json = json_decode( $response['body'] );
206 if ( ! $json || ! $json->success ) {
207 return $validation_error;
208 }
209 }
210 } elseif ( 'v3' === $this->recaptcha_version ) {
211 $recaptcha_url = 'https://www.google.com/recaptcha/api/siteverify';
212 $recaptcha_data = [
213 'secret' => $this->secret_key,
214 'response' => $input_recaptcha_response,
215 'remoteip' => sanitize_text_field( wp_unslash( $_SERVER['REMOTE_ADDR'] ) ),
216 ];
217
218 $response = wp_remote_post(
219 $recaptcha_url,
220 [
221 'body' => $recaptcha_data,
222 'headers' => [
223 'Content-Type' => 'application/x-www-form-urlencoded',
224 ],
225 ]
226 );
227
228 if ( is_wp_error( $response ) || empty( $response['body'] ) ) {
229 return $validation_error;
230 } else {
231 $response_body = wp_remote_retrieve_body( $response );
232 $response_body = json_decode( $response_body );
233 }
234
235 /**
236 * Filter the score tolerance for reCAPTCHA v3.
237 *
238 * The score tolerance determines how strict the reCAPTCHA v3 validation is. A higher tolerance allows more leniency in accepting scores. A higher score means more certainty that the user is human.
239 *
240 * @since 2.3.0
241 *
242 * @param float $score_tolerance The score tolerance value. Default is 0.5.
243 */
244 $score_tolerance = apply_filters( 'job_manager_recaptcha_v3_score_tolerance', 0.5 );
245
246 if ( ! $response_body->success || $response_body->score < $score_tolerance ) {
247 return $validation_error;
248 }
249 }
250 return $success;
251 }
252
253 /**
254 * Get the reCAPTCHA version.
255 *
256 * @return string
257 */
258 public function get_recaptcha_version() {
259 return $this->recaptcha_version;
260 }
261 }
262