hooks(); } /** * Hooks. * * @since 1.8.5.4 */ private function hooks() { // Maybe load settings page. add_action( 'admin_init', [ $this, 'init' ] ); } /** * Determine if the user is viewing the settings page, if so, party on. * * @since 1.0.0 */ public function init() { // phpcs:ignore WPForms.PHP.HooksMethod.InvalidPlaceForAddingHooks // Only load if we are actually on the settings page. if ( ! wpforms_is_admin_page( 'settings' ) ) { return; } // Include API callbacks and functions. require_once WPFORMS_PLUGIN_DIR . 'includes/admin/settings-api.php'; // Show downgraded notice. $this->maybe_display_downgraded_notice(); // Watch for triggered save. $this->save_settings(); // Determine the current active settings tab. // phpcs:ignore WordPress.Security.NonceVerification.Recommended $this->view = isset( $_GET['view'] ) ? sanitize_key( wp_unslash( $_GET['view'] ) ) : 'general'; $this->modify_url(); add_action( 'admin_enqueue_scripts', [ $this, 'enqueues' ] ); add_action( 'wpforms_admin_page', [ $this, 'output' ] ); // Monitor custom tables. $this->monitor_custom_tables(); // Hook for addons. do_action( 'wpforms_settings_init', $this ); } /** * Remove `wpforms-integration` query arg from URL. * The `wpforms-integration` query arg is used to highlight a specific provider on the Integrations page. * * @since 1.8.5.4 */ private function modify_url() { if ( $this->view !== 'integrations' ) { return; } $_SERVER['REQUEST_URI'] = remove_query_arg( 'wpforms-integration' ); } /** * Display admin notice about using a downgraded version of WPForms. * * @since 1.8.5.4 */ private function maybe_display_downgraded_notice() { if ( ! $this->is_downgraded_version() ) { return; } $notice = sprintf( wp_kses( /* translators: %1$s - WPForms.com doc page URL; %2$s - button text. */ __( 'It looks like you\'ve downgraded to an older version of WPForms. We recommend always using the latest version as some features may not function as expected in older versions. %2$s', 'wpforms-lite' ), [ 'a' => [ 'href' => [], 'target' => [], 'rel' => [], ], ] ), esc_url( wpforms_utm_link( 'https://wpforms.com/docs/why-you-should-always-use-the-latest-version-of-wpforms/', 'Settings', 'Downgrade notice' ) ), esc_html__( 'Learn More', 'wpforms-lite' ) ); Notice::warning( $notice, [ 'dismiss' => Notice::DISMISS_GLOBAL, 'slug' => 'wpforms_is_downgraded', ] ); } /** * Check if plugin was downgraded. * * @since 1.8.5.4 * * @return bool */ private function is_downgraded_version(): bool { // Get all installed versions. $installed_versions = wpforms()->is_pro() ? (array) get_option( Migrations::MIGRATED_OPTION_NAME, [] ) : (array) get_option( LiteMigration::MIGRATED_OPTION_NAME, [] ); // Get the most recent installed version. $db_latest = array_keys( $installed_versions )[ count( $installed_versions ) - 1 ]; // Check if downgrade happened. return version_compare( $db_latest, WPFORMS_VERSION, '>' ); } /** * Sanitize and save settings. * * @since 1.3.9 */ public function save_settings() { // phpcs:ignore Generic.Metrics.CyclomaticComplexity.MaxExceeded, Generic.Metrics.NestingLevel.MaxExceeded // Check nonce and other various security checks. if ( ! isset( $_POST['wpforms-settings-submit'] ) || empty( $_POST['nonce'] ) ) { return; } if ( ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['nonce'] ) ), 'wpforms-settings-nonce' ) ) { return; } if ( ! wpforms_current_user_can() ) { return; } if ( empty( $_POST['view'] ) ) { return; } $current_view = sanitize_key( $_POST['view'] ); // Get registered fields and current settings. $fields = $this->get_registered_settings( $current_view ); $settings = get_option( 'wpforms_settings', [] ); // Views excluded from saving list. $exclude_views = apply_filters( 'wpforms_settings_exclude_view', [], $fields, $settings ); if ( is_array( $exclude_views ) && in_array( $current_view, $exclude_views, true ) ) { // Run a custom save processing for excluded views. do_action( 'wpforms_settings_custom_process', $current_view, $fields, $settings ); return; } if ( empty( $fields ) || ! is_array( $fields ) ) { return; } // Sanitize and prep each field. foreach ( $fields as $id => $field ) { // Certain field types are not valid for saving and are skipped. $exclude = apply_filters( 'wpforms_settings_exclude_type', [ 'content', 'license', 'providers' ] ); if ( empty( $field['type'] ) || in_array( $field['type'], $exclude, true ) ) { continue; } // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized $value = isset( $_POST[ $id ] ) ? wp_unslash( $_POST[ $id ] ) : false; $value_prev = isset( $settings[ $id ] ) ? $settings[ $id ] : false; // Trim all string values. if ( is_string( $value ) ) { $value = trim( $value ); } // Custom filter can be provided for sanitizing, otherwise use defaults. if ( ! empty( $field['filter'] ) && is_callable( $field['filter'] ) ) { $value = call_user_func( $field['filter'], $value, $id, $field, $value_prev ); } else { switch ( $field['type'] ) { case 'checkbox': case 'toggle': $value = (bool) $value; break; case 'image': $value = esc_url_raw( $value ); break; case 'color': $value = wpforms_sanitize_hex_color( $value ); break; case 'color_scheme': $value = array_map( 'wpforms_sanitize_hex_color', $value ); break; case 'number': $value = (float) $value; break; case 'radio': case 'select': $value = $this->validate_field_with_options( $field, $value, $value_prev ); break; case 'text': default: $value = sanitize_text_field( $value ); break; } } // Add to settings. $settings[ $id ] = $value; } // Save settings. wpforms_update_settings( $settings ); Notice::success( esc_html__( 'Settings were successfully saved.', 'wpforms-lite' ) ); } /** * Enqueue assets for the settings page. * * @since 1.0.0 */ public function enqueues() { do_action( 'wpforms_settings_enqueue' ); } /** * Return registered settings tabs. * * @since 1.3.9 * * @return array */ public function get_tabs() { $tabs = [ 'general' => [ 'name' => esc_html__( 'General', 'wpforms-lite' ), 'form' => true, 'submit' => esc_html__( 'Save Settings', 'wpforms-lite' ), ], 'validation' => [ 'name' => esc_html__( 'Validation', 'wpforms-lite' ), 'form' => true, 'submit' => esc_html__( 'Save Settings', 'wpforms-lite' ), ], 'integrations' => [ 'name' => esc_html__( 'Integrations', 'wpforms-lite' ), 'form' => false, 'submit' => false, ], 'geolocation' => [ 'name' => esc_html__( 'Geolocation', 'wpforms-lite' ), 'form' => false, 'submit' => false, ], 'misc' => [ 'name' => esc_html__( 'Misc', 'wpforms-lite' ), 'form' => true, 'submit' => esc_html__( 'Save Settings', 'wpforms-lite' ), ], ]; return apply_filters( 'wpforms_settings_tabs', $tabs ); } /** * Output tab navigation area. * * @since 1.3.9 */ public function tabs() { $tabs = $this->get_tabs(); echo '
' . esc_html__( 'Your license key provides access to updates and addons.', 'wpforms-lite' ) . '
', 'type' => 'content', 'no_label' => true, 'class' => [ 'section-heading' ], ], 'license-key' => [ 'id' => 'license-key', 'name' => esc_html__( 'License Key', 'wpforms-lite' ), 'type' => 'license', ], 'general-heading' => [ 'id' => 'general-heading', 'content' => '', '', '' ), 'type' => 'content', 'no_label' => true, 'class' => [ 'section-heading' ], ], 'validation-required' => [ 'id' => 'validation-required', 'name' => esc_html__( 'Required', 'wpforms-lite' ), 'type' => 'text', 'default' => esc_html__( 'This field is required.', 'wpforms-lite' ), ], 'validation-email' => [ 'id' => 'validation-email', 'name' => esc_html__( 'Email', 'wpforms-lite' ), 'type' => 'text', 'default' => esc_html__( 'Please enter a valid email address.', 'wpforms-lite' ), ], 'validation-email-suggestion' => [ 'id' => 'validation-email-suggestion', 'name' => esc_html__( 'Email Suggestion', 'wpforms-lite' ), 'type' => 'text', 'default' => sprintf( /* translators: %s - suggested email address. */ esc_html__( 'Did you mean %s?', 'wpforms-lite' ), '{suggestion}' ), ], 'validation-email-restricted' => [ 'id' => 'validation-email-restricted', 'name' => esc_html__( 'Email Restricted', 'wpforms-lite' ), 'type' => 'text', 'default' => esc_html__( 'This email address is not allowed.', 'wpforms-lite' ), ], 'validation-number' => [ 'id' => 'validation-number', 'name' => esc_html__( 'Number', 'wpforms-lite' ), 'type' => 'text', 'default' => esc_html__( 'Please enter a valid number.', 'wpforms-lite' ), ], 'validation-number-positive' => [ 'id' => 'validation-number-positive', 'name' => esc_html__( 'Number Positive', 'wpforms-lite' ), 'type' => 'text', 'default' => esc_html__( 'Please enter a valid positive number.', 'wpforms-lite' ), ], 'validation-minimum-price' => [ 'id' => 'validation-minimum-price', 'name' => esc_html__( 'Minimum Price', 'wpforms-lite' ), 'type' => 'text', 'default' => esc_html__( 'Amount entered is less than the required minimum.', 'wpforms-lite' ), ], 'validation-confirm' => [ 'id' => 'validation-confirm', 'name' => esc_html__( 'Confirm Value', 'wpforms-lite' ), 'type' => 'text', 'default' => esc_html__( 'Field values do not match.', 'wpforms-lite' ), ], 'validation-inputmask-incomplete' => [ 'id' => 'validation-inputmask-incomplete', 'name' => esc_html__( 'Input Mask Incomplete', 'wpforms-lite' ), 'type' => 'text', 'default' => esc_html__( 'Please fill out the field in required format.', 'wpforms-lite' ), ], 'validation-check-limit' => [ 'id' => 'validation-check-limit', 'name' => esc_html__( 'Checkbox Selection Limit', 'wpforms-lite' ), 'type' => 'text', 'default' => esc_html__( 'You have exceeded the number of allowed selections: {#}.', 'wpforms-lite' ), ], 'validation-character-limit' => [ 'id' => 'validation-character-limit', 'name' => esc_html__( 'Character Limit', 'wpforms-lite' ), 'type' => 'text', 'default' => sprintf( /* translators: %1$s - characters limit, %2$s - number of characters left. */ esc_html__( 'Limit is %1$s characters. Characters remaining: %2$s.', 'wpforms-lite' ), '{limit}', '{remaining}' ), ], 'validation-word-limit' => [ 'id' => 'validation-word-limit', 'name' => esc_html__( 'Word Limit', 'wpforms-lite' ), 'type' => 'text', 'default' => sprintf( /* translators: %1$s - words limit, %2$s - number of words left. */ esc_html__( 'Limit is %1$s words. Words remaining: %2$s.', 'wpforms-lite' ), '{limit}', '{remaining}' ), ], ], // Provider integrations settings tab. 'integrations' => [ 'integrations-heading' => [ 'id' => 'integrations-heading', 'content' => '
' . esc_html__( 'Manage integrations with popular providers such as Constant Contact, Mailchimp, Zapier, and more.', 'wpforms-lite' ) . '
', 'type' => 'content', 'no_label' => true, 'class' => [ 'section-heading' ], ], 'integrations-providers' => [ 'id' => 'integrations-providers', 'content' => '' . esc_html__( 'Manage integrations with popular providers such as Constant Contact, Mailchimp, Zapier, and more.', 'wpforms-lite' ) . '
', 'type' => 'providers', 'wrap' => 'none', ], ], // Misc. settings tab. 'misc' => [ 'misc-heading' => [ 'id' => 'misc-heading', 'content' => '