PluginProbe
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More / 6.1
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More v6.1
6.35 6.34 6.33.1 6.33 6.32.1 6.32 6.31 6.25 6.25.1 6.26 6.26.1 6.27 6.28 6.29 6.3 6.3.1 6.3.2 6.30 6.4 6.4.1 6.4.2 6.5 6.5.1 6.5.2 6.5.3 All 141 releases
formidable / classes / models / fields / FrmFieldCaptcha.php

FrmFieldCaptcha.php in Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More 6.1, at classes/models/fields/FrmFieldCaptcha.php

334 lines 8.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 if ( ! defined( 'ABSPATH' ) ) {
3 die( 'You are not allowed to call this page directly.' );
4 }
5
6 /**
7 * @since 3.0
8 */
9 class FrmFieldCaptcha extends FrmFieldType {
10
11 /**
12 * @var string
13 * @since 3.0
14 */
15 protected $type = 'captcha';
16
17 /**
18 * @return string
19 */
20 protected function include_form_builder_file() {
21 return FrmAppHelper::plugin_path() . '/classes/views/frm-fields/back-end/field-captcha.php';
22 }
23
24 /**
25 * Returns the image name for a captcha.
26 *
27 * @return string
28 */
29 public static function get_captcha_image_name() {
30 $frm_settings = FrmAppHelper::get_settings();
31 $active_captcha = $frm_settings->active_captcha;
32 if ( $active_captcha === 'recaptcha' && $frm_settings->re_type === 'v3' ) {
33 $image_name = 'recaptcha_v3';
34 } else {
35 $image_name = $active_captcha;
36 }
37
38 return $image_name;
39 }
40
41 /**
42 * @return array
43 */
44 protected function field_settings_for_type() {
45 return array(
46 'required' => false,
47 'invalid' => true,
48 'captcha_size' => true,
49 'default' => false,
50 );
51 }
52
53 /**
54 * @return array
55 */
56 protected function new_field_settings() {
57 $frm_settings = FrmAppHelper::get_settings();
58
59 return array(
60 'invalid' => $frm_settings->re_msg,
61 );
62 }
63
64 /**
65 * @return array
66 */
67 protected function extra_field_opts() {
68 return array(
69 'label' => 'none',
70 'captcha_size' => 'normal',
71 'captcha_theme' => 'light',
72 );
73 }
74
75 /**
76 * Remove the "for" attribute for captcha
77 *
78 * @param array $args
79 * @param string $html
80 *
81 * @return string
82 */
83 protected function before_replace_html_shortcodes( $args, $html ) {
84 $frm_settings = FrmAppHelper::get_settings();
85 $replace_response = $frm_settings->active_captcha === 'recaptcha' ? 'g-recaptcha-response' : 'h-captcha-response';
86 $replaced_for = str_replace( ' for="field_[key]"', ' for="' . $replace_response . '"', $html );
87
88 return $replaced_for;
89 }
90
91 public function front_field_input( $args, $shortcode_atts ) {
92 $frm_settings = FrmAppHelper::get_settings();
93 if ( ! self::should_show_captcha() ) {
94 return '';
95 }
96
97 $class_prefix = $this->class_prefix( $frm_settings );
98 $captcha_class = $this->captcha_class( $frm_settings );
99 $captcha_size = $this->captcha_size( $frm_settings );
100 $allow_mutiple = $frm_settings->re_multi;
101
102 if ( $frm_settings->active_captcha === 'recaptcha' ) {
103 $site_key = $frm_settings->pubkey;
104 $recaptcha_options = ' data-size="' . esc_attr( $captcha_size ) . '" data-theme="' . esc_attr( $this->field['captcha_theme'] ) . '"';
105 } else {
106 $site_key = $frm_settings->hcaptcha_pubkey;
107 }
108
109 $html = '<div id="' . esc_attr( $args['html_id'] ) . '" class="' . esc_attr( $class_prefix ) . $captcha_class . '" data-sitekey="' . esc_attr( $site_key ) . '"';
110 $html .= ! empty( $recaptcha_options ) ? $recaptcha_options : '';
111 if ( $captcha_size === 'invisible' && ! $allow_mutiple ) {
112 $html .= ' data-callback="frmAfterRecaptcha"';
113 }
114 $html .= '></div>';
115
116 return $html;
117 }
118
119 protected function load_field_scripts( $args ) {
120 $api_js_url = $this->api_url();
121
122 wp_register_script( 'captcha-api', $api_js_url, array( 'formidable' ), '3', true );
123 wp_enqueue_script( 'captcha-api' );
124 }
125
126 protected function api_url() {
127 $frm_settings = FrmAppHelper::get_settings();
128 if ( $frm_settings->active_captcha === 'recaptcha' ) {
129 return $this->recaptcha_api_url( $frm_settings );
130 }
131
132 return $this->hcaptcha_api_url();
133 }
134
135 protected function recaptcha_api_url( $frm_settings ) {
136 $api_js_url = 'https://www.google.com/recaptcha/api.js?';
137
138 $allow_mutiple = $frm_settings->re_multi;
139 if ( $allow_mutiple ) {
140 $api_js_url .= '&onload=frmRecaptcha&render=explicit';
141 }
142
143 $lang = apply_filters( 'frm_recaptcha_lang', $frm_settings->re_lang, $this->field );
144 if ( ! empty( $lang ) ) {
145 $api_js_url .= '&hl=' . $lang;
146 }
147
148 $api_js_url = apply_filters( 'frm_recaptcha_js_url', $api_js_url );
149
150 return $api_js_url;
151 }
152
153 protected function hcaptcha_api_url() {
154 $api_js_url = 'https://js.hcaptcha.com/1/api.js';
155
156 /**
157 * Allows updating hcaptcha js api url.
158 *
159 * @since 6.0
160 *
161 * @param string $api_js_url
162 */
163 $api_js_url = apply_filters( 'frm_hcaptcha_js_url', $api_js_url );
164
165 return $api_js_url;
166 }
167
168 protected function class_prefix( $frm_settings ) {
169 if ( $this->allow_multiple( $frm_settings ) && $frm_settings->active_captcha === 'recaptcha' ) {
170 $class_prefix = 'frm-';
171 } else {
172 $class_prefix = '';
173 }
174
175 return $class_prefix;
176 }
177
178 protected function captcha_class( $frm_settings ) {
179 return $frm_settings->active_captcha === 'recaptcha' ? 'g-recaptcha' : 'h-captcha';
180 }
181
182 protected function allow_multiple( $frm_settings ) {
183 return $frm_settings->re_multi;
184 }
185
186 /**
187 * @return string
188 */
189 protected function captcha_size( $frm_settings ) {
190 if ( in_array( $frm_settings->re_type, array( 'invisible', 'v3' ), true ) ) {
191 return 'invisible';
192 }
193 // for reverse compatibility
194 return $this->field['captcha_size'] === 'default' ? 'normal' : $this->field['captcha_size'];
195 }
196
197 /**
198 * @since 4.07
199 * @param array $args
200 * @return array
201 */
202 protected function validate_against_api( $args ) {
203 $errors = array();
204 $frm_settings = FrmAppHelper::get_settings();
205 $resp = $this->send_api_check( $frm_settings );
206 $response = json_decode( wp_remote_retrieve_body( $resp ), true );
207
208 if ( is_wp_error( $resp ) ) {
209 $error_string = $resp->get_error_message();
210 $errors[ 'field' . $args['id'] ] = __( 'There was a problem verifying your captcha', 'formidable' );
211 $errors[ 'field' . $args['id'] ] .= ' ' . $error_string;
212 return $errors;
213 }
214
215 if ( ! is_array( $response ) ) {
216 return $errors;
217 }
218
219 if ( $frm_settings->active_captcha === 'recaptcha' ) {
220 if ( 'v3' === $frm_settings->re_type && array_key_exists( 'score', $response ) ) {
221 $threshold = floatval( $frm_settings->re_threshold );
222 $score = floatval( $response['score'] );
223
224 $this->set_score( $score );
225
226 if ( $score < $threshold ) {
227 $response['success'] = false;
228 }
229 }
230 }
231
232 if ( isset( $response['success'] ) && ! $response['success'] ) {
233 // What happens when the CAPTCHA was entered incorrectly
234 $invalid_message = FrmField::get_option( $this->field, 'invalid' );
235 if ( $invalid_message === __( 'The reCAPTCHA was not entered correctly', 'formidable' ) ) {
236 $invalid_message = '';
237 }
238 $errors[ 'field' . $args['id'] ] = ( $invalid_message === '' ? $frm_settings->re_msg : $invalid_message );
239 }
240
241 return $errors;
242 }
243
244 /**
245 * @param float $score
246 * @return void
247 */
248 private function set_score( $score ) {
249 global $frm_vars;
250 if ( ! isset( $frm_vars['captcha_scores'] ) ) {
251 $frm_vars['captcha_scores'] = array();
252 }
253 $form_id = is_object( $this->field ) ? $this->field->form_id : $this->field['form_id'];
254 if ( ! isset( $frm_vars['captcha_scores'][ $form_id ] ) ) {
255 $frm_vars['captcha_scores'][ $form_id ] = $score;
256 }
257 }
258
259 /**
260 * @param array $args
261 * @return array
262 */
263 public function validate( $args ) {
264 if ( ! $this->should_validate() ) {
265 return array();
266 }
267
268 // phpcs:ignore WordPress.Security.NonceVerification.Missing
269 if ( ! isset( $_POST['g-recaptcha-response'] ) && ! isset( $_POST['h-captcha-response'] ) ) {
270 // There was no captcha submitted.
271 return array( 'field' . $args['id'] => __( 'The captcha is missing from this form', 'formidable' ) );
272 }
273
274 return $this->validate_against_api( $args );
275 }
276
277 /**
278 * @since 4.07
279 * @return bool
280 */
281 public static function should_show_captcha() {
282 $frm_settings = FrmAppHelper::get_settings();
283 if ( $frm_settings->active_captcha === 'recaptcha' ) {
284 return ! empty( $frm_settings->pubkey );
285 }
286
287 return ! empty( $frm_settings->hcaptcha_pubkey );
288 }
289
290 protected function should_validate() {
291 $is_hidden_field = apply_filters( 'frm_is_field_hidden', false, $this->field, wp_unslash( $_POST ) ); // phpcs:ignore WordPress.Security.NonceVerification.Missing
292 if ( FrmAppHelper::is_admin() || $is_hidden_field ) {
293 return false;
294 }
295
296 // don't require the captcha if it shouldn't be shown
297 return self::should_show_captcha();
298 }
299
300 protected function send_api_check( $frm_settings ) {
301 $captcha_settings = new FrmFieldCaptchaSettings( $frm_settings );
302
303 $arg_array = array(
304 'body' => array(
305 'secret' => $captcha_settings->secret,
306 'response' => FrmAppHelper::get_param( $captcha_settings->token_field, '', 'post', 'sanitize_text_field' ),
307 'remoteip' => FrmAppHelper::get_ip_address(),
308 ),
309 );
310
311 return wp_remote_post( $captcha_settings->endpoint, $arg_array );
312 }
313
314 /**
315 * Updates field name in page builder to the currently activated captcha if it is set to the default.
316 *
317 * @since 6.0
318 *
319 * @param array $values
320 *
321 * @return array $values
322 */
323 public static function update_field_name( $values ) {
324 if ( $values['type'] === 'captcha' ) {
325 $name = $values['name'];
326 if ( in_array( $name, array( __( 'reCAPTCHA', 'formidable' ), __( 'hCaptcha', 'formidable' ) ), true ) ) {
327 $values['name'] = __( 'Captcha', 'formidable' );
328 }
329 }
330
331 return $values;
332 }
333 }
334