PluginProbe
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More / 6.25.1
Formidable Forms – WordPress Form Builder for Contact Forms, Calculators, Quizzes & More v6.25.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 / FrmSettings.php

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

510 lines 13.0 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 #[\AllowDynamicProperties]
7 class FrmSettings {
8 public $option_name = 'frm_options';
9 public $menu;
10 public $mu_menu;
11 public $fade_form;
12 public $admin_bar;
13
14 public $success_msg;
15 public $blank_msg;
16 public $unique_msg;
17 public $invalid_msg;
18 public $failed_msg;
19 public $submit_value;
20 public $login_msg;
21 public $admin_permission;
22
23 public $email_to;
24 public $load_style;
25 public $custom_style;
26
27 public $active_captcha;
28
29 /**
30 * Settings for reCAPTCHA.
31 */
32
33 /**
34 * @var string|null
35 */
36 public $pubkey;
37
38 /**
39 * @var string|null
40 */
41 public $privkey;
42 public $re_lang;
43 public $re_type;
44 public $re_msg;
45 public $re_multi;
46 public $re_threshold;
47
48 /**
49 * Settings for hCaptcha.
50 */
51
52 /**
53 * @var string
54 */
55 public $hcaptcha_pubkey;
56
57 /**
58 * @var string|null
59 */
60 public $hcaptcha_privkey;
61
62 /**
63 * Settings for Turnstile.
64 */
65
66 /**
67 * @var string
68 */
69 public $turnstile_pubkey;
70
71 /**
72 * @var string|null
73 */
74 public $turnstile_privkey;
75
76 public $no_ips;
77 public $custom_header_ip;
78 public $current_form = 0;
79 public $tracking;
80 public $summary_emails;
81 public $summary_emails_recipients;
82
83 public $default_email;
84 public $from_email;
85 public $currency;
86
87 /**
88 * @since 6.0
89 *
90 * @var false|string|null
91 */
92 public $custom_css;
93
94 public $honeypot;
95
96 public $wp_spam_check;
97
98 public $denylist_check;
99
100 /**
101 * @since 6.25.1
102 *
103 * @var int|null 1 if installed after welcome tour update, null otherwise.
104 */
105 public $installed_after_welcome_tour_update;
106
107 public $disallowed_words;
108
109 public $allowed_words;
110
111 public function __construct( $args = array() ) {
112 if ( ! defined( 'ABSPATH' ) ) {
113 die( 'You are not allowed to call this page directly.' );
114 }
115
116 $settings = get_option( $this->option_name );
117
118 if ( ! is_object( $settings ) ) {
119 $settings = $this->translate_settings( $settings );
120 }
121
122 foreach ( $settings as $setting_name => $setting ) {
123 $this->{$setting_name} = $setting;
124 unset( $setting_name, $setting );
125 }
126
127 $this->set_default_options();
128
129 $this->maybe_filter_for_form( $args );
130 }
131
132 private function translate_settings( $settings ) {
133 if ( $settings ) {
134 // Workaround for W3 total cache conflict.
135 return unserialize( serialize( $settings ) );
136 }
137
138 // If unserializing didn't work.
139 $settings = $this;
140
141 update_option( $this->option_name, $settings, 'yes' );
142
143 return $settings;
144 }
145
146 /**
147 * @return array
148 */
149 public function default_options() {
150 return array(
151 'menu' => apply_filters( 'frm_default_menu', 'Formidable' ),
152 'mu_menu' => 0,
153 'fade_form' => false,
154 'admin_bar' => false,
155
156 're_multi' => 1,
157
158 'success_msg' => __( 'Your responses were successfully submitted. Thank you!', 'formidable' ),
159 // translators: %s: [field_name] shortcode.
160 'blank_msg' => sprintf( __( '%s cannot be blank.', 'formidable' ), '[field_name]' ),
161 // translators: %s: [field_name] shortcode.
162 'unique_msg' => sprintf( __( '%s must be unique.', 'formidable' ), '[field_name]' ),
163 'invalid_msg' => __( 'There was a problem with your submission. Errors are marked below.', 'formidable' ),
164 'failed_msg' => __( 'We\'re sorry. It looks like you\'ve already submitted that.', 'formidable' ),
165 'submit_value' => __( 'Submit', 'formidable' ),
166 'login_msg' => __( 'You do not have permission to view this form.', 'formidable' ),
167 'admin_permission' => __( 'You do not have permission to do that', 'formidable' ),
168 'new_tab_msg' => __( 'The page has been opened in a new tab.', 'formidable' ),
169
170 'email_to' => '[admin_email]',
171 'enable_gdpr' => 0,
172 'no_gdpr_cookies' => 0,
173 'no_ips' => 0,
174 'custom_header_ip' => 0,
175 'tracking' => FrmAppHelper::pro_is_installed(),
176 // Only enable this by default for the main site.
177 'summary_emails' => get_current_blog_id() === get_main_site_id(),
178 'summary_emails_recipients' => '[admin_email]',
179
180 // Normally custom CSS is a string. A false value is used when nothing has been set.
181 // When it is false, we try to use the old custom_key value from the default style's post_content array.
182 'custom_css' => false,
183 'honeypot' => 1,
184 'wp_spam_check' => 0,
185 'denylist_check' => 0,
186 'disallowed_words' => '',
187 'allowed_words' => '',
188 'email_style' => 'classic',
189 );
190 }
191
192 /**
193 * @return void
194 */
195 private function set_default_options() {
196 $this->fill_captcha_settings();
197
198 if ( ! isset( $this->load_style ) ) {
199 if ( ! isset( $this->custom_style ) ) {
200 $this->custom_style = true;
201 }
202
203 $this->load_style = 'all';
204 }
205
206 $this->fill_with_defaults();
207
208 if ( is_multisite() && is_admin() ) {
209 $mu_menu = get_site_option( 'frm_admin_menu_name' );
210 if ( $mu_menu && ! empty( $mu_menu ) ) {
211 $this->menu = $mu_menu;
212 $this->mu_menu = 1;
213 }
214 }
215
216 $frm_roles = FrmAppHelper::frm_capabilities( 'pro' );
217 foreach ( $frm_roles as $frm_role => $frm_role_description ) {
218 if ( ! isset( $this->$frm_role ) ) {
219 $this->$frm_role = 'administrator';
220 }
221 }
222
223 if ( ! isset( $this->default_email ) ) {
224 $this->default_email = get_option( 'admin_email' );
225 }
226
227 if ( ! isset( $this->currency ) ) {
228 $this->currency = 'USD';
229 }
230 }
231
232 /**
233 * @param array $params
234 * @return void
235 */
236 public function fill_with_defaults( $params = array() ) {
237 $settings = $this->default_options();
238 $filter_html = ! FrmAppHelper::allow_unfiltered_html();
239
240 if ( $filter_html ) {
241 $filter_keys = array( 'failed_msg', 'blank_msg', 'invalid_msg', 'admin_permission', 'unique_msg', 'success_msg', 'submit_value', 'login_msg', 'menu' );
242 if ( ! empty( $params['additional_filter_keys'] ) ) {
243 $filter_keys = array_merge( $filter_keys, $params['additional_filter_keys'] );
244 }
245 } else {
246 $filter_keys = array();
247 }
248
249 foreach ( $settings as $setting => $default ) {
250 if ( isset( $params[ 'frm_' . $setting ] ) ) {
251 $this->{$setting} = $params[ 'frm_' . $setting ];
252 } elseif ( ! isset( $this->{$setting} ) ) {
253 $this->{$setting} = $default;
254 }
255
256 if ( $setting === 'menu' && empty( $this->{$setting} ) ) {
257 $this->{$setting} = $default;
258 }
259
260 $this->{$setting} = $this->maybe_sanitize_global_setting( $this->{$setting}, $setting, $filter_keys );
261 unset( $setting, $default );
262 }
263 }
264
265 /**
266 * Handle sanitizing for a target global setting key.
267 *
268 * @since 6.0
269 *
270 * @param mixed $value The unsanitized global setting value.
271 * @param string $key The key of the global setting being saved.
272 * @param array $filter_keys These keys that are filtered with kses.
273 * @return mixed
274 */
275 private function maybe_sanitize_global_setting( $value, $key, $filter_keys ) {
276 if ( 'custom_css' === $key ) {
277 if ( false === $value ) {
278 // Avoid changing the false default value to an empty string.
279 return $value;
280 }
281 return sanitize_textarea_field( $value );
282 }
283
284 if ( in_array( $key, $filter_keys, true ) ) {
285 return FrmAppHelper::kses( $value, 'all' );
286 }
287
288 return $value;
289 }
290
291 /**
292 * @return void
293 */
294 private function fill_captcha_settings() {
295 if ( ! isset( $this->active_captcha ) ) {
296 $this->active_captcha = 'recaptcha';
297 }
298
299 $privkey = '';
300 $re_lang = '';
301
302 if ( ! isset( $this->hcaptcha_privkey ) ) {
303 $this->hcaptcha_privkey = '';
304 }
305
306 if ( ! isset( $this->turnstile_privkey ) ) {
307 $this->turnstile_privkey = '';
308 }
309
310 if ( ! isset( $this->pubkey ) ) {
311 // Get the options from the database.
312 $recaptcha_opt = is_multisite() ? get_site_option( 'recaptcha' ) : get_option( 'recaptcha' );
313 $this->pubkey = $recaptcha_opt['pubkey'] ?? '';
314 $privkey = $recaptcha_opt['privkey'] ?? $privkey;
315 $re_lang = $recaptcha_opt['re_lang'] ?? $re_lang;
316 }
317
318 if ( empty( $this->re_msg ) ) {
319 $this->re_msg = __( 'The CAPTCHA was not entered correctly', 'formidable' );
320 }
321
322 if ( ! isset( $this->privkey ) ) {
323 $this->privkey = $privkey;
324 }
325
326 if ( ! isset( $this->re_lang ) ) {
327 $this->re_lang = $re_lang;
328 }
329
330 if ( ! isset( $this->re_type ) ) {
331 $this->re_type = '';
332 }
333
334 if ( ! isset( $this->re_threshold ) ) {
335 $this->re_threshold = .5;
336 }
337 }
338
339 /**
340 * Get values that may be shown on the front-end without an override in the form settings.
341 *
342 * @since 3.06.01
343 *
344 * @return string[]
345 */
346 public function translatable_strings() {
347 return array(
348 'invalid_msg',
349 'admin_permission',
350 'failed_msg',
351 'login_msg',
352 );
353 }
354
355 /**
356 * Allow strings to be filtered when a specific form may be displaying them.
357 *
358 * @since 3.06.01
359 *
360 * @return void
361 */
362 public function maybe_filter_for_form( $args ) {
363 if ( isset( $args['current_form'] ) && is_numeric( $args['current_form'] ) ) {
364 $this->current_form = $args['current_form'];
365 foreach ( $this->translatable_strings() as $string ) {
366 $this->{$string} = apply_filters( 'frm_global_setting', $this->{$string}, $string, $this );
367 $this->{$string} = apply_filters( 'frm_global_' . $string, $this->{$string}, $this );
368 }
369 }
370 }
371
372 /**
373 * @param array $params
374 * @param array $errors
375 */
376 public function validate( $params, $errors ) {
377 return apply_filters( 'frm_validate_settings', $errors, $params );
378 }
379
380 /**
381 * @param array $params
382 *
383 * @return void
384 */
385 public function update( $params ) {
386 $this->fill_with_defaults( $params );
387 $this->update_settings( $params );
388
389 if ( $this->mu_menu ) {
390 update_site_option( 'frm_admin_menu_name', $this->menu );
391 } elseif ( current_user_can( 'administrator' ) ) {
392 update_site_option( 'frm_admin_menu_name', false );
393 }
394
395 $this->update_roles( $params );
396
397 do_action( 'frm_update_settings', $params );
398
399 if ( function_exists( 'get_filesystem_method' ) ) {
400 // Save styling settings in case fallback setting changes.
401 $frm_style = new FrmStyle();
402 $frm_style->update( 'default' );
403 }
404 }
405
406 /**
407 * @param array $params
408 * @return void
409 */
410 private function update_settings( $params ) {
411 $this->active_captcha = $params['frm_active_captcha'];
412 $this->pubkey = trim( $params['frm_pubkey'] );
413 $this->privkey = trim( $params['frm_privkey'] );
414 $this->re_type = $params['frm_re_type'];
415 $this->re_lang = $params['frm_re_lang'];
416 $this->re_threshold = floatval( $params['frm_re_threshold'] );
417 $this->hcaptcha_pubkey = trim( $params['frm_hcaptcha_pubkey'] );
418 $this->hcaptcha_privkey = trim( $params['frm_hcaptcha_privkey'] );
419 $this->turnstile_pubkey = trim( $params['frm_turnstile_pubkey'] );
420 $this->turnstile_privkey = trim( $params['frm_turnstile_privkey'] );
421 $this->load_style = $params['frm_load_style'];
422 $this->custom_css = $params['frm_custom_css'];
423 $this->default_email = $params['frm_default_email'];
424 $this->from_email = $params['frm_from_email'];
425 $this->currency = $params['frm_currency'];
426
427 $checkboxes = array(
428 'mu_menu',
429 're_multi',
430 'fade_form',
431 'no_ips',
432 'no_gdpr_cookies',
433 'enable_gdpr',
434 'custom_header_ip',
435 'tracking',
436 'admin_bar',
437 'summary_emails',
438 'honeypot',
439 'wp_spam_check',
440 'denylist_check',
441 );
442 foreach ( $checkboxes as $set ) {
443 $this->$set = isset( $params[ 'frm_' . $set ] ) ? absint( $params[ 'frm_' . $set ] ) : 0;
444 }
445 }
446
447 /**
448 * @return void
449 */
450 private function update_roles( $params ) {
451 global $wp_roles;
452
453 $frm_roles = FrmAppHelper::frm_capabilities();
454 $roles = get_editable_roles();
455 foreach ( $frm_roles as $frm_role => $frm_role_description ) {
456 $this->$frm_role = (array) ( $params[ $frm_role ] ?? 'administrator' );
457
458 // Make sure administrators always have permissions
459 if ( ! in_array( 'administrator', $this->$frm_role, true ) ) {
460 array_push( $this->$frm_role, 'administrator' );
461 }
462
463 foreach ( $roles as $role => $details ) {
464 if ( in_array( $role, $this->$frm_role ) ) {
465 $wp_roles->add_cap( $role, $frm_role );
466 } else {
467 $wp_roles->remove_cap( $role, $frm_role );
468 }
469 }
470 }
471 }
472
473 /**
474 * Updates a single setting with specified sanitization.
475 *
476 * @since 6.9
477 *
478 * @param string $key The setting key to update.
479 * @param mixed $value The new value for the setting.
480 * @param string $sanitize The name of the sanitization function to apply to the new value.
481 * @return bool True on success, false on failure.
482 */
483 public function update_setting( $key, $value, $sanitize ) {
484 if ( ! property_exists( $this, $key ) || ! is_callable( $sanitize ) ) {
485 // Setting does not exist or sanitization function name is not callable.
486 return false;
487 }
488
489 // Update the property value.
490 FrmAppHelper::sanitize_value( $sanitize, $value );
491 $this->{$key} = $value;
492
493 return true;
494 }
495
496 /**
497 * @return void
498 */
499 public function store() {
500 // Save the posted value in the database
501
502 update_option( 'frm_options', $this );
503
504 delete_transient( 'frm_options' );
505 set_transient( 'frm_options', $this );
506
507 do_action( 'frm_store_settings' );
508 }
509 }
510