dvadf
File manager - Edit - /home/theblueo/tv/fb4e3b/includes.tar
Back
class-form.php 0000666 00000045221 15213301444 0007330 0 ustar 00 <?php /** * All the form goodness and basics. * * Contains a bunch of helper methods as well. * * @since 1.0.0 */ class WPForms_Form_Handler { /** * Primary class constructor. * * @since 1.0.0 */ public function __construct() { // Register wpforms custom post type. $this->register_cpt(); // Add wpforms to new-content admin bar menu. add_action( 'admin_bar_menu', array( $this, 'admin_bar' ), 99 ); } /** * Register the custom post type to be used for forms. * * @since 1.0.0 */ public function register_cpt() { // Custom post type arguments, which can be filtered if needed. $args = apply_filters( 'wpforms_post_type_args', array( 'label' => 'WPForms', 'public' => false, 'exclude_from_search' => true, 'show_ui' => false, 'show_in_admin_bar' => false, 'rewrite' => false, 'query_var' => false, 'can_export' => false, 'supports' => array( 'title' ), 'capability_type' => 'wpforms_form', // Not using 'capability_type' anywhere. It just has to be custom for security reasons. 'map_meta_cap' => false, // Don't let WP to map meta caps to have a granular control over this process via 'map_meta_cap' filter. ) ); // Register the post type. register_post_type( 'wpforms', $args ); } /** * Add "WPForms" item to new-content admin bar menu item. * * @since 1.1.7.2 * * @param WP_Admin_Bar $wp_admin_bar WP_Admin_Bar instance, passed by reference. */ public function admin_bar( $wp_admin_bar ) { if ( ! is_admin_bar_showing() || ! wpforms_current_user_can( 'create_forms' ) ) { return; } $args = array( 'id' => 'wpforms', 'title' => esc_html__( 'WPForms', 'wpforms-lite' ), 'href' => admin_url( 'admin.php?page=wpforms-builder' ), 'parent' => 'new-content', ); $wp_admin_bar->add_node( $args ); } /** * Fetch forms. * * @since 1.0.0 * * @param mixed $id Form ID. * @param array $args Additional arguments array. * * @return array|bool|null|WP_Post */ public function get( $id = '', $args = array() ) { $args = apply_filters( 'wpforms_get_form_args', $args, $id ); if ( false === $id ) { return false; } $forms = empty( $id ) ? $this->get_multiple( $args ) : $this->get_single( $id, $args ); if ( empty( $forms ) ) { return false; } return $forms; } /** * Fetch a single form. * * @since 1.5.8 * * @param string|int $id Form ID. * @param array $args Additional arguments array. * * @return array|bool|null|WP_Post */ protected function get_single( $id = '', $args = array() ) { $args = apply_filters( 'wpforms_get_single_form_args', $args, $id ); if ( ! isset( $args['cap'] ) && wpforms()->get( 'access' )->init_allowed() ) { $args['cap'] = 'view_form_single'; } if ( ! empty( $args['cap'] ) && ! wpforms_current_user_can( $args['cap'], $id ) ) { return false; } // @todo add $id array support // If ID is provided, we get a single form $form = get_post( absint( $id ) ); if ( ! empty( $args['content_only'] ) ) { $form = ! empty( $form ) && 'wpforms' === $form->post_type ? wpforms_decode( $form->post_content ) : false; } return $form; } /** * Fetch multiple forms. * * @since 1.5.8 * * @param array $args Additional arguments array. * * @return array */ protected function get_multiple( $args = array() ) { $args = apply_filters( 'wpforms_get_multiple_forms_args', $args ); // No ID provided, get multiple forms. $defaults = array( 'orderby' => 'id', 'order' => 'ASC', 'no_found_rows' => true, 'nopaging' => true, ); $args = wp_parse_args( $args, $defaults ); $args['post_type'] = 'wpforms'; return get_posts( $args ); } /** * Delete forms. * * @since 1.0.0 * * @param array $ids Form IDs. * * @return bool */ public function delete( $ids = array() ) { if ( ! is_array( $ids ) ) { $ids = array( $ids ); } $ids = array_map( 'absint', $ids ); foreach ( $ids as $id ) { // Check for permissions. if ( ! wpforms_current_user_can( 'delete_form_single', $id ) ) { return false; } if ( class_exists( 'WPForms_Entry_Handler', false ) ) { wpforms()->entry->delete_by( 'form_id', $id ); wpforms()->entry_meta->delete_by( 'form_id', $id ); wpforms()->entry_fields->delete_by( 'form_id', $id ); } $form = wp_delete_post( $id, true ); if ( ! $form ) { return false; } } do_action( 'wpforms_delete_form', $ids ); return true; } /** * Add new form. * * @since 1.0.0 * * @param string $title Form title. * @param array $args Additional arguments. * @param array $data Form data. * * @return mixed */ public function add( $title = '', $args = array(), $data = array() ) { // Must have a title. if ( empty( $title ) ) { return false; } // Check for permissions. if ( ! wpforms_current_user_can( 'create_forms' ) ) { return false; } // This filter breaks forms if they contain HTML. remove_filter( 'content_save_pre', 'balanceTags', 50 ); // Add filter of the link rel attr to avoid JSON damage. add_filter( 'wp_targeted_link_rel', '__return_empty_string', 50, 1 ); $args = apply_filters( 'wpforms_create_form_args', $args, $data ); $form_content = array( 'field_id' => '0', 'settings' => array( 'form_title' => sanitize_text_field( $title ), 'form_desc' => '', ), ); // Prevent $args['post_content'] from overwriting predefined $form_content. // Typically it happens if the form was created with a form template and a user was not redirected to a form editing screen afterwards. // This is only possible if a user has 'wpforms_create_forms' and no 'wpforms_edit_own_forms' capability. if ( isset( $args['post_content'] ) && is_array( wpforms_decode( $args['post_content'] ) ) ) { $args['post_content'] = wpforms_encode( array_replace_recursive( $form_content, wpforms_decode( $args['post_content'] ) ) ); } // Merge args and create the form. $form = wp_parse_args( $args, array( 'post_title' => esc_html( $title ), 'post_status' => 'publish', 'post_type' => 'wpforms', 'post_content' => wpforms_encode( $form_content ), ) ); $form_id = wp_insert_post( $form ); // If user has no editing permissions the form considered to be created out of the WPForms form builder's context. if ( ! wpforms_current_user_can( 'edit_form_single', $form_id ) ) { $data['builder'] = false; } // If the form is created outside the context of the WPForms form // builder, then we define some additional default values. if ( ! empty( $form_id ) && isset( $data['builder'] ) && $data['builder'] === false ) { $form_data = json_decode( wp_unslash( $form['post_content'] ), true ); $form_data['id'] = $form_id; $form_data['settings']['submit_text'] = esc_html__( 'Submit', 'wpforms-lite' ); $form_data['settings']['submit_text_processing'] = esc_html__( 'Sending...', 'wpforms-lite' ); $form_data['settings']['notification_enable'] = '1'; $form_data['settings']['notifications'] = array( '1' => array( 'email' => '{admin_email}', 'subject' => sprintf( esc_html__( 'New Entry: %s', 'wpforms-lite' ), esc_html( $title ) ), 'sender_name' => get_bloginfo( 'name' ), 'sender_address' => '{admin_email}', 'replyto' => '{field_id="1"}', 'message' => '{all_fields}', ), ); $form_data['settings']['confirmations'] = array( '1' => array( 'type' => 'message', 'message' => esc_html__( 'Thanks for contacting us! We will be in touch with you shortly.', 'wpforms-lite' ), 'message_scroll' => '1', ), ); $this->update( $form_id, $form_data, array( 'cap' => 'create_forms' ) ); } do_action( 'wpforms_create_form', $form_id, $form, $data ); return $form_id; } /** * Update form. * * @since 1.0.0 * * @param string|int $form_id Form ID. * @param array $data Data retrieved from $_POST and processed. * @param array $args Empty by default, may have custom data not intended to be saved. * * @return mixed * @internal param string $title */ public function update( $form_id = '', $data = array(), $args = array() ) { if ( empty( $data ) ) { return false; } if ( empty( $form_id ) && isset( $data['id'] ) ) { $form_id = $data['id']; } if ( ! isset( $args['cap'] ) ) { $args['cap'] = 'edit_form_single'; } if ( ! empty( $args['cap'] ) && ! wpforms_current_user_can( $args['cap'], $form_id ) ) { return false; } // This filter breaks forms if they contain HTML. remove_filter( 'content_save_pre', 'balanceTags', 50 ); // Add filter of the link rel attr to avoid JSON damage. add_filter( 'wp_targeted_link_rel', '__return_empty_string', 50, 1 ); $data = wp_unslash( $data ); $title = empty( $data['settings']['form_title'] ) ? get_the_title( $form_id ) : $data['settings']['form_title']; $desc = empty( $data['settings']['form_desc'] ) ? '' : $data['settings']['form_desc']; $data['field_id'] = ! empty( $data['field_id'] ) ? absint( $data['field_id'] ) : '0'; // Preserve form meta. $meta = $this->get_meta( $form_id ); if ( $meta ) { $data['meta'] = $meta; } // Preserve fields meta. if ( isset( $data['fields'] ) ) { $data['fields'] = $this->update__preserve_fields_meta( $data['fields'], $form_id ); } // Sanitize - don't allow tags for users who do not have appropriate cap. // If we don't do this, forms for these users can get corrupt due to // conflicts with wp_kses(). if ( ! current_user_can( 'unfiltered_html' ) ) { $data = map_deep( $data, 'wp_strip_all_tags' ); } // Sanitize notifications names. if ( isset( $data['settings']['notifications'] ) ) { $data['settings']['notifications'] = $this->update__sanitize_notifications_names( $data['settings']['notifications'] ); } unset( $notification ); $form = apply_filters( 'wpforms_save_form_args', array( 'ID' => $form_id, 'post_title' => esc_html( $title ), 'post_excerpt' => $desc, 'post_content' => wpforms_encode( $data ), ), $data, $args ); $_form_id = wp_update_post( $form ); do_action( 'wpforms_save_form', $_form_id, $form ); return $_form_id; } /** * Preserve fields meta in 'update' method. * * @since 1.5.8 * * @param array $fields Form fields. * @param string|int $form_id Form ID. * * @return array */ protected function update__preserve_fields_meta( $fields, $form_id ) { foreach ( $fields as $i => $field_data ) { if ( isset( $field_data['id'] ) ) { $field_meta = $this->get_field_meta( $form_id, $field_data['id'] ); if ( $field_meta ) { $fields[ $i ]['meta'] = $field_meta; } } } return $fields; } /** * Sanitize notifications names meta in 'update' method. * * @since 1.5.8 * * @param array $notifications Form notifications. * * @return array */ protected function update__sanitize_notifications_names( $notifications ) { foreach ( $notifications as $id => &$notification ) { if ( ! empty( $notification['notification_name'] ) ) { $notification['notification_name'] = sanitize_text_field( $notification['notification_name'] ); } } return $notifications; } /** * Duplicate forms. * * @since 1.1.4 * * @param array $ids Form IDs to duplicate. * * @return bool */ public function duplicate( $ids = array() ) { // Check for permissions. if ( ! wpforms_current_user_can( 'create_forms' ) ) { return false; } // Add filter of the link rel attr to avoid JSON damage. add_filter( 'wp_targeted_link_rel', '__return_empty_string', 50, 1 ); // This filter breaks forms if they contain HTML. remove_filter( 'content_save_pre', 'balanceTags', 50 ); if ( ! is_array( $ids ) ) { $ids = array( $ids ); } $ids = array_map( 'absint', $ids ); foreach ( $ids as $id ) { // Get original entry. $form = get_post( $id ); if ( ! wpforms_current_user_can( 'view_form_single', $id ) ) { return false; } // Confirm form exists. if ( ! $form || empty( $form ) ) { return false; } // Get the form data. $new_form_data = wpforms_decode( $form->post_content ); // Remove form ID from title if present. $new_form_data['settings']['form_title'] = str_replace( '(ID #' . absint( $id ) . ')', '', $new_form_data['settings']['form_title'] ); // Create the duplicate form. $new_form = array( 'post_content' => wpforms_encode( $new_form_data ), 'post_excerpt' => $form->post_excerpt, 'post_status' => $form->post_status, 'post_title' => $new_form_data['settings']['form_title'], 'post_type' => $form->post_type, ); $new_form_id = wp_insert_post( $new_form ); if ( ! $new_form_id || is_wp_error( $new_form_id ) ) { return false; } // Set new form name. $new_form_data['settings']['form_title'] .= ' (ID #' . absint( $new_form_id ) . ')'; // Set new form ID. $new_form_data['id'] = absint( $new_form_id ); // Update new duplicate form. $new_form_id = $this->update( $new_form_id, $new_form_data, array( 'cap' => 'create_forms' ) ); if ( ! $new_form_id || is_wp_error( $new_form_id ) ) { return false; } } return true; } /** * Get the next available field ID and increment by one. * * @since 1.0.0 * * @param string|int $form_id Form ID. * @param array $args Additional arguments. * * @return mixed int or false */ public function next_field_id( $form_id, $args = array() ) { if ( empty( $form_id ) ) { return false; } $defaults = array( 'content_only' => true, ); if ( isset( $args['cap'] ) ) { $defaults['cap'] = $args['cap']; } $form = $this->get( $form_id, $defaults ); if ( empty( $form ) ) { return false; } if ( ! empty( $form['field_id'] ) ) { $field_id = absint( $form['field_id'] ); if ( ! empty( $form['fields'] ) && max( array_keys( $form['fields'] ) ) > $field_id ) { $field_id = max( array_keys( $form['fields'] ) ) + 1; } $form['field_id'] = $field_id + 1; } else { $field_id = '0'; $form['field_id'] = '1'; } $this->update( $form_id, $form ); return $field_id; } /** * Get private meta information for a form. * * @since 1.0.0 * * @param string|int $form_id Form ID. * @param string $field Field. * @param array $args Additional arguments. * * @return false|array */ public function get_meta( $form_id, $field = '', $args = array() ) { if ( empty( $form_id ) ) { return false; } $defaults = array( 'content_only' => true, ); if ( isset( $args['cap'] ) ) { $defaults['cap'] = $args['cap']; } $data = $this->get( $form_id, $defaults ); if ( isset( $data['meta'] ) ) { if ( empty( $field ) ) { return $data['meta']; } elseif ( isset( $data['meta'][ $field ] ) ) { return $data['meta'][ $field ]; } } return false; } /** * Update or add form meta information to a form. * * @since 1.4.0 * * @param string|int $form_id Form ID. * @param string $meta_key Meta key. * @param mixed $meta_value Meta value. * @param array $args Additional arguments. * * @return bool */ public function update_meta( $form_id, $meta_key, $meta_value, $args = array() ) { if ( empty( $form_id ) || empty( $meta_key ) ) { return false; } // Add filter of the link rel attr to avoid JSON damage. add_filter( 'wp_targeted_link_rel', '__return_empty_string', 50, 1 ); // This filter breaks forms if they contain HTML. remove_filter( 'content_save_pre', 'balanceTags', 50 ); if ( ! isset( $args['cap'] ) ) { $args['cap'] = 'edit_form_single'; } $form = $this->get_single( absint( $form_id ), $args ); if ( empty( $form ) ) { return false; } $data = wpforms_decode( $form->post_content ); $meta_key = wpforms_sanitize_key( $meta_key ); $data['meta'][ $meta_key ] = $meta_value; $form = array( 'ID' => $form_id, 'post_content' => wpforms_encode( $data ), ); $form = apply_filters( 'wpforms_update_form_meta_args', $form, $data ); $form_id = wp_update_post( $form ); do_action( 'wpforms_update_form_meta', $form_id, $form, $meta_key, $meta_value ); return $form_id; } /** * Delete form meta information from a form. * * @since 1.4.0 * * @param string|int $form_id Form ID. * @param string $meta_key Meta key. * @param array $args Additional arguments. * * @return bool */ public function delete_meta( $form_id, $meta_key, $args = array() ) { if ( empty( $form_id ) || empty( $meta_key ) ) { return false; } // Add filter of the link rel attr to avoid JSON damage. add_filter( 'wp_targeted_link_rel', '__return_empty_string', 50, 1 ); // This filter breaks forms if they contain HTML. remove_filter( 'content_save_pre', 'balanceTags', 50 ); if ( ! isset( $args['cap'] ) ) { $args['cap'] = 'edit_form_single'; } $form = $this->get_single( absint( $form_id ), $args ); if ( empty( $form ) ) { return false; } $data = wpforms_decode( $form->post_content ); $meta_key = wpforms_sanitize_key( $meta_key ); unset( $data['meta'][ $meta_key ] ); $form = array( 'ID' => $form_id, 'post_content' => wpforms_encode( $data ), ); $form = apply_filters( 'wpforms_delete_form_meta_args', $form, $data ); $form_id = wp_update_post( $form ); do_action( 'wpforms_delete_form_meta', $form_id, $form, $meta_key ); return $form_id; } /** * Get private meta information for a form field. * * @since 1.0.0 * * @param string|int $form_id Form ID. * @param string $field_id Field ID. * @param array $args Additional arguments. * * @return array|bool */ public function get_field( $form_id, $field_id = '', $args = array() ) { if ( empty( $form_id ) ) { return false; } $defaults = array( 'content_only' => true, ); if ( isset( $args['cap'] ) ) { $defaults['cap'] = $args['cap']; } $data = $this->get( $form_id, $defaults ); return isset( $data['fields'][ $field_id ] ) ? $data['fields'][ $field_id ] : false; } /** * Get private meta information for a form field. * * @since 1.0.0 * * @param string|int $form_id Form ID. * @param string $field_id Field ID. * @param array $args Additional arguments. * * @return array|bool */ public function get_field_meta( $form_id, $field_id = '', $args = array() ) { $field = $this->get_field( $form_id, $field_id, $args ); if ( ! $field ) { return false; } return isset( $field['meta'] ) ? $field['meta'] : false; } } class-conditional-logic-core.php 0000666 00000064513 15213301444 0012716 0 ustar 00 <?php /** * Conditional logic core. * * Contains functionality for using conditional logic in the form builder as * well as a global processing method that can be leveraged by all types of * conditional logic. * * This was contained in an addon until version 1.3.8 when it was rolled into * core. * * @since 1.3.8 */ class WPForms_Conditional_Logic_Core { /** * One is the loneliest number that you'll ever do. * * @since 1.1.0 * @var WPForms_Conditional_Logic_Core */ private static $instance; /** * Main Instance. * * @since 1.1.0 * @return WPForms_Conditional_Logic_Core */ public static function instance() { if ( ! isset( self::$instance ) && ! ( self::$instance instanceof WPForms_Conditional_Logic_Core ) ) { self::$instance = new WPForms_Conditional_Logic_Core; add_action( 'wpforms_loaded', array( self::$instance, 'init' ), 10 ); } return self::$instance; } /** * Initialize. * * @since 1.0.0 */ public function init() { // Form builder. add_action( 'wpforms_builder_enqueues', array( $this, 'builder_assets' ) ); add_action( 'wpforms_builder_print_footer_scripts', array( $this, 'builder_footer_scripts' ) ); } /** * Enqueue assets for the builder. * * @since 1.0.0 */ public function builder_assets() { // CSS. wp_enqueue_style( 'wpforms-builder-conditionals', WPFORMS_PLUGIN_URL . 'assets/css/admin-builder-conditional-logic-core.css', array(), WPFORMS_VERSION ); // JavaScript. wp_enqueue_script( 'wpforms-builder-conditionals', WPFORMS_PLUGIN_URL . 'assets/js/admin-builder-conditional-logic-core.js', array( 'jquery', 'wpforms-utils', 'wpforms-builder' ), WPFORMS_VERSION, false ); } /** * Output footer scripts inside the form builder. * * @since 1.3.8 */ public function builder_footer_scripts() { ?> <script type="text/html" id="tmpl-wpforms-conditional-block"> <# var containerID = data.fieldName.replace(/]/g, '').replace(/\[/g, '-'); #> <div class="wpforms-conditional-groups" id="wpforms-conditional-groups-{{ containerID }}"> <h4> <select name="{{ data.fieldName }}[conditional_type]"> <# _.each(data.actions, function(key, val) { #> <option value="{{ val }}">{{ key }}</option> <# }) #> </select> {{ data.actionDesc }} </h4> <div class="wpforms-conditional-group" data-reference="{{ data.fieldID }}"> <table><tbody> <tr class="wpforms-conditional-row" data-field-id="{{ data.fieldID }}" data-input-name="{{ data.fieldName }}"> <td class="field"> <select name="{{ data.fieldName }}[conditionals][0][0][field]" class="wpforms-conditional-field" data-groupid="0" data-ruleid="0"> <option value="">{{ wpforms_builder.select_field }}</option> </select> </td> <td class="operator"> <select name="{{ data.fieldName }}[conditionals][0][0][operator]" class="wpforms-conditional-operator"> <option value="==">{{ wpforms_builder.operator_is }}</option> <option value="!=">{{ wpforms_builder.operator_is_not }}</option> <option value="e">{{ wpforms_builder.operator_empty }}</option> <option value="!e">{{ wpforms_builder.operator_not_empty }}</option> <option value="c">{{ wpforms_builder.operator_contains }}</option> <option value="!c">{{ wpforms_builder.operator_not_contains }}</option> <option value="^">{{ wpforms_builder.operator_starts }}</option> <option value="~">{{ wpforms_builder.operator_ends }}</option> <option value=">">{{ wpforms_builder.operator_greater_than }}</option> <option value="<">{{ wpforms_builder.operator_less_than }}</option> </select> </td> <td class="value"> <select name="{{ data.fieldName }}[conditionals][0][0][value]" class="wpforms-conditional-value"> <option value="">{{ wpforms_builder.select_choice }}</option> </select> </td> <td class="actions"> <button class="wpforms-conditional-rule-add" title="{{ wpforms_builder.rule_create }}">{{ wpforms_builder.and }}</button><button class="wpforms-conditional-rule-delete" title="{{ wpforms_builder.rule_delete }}"><i class="fa fa-times-circle" aria-hidden="true"></i></button> </td> </tr> </tbody></table> <h5>{{ wpforms_builder.or }}</h5> </div> <button class="wpforms-conditional-groups-add">{{ wpforms_builder.rule_create_group }}</button> </div> </script> <?php } /** * Build the conditional logic settings to display in the form builder. * * @since 1.3.8 * * @param array $args Data needed for a block to be generated properly. * @param bool $echo Whether to return or print. Default: print. * * @return string */ public function builder_block( $args = array(), $echo = true ) { if ( ! empty( $args['form'] ) ) { $form_fields = wpforms_get_form_fields( $args['form'], wpforms_get_conditional_logic_form_fields_supported() ); } else { $form_fields = array(); } // Define data. $type = ! empty( $args['type'] ) ? $args['type'] : 'field'; $panel = ! empty( $args['panel'] ) ? $args['panel'] : false; // notifications/connections. $parent = ! empty( $args['parent'] ) ? $args['parent'] : false; // settings. $subsection = ! empty( $args['subsection'] ) ? $args['subsection'] : false; $field = ! empty( $args['field'] ) ? $args['field'] : false; $reference = ! empty( $args['reference'] ) ? $args['reference'] : ''; $data_attrs = ''; ob_start(); // Block open markup. printf( '<div class="wpforms-conditional-block wpforms-conditional-block-%s" data-type="%s">', esc_attr( $type ), esc_attr( $type ) ); switch ( $type ) { case 'field': /* * This settings block is for a field. */ // Define more data for this field. $fields_instance = $args['instance']; $field_id = absint( $field['id'] ); $field_name = "fields[{$field_id}]"; $groups_id = "wpforms-conditional-groups-fields-{$field_id}"; $action_selected = ! empty( $field['conditional_type'] ) ? $field['conditional_type'] : ''; $conditionals = ! empty( $field['conditionals'] ) ? $field['conditionals'] : array( array( array() ) ); $data_attrs = 'data-field-id="' . $field_id . '" '; $reference = $field_id; $enabled = isset( $field['conditional_logic'] ) ? $field['conditional_logic'] : false; $action_desc = ! empty( $args['action_desc'] ) ? $args['action_desc'] : esc_html__( 'this field if', 'wpforms-lite' ); if ( empty( $args['actions'] ) ) { $actions = array( 'show' => esc_attr__( 'Show', 'wpforms-lite' ), 'hide' => esc_attr__( 'Hide', 'wpforms-lite' ), ); } else { $actions = array_map( 'esc_attr', $args['actions'] ); } // Output Conditional Logic toggle checkbox field option. $fld = $fields_instance->field_element( 'checkbox', $field, array( 'slug' => 'conditional_logic', 'value' => $enabled, 'desc' => esc_html__( 'Enable conditional logic', 'wpforms-lite' ), 'tooltip' => '<a href="https://wpforms.com/docs/how-to-use-conditional-logic-with-wpforms/" target="_blank" rel="noopener noreferrer">' . esc_html__( 'How to use Conditional Logic', 'wpforms-lite' ) . '</a>', 'data' => array( 'name' => $field_name, 'actions' => $actions, 'action-desc' => esc_attr( $action_desc ), ), ), false ); $fields_instance->field_element( 'row', $field, array( 'slug' => 'conditional_logic', 'content' => $fld, 'class' => 'wpforms-conditionals-enable-toggle', ) ); // Prevent conditional logic from being applied to itself. if ( ! empty( $form_fields[ $field['id'] ] ) ) { unset( $form_fields[ $field['id'] ] ); } break; case 'panel': /* * This settings block is for something else - connections / notifications etc. */ $form_data = $args['form']; $action_desc = ! empty( $args['action_desc'] ) ? $args['action_desc'] : esc_html__( 'this connection if', 'wpforms-lite' ); if ( empty( $args['actions'] ) ) { $actions = array( 'go' => esc_attr__( 'Process', 'wpforms-lite' ), 'stop' => esc_attr__( 'Don\'t process', 'wpforms-lite' ), ); } else { $actions = array_map( 'esc_attr', $args['actions'] ); } // Below we do a bunch of voodoo to determine where this block // is located in the form builder - eg is it in a top level // setting or in a subsection, etc. if ( ! empty( $parent ) ) { if ( ! empty( $subsection ) ) { $field_name = sprintf( '%s[%s][%s]', $parent, $panel, $subsection ); $groups_id = sprintf( 'wpforms-conditional-groups-%s-%s-%s', $parent, $panel, $subsection ); $enabled = ! empty( $form_data[ $parent ][ $panel ][ $subsection ]['conditional_logic'] ) ? true : false; $action_selected = ! empty( $form_data[ $parent ][ $panel ][ $subsection ]['conditional_type'] ) ? $form_data[ $parent ][ $panel ][ $subsection ]['conditional_type'] : ''; $conditionals = ! empty( $form_data[ $parent ][ $panel ][ $subsection ]['conditionals'] ) ? $form_data[ $parent ][ $panel ][ $subsection ]['conditionals'] : array( array( array() ) ); } else { $field_name = sprintf( '%s[%s]', $parent, $panel ); $groups_id = sprintf( 'wpforms-conditional-groups-%s-%s', $parent, $panel ); $enabled = ! empty( $form_data[ $parent ][ $panel ]['conditional_logic'] ) ? true : false; $action_selected = ! empty( $form_data[ $parent ][ $panel ]['conditional_type'] ) ? $form_data[ $parent ][ $panel ]['conditional_type'] : ''; $conditionals = ! empty( $form_data[ $parent ][ $panel ]['conditionals'] ) ? $form_data[ $parent ][ $panel ]['conditionals'] : array( array( array() ) ); } } else { $field_name = sprintf( '%s', $panel ); $groups_id = sprintf( 'wpforms-conditional-groups-%s', $panel ); $enabled = ! empty( $form_data[ $panel ]['conditional_logic'] ) ? true : false; $action_selected = ! empty( $form_data[ $panel ]['conditional_type'] ) ? $form_data[ $panel ]['conditional_type'] : ''; $conditionals = ! empty( $form_data[ $panel ]['conditionals'] ) ? $form_data[ $panel ]['conditionals'] : array( array( array() ) ); } // Output Conditional Logic toggle checkbox panel setting. wpforms_panel_field( 'checkbox', $panel, 'conditional_logic', $args['form'], esc_html__( 'Enable conditional logic', 'wpforms-lite' ), array( 'tooltip' => '<a href="https://wpforms.com/docs/how-to-use-conditional-logic-with-wpforms/" target="_blank" rel="noopener noreferrer">' . esc_html__( 'How to use Conditional Logic', 'wpforms-lite' ) . '</a>', 'parent' => $parent, 'subsection' => $subsection, 'input_id' => 'wpforms-panel-field-' . implode( '-', array_filter( array( $parent, $panel, $subsection, 'conditional_logic', 'checkbox' ) ) ), 'input_class' => 'wpforms-panel-field-conditional_logic-checkbox', 'class' => 'wpforms-conditionals-enable-toggle', 'data' => array( 'name' => $field_name, 'actions' => $actions, 'action-desc' => esc_attr( $action_desc ), ), ) ); break; default: $enabled = false; $field_name = ''; $reference = ''; $action_selected = ''; $action_desc = ''; $groups_id = ''; $actions = array(); $conditionals = array(); } // Only display the block details if conditional logic is enabled. if ( $enabled ) : $data_attrs .= 'data-input-name="' . esc_attr( $field_name ) . '"'; $style = $enabled ? '' : 'display:none;'; // Groups wrap open markup. printf( '<div class="wpforms-conditional-groups" id="%s" style="%s">', sanitize_html_class( $groups_id ), esc_attr( $style ) ); // This is the "[Show] this field if" type text and setting. echo '<h4>'; echo '<select name="' . esc_attr( $field_name ) . '[conditional_type]">'; foreach ( $actions as $key => $label ) { printf( '<option value="%s" %s>%s</option>', esc_attr( trim( $key ) ), selected( $key, $action_selected, false ), esc_html( $label ) ); } echo '</select>'; echo esc_html( $action_desc ); // Eg "this field if". echo '</h4>'; // Go through each conditional logic group. foreach ( $conditionals as $group_id => $group ) : // Individual group open markup. echo '<div class="wpforms-conditional-group" data-reference="' . $reference . '">'; echo '<table><tbody>'; foreach ( $group as $rule_id => $rule ) : $selected_current = false; // Individual rule table row. echo '<tr class="wpforms-conditional-row" ' . $data_attrs . '>'; // Rule field - allows the user to select // which field the conditional logic rule is // anchored to. echo '<td class="field">'; printf( '<select name="%s[conditionals][%d][%d][field]" class="wpforms-conditional-field" data-groupid="%d" data-ruleid="%d">', esc_attr( $field_name ), (int) $group_id, (int) $rule_id, (int) $group_id, (int) $rule_id ); echo '<option value="">' . esc_html__( '--- Select Field ---', 'wpforms-lite' ) . '</option>'; if ( ! empty( $form_fields ) ) { foreach ( $form_fields as $form_field ) { // Exclude fields that are // leveraging dynamic choices. if ( ! empty( $form_field['dynamic_choices'] ) ) { continue; } if ( isset( $rule['field'] ) ) { $selected = $rule['field']; $selected_current = $rule['field']; } else { $selected = false; } $selected = selected( $selected, $form_field['id'], false ); printf( '<option value="%s" %s>%s</option>', absint( $form_field['id'] ), $selected, esc_html( $form_field['label'] ) ); } } echo '</select>'; echo '</td>'; // Rule operator - allows the user to // determine the comparison operator used // for processing. echo '<td class="operator">'; printf( '<select name="%s[conditionals][%s][%s][operator]" class="wpforms-conditional-operator">', $field_name, $group_id, $rule_id ); $operator = ! empty( $rule['operator'] ) ? $rule['operator'] : false; printf( '<option value="==" %s>%s</option>', selected( $operator, '==', false ), esc_html__( 'is', 'wpforms-lite' ) ); printf( '<option value="!=" %s>%s</option>', selected( $operator, '!=', false ), esc_html__( 'is not', 'wpforms-lite' ) ); printf( '<option value="e" %s>%s</option>', selected( $operator, 'e', false ), esc_html__( 'empty', 'wpforms-lite' ) ); printf( '<option value="!e" %s>%s</option>', selected( $operator, '!e', false ), esc_html__( 'not empty', 'wpforms-lite' ) ); // Only text based fields support // these additional operators. $disabled = ''; if ( ! empty( $rule['field'] ) && ! empty( $form_fields[ $rule['field'] ]['type'] ) ) { $disabled = in_array( $form_fields[ $rule['field'] ]['type'], array( 'text', 'textarea', 'email', 'url', 'number', 'hidden', 'rating', 'number-slider', 'net_promoter_score' ), true ) ? '' : ' disabled'; } printf( '<option value="c" %s%s>%s</option>', selected( $operator, 'c', false ), $disabled, esc_html__( 'contains', 'wpforms-lite' ) ); printf( '<option value="!c" %s%s>%s</option>', selected( $operator, '!c', false ), $disabled, esc_html__( 'does not contain', 'wpforms-lite' ) ); printf( '<option value="^" %s%s>%s</option>', selected( $operator, '^', false ), $disabled, esc_html__( 'starts with', 'wpforms-lite' ) ); printf( '<option value="~" %s%s>%s</option>', selected( $operator, '~', false ), $disabled, esc_html__( 'ends with', 'wpforms-lite' ) ); printf( '<option value=">" %s%s>%s</option>', selected( $operator, '>', false ), $disabled, esc_html__( 'greater than', 'wpforms-lite' ) ); printf( '<option value="<" %s%s>%s</option>', selected( $operator, '<', false ), $disabled, esc_html__( 'less than', 'wpforms-lite' ) ); echo '</select>'; echo '</td>'; // Rule value - allows the user to // determine the value we are using for // comparison. echo '<td class="value">'; if ( isset( $rule['field'] ) ) { // For empty/not empty fields the field value input is not needed so we disable it. if ( ! empty( $rule['operator'] ) && in_array( $rule['operator'], array( 'e', '!e' ), true ) ) { $disabled = 'disabled'; $rule['value'] = ''; } else { $disabled = ''; } if ( isset( $form_fields[ $rule['field'] ]['type'] ) && in_array( $form_fields[ $rule['field'] ]['type'], array( 'text', 'textarea', 'email', 'url', 'number', 'hidden', 'rating', 'number-slider', 'net_promoter_score' ), true ) ) { $type = in_array( $form_fields[ $rule['field'] ]['type'], array( 'rating', 'net_promoter_score', 'number-slider' ), true ) ? 'number' : 'text'; printf( '<input type="%s" name="%s[conditionals][%s][%s][value]" value="%s" class="wpforms-conditional-value" %s>', $type, $field_name, $group_id, $rule_id, esc_attr( $rule['value'] ), $disabled ); } else { printf( '<select name="%s[conditionals][%s][%s][value]" class="wpforms-conditional-value" %d>', $field_name, $group_id, $rule_id, $disabled ); echo '<option value="">' . esc_html__( '--- Select Choice ---', 'wpforms-lite' ) . '</option>'; if ( ! empty( $form_fields[ $rule['field'] ]['choices'] ) ) { foreach ( $form_fields[ $rule['field'] ]['choices'] as $option_id => $option ) { $value = isset( $rule['value'] ) ? $rule['value'] : ''; $selected = selected( $option_id, $value, false ); printf( '<option value="%s" %s>%s</option>', $option_id, $selected, esc_html( $option['label'] ) ); } } echo '</select>'; } } else { echo '<select></select>'; } // End if(). echo '</td>'; // Rule actions. echo '<td class="actions">'; echo '<button class="wpforms-conditional-rule-add" title="' . esc_attr__( 'Create new rule', 'wpforms-lite' ) . '">' . esc_html_x( 'AND', 'Conditional Logic: new rule logic.', 'wpforms-lite' ) . '</button>'; echo '<button class="wpforms-conditional-rule-delete" title="' . esc_attr__( 'Delete rule', 'wpforms-lite' ) . '"><i class="fa fa-times-circle" aria-hidden="true"></i></button>'; echo '</td>'; echo '</tr>'; // Close individual rule table row. endforeach; // End foreach() for individual rules. echo '</tbody></table>'; echo '<h5>' . esc_html_x( 'or', 'Conditional Logic: new rule logic.', 'wpforms-lite' ) . '</h5>'; echo '</div>'; // Close individual group markup. endforeach; // End foreach() for conditional logic groups. echo '<button class="wpforms-conditional-groups-add">' . esc_html__( 'Add rule group', 'wpforms-lite' ) . '</button>'; echo '</div>'; // Close Groups wrap markup. endif; // End $enabled. echo '</div>'; // Close block markup. $output = ob_get_clean(); if ( $echo ) { echo $output; //phpcs:ignore } else { return $output; } } /** * Alias method for backwards compatibility. * * @since 1.1.0 * @deprecated 1.3.8 Use wpforms_conditional_logic()->builder_block() instead. * * @param array $args Data needed for a block to be generated properly. * @param bool $echo Whether to return or print. Default: print. * * @return string */ public function conditionals_block( $args = array(), $echo = true ) { if ( $echo ) { echo $this->builder_block( $args, $echo ); //phpcs:ignore } else { return $this->builder_block( $args, $echo ); } } /** * Process conditional rules. * * Check if a form passes the conditional logic rules that are provided. * * @since 1.3.8 * * @param array $fields List of fields with data and settings. * @param array $form_data Form data and settings. * @param array $conditionals List of conditionals. * * @return bool */ public function process( $fields, $form_data, $conditionals ) { if ( empty( $conditionals ) ) { return true; } $pass = false; foreach ( $conditionals as $group_id => $group ) { $pass_group = true; if ( ! empty( $group ) ) { foreach ( $group as $rule_id => $rule ) { if ( ! isset( $rule['field'] ) || '' == $rule['field'] || ! isset( $rule['operator'] ) ) { continue; } if ( ! isset( $rule['value'] ) && ! in_array( $rule['operator'], array( 'e', '!e' ), true ) ) { continue; } $rule_field = $rule['field']; $rule_operator = $rule['operator']; $rule_value = isset( $rule['value'] ) ? $rule['value'] : ''; if ( in_array( $fields[ $rule_field ]['type'], array( 'text', 'textarea', 'email', 'url', 'number', 'hidden', 'rating', 'number-slider', 'net_promoter_score' ), true ) ) { // Text based fields. $left = strtolower( trim( wpforms_decode_string( $fields[ $rule_field ]['value'] ) ) ); $right = strtolower( trim( $rule_value ) ); switch ( $rule_operator ) { case '==': $pass_rule = ( $left == $right ); break; case '!=': $pass_rule = ( $left != $right ); break; case 'c': $pass_rule = ( strpos( $left, $right ) !== false ); break; case '!c': $pass_rule = ( strpos( $left, $right ) === false ); break; case '^': $pass_rule = ( strrpos( $left, $right, -strlen( $left ) ) !== false ); break; case '~': $pass_rule = ( ( $temp = strlen( $left ) - strlen( $right ) ) >= 0 && strpos( $left, $right, $temp ) !== false ); break; case 'e': $pass_rule = ( '' == $left ); break; case '!e': $pass_rule = ( '' != $left ); break; case '>': $left = preg_replace( '/[^-0-9.]/', '', $left ); $pass_rule = ( '' !== $left ) && ( floatval( $left ) > floatval( $right ) ); break; case '<': $left = preg_replace( '/[^-0-9.]/', '', $left ); $pass_rule = ( '' !== $left ) && ( floatval( $left ) < floatval( $right ) ); break; default: $pass_rule = apply_filters( 'wpforms_process_conditional_logic', false, $rule_operator, $left, $right ); break; } } else { // Selector based fields. $provided_id = false; if ( in_array( $fields[ $rule_field ]['type'], array( 'payment-multiple', 'payment-checkbox', 'payment-select' ), true ) && isset( $fields[ $rule_field ]['value_raw'] ) && '' != $fields[ $rule_field ]['value_raw'] ) { // Payment Multiple/Checkbox fields store the option key, // so we can reference that easily. $provided_id = explode( ',', (string) $fields[ $rule_field ]['value_raw'] ); } elseif ( isset( $fields[ $rule_field ]['value'] ) && '' != $fields[ $rule_field ]['value'] ) { // Other select type fields we don't store the // option key so we have to do the logic to locate // it ourselves. $provided_id = array(); if ( 'checkbox' === $fields[ $rule_field ]['type'] ) { $values = explode( "\n", $fields[ $rule_field ]['value'] ); } else { $values = (array) $fields[ $rule_field ]['value']; } foreach ( $form_data['fields'][ $rule_field ]['choices'] as $key => $choice ) { $choice = array_map( 'wpforms_decode_string', $choice ); foreach ( $values as $value ) { $value = wpforms_decode_string( $value ); if ( in_array( $value, $choice, true ) ) { $provided_id[] = $key; } } } } $left = (array) $provided_id; $right = strtolower( trim( (int) $rule_value ) ); switch ( $rule_operator ) { case '==': case 'c': // BC, no longer available. case '^': // BC, no longer available. case '~': // BC, no longer available. $pass_rule = in_array( $right, $left ); break; case '!=': case '!c': // BC, no longer available. $pass_rule = ! in_array( $right, $left ); break; case 'e': $pass_rule = empty( $left[0] ); break; case '!e': $pass_rule = ! empty( $left[0] ); break; default: $pass_rule = apply_filters( 'wpforms_process_conditional_logic', false, $rule_operator, $left, $right ); break; } } // End if(). if ( ! $pass_rule ) { $pass_group = false; break; } } // End foreach(). } // End if(). if ( $pass_group ) { $pass = true; } } // End foreach(). return $pass; } /** * Alias function for backwards compatibility. * * @since 1.0.0 * * @param array $fields List of fields with data and settings. * @param array $form_data Form data and settings. * @param array $conditionals List of conditionals. * * @return bool */ public function conditionals_process( $fields, $form_data, $conditionals ) { return $this->process( $fields, $form_data, $conditionals ); } } /** * The function which returns the one WPForms_Conditional_Logic_Core instance. * * Use this function like you would a global variable, except without needing * to declare the global. * * @since 1.1.0 * * @return WPForms_Conditional_Logic_Core */ function wpforms_conditional_logic() { return WPForms_Conditional_Logic_Core::instance(); } wpforms_conditional_logic(); emails/templates/header-default.php 0000666 00000020245 15213301444 0013403 0 ustar 00 <?php /** * Email Header * * @since 1.1.3 */ // Exit if accessed directly. if ( ! defined( 'ABSPATH' ) ) exit; $header_image = wpforms_setting( 'email-header-image', false ); $background_color = wpforms_setting( 'email-background-color', '#e9eaec' ); $text_direction = is_rtl() ? 'rtl' : 'ltr'; ?> <!doctype html> <html dir="<?php echo $text_direction; ?>" xmlns="http://www.w3.org/1999/xhtml" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office"> <head> <!--[if gte mso 15]> <xml> <o:OfficeDocumentSettings> <o:AllowPNG/> <o:PixelsPerInch>96</o:PixelsPerInch> </o:OfficeDocumentSettings> </xml> <![endif]--> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title><?php echo get_bloginfo( 'name' ); ?></title> <style type="text/css"> p{ margin:10px 0; padding:0; } table{ border-collapse:collapse; } h1,h2,h3,h4,h5,h6{ display:block; margin:0; padding:0; } img,a img{ border:0; height:auto; outline:none; text-decoration:none; } body,#bodyTable,#bodyCell{ height:100%; margin:0; padding:0; width:100%; } #outlook a{ padding:0; } img{ -ms-interpolation-mode:bicubic; } table{ mso-table-lspace:0pt; mso-table-rspace:0pt; } .ReadMsgBody{ width:100%; } .ExternalClass{ width:100%; } p,a,li,td,blockquote{ mso-line-height-rule:exactly; } a[href^=tel],a[href^=sms]{ color:inherit; cursor:default; text-decoration:none; } p,a,li,td,body,table,blockquote{ -ms-text-size-adjust:100%; -webkit-text-size-adjust:100%; } .ExternalClass,.ExternalClass p,.ExternalClass td,.ExternalClass div,.ExternalClass span,.ExternalClass font{ line-height:100%; } a[x-apple-data-detectors]{ color:inherit !important; text-decoration:none !important; font-size:inherit !important; font-family:inherit !important; font-weight:inherit !important; line-height:inherit !important; } #bodyCell{ padding:50px 50px; } .templateContainer{ max-width:600px !important; border:0; } a.mcnButton{ display:block; } .mcnTextContent{ word-break:break-word; } .mcnTextContent img{ height:auto !important; } .mcnDividerBlock{ table-layout:fixed !important; } /***** Make theme edits below if needed *****/ /* Page - Background Style */ body,#bodyTable{ background-color:<?php echo $background_color; ?>; } /* Page - Heading 1 */ h1{ color:#202020; font-family: 'Helvetica Neue', Helvetica, Arial, 'Lucida Grande', sans-serif; font-size:26px; font-style:normal; font-weight:bold; line-height:125%; letter-spacing:normal; } /* Page - Heading 2 */ h2{ color:#202020; font-family: 'Helvetica Neue', Helvetica, Arial, 'Lucida Grande', sans-serif; font-size:22px; font-style:normal; font-weight:bold; line-height:125%; letter-spacing:normal; } /* Page - Heading 3 */ h3{ color:#202020; font-family: 'Helvetica Neue', Helvetica, Arial, 'Lucida Grande', sans-serif; font-size:20px; font-style:normal; font-weight:bold; line-height:125%; letter-spacing:normal; } /* Page - Heading 4 */ h4{ color:#202020; font-family: 'Helvetica Neue', Helvetica, Arial, 'Lucida Grande', sans-serif; font-size:18px; font-style:normal; font-weight:bold; line-height:125%; letter-spacing:normal; } /* Header - Header Style */ #templateHeader{ border-top:0; border-bottom:0; padding-top:0; padding-bottom:20px; text-align: center; } /* Body - Body Style */ #templateBody{ background-color:#FFFFFF; border-top:0; border: 1px solid #c1c1c1; padding-top:0; padding-bottom:0px; } /* Body -Body Text */ #templateBody .mcnTextContent, #templateBody .mcnTextContent p{ color:#555555; font-family: 'Helvetica Neue', Helvetica, Arial, 'Lucida Grande', sans-serif; font-size:14px; line-height:150%; } /* Body - Body Link */ #templateBody .mcnTextContent a, #templateBody .mcnTextContent p a{ color:#ff7f50; font-weight:normal; text-decoration:underline; } /* Footer - Footer Style */ #templateFooter{ background-color:<?php echo $background_color; ?>; border-top:0; border-bottom:0; padding-top:12px; padding-bottom:12px; } /* Footer - Footer Text */ #templateFooter .mcnTextContent, #templateFooter .mcnTextContent p{ color:#cccccc; font-family: 'Helvetica Neue', Helvetica, Arial, 'Lucida Grande', sans-serif; font-size:12px; line-height:150%; text-align:center; } /* Footer - Footer Link */ #templateFooter .mcnTextContent a, #templateFooter .mcnTextContent p a{ color:#cccccc; font-weight:normal; text-decoration:underline; } @media only screen and (min-width:768px){ .templateContainer{ width:600px !important; } } @media only screen and (max-width: 480px){ body,table,td,p,a,li,blockquote{ -webkit-text-size-adjust:none !important; } } @media only screen and (max-width: 480px){ body{ width:100% !important; min-width:100% !important; } } @media only screen and (max-width: 680px){ #bodyCell{ padding:20px 20px !important; } } @media only screen and (max-width: 480px){ .mcnTextContentContainer{ max-width:100% !important; width:100% !important; } } </style> </head> <body style="height: 100%;margin: 0;padding: 0;width: 100%;-ms-text-size-adjust: 100%;-webkit-text-size-adjust: 100%;background-color: <?php echo $background_color; ?>;"> <!-- Don't forget to run final template through http://templates.mailchimp.com/resources/inline-css/ --> <center> <table align="center" border="0" cellpadding="0" cellspacing="0" height="100%" width="100%" id="bodyTable" style="border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;-ms-text-size-adjust: 100%;-webkit-text-size-adjust: 100%;height: 100%;margin: 0;padding: 0;width: 100%;background-color: <?php echo $background_color; ?>;"> <tr> <td align="center" valign="top" id="bodyCell" style="mso-line-height-rule: exactly;-ms-text-size-adjust: 100%;-webkit-text-size-adjust: 100%;height: 100%;margin: 0;padding: 50px 50px;width: 100%;"> <!-- BEGIN TEMPLATE // --> <!--[if gte mso 9]> <table align="center" border="0" cellspacing="0" cellpadding="0" width="600" style="width:600px;"> <tr> <td align="center" valign="top" width="600" style="width:600px;"> <![endif]--> <table border="0" cellpadding="0" cellspacing="0" width="100%" class="templateContainer" style="border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;-ms-text-size-adjust: 100%;-webkit-text-size-adjust: 100%;border: 0;max-width: 600px !important;"> <?php if ( ! empty( $header_image ) ) { echo '<tr><td valign="top" align="center" id="templateHeader" style="padding-bottom:20px;text-align:center;">'; echo '<img src="' . esc_url( $header_image ) . '" alt="' . esc_attr( get_bloginfo( 'name' ) ) . '" />'; echo '</td></tr>'; } ?> <tr> <td valign="top" id="templateBody" style="mso-line-height-rule: exactly;-ms-text-size-adjust: 100%;-webkit-text-size-adjust: 100%;background-color: #FFFFFF;border-top: 0;border: 1px solid #c1c1c1;padding-top: 0;padding-bottom: 0px;"> <table border="0" cellpadding="0" cellspacing="0" width="100%" class="mcnTextBlock" style="min-width: 100%;border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;-ms-text-size-adjust: 100%;-webkit-text-size-adjust: 100%;"> <tbody class="mcnTextBlockOuter"> <tr> <td valign="top" class="mcnTextBlockInner" style="mso-line-height-rule: exactly;-ms-text-size-adjust: 100%;-webkit-text-size-adjust: 100%;"> <table align="left" border="0" cellpadding="0" cellspacing="0" width="100%" style="min-width: 100%;border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;-ms-text-size-adjust: 100%;-webkit-text-size-adjust: 100%;" class="mcnTextContentContainer"> <tbody> <tr> <td valign="top" style="padding-top: 30px;padding-right: 30px;padding-bottom: 30px;padding-left: 30px;" class="mcnTextContent"> emails/templates/field-default.php 0000666 00000001121 15213301444 0013226 0 ustar 00 <?php /** * Email form field entry. * * This is used with the {all_fields} smart tag. * * @since 1.1.3 */ // Exit if accessed directly. if ( ! defined( 'ABSPATH' ) ) exit; ?> <table align="left" border="0" cellpadding="0" cellspacing="0" width="100%" style="border-top:1px solid #dddddd; display:block;min-width: 100%;border-collapse: collapse;width:100%;"><tbody> <tr><td style="color:#333333;padding-top: 20px;padding-bottom: 3px;"><strong>{field_name}</strong></td></tr> <tr><td style="color:#555555;padding-top: 3px;padding-bottom: 20px;">{field_value}</td></tr> </tbody></table> emails/templates/body-default.php 0000666 00000000434 15213301444 0013106 0 ustar 00 <?php /** * Email Body * * Heavily influenced by the great AffiliateWP plugin by Pippin Williamson. * https://github.com/AffiliateWP/AffiliateWP/tree/master/templates/emails * * @since 1.1.3 */ // Exit if accessed directly. if ( ! defined( 'ABSPATH' ) ) { exit; } ?> {email} emails/templates/default.php 0000666 00000017776 15213301444 0012174 0 ustar 00 <?php /** * Default email template. * * Don't forget to run final template through * http://templates.mailchimp.com/resources/inline-css/ * * @since 1.1.3 */ // Exit if accessed directly. if ( ! defined( 'ABSPATH' ) ) exit; $header_image = wpforms_setting( 'email-header-image', false ); ?> <!doctype html> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office"> <head> <!--[if gte mso 15]> <xml> <o:OfficeDocumentSettings> <o:AllowPNG/> <o:PixelsPerInch>96</o:PixelsPerInch> </o:OfficeDocumentSettings> </xml> <![endif]--> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title></title> <style type="text/css"> p{ margin:10px 0; padding:0; } table{ border-collapse:collapse; } h1,h2,h3,h4,h5,h6{ display:block; margin:0; padding:0; } img,a img{ border:0; height:auto; outline:none; text-decoration:none; } body,#bodyTable,#bodyCell{ height:100%; margin:0; padding:0; width:100%; } #outlook a{ padding:0; } img{ -ms-interpolation-mode:bicubic; } table{ mso-table-lspace:0pt; mso-table-rspace:0pt; } .ReadMsgBody{ width:100%; } .ExternalClass{ width:100%; } p,a,li,td,blockquote{ mso-line-height-rule:exactly; } a[href^=tel],a[href^=sms]{ color:inherit; cursor:default; text-decoration:none; } p,a,li,td,body,table,blockquote{ -ms-text-size-adjust:100%; -webkit-text-size-adjust:100%; } .ExternalClass,.ExternalClass p,.ExternalClass td,.ExternalClass div,.ExternalClass span,.ExternalClass font{ line-height:100%; } a[x-apple-data-detectors]{ color:inherit !important; text-decoration:none !important; font-size:inherit !important; font-family:inherit !important; font-weight:inherit !important; line-height:inherit !important; } #bodyCell{ padding:50px 50px; } .templateContainer{ max-width:600px !important; border:0; } a.mcnButton{ display:block; } .mcnTextContent{ word-break:break-word; } .mcnTextContent img{ height:auto !important; } .mcnDividerBlock{ table-layout:fixed !important; } /***** Make theme edits below if needed *****/ /* Page - Background Style */ body,#bodyTable{ background-color:#e9eaec; } /* Page - Heading 1 */ h1{ color:#202020; font-family: 'Helvetica Neue', Helvetica, Arial, 'Lucida Grande', sans-serif; font-size:26px; font-style:normal; font-weight:bold; line-height:125%; letter-spacing:normal; text-align:left; } /* Page - Heading 2 */ h2{ color:#202020; font-family: 'Helvetica Neue', Helvetica, Arial, 'Lucida Grande', sans-serif; font-size:22px; font-style:normal; font-weight:bold; line-height:125%; letter-spacing:normal; text-align:left; } /* Page - Heading 3 */ h3{ color:#202020; font-family: 'Helvetica Neue', Helvetica, Arial, 'Lucida Grande', sans-serif; font-size:20px; font-style:normal; font-weight:bold; line-height:125%; letter-spacing:normal; text-align:left; } /* Page - Heading 4 */ h4{ color:#202020; font-family: 'Helvetica Neue', Helvetica, Arial, 'Lucida Grande', sans-serif; font-size:18px; font-style:normal; font-weight:bold; line-height:125%; letter-spacing:normal; text-align:left; } /* Header - Header Style */ #templateHeader{ border-top:0; border-bottom:0; padding-top:0px; padding-bottom:20px; } /* Body - Body Style */ #templateBody{ background-color:#FFFFFF; border-top:0; border: 1px solid #c1c1c1; padding-top:0; padding-bottom:0px; } /* Body -Body Text */ #templateBody .mcnTextContent, #templateBody .mcnTextContent p{ color:#555555; font-family: 'Helvetica Neue', Helvetica, Arial, 'Lucida Grande', sans-serif; font-size:14px; line-height:150%; text-align:left; } /* Body - Body Link */ #templateBody .mcnTextContent a, #templateBody .mcnTextContent p a{ color:#ff7f50; font-weight:normal; text-decoration:underline; } /* Footer - Footer Style */ #templateFooter{ background-color:#e9eaec; border-top:0; border-bottom:0; padding-top:12px; padding-bottom:12px; } /* Footer - Footer Text */ #templateFooter .mcnTextContent, #templateFooter .mcnTextContent p{ color:#cccccc; font-family: 'Helvetica Neue', Helvetica, Arial, 'Lucida Grande', sans-serif; font-size:12px; line-height:150%; text-align:center; } /* Footer - Footer Link */ #templateFooter .mcnTextContent a, #templateFooter .mcnTextContent p a{ color:#cccccc; font-weight:normal; text-decoration:underline; } @media only screen and (min-width:768px){ .templateContainer{ width:600px !important; } } @media only screen and (max-width: 480px){ body,table,td,p,a,li,blockquote{ -webkit-text-size-adjust:none !important; } } @media only screen and (max-width: 480px){ body{ width:100% !important; min-width:100% !important; } } @media only screen and (max-width: 480px){ #bodyCell{ padding:20px !important; } } @media only screen and (max-width: 480px){ .mcnTextContentContainer{ max-width:100% !important; width:100% !important; } } </style> </head> <body> <center> <table align="center" border="0" cellpadding="0" cellspacing="0" height="100%" width="100%" id="bodyTable"> <tr> <td align="center" valign="top" id="bodyCell"> <!-- BEGIN TEMPLATE // --> <!--[if gte mso 9]> <table align="center" border="0" cellspacing="0" cellpadding="0" width="600" style="width:600px;"> <tr> <td align="center" valign="top" width="600" style="width:600px;"> <![endif]--> <table border="0" cellpadding="0" cellspacing="0" width="100%" class="templateContainer"> <?php if ( !empty( $header_image ) ) { echo '<tr><td valign="top" align="center" id="templateHeader" style="padding-bottom:20px;text-align:center;">'; echo '<img src="' . esc_url( $header_image ) . '" alt="' . get_bloginfo( 'name' ) . '" />'; echo '</td></tr>'; } ?> <tr> <td valign="top" id="templateBody"> <table border="0" cellpadding="0" cellspacing="0" width="100%" class="mcnTextBlock" style="min-width:100%;"> <tbody class="mcnTextBlockOuter"> <tr> <td valign="top" class="mcnTextBlockInner"> <table align="left" border="0" cellpadding="0" cellspacing="0" width="100%" style="min-width:100%;" class="mcnTextContentContainer"> <tbody> <tr> <td valign="top" class="mcnTextContent" style="padding-top:30px; padding-right: 30px; padding-bottom: 30px; padding-left: 30px;"> <!-- Content --> <h1>Content.</h1> </td> </tr> </tbody> </table> </td> </tr> </tbody> </table> </td> </tr> <tr> <td valign="top" id="templateFooter"> <table border="0" cellpadding="0" cellspacing="0" width="100%" class="mcnTextBlock" style="min-width:100%;"> <tbody class="mcnTextBlockOuter"> <tr> <td valign="top" class="mcnTextBlockInner"> <table align="left" border="0" cellpadding="0" cellspacing="0" width="100%" style="min-width:100%;" class="mcnTextContentContainer"> <tbody> <tr> <td valign="top" class="mcnTextContent" style="padding-top:9px; padding-right: 18px; padding-bottom: 9px; padding-left: 18px;"> <!-- Footer content --> Footer </td> </tr> </tbody> </table> </td> </tr> </tbody> </table> </td> </tr> </table> <!--[if gte mso 9]> </td> </tr> </table> <![endif]--> <!-- // END TEMPLATE --> </td> </tr> </table> </center> </body> </html> emails/templates/footer-default.php 0000666 00000004761 15213301444 0013456 0 ustar 00 <?php /** * Email Footer. * * @since 1.1.3 */ // Exit if accessed directly. if ( ! defined( 'ABSPATH' ) ) exit; $background_color = wpforms_setting( 'email-background-color', '#e9eaec' ); ?> </td> </tr> </tbody> </table> </td> </tr> </tbody> </table> </td> </tr> <tr> <td valign="top" id="templateFooter" style="mso-line-height-rule: exactly;-ms-text-size-adjust: 100%;-webkit-text-size-adjust: 100%;background-color: <?php echo $background_color; ?>;border-top: 0;border-bottom: 0;padding-top: 12px;padding-bottom: 12px;"> <table border="0" cellpadding="0" cellspacing="0" width="100%" class="mcnTextBlock" style="min-width: 100%;border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;-ms-text-size-adjust: 100%;-webkit-text-size-adjust: 100%;"> <tbody class="mcnTextBlockOuter"> <tr> <td valign="top" class="mcnTextBlockInner" style="mso-line-height-rule: exactly;-ms-text-size-adjust: 100%;-webkit-text-size-adjust: 100%;"> <table align="left" border="0" cellpadding="0" cellspacing="0" width="100%" style="min-width: 100%;border-collapse: collapse;mso-table-lspace: 0pt;mso-table-rspace: 0pt;-ms-text-size-adjust: 100%;-webkit-text-size-adjust: 100%;" class="mcnTextContentContainer"> <tbody> <tr> <td valign="top" class="mcnTextContent" style="padding-top: 9px;padding-right: 18px;padding-bottom: 9px;padding-left: 18px;mso-line-height-rule: exactly;-ms-text-size-adjust: 100%;-webkit-text-size-adjust: 100%;word-break: break-word;color: #aaa;font-family: Helvetica;font-size: 12px;line-height: 150%;text-align: center;"> <!-- Footer content --> <?php /* translators: %s - link to a site. */ $footer = sprintf( esc_html__( 'Sent from %s', 'wpforms-lite' ), '<a href="' . esc_url( home_url() ) . '" style="color:#bbbbbb;">' . wp_specialchars_decode( get_bloginfo( 'name' ) ) . '</a>' ); echo apply_filters( 'wpforms_email_footer_text', $footer ); ?> </td> </tr> </tbody> </table> </td> </tr> </tbody> </table> </td> </tr> </table> <!--[if gte mso 9]> </td> </tr> </table> <![endif]--> <!-- // END TEMPLATE --> </td> </tr> </table> </center> </body> </html> emails/class-emails.php 0000666 00000043734 15213301444 0011120 0 ustar 00 <?php use WPForms\Tasks\Actions\EntryEmailsTask; /** * Emails. * * This class handles all (notification) emails sent by WPForms. * * Heavily influenced by the great AffiliateWP plugin by Pippin Williamson. * https://github.com/AffiliateWP/AffiliateWP/blob/master/includes/emails/class-affwp-emails.php * * @since 1.1.3 */ class WPForms_WP_Emails { /** * Store the from address. * * @since 1.1.3 * * @var string */ private $from_address; /** * Store the from name. * * @since 1.1.3 * * @var string */ private $from_name; /** * Store the reply-to address. * * @since 1.1.3 * * @var string */ private $reply_to = false; /** * Store the carbon copy addresses. * * @since 1.3.1 * * @var string */ private $cc = false; /** * Store the email content type. * * @since 1.1.3 * * @var string */ private $content_type; /** * Store the email headers. * * @since 1.1.3 * * @var string */ private $headers; /** * Whether to send email in HTML. * * @since 1.1.3 * * @var bool */ private $html = true; /** * The email template to use. * * @since 1.1.3 * * @var string */ private $template; /** * Form data and settings. * * @since 1.1.3 * * @var array */ public $form_data = array(); /** * Fields, formatted, and sanitized. * * @since 1.1.3 * * @var array */ public $fields = array(); /** * Entry ID. * * @since 1.2.3 * * @var int */ public $entry_id = ''; /** * Notification ID that is currently being processed. * * @since 1.5.7 * * @var int */ public $notification_id = ''; /** * Get things going. * * @since 1.1.3 */ public function __construct() { if ( 'none' === $this->get_template() ) { $this->html = false; } add_action( 'wpforms_email_send_before', array( $this, 'send_before' ) ); add_action( 'wpforms_email_send_after', array( $this, 'send_after' ) ); } /** * Set a property. * * @since 1.1.3 * * @param string $key Object property key. * @param mixed $value Object property value. */ public function __set( $key, $value ) { $this->$key = $value; } /** * Get the email from name. * * @since 1.1.3 * * @return string The email from name */ public function get_from_name() { if ( ! empty( $this->from_name ) ) { $this->from_name = $this->process_tag( $this->from_name ); } else { $this->from_name = get_bloginfo( 'name' ); } return apply_filters( 'wpforms_email_from_name', wpforms_decode_string( $this->from_name ), $this ); } /** * Get the email from address. * * @since 1.1.3 * * @return string The email from address. */ public function get_from_address() { if ( ! empty( $this->from_address ) ) { $this->from_address = $this->process_tag( $this->from_address ); } else { $this->from_address = get_option( 'admin_email' ); } return apply_filters( 'wpforms_email_from_address', wpforms_decode_string( $this->from_address ), $this ); } /** * Get the email reply-to. * * @since 1.1.3 * * @return string The email reply-to address. */ public function get_reply_to() { if ( ! empty( $this->reply_to ) ) { $this->reply_to = $this->process_tag( $this->reply_to ); if ( ! is_email( $this->reply_to ) ) { $this->reply_to = false; } } return apply_filters( 'wpforms_email_reply_to', wpforms_decode_string( $this->reply_to ), $this ); } /** * Get the email carbon copy addresses. * * @since 1.3.1 * * @return string The email reply-to address. */ public function get_cc() { if ( ! empty( $this->cc ) ) { $this->cc = $this->process_tag( $this->cc ); $addresses = array_map( 'trim', explode( ',', $this->cc ) ); foreach ( $addresses as $key => $address ) { if ( ! is_email( $address ) ) { unset( $addresses[ $key ] ); } } $this->cc = implode( ',', $addresses ); } return apply_filters( 'wpforms_email_cc', wpforms_decode_string( $this->cc ), $this ); } /** * Get the email content type. * * @since 1.1.3 * * @return string The email content type. */ public function get_content_type() { if ( ! $this->content_type && $this->html ) { $this->content_type = apply_filters( 'wpforms_email_default_content_type', 'text/html', $this ); } elseif ( ! $this->html ) { $this->content_type = 'text/plain'; } return apply_filters( 'wpforms_email_content_type', $this->content_type, $this ); } /** * Get the email headers. * * @since 1.1.3 * * @return string The email headers. */ public function get_headers() { if ( ! $this->headers ) { $this->headers = "From: {$this->get_from_name()} <{$this->get_from_address()}>\r\n"; if ( $this->get_reply_to() ) { $this->headers .= "Reply-To: {$this->get_reply_to()}\r\n"; } if ( $this->get_cc() ) { $this->headers .= "Cc: {$this->get_cc()}\r\n"; } $this->headers .= "Content-Type: {$this->get_content_type()}; charset=utf-8\r\n"; } return apply_filters( 'wpforms_email_headers', $this->headers, $this ); } /** * Build the email. * * @since 1.1.3 * * @param string $message The email message. * * @return string */ public function build_email( $message ) { // Plain text email shortcut. if ( false === $this->html ) { $message = $this->process_tag( $message ); $message = str_replace( '{all_fields}', $this->wpforms_html_field_value( false ), $message ); return apply_filters( 'wpforms_email_message', wpforms_decode_string( $message ), $this ); } /* * Generate an HTML email. */ ob_start(); $this->get_template_part( 'header', $this->get_template(), true ); // Hooks into the email header. do_action( 'wpforms_email_header', $this ); $this->get_template_part( 'body', $this->get_template(), true ); // Hooks into the email body. do_action( 'wpforms_email_body', $this ); $this->get_template_part( 'footer', $this->get_template(), true ); // Hooks into the email footer. do_action( 'wpforms_email_footer', $this ); $message = $this->process_tag( $message ); $message = nl2br( $message ); $body = ob_get_clean(); $message = str_replace( '{email}', $message, $body ); $message = str_replace( '{all_fields}', $this->wpforms_html_field_value( true ), $message ); $message = make_clickable( $message ); return apply_filters( 'wpforms_email_message', $message, $this ); } /** * Send the email. * * @since 1.1.3 * * @param string $to The To address. * @param string $subject The subject line of the email. * @param string $message The body of the email. * @param array $attachments Attachments to the email. * * @return bool */ public function send( $to, $subject, $message, $attachments = array() ) { if ( ! did_action( 'init' ) && ! did_action( 'admin_init' ) ) { _doing_it_wrong( __FUNCTION__, esc_html__( 'You cannot send emails with WPForms_WP_Emails() until init/admin_init has been reached.', 'wpforms-lite' ), null ); return false; } // Don't send anything if emails have been disabled. if ( $this->is_email_disabled() ) { return false; } // Don't send if email address is invalid. if ( ! is_email( $to ) ) { return false; } // Hooks before email is sent. do_action( 'wpforms_email_send_before', $this ); // Deprecated filter for $attachments. $attachments = apply_filters_deprecated( 'wpforms_email_attachments', array( $attachments, $this ), '1.5.7 of the WPForms plugin', 'wpforms_emails_send_email_data' ); /* * Allow to filter data on per-email basis, * useful for localizations based on recipient email address, form settings, * or for specific notifications - whatever available in WPForms_WP_Emails class. */ $data = apply_filters( 'wpforms_emails_send_email_data', array( 'to' => $to, 'subject' => $subject, 'message' => $message, 'headers' => $this->get_headers(), 'attachments' => $attachments, ), $this ); $send_same_process = apply_filters( 'wpforms_tasks_entry_emails_trigger_send_same_process', false, $this->fields, ! empty( wpforms()->entry ) ? wpforms()->entry->get( $this->entry_id ) : [], $this->form_data, $this->entry_id, 'entry' ); if ( $send_same_process || ! empty( $this->form_data['settings']['disable_entries'] ) ) { // Let's do this NOW. $result = wp_mail( $data['to'], wpforms_decode_string( $this->process_tag( $data['subject'] ) ), $this->build_email( $data['message'] ), $data['headers'], $data['attachments'] ); } else { // Schedule the email. $result = (bool) ( new EntryEmailsTask() ) ->params( $data['to'], wpforms_decode_string( $this->process_tag( $data['subject'] ) ), $this->build_email( $data['message'] ), $data['headers'], $data['attachments'] ) ->register(); } // Hooks after the email is sent. do_action( 'wpforms_email_send_after', $this ); return $result; } /** * Add filters/actions before the email is sent. * * @since 1.1.3 */ public function send_before() { add_filter( 'wp_mail_from', array( $this, 'get_from_address' ) ); add_filter( 'wp_mail_from_name', array( $this, 'get_from_name' ) ); add_filter( 'wp_mail_content_type', array( $this, 'get_content_type' ) ); } /** * Remove filters/actions after the email is sent. * * @since 1.1.3 */ public function send_after() { remove_filter( 'wp_mail_from', array( $this, 'get_from_address' ) ); remove_filter( 'wp_mail_from_name', array( $this, 'get_from_name' ) ); remove_filter( 'wp_mail_content_type', array( $this, 'get_content_type' ) ); } /** * Convert text formatted HTML. This is primarily for turning line breaks * into <p> and <br/> tags. * * @since 1.1.3 * * @param string $message Text to convert. * * @return string */ public function text_to_html( $message ) { if ( 'text/html' === $this->content_type || true === $this->html ) { $message = wpautop( $message ); } return $message; } /** * Process a smart tag. * Decodes entities and sanitized (keeping line breaks) by default. * * @uses wpforms_decode_string() * * @since 1.1.3 * @since 1.6.0 Deprecated 2 params: $sanitize, $linebreaks. * * @param string $string String that may contain tags. * * @return string */ public function process_tag( $string = '' ) { return apply_filters( 'wpforms_process_smart_tags', $string, $this->form_data, $this->fields, $this->entry_id ); } /** * Process the all fields smart tag if present. * * @since 1.1.3 * * @param bool $is_html_email Toggle to use HTML or plaintext. * * @return string */ public function wpforms_html_field_value( $is_html_email = true ) { // phpcs:ignore if ( empty( $this->fields ) ) { return ''; } if ( empty( $this->form_data['fields'] ) ) { $is_html_email = false; } $message = ''; if ( $is_html_email ) { /* * HTML emails. */ ob_start(); // Hooks into the email field. do_action( 'wpforms_email_field', $this ); $this->get_template_part( 'field', $this->get_template(), true ); $field_template = ob_get_clean(); // Check to see if user has added support for field type. $other_fields = apply_filters( 'wpforms_email_display_other_fields', array(), $this ); $x = 1; foreach ( $this->form_data['fields'] as $field_id => $field ) { $field_name = ''; $field_val = ''; // If the field exists in the form_data but not in the final // field data, then it's a non-input based field, "other fields". if ( empty( $this->fields[ $field_id ] ) ) { if ( empty( $other_fields ) || ! in_array( $field['type'], $other_fields, true ) ) { continue; } if ( 'divider' === $field['type'] ) { $field_name = ! empty( $field['label'] ) ? str_repeat( '—', 3 ) . ' ' . $field['label'] . ' ' . str_repeat( '—', 3 ) : null; $field_val = ! empty( $field['description'] ) ? $field['description'] : ''; } elseif ( 'pagebreak' === $field['type'] ) { if ( ! empty( $field['position'] ) && 'bottom' === $field['position'] ) { continue; } $title = ! empty( $field['title'] ) ? $field['title'] : esc_html__( 'Page Break', 'wpforms-lite' ); $field_name = str_repeat( '—', 6 ) . ' ' . $title . ' ' . str_repeat( '—', 6 ); } elseif ( 'html' === $field['type'] ) { $field_name = null; $field_val = $field['code']; } } else { if ( ! apply_filters( 'wpforms_email_display_empty_fields', false ) && ( ! isset( $this->fields[ $field_id ]['value'] ) || (string) $this->fields[ $field_id ]['value'] === '' ) ) { continue; } $field_name = $this->fields[ $field_id ]['name']; $field_val = empty( $this->fields[ $field_id ]['value'] ) && ! is_numeric( $this->fields[ $field_id ]['value'] ) ? '<em>' . esc_html__( '(empty)', 'wpforms-lite' ) . '</em>' : $this->fields[ $field_id ]['value']; } if ( empty( $field_name ) && null !== $field_name ) { $field_name = sprintf( /* translators: %d - field ID. */ esc_html__( 'Field ID #%d', 'wpforms-lite' ), absint( $field['id'] ) ); } $field_item = $field_template; if ( 1 === $x ) { $field_item = str_replace( 'border-top:1px solid #dddddd;', '', $field_item ); } $field_item = str_replace( '{field_name}', $field_name, $field_item ); $field_item = str_replace( '{field_value}', apply_filters( 'wpforms_html_field_value', $field_val, isset( $this->fields[ $field_id ] ) ? $this->fields[ $field_id ] : $field, $this->form_data, 'email-html' ), $field_item ); $message .= wpautop( $field_item ); $x ++; } } else { /* * Plain Text emails. */ foreach ( $this->fields as $field ) { if ( ! apply_filters( 'wpforms_email_display_empty_fields', false ) && ( ! isset( $field['value'] ) || (string) $field['value'] === '' ) ) { continue; } $field_val = empty( $field['value'] ) && ! is_numeric( $field['value'] ) ? esc_html__( '(empty)', 'wpforms-lite' ) : $field['value']; $field_name = $field['name']; if ( empty( $field_name ) ) { $field_name = sprintf( /* translators: %d - field ID. */ esc_html__( 'Field ID #%d', 'wpforms-lite' ), absint( $field['id'] ) ); } $message .= '--- ' . $field_name . " ---\r\n\r\n"; $field_value = $field_val . "\r\n\r\n"; $message .= apply_filters( 'wpforms_plaintext_field_value', $field_value, $field, $this->form_data ); } } if ( empty( $message ) ) { $empty_message = esc_html__( 'An empty form was submitted.', 'wpforms-lite' ); $message = $is_html_email ? wpautop( $empty_message ) : $empty_message; } return $message; } /** * Email kill switch if needed. * * @since 1.1.3 * * @return bool */ public function is_email_disabled() { return (bool) apply_filters( 'wpforms_disable_all_emails', false, $this ); } /** * Get the enabled email template. * * @since 1.1.3 * * @return string When filtering return 'none' to switch to text/plain email. */ public function get_template() { if ( ! $this->template ) { $this->template = wpforms_setting( 'email-template', 'default' ); } return apply_filters( 'wpforms_email_template', $this->template ); } /** * Retrieve a template part. Taken from bbPress. * * @since 1.1.3 * * @param string $slug Template file slug. * @param string $name Optional. Default null. * @param bool $load Maybe load. * * @return string */ public function get_template_part( $slug, $name = null, $load = true ) { // Setup possible parts. $templates = array(); if ( isset( $name ) ) { $templates[] = $slug . '-' . $name . '.php'; } $templates[] = $slug . '.php'; // Return the part that is found. return $this->locate_template( $templates, $load, false ); } /** * Retrieve the name of the highest priority template file that exists. * * Search in the STYLESHEETPATH before TEMPLATEPATH so that themes which * inherit from a parent theme can just overload one file. If the template is * not found in either of those, it looks in the theme-compat folder last. * * Taken from bbPress. * * @since 1.1.3 * * @param string|array $template_names Template file(s) to search for, in order. * @param bool $load If true the template file will be loaded if it is found. * @param bool $require_once Whether to require_once or require. Default true. * Has no effect if $load is false. * * @return string The template filename if one is located. */ public function locate_template( $template_names, $load = false, $require_once = true ) { // No file found yet. $located = false; // Try to find a template file. foreach ( (array) $template_names as $template_name ) { // Continue if template is empty. if ( empty( $template_name ) ) { continue; } // Trim off any slashes from the template name. $template_name = ltrim( $template_name, '/' ); // Try locating this template file by looping through the template paths. foreach ( $this->get_theme_template_paths() as $template_path ) { if ( file_exists( $template_path . $template_name ) ) { $located = $template_path . $template_name; break; } } } if ( ( true === $load ) && ! empty( $located ) ) { load_template( $located, $require_once ); } return $located; } /** * Return a list of paths to check for template locations * * @since 1.1.3 * * @return array */ public function get_theme_template_paths() { $template_dir = 'wpforms-email'; $file_paths = array( 1 => trailingslashit( get_stylesheet_directory() ) . $template_dir, 10 => trailingslashit( get_template_directory() ) . $template_dir, 100 => WPFORMS_PLUGIN_DIR . 'includes/emails/templates', ); $file_paths = apply_filters( 'wpforms_email_template_paths', $file_paths ); // Sort the file paths based on priority. ksort( $file_paths, SORT_NUMERIC ); return array_map( 'trailingslashit', $file_paths ); } } class-widget.php 0000666 00000012377 15213301444 0007656 0 ustar 00 <?php /** * WPForms widget. * * @since 1.0.2 */ class WPForms_Widget extends WP_Widget { /** * Hold widget settings defaults, populated in constructor. * * @since 1.0.2 * * @var array */ protected $defaults; /** * Constructor * * @since 1.0.2 */ public function __construct() { // Widget defaults. $this->defaults = array( 'title' => '', 'form_id' => '', 'show_title' => false, 'show_desc' => false, ); // Widget Slug. $widget_slug = 'wpforms-widget'; // Widget basics. $widget_ops = array( 'classname' => $widget_slug, 'description' => esc_html_x( 'Display a form.', 'Widget', 'wpforms-lite' ), ); // Widget controls. $control_ops = array( 'id_base' => $widget_slug, ); // Load widget. parent::__construct( $widget_slug, esc_html_x( 'WPForms', 'Widget', 'wpforms-lite' ), $widget_ops, $control_ops ); } /** * Output the HTML for this widget. * * @since 1.0.2 * * @param array $args An array of standard parameters for widgets in this theme. * @param array $instance An array of settings for this widget instance. */ public function widget( $args, $instance ) { // Merge with defaults. $instance = wp_parse_args( (array) $instance, $this->defaults ); echo $args['before_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped // Title. if ( ! empty( $instance['title'] ) ) { echo $args['before_title'] . apply_filters( 'widget_title', $instance['title'], $instance, $this->id_base ) . $args['after_title']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped } // Form. if ( ! empty( $instance['form_id'] ) ) { wpforms()->frontend->output( absint( $instance['form_id'] ), $instance['show_title'], $instance['show_desc'] ); } echo $args['after_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped } /** * Deal with the settings when they are saved by the admin. Here is * where any validation should be dealt with. * * @since 1.0.2 * * @param array $new_instance An array of new settings as submitted by the admin. * @param array $old_instance An array of the previous settings. * * @return array The validated and (if necessary) amended settings */ public function update( $new_instance, $old_instance ) { $new_instance['title'] = wp_strip_all_tags( $new_instance['title'] ); $new_instance['form_id'] = ! empty( $new_instance['form_id'] ) ? (int) $new_instance['form_id'] : 0; $new_instance['show_title'] = isset( $new_instance['show_title'] ) ? '1' : false; $new_instance['show_desc'] = isset( $new_instance['show_desc'] ) ? '1' : false; return $new_instance; } /** * Display the form for this widget on the Widgets page of the WP Admin area. * * @since 1.0.2 * * @param array $instance An array of the current settings for this widget. */ public function form( $instance ) { // Merge with defaults. $instance = wp_parse_args( (array) $instance, $this->defaults ); ?> <p> <label for="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>"> <?php echo esc_html( _x( 'Title:', 'Widget', 'wpforms-lite' ) ); ?> </label> <input type="text" id="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'title' ) ); ?>" value="<?php echo esc_attr( $instance['title'] ); ?>" class="widefat"/> </p> <p> <label for="<?php echo esc_attr( $this->get_field_id( 'form_id' ) ); ?>"> <?php echo esc_html( _x( 'Form:', 'Widget', 'wpforms-lite' ) ); ?> </label> <select class="widefat" id="<?php echo esc_attr( $this->get_field_id( 'form_id' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'form_id' ) ); ?>"> <?php $forms = wpforms()->form->get(); if ( ! empty( $forms ) ) { echo '<option value="" selected disabled>' . esc_html_x( 'Select your form', 'Widget', 'wpforms-lite' ) . '</option>'; foreach ( $forms as $form ) { echo '<option value="' . esc_attr( $form->ID ) . '" ' . selected( $instance['form_id'], $form->ID, false ) . '>' . esc_html( $form->post_title ) . '</option>'; } } else { echo '<option value="">' . esc_html_x( 'No forms', 'Widget', 'wpforms-lite' ) . '</option>'; } ?> </select> </p> <p> <input type="checkbox" id="<?php echo esc_attr( $this->get_field_id( 'show_title' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'show_title' ) ); ?>" <?php checked( '1', $instance['show_title'] ); ?>> <label for="<?php echo esc_attr( $this->get_field_id( 'show_title' ) ); ?>"> <?php echo esc_html( _x( 'Display form name', 'Widget', 'wpforms-lite' ) ); ?> </label> <br> <input type="checkbox" id="<?php echo esc_attr( $this->get_field_id( 'show_desc' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'show_desc' ) ); ?>" <?php checked( '1', $instance['show_desc'] ); ?>> <label for="<?php echo esc_attr( $this->get_field_id( 'show_desc' ) ); ?>"> <?php echo esc_html( _x( 'Display form description', 'Widget', 'wpforms-lite' ) ); ?> </label> </p> <?php } } /** * Register WPForms plugin widgets. */ function wpforms_register_widgets() { register_widget( 'WPForms_Widget' ); } add_action( 'widgets_init', 'wpforms_register_widgets' ); class-frontend.php 0000666 00000134476 15213301444 0010217 0 ustar 00 <?php /** * Form front-end rendering. * * @since 1.0.0 */ class WPForms_Frontend { /** * Store form data to be referenced later. * * @since 1.0.0 * @var array */ public $forms; /** * Store information for multi-page forms. * * Forms that do not contain pages return false, otherwise returns an array * that contains the number of total pages and page counter used when * displaying pagebreak fields. * * @since 1.3.7 * * @var array */ public $pages = false; /** * Store a form confirmation message. * * @since 1.4.8 * @todo Remove in favor of \WPForms_Process::$confirmation_message(). * * @var string */ public $confirmation_message = ''; /** * If the active form confirmation should auto scroll. * * @since 1.4.9 * * @var bool */ public $confirmation_message_scroll = false; /** * Primary class constructor. * * @since 1.0.0 */ public function __construct() { $this->forms = array(); // Filters. add_filter( 'amp_skip_post', array( $this, 'amp_skip_post' ) ); // Actions. add_action( 'wpforms_frontend_output_success', array( $this, 'confirmation' ), 10, 3 ); add_action( 'wpforms_frontend_output', array( $this, 'head' ), 5, 5 ); add_action( 'wpforms_frontend_output', array( $this, 'fields' ), 10, 5 ); add_action( 'wpforms_display_field_before', array( $this, 'field_container_open' ), 5, 2 ); add_action( 'wpforms_display_field_before', array( $this, 'field_label' ), 15, 2 ); add_action( 'wpforms_display_field_before', array( $this, 'field_description' ), 20, 2 ); add_action( 'wpforms_display_field_after', array( $this, 'field_error' ), 3, 2 ); add_action( 'wpforms_display_field_after', array( $this, 'field_description' ), 5, 2 ); add_action( 'wpforms_display_field_after', array( $this, 'field_container_close' ), 15, 2 ); add_action( 'wpforms_frontend_output', array( $this, 'honeypot' ), 15, 5 ); add_action( 'wpforms_frontend_output', array( $this, 'recaptcha' ), 20, 5 ); add_action( 'wpforms_frontend_output', array( $this, 'foot' ), 25, 5 ); add_action( 'wp_enqueue_scripts', array( $this, 'assets_header' ) ); add_action( 'wp_enqueue_scripts', array( $this, 'recaptcha_noconflict' ), 9999 ); add_action( 'wp_footer', array( $this, 'assets_footer' ), 15 ); add_action( 'wp_footer', array( $this, 'recaptcha_noconflict' ), 19 ); add_action( 'wp_footer', array( $this, 'footer_end' ), 99 ); // Register shortcode. add_shortcode( 'wpforms', array( $this, 'shortcode' ) ); } /** * Get the amp-state ID for a given form. * * @param int $form_id Form ID. * @return string State ID. */ protected function get_form_amp_state_id( $form_id ) { return sprintf( 'wpforms_form_state_%d', $form_id ); } /** * Disable AMP if query param is detected. * * This allows the full form to be accessible for Pro users or sites * that do not have SSL. * * @since 1.5.3 * * @param bool $skip Skip AMP mode, display full post. * * @return bool */ public function amp_skip_post( $skip ) { return isset( $_GET['nonamp'] ) ? true : $skip; } /** * Primary function to render a form on the frontend. * * @since 1.0.0 * * @param int $id Form ID. * @param bool $title Whether to display form title. * @param bool $description Whether to display form description. */ public function output( $id, $title = false, $description = false ) { if ( empty( $id ) ) { return; } // Grab the form data, if not found then we bail. $form = wpforms()->form->get( (int) $id ); if ( empty( $form ) ) { return; } // Basic information. $form_data = apply_filters( 'wpforms_frontend_form_data', wpforms_decode( $form->post_content ) ); $form_id = absint( $form->ID ); $settings = $form_data['settings']; $action = esc_url_raw( remove_query_arg( 'wpforms' ) ); $classes = wpforms_setting( 'disable-css', '1' ) == '1' ? array( 'wpforms-container-full' ) : array(); $errors = empty( wpforms()->process->errors[ $form_id ] ) ? array() : wpforms()->process->errors[ $form_id ]; $title = filter_var( $title, FILTER_VALIDATE_BOOLEAN ); $description = filter_var( $description, FILTER_VALIDATE_BOOLEAN ); // If the form does not contain any fields - do not proceed. if ( empty( $form_data['fields'] ) ) { echo '<!-- WPForms: no fields, form hidden -->'; return; } // We need to stop output processing in case we are on AMP page. if ( wpforms_is_amp( false ) && ( ! current_theme_supports( 'amp' ) || apply_filters( 'wpforms_amp_pro', wpforms()->pro ) || ! is_ssl() || ! defined( 'AMP__VERSION' ) || version_compare( AMP__VERSION, '1.2', '<' ) ) ) { $text = apply_filters( 'wpforms_frontend_shortcode_amp_text', sprintf( wp_kses( /* translators: %s - URL to a non-amp version of a page with the form. */ __( '<a href="%s">Go to the full page</a> to view and submit the form.', 'wpforms-lite' ), array( 'a' => array( 'href' => array(), ), ) ), esc_url( home_url( add_query_arg( 'nonamp', '1' ) . '#wpforms-' . absint( $form->ID ) ) ) ) ); echo '<p class="wpforms-shortcode-amp-text">' . $text . '</p>'; return; } // Add url query var wpforms_form_id to track post_max_size overflows. if ( in_array( 'file-upload', wp_list_pluck( $form_data['fields'], 'type' ), true ) ) { $action = add_query_arg( 'wpforms_form_id', $form_id, $action ); } // Before output hook. do_action( 'wpforms_frontend_output_before', $form_data, $form ); // Check for return hash. if ( ! empty( $_GET['wpforms_return'] ) && wpforms()->process->valid_hash && absint( wpforms()->process->form_data['id'] ) === $form_id ) { do_action( 'wpforms_frontend_output_success', wpforms()->process->form_data, wpforms()->process->fields, wpforms()->process->entry_id ); wpforms_debug_data( $_POST ); // phpcs:ignore WordPress.Security.NonceVerification.Missing return; } // Check for error-free completed form. if ( empty( $errors ) && ! empty( $form_data ) && ! empty( $_POST['wpforms']['id'] ) && absint( $_POST['wpforms']['id'] ) === $form_id ) { do_action( 'wpforms_frontend_output_success', $form_data, false, false ); wpforms_debug_data( $_POST ); // phpcs:ignore WordPress.Security.NonceVerification.Missing return; } // Allow filter to return early if some condition is not met. if ( ! apply_filters( 'wpforms_frontend_load', true, $form_data, null ) ) { do_action( 'wpforms_frontend_not_loaded', $form_data, $form ); return; } // All checks have passed, so calculate multi-page details for the form. $pages = wpforms_get_pagebreak_details( $form_data ); if ( $pages ) { $this->pages = $pages; } else { $this->pages = false; } // Allow final action to be customized - 3rd param ($form) has been deprecated. $action = apply_filters( 'wpforms_frontend_form_action', $action, $form_data, null ); // Allow form container classes to be filtered and user defined classes. $classes = apply_filters( 'wpforms_frontend_container_class', $classes, $form_data ); if ( ! empty( $settings['form_class'] ) ) { $classes = array_merge( $classes, explode( ' ', $settings['form_class'] ) ); } $classes = wpforms_sanitize_classes( $classes, true ); $form_classes = array( 'wpforms-validate', 'wpforms-form' ); if ( ! empty( $form_data['settings']['ajax_submit'] ) && ! wpforms_is_amp() ) { $form_classes[] = 'wpforms-ajax-form'; } $form_atts = array( 'id' => sprintf( 'wpforms-form-%d', absint( $form_id ) ), 'class' => $form_classes, 'data' => array( 'formid' => absint( $form_id ), ), 'atts' => array( 'method' => 'post', 'enctype' => 'multipart/form-data', 'action' => esc_url( $action ), ), ); if ( wpforms_is_amp() ) { // Set submitting state. if ( ! isset( $form_atts['atts']['on'] ) ) { $form_atts['atts']['on'] = ''; } else { $form_atts['atts']['on'] .= ';'; } $form_atts['atts']['on'] .= sprintf( 'submit:AMP.setState( %1$s ); submit-success:AMP.setState( %2$s ); submit-error:AMP.setState( %2$s );', wp_json_encode( array( $this->get_form_amp_state_id( $form_id ) => array( 'submitting' => true, ), ) ), wp_json_encode( array( $this->get_form_amp_state_id( $form_id ) => array( 'submitting' => false, ), ) ) ); // Upgrade the form to be an amp-form to avoid sanitizer conversion. if ( isset( $form_atts['atts']['action'] ) ) { $form_atts['atts']['action-xhr'] = $form_atts['atts']['action']; unset( $form_atts['atts']['action'] ); $form_atts['atts']['verify-xhr'] = $form_atts['atts']['action-xhr']; } } $form_atts = apply_filters( 'wpforms_frontend_form_atts', $form_atts, $form_data ); // Begin to build the output. do_action( 'wpforms_frontend_output_container_before', $form_data, $form ); printf( '<div class="wpforms-container %s" id="wpforms-%d">', esc_attr( $classes ), absint( $form_id ) ); do_action( 'wpforms_frontend_output_form_before', $form_data, $form ); echo '<form ' . wpforms_html_attributes( $form_atts['id'], $form_atts['class'], $form_atts['data'], $form_atts['atts'] ) . '>'; if ( wpforms_is_amp() ) { $state = array( 'submitting' => false, ); printf( '<amp-state id="%s"><script type="application/json">%s</script></amp-state>', $this->get_form_amp_state_id( $form_id ), wp_json_encode( $state ) ); } do_action( 'wpforms_frontend_output', $form_data, null, $title, $description, $errors ); echo '</form>'; do_action( 'wpforms_frontend_output_form_after', $form_data, $form ); echo '</div> <!-- .wpforms-container -->'; do_action( 'wpforms_frontend_output_container_after', $form_data, $form ); // Add form to class property that tracks all forms in a page. $this->forms[ $form_id ] = $form_data; // Optional debug information if WPFORMS_DEBUG is defined. wpforms_debug_data( $_POST ); // phpcs:ignore WordPress.Security.NonceVerification.Missing // After output hook. do_action( 'wpforms_frontend_output_after', $form_data, $form ); } /** * Display form confirmation message. * * @since 1.0.0 * * @param array $form_data Form data and settings. * @param array $fields Sanitized field data. * @param int $entry_id Entry id. */ public function confirmation( $form_data, $fields = array(), $entry_id = 0 ) { $class = intval( wpforms_setting( 'disable-css', '1' ) ) === 1 ? 'wpforms-confirmation-container-full' : 'wpforms-confirmation-container'; // In AMP, just print template. if ( wpforms_is_amp() ) { $this->assets_confirmation(); printf( '<div submit-success><template type="amp-mustache"><div class="%s {{#redirecting}}wpforms-redirection-message{{/redirecting}}">{{{message}}}</div></template></div>', esc_attr( $class ) ); return; } if ( empty( $fields ) ) { $fields = ! empty( $_POST['wpforms']['complete'] ) ? $_POST['wpforms']['complete'] : array(); } if ( empty( $entry_id ) ) { $entry_id = ! empty( $_POST['wpforms']['entry_id'] ) ? $_POST['wpforms']['entry_id'] : 0; } $confirmation_message = wpforms()->process->get_confirmation_message( $form_data, $fields, $entry_id ); // Only display if a confirmation message has been configured. if ( empty( $confirmation_message ) ) { return; } // Load confirmation specific assets. $this->assets_confirmation(); $class .= $this->confirmation_message_scroll ? ' wpforms-confirmation-scroll' : ''; printf( '<div class="%s" id="wpforms-confirmation-%d">%s</div>', $class, absint( $form_data['id'] ), $confirmation_message ); } /** * Form head area, for displaying form title and description if enabled. * * @since 1.0.0 * * @param array $form_data Form data and settings. * @param null $deprecated Deprecated in v1.3.7, previously was $form object. * @param bool $title Whether to display form title. * @param bool $description Whether to display form description. * @param array $errors List of all errors filled in WPForms_Process::process(). */ public function head( $form_data, $deprecated, $title, $description, $errors ) { $settings = $form_data['settings']; // Output title and/or description. if ( true === $title || true === $description ) { echo '<div class="wpforms-head-container">'; if ( true === $title && ! empty( $settings['form_title'] ) ) { echo '<div class="wpforms-title">' . esc_html( $settings['form_title'] ) . '</div>'; } if ( true === $description && ! empty( $settings['form_desc'] ) ) { echo '<div class="wpforms-description">' . $settings['form_desc'] . '</div>'; } echo '</div>'; } // Output <noscript> error message. $noscript_msg = apply_filters( 'wpforms_frontend_noscript_error_message', __( 'Please enable JavaScript in your browser to complete this form.', 'wpforms-lite' ), $form_data ); if ( ! empty( $noscript_msg ) && ! empty( $form_data['fields'] ) && ! wpforms_is_amp() ) { echo '<noscript class="wpforms-error-noscript">' . esc_html( $noscript_msg ) . '</noscript>'; } // Output header errors if they exist. if ( ! empty( $errors['header'] ) ) { $this->form_error( 'header', $errors['header'] ); } } /** * Form field area. * * @since 1.0.0 * * @param array $form_data Form data and settings. * @param null $deprecated Deprecated in v1.3.7, previously was $form object. * @param bool $title Whether to display form title. * @param bool $description Whether to display form description. * @param array $errors List of all errors filled in WPForms_Process::process(). */ public function fields( $form_data, $deprecated, $title, $description, $errors ) { // Obviously we need to have form fields to proceed. if ( empty( $form_data['fields'] ) ) { return; } // Form fields area. echo '<div class="wpforms-field-container">'; /** * Core actions on this hook: * Priority / Description * 20 Pagebreak markup (open first page) */ do_action( 'wpforms_display_fields_before', $form_data ); // Loop through all the fields we have. foreach ( $form_data['fields'] as $field ) : $field = apply_filters( 'wpforms_field_data', $field, $form_data ); if ( empty( $field ) ) { continue; } // Get field attributes. Deprecated; Customizations should use // field properties instead. $attributes = $this->get_field_attributes( $field, $form_data ); // Add properties to the field so it's available everywhere. $field['properties'] = $this->get_field_properties( $field, $form_data, $attributes ); /** * Core actions on this hook: * Priority / Description * 5 Field opening container markup. * 15 Field label. * 20 Field description (depending on position). */ do_action( 'wpforms_display_field_before', $field, $form_data ); /** * Individual field classes use this hook to display the actual * field form elements. * See `field_display` methods in /includes/fields. */ do_action( "wpforms_display_field_{$field['type']}", $field, $attributes, $form_data ); /** * Core actions on this hook: * Priority / Description * 3 Field error messages. * 5 Field description (depending on position). * 15 Field closing container markup. * 20 Pagebreak markup (close previous page, open next) */ do_action( 'wpforms_display_field_after', $field, $form_data ); endforeach; /** * Core actions on this hook: * Priority / Description * 5 Pagebreak markup (close last page) */ do_action( 'wpforms_display_fields_after', $form_data ); echo '</div>'; } /** * Return base attributes for a specific field. This is deprecated and * exists for backwards-compatibility purposes. Use field properties instead. * * @since 1.3.7 * * @param array $field Field data and settings. * @param array $form_data Form data and settings. * * @return array */ public function get_field_attributes( $field, $form_data ) { $form_id = absint( $form_data['id'] ); $field_id = absint( $field['id'] ); $attributes = array( 'field_class' => array( 'wpforms-field', 'wpforms-field-' . sanitize_html_class( $field['type'] ) ), 'field_id' => array( sprintf( 'wpforms-%d-field_%d-container', $form_id, $field_id ) ), 'field_style' => '', 'label_class' => array( 'wpforms-field-label' ), 'label_id' => '', 'description_class' => array( 'wpforms-field-description' ), 'description_id' => array(), 'input_id' => array( sprintf( 'wpforms-%d-field_%d', $form_id, $field_id ) ), 'input_class' => array(), 'input_data' => array(), ); // Check user field defined classes. if ( ! empty( $field['css'] ) ) { $attributes['field_class'] = array_merge( $attributes['field_class'], wpforms_sanitize_classes( $field['css'], true ) ); } // Check for input column layouts. if ( ! empty( $field['input_columns'] ) ) { if ( '2' === $field['input_columns'] ) { $attributes['field_class'][] = 'wpforms-list-2-columns'; } elseif ( '3' === $field['input_columns'] ) { $attributes['field_class'][] = 'wpforms-list-3-columns'; } elseif ( 'inline' === $field['input_columns'] ) { $attributes['field_class'][] = 'wpforms-list-inline'; } } // Check label visibility. if ( ! empty( $field['label_hide'] ) ) { $attributes['label_class'][] = 'wpforms-label-hide'; } // Check size. if ( ! empty( $field['size'] ) ) { $attributes['input_class'][] = 'wpforms-field-' . sanitize_html_class( $field['size'] ); } // Check if required. if ( ! empty( $field['required'] ) ) { $attributes['input_class'][] = 'wpforms-field-required'; } // Check if there are errors. if ( ! empty( wpforms()->process->errors[ $form_id ][ $field_id ] ) ) { $attributes['input_class'][] = 'wpforms-error'; } // This filter is deprecated, filter the properties (below) instead. $attributes = apply_filters( 'wpforms_field_atts', $attributes, $field, $form_data ); return $attributes; } /** * Return base properties for a specific field. * * @since 1.3.7 * * @param array $field Field data and settings. * @param array $form_data Form data and settings. * @param array $attributes List of field attributes. * * @return array */ public function get_field_properties( $field, $form_data, $attributes = array() ) { if ( empty( $attributes ) ) { $attributes = $this->get_field_attributes( $field, $form_data ); } // This filter is for backwards compatibility purposes. $types = array( 'text', 'textarea', 'name', 'number', 'email', 'hidden', 'url', 'html', 'divider', 'password', 'phone', 'address', 'select', 'checkbox', 'radio' ); if ( in_array( $field['type'], $types, true ) ) { $field = apply_filters( "wpforms_{$field['type']}_field_display", $field, $attributes, $form_data ); } elseif ( 'credit-card' === $field['type'] ) { $field = apply_filters( 'wpforms_creditcard_field_display', $field, $attributes, $form_data ); } elseif ( in_array( $field['type'], array( 'payment-multiple', 'payment-single', 'payment-checkbox' ), true ) ) { $filter_field_type = str_replace( '-', '_', $field['type'] ); $field = apply_filters( 'wpforms_' . $filter_field_type . '_field_display', $field, $attributes, $form_data ); } $form_id = absint( $form_data['id'] ); $field_id = absint( $field['id'] ); $error = ! empty( wpforms()->process->errors[ $form_id ][ $field_id ] ) ? wpforms()->process->errors[ $form_id ][ $field_id ] : ''; $properties = array( 'container' => array( 'attr' => array( 'style' => $attributes['field_style'], ), 'class' => $attributes['field_class'], 'data' => array(), 'id' => implode( '', array_slice( $attributes['field_id'], 0 ) ), ), 'label' => array( 'attr' => array( 'for' => sprintf( 'wpforms-%d-field_%d', $form_id, $field_id ), ), 'class' => $attributes['label_class'], 'data' => array(), 'disabled' => ! empty( $field['label_disable'] ) ? true : false, 'hidden' => ! empty( $field['label_hide'] ) ? true : false, 'id' => $attributes['label_id'], 'required' => ! empty( $field['required'] ) ? true : false, 'value' => ! empty( $field['label'] ) ? $field['label'] : '', ), 'inputs' => array( 'primary' => array( 'attr' => array( 'name' => "wpforms[fields][{$field_id}]", 'value' => isset( $field['default_value'] ) ? apply_filters( 'wpforms_process_smart_tags', $field['default_value'], $form_data ) : '', 'placeholder' => isset( $field['placeholder'] ) ? $field['placeholder'] : '', ), 'class' => $attributes['input_class'], 'data' => $attributes['input_data'], 'id' => implode( array_slice( $attributes['input_id'], 0 ) ), 'required' => ! empty( $field['required'] ) ? 'required' : '', ), ), 'error' => array( 'attr' => array( 'for' => sprintf( 'wpforms-%d-field_%d', $form_id, $field_id ), ), 'class' => array( 'wpforms-error' ), 'data' => array(), 'id' => '', 'value' => $error, ), 'description' => array( 'attr' => array(), 'class' => $attributes['description_class'], 'data' => array(), 'id' => implode( '', array_slice( $attributes['description_id'], 0 ) ), 'position' => 'after', 'value' => ! empty( $field['description'] ) ? apply_filters( 'wpforms_process_smart_tags', $field['description'], $form_data ) : '', ), ); $properties = apply_filters( "wpforms_field_properties_{$field['type']}", $properties, $field, $form_data ); $properties = apply_filters( 'wpforms_field_properties', $properties, $field, $form_data ); return $properties; } /** * Display the opening container markup for each field. * * @since 1.3.7 * * @param array $field Field data and settings. * @param array $form_data Form data and settings. */ public function field_container_open( $field, $form_data ) { $container = $field['properties']['container']; $container['data']['field-id'] = absint( $field['id'] ); printf( '<div %s>', wpforms_html_attributes( $container['id'], $container['class'], $container['data'], $container['attr'] ) ); } /** * Display the label for each field. * * @since 1.3.7 * * @param array $field Field data and settings. * @param array $form_data Form data and settings. */ public function field_label( $field, $form_data ) { $label = $field['properties']['label']; // If the label is empty or disabled don't proceed. if ( empty( $label['value'] ) || $label['disabled'] ) { return; } $required = $label['required'] ? wpforms_get_field_required_label() : ''; printf( '<label %s>%s%s</label>', wpforms_html_attributes( $label['id'], $label['class'], $label['data'], $label['attr'] ), esc_html( $label['value'] ), $required ); } /** * Display any errors for each field. * * @since 1.3.7 * * @param array $field Field data and settings. * @param array $form_data Form data and settings. */ public function field_error( $field, $form_data ) { $error = $field['properties']['error']; // If there are no errors don't proceed. // Advanced fields with multiple inputs (address, name, etc) errors // will be an array and are handled within the respective field class. if ( empty( $error['value'] ) || is_array( $error['value'] ) ) { return; } printf( '<label %s>%s</label>', wpforms_html_attributes( $error['id'], $error['class'], $error['data'], $error['attr'] ), esc_html( $error['value'] ) ); } /** * Display the description for each field. * * @since 1.3.7 * * @param array $field Field data and settings. * @param array $form_data Form data and settings. */ public function field_description( $field, $form_data ) { $action = current_action(); $description = $field['properties']['description']; // If the description is empty don't proceed. if ( empty( $description['value'] ) ) { return; } // Determine positioning. if ( 'wpforms_display_field_before' === $action && 'before' !== $description['position'] ) { return; } if ( 'wpforms_display_field_after' === $action && 'after' !== $description['position'] ) { return; } if ( 'before' === $description['position'] ) { $description['class'][] = 'before'; } printf( '<div %s>%s</div>', wpforms_html_attributes( $description['id'], $description['class'], $description['data'], $description['attr'] ), do_shortcode( $description['value'] ) ); } /** * Display the closing container markup for each field. * * @since 1.3.7 * * @param array $field Field data and settings. * @param array $form_data Form data and settings. */ public function field_container_close( $field, $form_data ) { echo '</div>'; } /** * Anti-spam honeypot output if configured. * * @since 1.0.0 * * @param array $form_data Form data and settings. * @param null $deprecated Deprecated in v1.3.7, previously was $form object. * @param bool $title Whether to display form title. * @param bool $description Whether to display form description. * @param array $errors List of all errors filled in WPForms_Process::process(). */ public function honeypot( $form_data, $deprecated, $title, $description, $errors ) { if ( empty( $form_data['settings']['honeypot'] ) || '1' !== $form_data['settings']['honeypot'] ) { return; } $names = array( 'Name', 'Phone', 'Comment', 'Message', 'Email', 'Website' ); echo '<div class="wpforms-field wpforms-field-hp">'; echo '<label for="wpforms-' . $form_data['id'] . '-field-hp" class="wpforms-field-label">' . $names[ array_rand( $names ) ] . '</label>'; // phpcs:ignore echo '<input type="text" name="wpforms[hp]" id="wpforms-' . $form_data['id'] . '-field-hp" class="wpforms-field-medium">'; // phpcs:ignore echo '</div>'; } /** * Google reCAPTCHA output if configured. * * @since 1.0.0 * * @param array $form_data Form data and settings. * @param null $deprecated Deprecated in v1.3.7, previously was $form object. * @param bool $title Whether to display form title. * @param bool $description Whether to display form description. * @param array $errors List of all errors filled in WPForms_Process::process(). */ public function recaptcha( $form_data, $deprecated, $title, $description, $errors ) { // Check that recaptcha is configured in the settings. $site_key = wpforms_setting( 'recaptcha-site-key' ); $secret_key = wpforms_setting( 'recaptcha-secret-key' ); $type = wpforms_setting( 'recaptcha-type', 'v2' ); if ( ! $site_key || ! $secret_key ) { return; } // Check that the recaptcha is configured for the specific form. if ( ! isset( $form_data['settings']['recaptcha'] ) || '1' != $form_data['settings']['recaptcha'] ) { return; } if ( wpforms_is_amp() ) { if ( 'v3' === $type ) { printf( '<amp-recaptcha-input name="wpforms[recaptcha]" data-sitekey="%s" data-action="%s" layout="nodisplay"></amp-recaptcha-input>', esc_attr( $site_key ), esc_attr( 'wpforms_' . $form_data['id'] ) ); } elseif ( is_super_admin() ) { echo '<div class="wpforms-notice wpforms-warning" style="margin: 20px 0;">'; printf( wp_kses( /* translators: %s - URL to reCAPTCHA documentation. */ __( 'Google reCAPTCHA v2 is not supported by AMP and is currently disabled.<br><a href="%s" rel="noopener noreferrer" target="_blank">Upgrade to reCAPTCHA v3</a> for full AMP support. <br><em>Please note: this message is only displayed to site administrators.</em>', 'wpforms-drip' ), array( 'a' => array( 'href' => array(), 'rel' => array(), 'target' => array(), ), 'br' => array(), 'em' => array(), ) ), 'https://wpforms.com/docs/setup-captcha-wpforms/' ); echo '</div>'; } return; // Only v3 is supported in AMP. } if ( 'v3' === $type ) { echo '<input type="hidden" name="wpforms[recaptcha]" value="">'; return; } $visible = $this->pages ? 'style="display:none;"' : ''; $data = array( 'sitekey' => trim( sanitize_text_field( $site_key ) ), ); $data = apply_filters( 'wpforms_frontend_recaptcha', $data, $form_data ); if ( 'invisible' === $type ) { $data['size'] = 'invisible'; } echo '<div class="wpforms-recaptcha-container" ' . $visible . '>'; echo '<div ' . wpforms_html_attributes( '', array( 'g-recaptcha' ), $data ) . '></div>'; if ( 'invisible' !== $type ) { echo '<input type="text" name="g-recaptcha-hidden" class="wpforms-recaptcha-hidden" style="position:absolute!important;clip:rect(0,0,0,0)!important;height:1px!important;width:1px!important;border:0!important;overflow:hidden!important;padding:0!important;margin:0!important;" required>'; } if ( ! empty( $errors['recaptcha'] ) ) { $this->form_error( 'recaptcha', $errors['recaptcha'] ); } echo '</div>'; } /** * Form footer area. * * @since 1.0.0 * * @param array $form_data Form data and settings. * @param null $deprecated Deprecated in v1.3.7, previously was $form object. * @param bool $title Whether to display form title. * @param bool $description Whether to display form description. * @param array $errors List of all errors filled in WPForms_Process::process(). */ public function foot( $form_data, $deprecated, $title, $description, $errors ) { $form_id = absint( $form_data['id'] ); $settings = $form_data['settings']; $submit = apply_filters( 'wpforms_field_submit', $settings['submit_text'], $form_data ); $process = 'aria-live="assertive" '; $classes = ''; $visible = $this->pages ? 'style="display:none;"' : ''; // Check for submit button alt-text. if ( ! empty( $settings['submit_text_processing'] ) ) { if ( wpforms_is_amp() ) { $bound_text = sprintf( '%s.submitting ? %s : %s', $this->get_form_amp_state_id( $form_id ), wp_json_encode( $settings['submit_text_processing'], JSON_UNESCAPED_UNICODE ), wp_json_encode( $submit, JSON_UNESCAPED_UNICODE ) ); $process .= '[text]="' . esc_attr( $bound_text ) . '"'; } else { $process .= 'data-alt-text="' . esc_attr( $settings['submit_text_processing'] ) . '" data-submit-text="' . esc_attr( $submit ) . '"'; } } // Check user defined submit button classes. if ( ! empty( $settings['submit_class'] ) ) { $classes = wpforms_sanitize_classes( $settings['submit_class'] ); } // AMP submit error template. if ( wpforms_is_amp() ) { echo '<div submit-error><template type="amp-mustache"><div class="wpforms-error-container"><p>{{{message}}}</p></div></template></div>'; } // Output footer errors if they exist. if ( ! empty( $errors['footer'] ) ) { $this->form_error( 'footer', $errors['footer'] ); } // Submit button area. echo '<div class="wpforms-submit-container" ' . $visible . '>'; echo '<input type="hidden" name="wpforms[id]" value="' . esc_attr( $form_id ) . '">'; echo '<input type="hidden" name="wpforms[author]" value="' . absint( get_the_author_meta( 'ID' ) ) . '">'; if ( is_singular() ) { echo '<input type="hidden" name="wpforms[post_id]" value="' . esc_attr( get_the_ID() ) . '">'; } do_action( 'wpforms_display_submit_before', $form_data ); printf( '<button type="submit" name="wpforms[submit]" class="wpforms-submit %s" id="wpforms-submit-%d" value="wpforms-submit" %s>%s</button>', esc_attr( $classes ), esc_attr( $form_id ), $process, esc_html( $submit ) ); if ( ! empty( $settings['ajax_submit'] ) && ! wpforms_is_amp() ) { printf( '<img src="%s" class="wpforms-submit-spinner" style="display: none;" width="26" height="26" alt="">', esc_url( apply_filters( 'wpforms_display_sumbit_spinner_src', WPFORMS_PLUGIN_URL . 'assets/images/submit-spin.svg', $form_data ) ) ); } do_action( 'wpforms_display_submit_after', $form_data ); echo '</div>'; // Load the success template in AMP. if ( wpforms_is_amp() ) { $this->confirmation( $form_data, $form_data['fields'] ); } } /** * Display form error. * * @since 1.5.3 * * @param string $type Error type. * @param string $error Error text. */ public function form_error( $type, $error ) { switch ( $type ) { case 'header': case 'footer': echo '<div class="wpforms-error-container">' . wpforms_sanitize_error( $error ) . '</div>'; break; case 'recaptcha': echo '<label id="wpforms-field_recaptcha-error" class="wpforms-error">' . wpforms_sanitize_error( $error ) . '</label>'; break; } } /** * Determine if we should load assets globally. * If false assets will load conditionally (default). * * @since 1.2.4 * * @return bool */ public function assets_global() { return apply_filters( 'wpforms_global_assets', wpforms_setting( 'global-assets', false ) ); } /** * Load the necessary CSS for single pages/posts earlier if possible. * * If we are viewing a singular page, then we can check the content early * to see if the shortcode was used. If not we fallback and load the assets * later on during the page (widgets, archives, etc). * * @since 1.0.0 */ public function assets_header() { if ( ! is_singular() ) { return; } global $post; if ( has_shortcode( $post->post_content, 'wpforms' ) || ( function_exists( 'has_block' ) && has_block( 'wpforms/form-selector' ) ) ) { $this->assets_css(); } } /** * Load the CSS assets for frontend output. * * @since 1.0.0 */ public function assets_css() { do_action( 'wpforms_frontend_css', $this->forms ); $min = wpforms_get_min_suffix(); // jQuery date/time library CSS. if ( $this->assets_global() || true === wpforms_has_field_type( 'date-time', $this->forms, true ) ) { wp_enqueue_style( 'wpforms-jquery-timepicker', WPFORMS_PLUGIN_URL . 'assets/css/jquery.timepicker.css', array(), '1.11.5' ); wp_enqueue_style( 'wpforms-flatpickr', WPFORMS_PLUGIN_URL . 'assets/css/flatpickr.min.css', array(), '4.6.3' ); } // Load CSS per global setting. if ( wpforms_setting( 'disable-css', '1' ) == '1' ) { wp_enqueue_style( 'wpforms-full', WPFORMS_PLUGIN_URL . 'assets/css/wpforms-full.css', array(), WPFORMS_VERSION ); } if ( wpforms_setting( 'disable-css', '1' ) == '2' ) { wp_enqueue_style( 'wpforms-base', WPFORMS_PLUGIN_URL . "assets/css/wpforms-base{$min}.css", array(), WPFORMS_VERSION ); } } /** * Load the JS assets for frontend output. * * @since 1.0.0 */ public function assets_js() { if ( wpforms_is_amp() ) { return; } do_action( 'wpforms_frontend_js', $this->forms ); // Load jQuery validation library - https://jqueryvalidation.org/. wp_enqueue_script( 'wpforms-validation', WPFORMS_PLUGIN_URL . 'assets/js/jquery.validate.min.js', array( 'jquery' ), '1.19.0', true ); // Load jQuery date/time libraries. if ( $this->assets_global() || true === wpforms_has_field_type( 'date-time', $this->forms, true ) ) { wp_enqueue_script( 'wpforms-flatpickr', WPFORMS_PLUGIN_URL . 'assets/js/flatpickr.min.js', array( 'jquery' ), '4.6.3', true ); wp_enqueue_script( 'wpforms-jquery-timepicker', WPFORMS_PLUGIN_URL . 'assets/js/jquery.timepicker.min.js', array( 'jquery' ), '1.11.5', true ); } // Load jQuery input mask library - https://github.com/RobinHerbots/jquery.inputmask. if ( $this->assets_global() || true === wpforms_has_field_type( array( 'phone', 'address' ), $this->forms, true ) || true === wpforms_has_field_setting( 'input_mask', $this->forms, true ) ) { wp_enqueue_script( 'wpforms-maskedinput', WPFORMS_PLUGIN_URL . 'assets/js/jquery.inputmask.bundle.min.js', array( 'jquery' ), '4.0.6', true ); } // Load mailcheck library - https://github.com/mailcheck/mailcheck. if ( $this->assets_global() || true === wpforms_has_field_type( array( 'email' ), $this->forms, true ) ) { wp_enqueue_script( 'wpforms-mailcheck', WPFORMS_PLUGIN_URL . 'assets/js/mailcheck.min.js', false, '1.1.2', true ); } // Load CC payment library - https://github.com/stripe/jquery.payment/. if ( $this->assets_global() || true === wpforms_has_field_type( 'credit-card', $this->forms, true ) ) { wp_enqueue_script( 'wpforms-payment', WPFORMS_PLUGIN_URL . 'assets/js/jquery.payment.min.js', array( 'jquery' ), WPFORMS_VERSION, true ); } // Load base JS. wp_enqueue_script( 'wpforms', WPFORMS_PLUGIN_URL . 'assets/js/wpforms.js', array( 'jquery' ), WPFORMS_VERSION, true ); // Load reCAPTCHA support if form supports it. $site_key = wpforms_setting( 'recaptcha-site-key' ); $secret_key = wpforms_setting( 'recaptcha-secret-key' ); $type = wpforms_setting( 'recaptcha-type', 'v2' ); $recaptcha = false; foreach ( $this->forms as $form ) { if ( ! empty( $form['settings']['recaptcha'] ) ) { $recaptcha = true; break; } } if ( ( $recaptcha || $this->assets_global() ) && ( $secret_key && $site_key ) ) { if ( $type === 'v3' ) { $recaptcha_api = 'https://www.google.com/recaptcha/api.js?render=' . $site_key; } else { $recaptcha_api = apply_filters( 'wpforms_frontend_recaptcha_url', 'https://www.google.com/recaptcha/api.js?onload=wpformsRecaptchaLoad&render=explicit' ); } wp_enqueue_script( 'wpforms-recaptcha', $recaptcha_api, $type === 'v3' ? array() : array( 'jquery' ), null, true ); if ( 'v3' === $type ) { $recaptch_inline = 'var wpformsRecaptchaLoad = function(){grecaptcha.execute("' . esc_html( $site_key ) . '",{action:"wpforms"}).then(function(token){var f=document.getElementsByName("wpforms[recaptcha]");for(var i=0;i<f.length;i++){f[i].value = token;}});}; grecaptcha.ready(wpformsRecaptchaLoad);'; } elseif ( 'invisible' === $type ) { $recaptch_inline = 'var wpformsRecaptchaLoad = function(){jQuery(".g-recaptcha").each(function(index,el){var recaptchaID = grecaptcha.render(el,{callback:function(){wpformsRecaptchaCallback(el);}},true);jQuery(el).closest("form").find("button[type=submit]").get(0).recaptchaID = recaptchaID;});};'; $recaptch_inline .= 'var wpformsRecaptchaCallback = function(el){var $form = jQuery(el).closest("form");if(typeof wpforms.formSubmit === "function"){wpforms.formSubmit($form);}else{$form.find("button[type=submit]").get(0).recaptchaID = false;$form.submit();}};'; } else { $recaptch_inline = 'var wpformsRecaptchaLoad = function(){jQuery(".g-recaptcha").each(function(index, el){var recaptchaID = grecaptcha.render(el,{callback:function(){wpformsRecaptchaCallback(el);}},true);jQuery(el).attr( "data-recaptcha-id", recaptchaID);});};'; $recaptch_inline .= 'var wpformsRecaptchaCallback = function(el){jQuery(el).parent().find(".wpforms-recaptcha-hidden").val("1").trigger("change").valid();};'; } wp_add_inline_script( 'wpforms-recaptcha', $recaptch_inline ); } } /** * Load the necessary assets for the confirmation message. * * @since 1.1.2 */ public function assets_confirmation() { // Base CSS only. if ( wpforms_setting( 'disable-css', '1' ) == '1' ) { wp_enqueue_style( 'wpforms-full', WPFORMS_PLUGIN_URL . 'assets/css/wpforms-full.css', array(), WPFORMS_VERSION ); } // Special confirmation JS. if ( ! wpforms_is_amp() ) { wp_enqueue_script( 'wpforms-confirmation', WPFORMS_PLUGIN_URL . 'assets/js/wpforms-confirmation.js', array( 'jquery' ), WPFORMS_VERSION, true ); } do_action( 'wpforms_frontend_confirmation' ); } /** * Load the assets in footer if needed (archives, widgets, etc). * * @since 1.0.0 */ public function assets_footer() { if ( empty( $this->forms ) && ! $this->assets_global() ) { return; } $this->assets_css(); $this->assets_js(); do_action( 'wpforms_wp_footer', $this->forms ); } /** * Get strings to localize. * * @since 1.6.0 * * @return array Array of strings to localize. */ public function get_strings() { // Define base strings. $strings = array( 'val_required' => wpforms_setting( 'validation-required', esc_html__( 'This field is required.', 'wpforms-lite' ) ), 'val_url' => wpforms_setting( 'validation-url', esc_html__( 'Please enter a valid URL.', 'wpforms-lite' ) ), 'val_email' => wpforms_setting( 'validation-email', esc_html__( 'Please enter a valid email address.', 'wpforms-lite' ) ), 'val_email_suggestion' => wpforms_setting( 'validation-email-suggestion', esc_html__( 'Did you mean {suggestion}?', 'wpforms-lite' ) ), 'val_email_suggestion_title' => esc_attr__( 'Click to accept this suggestion.', 'wpforms-lite' ), 'val_number' => wpforms_setting( 'validation-number', esc_html__( 'Please enter a valid number.', 'wpforms-lite' ) ), 'val_confirm' => wpforms_setting( 'validation-confirm', esc_html__( 'Field values do not match.', 'wpforms-lite' ) ), 'val_fileextension' => wpforms_setting( 'validation-fileextension', esc_html__( 'File type is not allowed.', 'wpforms-lite' ) ), 'val_filesize' => wpforms_setting( 'validation-filesize', esc_html__( 'File exceeds max size allowed. File was not uploaded.', 'wpforms-lite' ) ), 'val_time12h' => wpforms_setting( 'validation-time12h', esc_html__( 'Please enter time in 12-hour AM/PM format (eg 8:45 AM).', 'wpforms-lite' ) ), 'val_time24h' => wpforms_setting( 'validation-time24h', esc_html__( 'Please enter time in 24-hour format (eg 22:45).', 'wpforms-lite' ) ), 'val_requiredpayment' => wpforms_setting( 'validation-requiredpayment', esc_html__( 'Payment is required.', 'wpforms-lite' ) ), 'val_creditcard' => wpforms_setting( 'validation-creditcard', esc_html__( 'Please enter a valid credit card number.', 'wpforms-lite' ) ), 'val_post_max_size' => wpforms_setting( 'validation-post_max_size', esc_html__( 'The total size of the selected files {totalSize} Mb exceeds the allowed limit {maxSize} Mb.', 'wpforms-lite' ) ), 'val_checklimit' => wpforms_setting( 'validation-check-limit', esc_html__( 'You have exceeded the number of allowed selections: {#}.', 'wpforms-lite' ) ), 'val_limit_characters' => esc_html__( '{count} of {limit} max characters.', 'wpforms-lite' ), 'val_limit_words' => esc_html__( '{count} of {limit} max words.', 'wpforms-lite' ), 'val_recaptcha_fail_msg' => wpforms_setting( 'recaptcha-fail-msg', esc_html__( 'Google reCAPTCHA verification failed, please try again later.', 'wpforms-lite' ) ), 'post_max_size' => wpforms_size_to_bytes( ini_get( 'post_max_size' ) ), 'uuid_cookie' => false, 'locale' => wpforms_get_language_code(), 'wpforms_plugin_url' => WPFORMS_PLUGIN_URL, 'gdpr' => wpforms_setting( 'gdpr' ), 'ajaxurl' => admin_url( 'admin-ajax.php' ), 'mailcheck_enabled' => (bool) apply_filters( 'wpforms_mailcheck_enabled', true ), 'mailcheck_domains' => array_map( 'sanitize_text_field', (array) apply_filters( 'wpforms_mailcheck_domains', array() ) ), 'mailcheck_toplevel_domains' => array_map( 'sanitize_text_field', (array) apply_filters( 'wpforms_mailcheck_toplevel_domains', array( 'dev' ) ) ), ); // Include payment related strings if needed. if ( function_exists( 'wpforms_get_currencies' ) ) { $currency = wpforms_setting( 'currency', 'USD' ); $currencies = wpforms_get_currencies(); $strings['currency_code'] = $currency; $strings['currency_thousands'] = $currencies[ $currency ]['thousands_separator']; $strings['currency_decimal'] = $currencies[ $currency ]['decimal_separator']; $strings['currency_symbol'] = $currencies[ $currency ]['symbol']; $strings['currency_symbol_pos'] = $currencies[ $currency ]['symbol_pos']; } $strings = apply_filters( 'wpforms_frontend_strings', $strings ); foreach ( (array) $strings as $key => $value ) { if ( ! is_scalar( $value ) ) { continue; } $strings[ $key ] = html_entity_decode( (string) $value, ENT_QUOTES, 'UTF-8' ); } return $strings; } /** * Hook at fires at a later priority in wp_footer * * @since 1.0.5 */ public function footer_end() { if ( ( empty( $this->forms ) && ! $this->assets_global() ) || wpforms_is_amp() ) { return; } $strings = $this->get_strings(); /* * Below we do our own implementation of wp_localize_script in an effort * to be better compatible with caching plugins which were causing * conflicts. */ echo "<script type='text/javascript'>\n"; echo "/* <![CDATA[ */\n"; echo 'var wpforms_settings = ' . wp_json_encode( $strings ) . "\n"; echo "/* ]]> */\n"; echo "</script>\n"; do_action( 'wpforms_wp_footer_end', $this->forms ); } /** * Google reCAPTCHA no-conflict mode. * * When enabled in the WPForms settings, forcefully remove all other * reCAPTCHA enqueues to prevent conflicts. Filter can be used to target * specific pages, etc. * * @since 1.4.5 */ public function recaptcha_noconflict() { $noconflict = wpforms_setting( 'recaptcha-noconflict' ); if ( empty( $noconflict ) ) { return; } if ( ! apply_filters( 'wpforms_frontend_recaptcha_noconflict', true ) ) { return; } global $wp_scripts; $urls = array( 'google.com/recaptcha', 'gstatic.com/recaptcha' ); foreach ( $wp_scripts->queue as $handle ) { if ( false !== strpos( $wp_scripts->registered[ $handle ]->handle, 'wpforms' ) ) { return; } foreach ( $urls as $url ) { if ( false !== strpos( $wp_scripts->registered[ $handle ]->src, $url ) ) { wp_dequeue_script( $handle ); wp_deregister_script( $handle ); break; } } } } /** * Shortcode wrapper for the outputting a form. * * @since 1.0.0 * * @param array $atts Shortcode attributes provided by a user. * * @return string */ public function shortcode( $atts ) { $defaults = array( 'id' => false, 'title' => false, 'description' => false, ); $atts = shortcode_atts( $defaults, shortcode_atts( $defaults, $atts, 'output' ), 'wpforms' ); ob_start(); $this->output( $atts['id'], $atts['title'], $atts['description'] ); return ob_get_clean(); } } class-smart-tags.php 0000666 00000027761 15213301444 0010460 0 ustar 00 <?php /** * Smart tag functionality. * * @since 1.0.0 */ class WPForms_Smart_Tags { /** * Primary class constructor. * * @since 1.0.0 */ public function __construct() { add_filter( 'wpforms_process_smart_tags', array( $this, 'process' ), 10, 4 ); } /** * Approved smart tags. * * @since 1.0.0 * * @param string $return Type of data to return. * * @return string|array */ public function get( $return = 'array' ) { $tags = array( 'admin_email' => esc_html__( 'Site Administrator Email', 'wpforms-lite' ), 'entry_id' => esc_html__( 'Entry ID', 'wpforms-lite' ), 'form_id' => esc_html__( 'Form ID', 'wpforms-lite' ), 'form_name' => esc_html__( 'Form Name', 'wpforms-lite' ), 'page_title' => esc_html__( 'Embedded Post/Page Title', 'wpforms-lite' ), 'page_url' => esc_html__( 'Embedded Post/Page URL', 'wpforms-lite' ), 'page_id' => esc_html__( 'Embedded Post/Page ID', 'wpforms-lite' ), 'date format="m/d/Y"' => esc_html__( 'Date', 'wpforms-lite' ), 'query_var key=""' => esc_html__( 'Query String Variable', 'wpforms-lite' ), 'user_ip' => esc_html__( 'User IP Address', 'wpforms-lite' ), 'user_id' => esc_html__( 'User ID', 'wpforms-lite' ), 'user_display' => esc_html__( 'User Display Name', 'wpforms-lite' ), 'user_full_name' => esc_html__( 'User Full Name', 'wpforms-lite' ), 'user_first_name' => esc_html__( 'User First Name', 'wpforms-lite' ), 'user_last_name' => esc_html__( 'User Last Name', 'wpforms-lite' ), 'user_email' => esc_html__( 'User Email', 'wpforms-lite' ), 'user_meta key=""' => esc_html__( 'User Meta', 'wpforms-lite' ), 'author_id' => esc_html__( 'Author ID', 'wpforms-lite' ), 'author_display' => esc_html__( 'Author Name', 'wpforms-lite' ), 'author_email' => esc_html__( 'Author Email', 'wpforms-lite' ), 'url_referer' => esc_html__( 'Referrer URL', 'wpforms-lite' ), 'url_login' => esc_html__( 'Login URL', 'wpforms-lite' ), 'url_logout' => esc_html__( 'Logout URL', 'wpforms-lite' ), 'url_register' => esc_html__( 'Register URL', 'wpforms-lite' ), 'url_lost_password' => esc_html__( 'Lost Password URL', 'wpforms-lite' ), ); $tags = apply_filters( 'wpforms_smart_tags', $tags ); if ( 'list' === $return ) { // Return formatted list. $output = '<ul class="smart-tags-list">'; foreach ( $tags as $key => $tag ) { $output .= '<li><a href="#" data-value="' . esc_attr( $key ) . '">' . esc_html( $tag ) . '</a></li>'; } $output .= '</ul>'; return $output; } else { // Return raw array. return $tags; } } /** * Process and parse smart tags. * * @since 1.0.0 * * @param string $content The string to preprocess. * @param array $form_data Form data and settings. * @param string|array $fields Form fields. * @param int|string $entry_id Entry ID. * * @return string */ public function process( $content, $form_data, $fields = '', $entry_id = '' ) { // Basic smart tags. preg_match_all( "/\{(.+?)\}/", $content, $tags ); if ( ! empty( $tags[1] ) ) { foreach ( $tags[1] as $key => $tag ) { switch ( $tag ) { case 'admin_email': $content = $this->parse( '{' . $tag . '}', sanitize_email( get_option( 'admin_email' ) ), $content ); break; case 'entry_id': $content = $this->parse( '{' . $tag . '}', absint( $entry_id ), $content ); break; case 'form_id': $content = $this->parse( '{' . $tag . '}', absint( $form_data['id'] ), $content ); break; case 'form_name': if ( isset( $form_data['settings']['form_title'] ) && ! empty( $form_data['settings']['form_title'] ) ) { $name = $form_data['settings']['form_title']; } else { $name = ''; } $content = $this->parse( '{' . $tag . '}', sanitize_text_field( $name ), $content ); break; case 'page_title': $title = get_the_ID() ? get_the_title( get_the_ID() ) : ''; $content = $this->parse( '{' . $tag . '}', $title, $content ); break; case 'page_url': global $wp; $url = empty( $_POST['page_url'] ) ? home_url( add_query_arg( $_GET, $wp->request ) ) : esc_url_raw( wp_unslash( $_POST['page_url'] ) ); // phpcs:ignore WordPress.Security.NonceVerification $content = $this->parse( '{' . $tag . '}', $url, $content ); break; case 'page_id': $id = get_the_ID() ? get_the_ID() : ''; $content = $this->parse( '{' . $tag . '}', $id, $content ); break; case 'user_ip': $content = $this->parse( '{' . $tag . '}', wpforms_get_ip(), $content ); break; case 'user_id': $id = is_user_logged_in() ? get_current_user_id() : ''; $content = $this->parse( '{' . $tag . '}', $id, $content ); break; case 'user_display': if ( is_user_logged_in() ) { $user = wp_get_current_user(); $name = sanitize_text_field( $user->display_name ); } else { $name = ''; } $content = $this->parse( '{' . $tag . '}', $name, $content ); break; case 'user_full_name': if ( is_user_logged_in() ) { $user = wp_get_current_user(); $name = sanitize_text_field( $user->user_firstname . ' ' . $user->user_lastname ); } else { $name = ''; } $content = $this->parse( '{' . $tag . '}', $name, $content ); break; case 'user_first_name': if ( is_user_logged_in() ) { $user = wp_get_current_user(); $name = sanitize_text_field( $user->user_firstname ); } else { $name = ''; } $content = $this->parse( '{' . $tag . '}', $name, $content ); break; case 'user_last_name': if ( is_user_logged_in() ) { $user = wp_get_current_user(); $name = sanitize_text_field( $user->user_lastname ); } else { $name = ''; } $content = $this->parse( '{' . $tag . '}', $name, $content ); break; case 'user_email': if ( is_user_logged_in() ) { $user = wp_get_current_user(); $email = sanitize_email( $user->user_email ); } else { $email = ''; } $content = $this->parse( '{' . $tag . '}', $email, $content ); break; case 'author_id': $id = get_the_author_meta( 'ID' ); if ( empty( $id ) && ! empty( $_POST['wpforms']['author'] ) ) { $id = get_the_author_meta( 'ID', absint( $_POST['wpforms']['author'] ) ); } $id = absint( $id ); $content = $this->parse( '{' . $tag . '}', $id, $content ); break; case 'author_display': $name = get_the_author(); if ( empty( $name ) && ! empty( $_POST['wpforms']['author'] ) ) { $name = get_the_author_meta( 'display_name', absint( $_POST['wpforms']['author'] ) ); } $name = ! empty( $name ) ? sanitize_text_field( $name ) : ''; $content = $this->parse( '{' . $tag . '}', $name, $content ); break; case 'author_email': $email = get_the_author_meta( 'user_email' ); if ( empty( $email ) && ! empty( $_POST['wpforms']['author'] ) ) { $email = get_the_author_meta( 'user_email', absint( $_POST['wpforms']['author'] ) ); } $email = sanitize_email( $email ); $content = $this->parse( '{' . $tag . '}', $email, $content ); break; case 'url_referer': $referer = ! empty( $_SERVER['HTTP_REFERER'] ) ? $_SERVER['HTTP_REFERER'] : ''; $content = $this->parse( '{' . $tag . '}', sanitize_text_field( $referer ), $content ); break; case 'url_login': $content = $this->parse( '{' . $tag . '}', wp_login_url(), $content ); break; case 'url_logout': $content = $this->parse( '{' . $tag . '}', wp_logout_url(), $content ); break; case 'url_register': $content = $this->parse( '{' . $tag . '}', wp_registration_url(), $content ); break; case 'url_lost_password': $content = $this->parse( '{' . $tag . '}', wp_lostpassword_url(), $content ); break; default: $content = apply_filters( 'wpforms_smart_tag_process', $content, $tag ); break; } } } // Query string var smart tags. preg_match_all( "/\{query_var key=\"(.+?)\"\}/", $content, $query_vars ); if ( ! empty( $query_vars[1] ) ) { foreach ( $query_vars[1] as $key => $query_var ) { $value = ! empty( $_GET[ $query_var ] ) ? wp_unslash( sanitize_text_field( $_GET[ $query_var ] ) ) : ''; // phpcs:ignore $content = $this->parse( $query_vars[0][ $key ], $value, $content ); } } // Date smart tags. preg_match_all( "/\{date format=\"(.+?)\"\}/", $content, $dates ); if ( ! empty( $dates[1] ) ) { foreach ( $dates[1] as $key => $date ) { $value = date( $date, time() + ( get_option( 'gmt_offset' ) * 3600 ) ); $content = $this->parse( $dates[0][ $key ], $value, $content ); } } // User meta smart tags. preg_match_all( "/\{user_meta key=\"(.+?)\"\}/", $content, $user_metas ); if ( ! empty( $user_metas[1] ) ) { foreach ( $user_metas[1] as $key => $user_meta ) { $value = is_user_logged_in() ? get_user_meta( get_current_user_id(), sanitize_text_field( $user_meta ), true ) : ''; $content = $this->parse( $user_metas[0][ $key ], $value, $content ); } } // Field smart tag to get data from 'value'. preg_match_all( "/\{field_id=\"(.+?)\"\}/", $content, $ids ); // We can only process field smart tags if we have $fields. if ( ! empty( $ids[1] ) && ! empty( $fields ) ) { foreach ( $ids[1] as $key => $parts ) { $field_parts = explode( '|', $parts ); $field_id = $field_parts[0]; $field_key = ! empty( $field_parts[1] ) ? sanitize_key( $field_parts[1] ) : 'value'; $value = isset( $fields[ $field_id ][ $field_key ] ) ? wpforms_sanitize_textarea_field( $fields[ $field_id ][ $field_key ] ) : ''; $value = apply_filters( 'wpforms_field_smart_tag_value', $value ); $content = $this->parse( '{field_id="' . $parts . '"}', $value, $content ); } } // Field smart tag to get data from 'value_raw'. preg_match_all( "/\{field_value_id=\"(.+?)\"\}/", $content, $value_ids ); // We can only process field smart tags if we have $fields. if ( ! empty( $value_ids[1] ) && ! empty( $fields ) ) { foreach ( $value_ids[1] as $key => $field_id ) { if ( isset( $fields[ $field_id ]['value_raw'] ) && ! is_array( $fields[ $field_id ]['value_raw'] ) && (string) $fields[ $field_id ]['value_raw'] !== '' ) { $value = wpforms_sanitize_textarea_field( $fields[ $field_id ]['value_raw'] ); } else { $value = isset( $fields[ $field_id ]['value'] ) ? wpforms_sanitize_textarea_field( $fields[ $field_id ]['value'] ) : ''; } $content = $this->parse( '{field_value_id="' . $field_id . '"}', $value, $content ); } } // Field smart tag to get HTML-postprocessed value (as seen in {all_fields}). preg_match_all( '/\{field_html_id="(.+?)"\}/', $content, $html_ids ); // We can only process field smart tags if we have $fields. if ( ! empty( $html_ids[1] ) && ! empty( $fields ) ) { foreach ( $html_ids[1] as $key => $field_id ) { $value = ''; if ( ! empty( $fields[ $field_id ] ) ) { $value = ! isset( $fields[ $field_id ]['value'] ) || (string) $fields[ $field_id ]['value'] === '' ? '<em>' . esc_html__( '(empty)', 'wpforms-lite' ) . '</em>' : wpforms_sanitize_textarea_field( $fields[ $field_id ]['value'] ); $value = apply_filters( 'wpforms_html_field_value', $value, $fields[ $field_id ], $form_data, 'smart-tag' ); } $content = $this->parse( '{field_html_id="' . $field_id . '"}', $value, $content ); } } return $content; } /** * Replace a found smart tag with the final value. * * @since 1.5.9 * * @param string $tag The tag. * @param string $value The value. * @param string $content Content. * * @return string */ public function parse( $tag, $value, $content ) { return str_replace( $tag, strip_shortcodes( $value ), $content ); } } class-fields.php 0000666 00000003220 15213301444 0007624 0 ustar 00 <?php /** * Load the field types. * * @since 1.0.0 */ class WPForms_Fields { /** * Primary class constructor. * * @since 1.0.0 */ public function __construct() { $this->init(); } /** * Load and init the base field class. * * @since 1.2.8 */ public function init() { // Parent class template. require_once WPFORMS_PLUGIN_DIR . 'includes/fields/class-base.php'; // Load default fields on WP init. add_action( 'init', array( $this, 'load' ) ); } /** * Load default field types. * * @since 1.0.0 */ public function load() { $fields = apply_filters( 'wpforms_load_fields', array( 'text', 'textarea', 'select', 'radio', 'checkbox', 'divider', 'email', 'url', 'hidden', 'html', 'name', 'password', 'address', 'phone', 'date-time', 'number', 'page-break', 'rating', 'file-upload', 'payment-single', 'payment-multiple', 'payment-checkbox', 'payment-dropdown', 'payment-credit-card', 'payment-total', 'number-slider', ) ); // Include GDPR Checkbox field if GDPR enhancements are enabled. if ( wpforms_setting( 'gdpr', false ) ) { $fields[] = 'gdpr-checkbox'; } foreach ( $fields as $field ) { if ( file_exists( WPFORMS_PLUGIN_DIR . 'includes/fields/class-' . $field . '.php' ) ) { require_once WPFORMS_PLUGIN_DIR . 'includes/fields/class-' . $field . '.php'; } elseif ( wpforms()->pro && file_exists( WPFORMS_PLUGIN_DIR . 'pro/includes/fields/class-' . $field . '.php' ) ) { require_once WPFORMS_PLUGIN_DIR . 'pro/includes/fields/class-' . $field . '.php'; } } } } new WPForms_Fields(); class-process.php 0000666 00000065477 15213301444 0010062 0 ustar 00 <?php /** * Process and validate form entries. * * @since 1.0.0 */ class WPForms_Process { /** * Store errors. * * @since 1.0.0 * * @var array */ public $errors; /** * Confirmation message. * * @var string */ public $confirmation_message; /** * Store formatted fields. * * @since 1.0.0 * * @var array */ public $fields; /** * Store the ID of a successful entry. * * @since 1.2.3 * * @var int */ public $entry_id = 0; /** * Form data and settings. * * @since 1.4.5 * * @var array */ public $form_data; /** * If a valid return has was processed. * * @since 1.4.5 * * @var bool */ public $valid_hash = false; /** * Primary class constructor. * * @since 1.0.0 */ public function __construct() { add_action( 'wp', array( $this, 'listen' ) ); add_action( 'wp_ajax_wpforms_submit', array( $this, 'ajax_submit' ) ); add_action( 'wp_ajax_nopriv_wpforms_submit', array( $this, 'ajax_submit' ) ); } /** * Listen to see if this is a return callback or a posted form entry. * * @since 1.0.0 */ public function listen() { // Catch the post_max_size overflow. if ( $this->post_max_size_overflow() ) { return; } if ( ! empty( $_GET['wpforms_return'] ) ) { // phpcs:ignore $this->entry_confirmation_redirect( '', $_GET['wpforms_return'] ); // phpcs:ignore } if ( ! empty( $_POST['wpforms']['id'] ) ) { // phpcs:ignore $this->process( stripslashes_deep( $_POST['wpforms'] ) ); // phpcs:ignore $form_id = wp_unslash( $_POST['wpforms']['id'] ); if ( wpforms_is_amp() ) { // Send 400 Bad Request when there are errors. if ( ! empty( $this->errors[ $form_id ] ) ) { $message = $this->errors[ $form_id ]['header']; if ( ! empty( $this->errors[ $form_id ]['footer'] ) ) { $message .= ' ' . $this->errors[ $form_id ]['footer']; } wp_send_json( array( 'message' => $message, ), 400 ); } else { wp_send_json( array( 'message' => $this->get_confirmation_message( $this->form_data, $this->fields, $this->entry_id ), ), 200 ); } } } } /** * Process the form entry. * * @since 1.0.0 * * @param array $entry Form submission raw data ($_POST). */ public function process( $entry ) { $this->errors = array(); $this->fields = array(); $form_id = absint( $entry['id'] ); $form = wpforms()->form->get( $form_id ); $honeypot = false; // Validate form is real and active (published). if ( ! $form || 'publish' !== $form->post_status ) { $this->errors[ $form_id ]['header'] = esc_html__( 'Invalid form.', 'wpforms-lite' ); return; } // Formatted form data for hooks. $this->form_data = apply_filters( 'wpforms_process_before_form_data', wpforms_decode( $form->post_content ), $entry ); // Pre-process/validate hooks and filter. // Data is not validated or cleaned yet so use with caution. $entry = apply_filters( 'wpforms_process_before_filter', $entry, $this->form_data ); do_action( 'wpforms_process_before', $entry, $this->form_data ); do_action( "wpforms_process_before_{$form_id}", $entry, $this->form_data ); // Validate fields. foreach ( $this->form_data['fields'] as $field_properties ) { $field_id = $field_properties['id']; $field_type = $field_properties['type']; $field_submit = isset( $entry['fields'][ $field_id ] ) ? $entry['fields'][ $field_id ] : ''; do_action( "wpforms_process_validate_{$field_type}", $field_id, $field_submit, $this->form_data ); } // reCAPTCHA check. $site_key = wpforms_setting( 'recaptcha-site-key', '' ); $secret_key = wpforms_setting( 'recaptcha-secret-key', '' ); $type = wpforms_setting( 'recaptcha-type', 'v2' ); if ( ! empty( $site_key ) && ! empty( $secret_key ) && isset( $this->form_data['settings']['recaptcha'] ) && '1' == $this->form_data['settings']['recaptcha'] && ! isset( $_POST['__amp_form_verify'] ) // phpcs:ignore WordPress.Security.NonceVerification.Missing -- No need to check reCAPTCHA until form is submitted. && ( 'v3' === $type || ! wpforms_is_amp() ) // AMP requires v3. ) { $error = wpforms_setting( 'recaptcha-fail-msg', esc_html__( 'Google reCAPTCHA verification failed, please try again later.', 'wpforms-lite' ) ); $token = ! empty( $_POST['g-recaptcha-response'] ) ? $_POST['g-recaptcha-response'] : false; if ( 'v3' === $type ) { $token = ! empty( $_POST['wpforms']['recaptcha'] ) ? $_POST['wpforms']['recaptcha'] : false; } $response = json_decode( wp_remote_retrieve_body( wp_remote_get( 'https://www.google.com/recaptcha/api/siteverify?secret=' . $secret_key . '&response=' . $token ) ) ); if ( empty( $response->success ) || ( 'v3' === $type && $response->score <= wpforms_setting( 'recaptcha-v3-threshold', '0.4' ) ) ) { if ( 'v3' === $type ) { if ( isset( $response->score ) ) { $error .= ' (' . esc_html( $response->score ) . ')'; } $this->errors[ $form_id ]['footer'] = $error; } else { $this->errors[ $form_id ]['recaptcha'] = $error; } } } // Check if combined upload size exceeds allowed maximum. $this->validate_combined_upload_size( $form ); // Initial error check. // Don't proceed if there are any errors thus far. We provide a filter // so that other features, such as conditional logic, have the ability // to adjust blocking errors. $errors = apply_filters( 'wpforms_process_initial_errors', $this->errors, $this->form_data ); if ( isset( $_POST['__amp_form_verify'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing if ( empty( $errors[ $form_id ] ) ) { wp_send_json( array(), 200 ); } else { $verify_errors = array(); foreach ( $errors[ $form_id ] as $field_id => $error_fields ) { $field = $this->form_data['fields'][ $field_id ]; $field_properties = wpforms()->frontend->get_field_properties( $field, $this->form_data ); if ( is_string( $error_fields ) ) { if ( 'checkbox' === $field['type'] || 'radio' === $field['type'] || 'select' === $field['type'] ) { $first = current( $field_properties['inputs'] ); $name = $first['attr']['name']; } elseif ( isset( $field_properties['inputs']['primary']['attr']['name'] ) ) { $name = $field_properties['inputs']['primary']['attr']['name']; } $verify_errors[] = array( 'name' => $name, 'message' => $error_fields, ); } else { foreach ( $error_fields as $error_field => $error_message ) { if ( isset( $field_properties['inputs'][ $error_field ]['attr']['name'] ) ) { $name = $field_properties['inputs'][ $error_field ]['attr']['name']; } $verify_errors[] = array( 'name' => $name, 'message' => $error_message, ); } } } wp_send_json( array( 'verifyErrors' => $verify_errors, ), 400 ); } return; } if ( ! empty( $errors[ $form_id ] ) ) { if ( empty( $errors[ $form_id ]['header'] ) ) { $errors[ $form_id ]['header'] = esc_html__( 'Form has not been submitted, please see the errors below.', 'wpforms-lite' ); } $this->errors = $errors; return; } // Validate honeypot early - before actual processing. if ( ! empty( $this->form_data['settings']['honeypot'] ) && '1' == $this->form_data['settings']['honeypot'] && ! empty( $entry['hp'] ) ) { $honeypot = esc_html__( 'WPForms honeypot field triggered.', 'wpforms-lite' ); } $honeypot = apply_filters( 'wpforms_process_honeypot', $honeypot, $this->fields, $entry, $this->form_data ); // If spam - return early. if ( $honeypot ) { // Logs spam entry depending on log levels set. wpforms_log( 'Spam Entry ' . uniqid(), array( $honeypot, $entry ), array( 'type' => array( 'spam' ), 'form_id' => $this->form_data['id'], ) ); return; } // Pass the form created date into the form data. $this->form_data['created'] = $form->post_date; // Format fields. foreach ( (array) $this->form_data['fields'] as $field_properties ) { $field_id = $field_properties['id']; $field_type = $field_properties['type']; $field_submit = isset( $entry['fields'][ $field_id ] ) ? $entry['fields'][ $field_id ] : ''; do_action( "wpforms_process_format_{$field_type}", $field_id, $field_submit, $this->form_data ); } // This hook is for internal purposes and should not be leveraged. do_action( 'wpforms_process_format_after', $this->form_data ); // Process hooks/filter - this is where most addons should hook // because at this point we have completed all field validation and // formatted the data. $this->fields = apply_filters( 'wpforms_process_filter', $this->fields, $entry, $this->form_data ); do_action( 'wpforms_process', $this->fields, $entry, $this->form_data ); do_action( "wpforms_process_{$form_id}", $this->fields, $entry, $this->form_data ); $this->fields = apply_filters( 'wpforms_process_after_filter', $this->fields, $entry, $this->form_data ); // One last error check - don't proceed if there are any errors. if ( ! empty( $this->errors[ $form_id ] ) ) { if ( empty( $this->errors[ $form_id ]['header'] ) ) { $this->errors[ $form_id ]['header'] = esc_html__( 'Form has not been submitted, please see the errors below.', 'wpforms-lite' ); } return; } // Success - add entry to database. $this->entry_id = $this->entry_save( $this->fields, $entry, $this->form_data['id'], $this->form_data ); // Fire the logic to send notification emails. $this->entry_email( $this->fields, $entry, $this->form_data, $this->entry_id, 'entry' ); // Pass completed and formatted fields in POST. $_POST['wpforms']['complete'] = $this->fields; // Pass entry ID in POST. $_POST['wpforms']['entry_id'] = $this->entry_id; // Logs entry depending on log levels set. wpforms_log( $this->entry_id ? "Entry {$this->entry_id}" : 'Entry', $this->fields, array( 'type' => array( 'entry' ), 'parent' => $this->entry_id, 'form_id' => $this->form_data['id'], ) ); // Post-process hooks. do_action( 'wpforms_process_complete', $this->fields, $entry, $this->form_data, $this->entry_id ); do_action( "wpforms_process_complete_{$form_id}", $this->fields, $entry, $this->form_data, $this->entry_id ); $this->entry_confirmation_redirect( $this->form_data ); } /** * Check if combined upload size exceeds allowed maximum. * * @since 1.6.0 * * @param \WP_Post $form Form post object. */ public function validate_combined_upload_size( $form ) { $form_id = (int) $form->ID; $upload_fields = wpforms_get_form_fields( $form, array( 'file-upload' ) ); if ( ! empty( $upload_fields ) && ! empty( $_FILES ) ) { // Get $_FILES keys generated by WPForms only. $files_keys = preg_filter( '/^/', 'wpforms_' . $form_id . '_', array_keys( $upload_fields ) ); // Filter uploads without errors. Individual errors are handled by WPForms_Field_File_Upload class. $files = wp_list_filter( wp_array_slice_assoc( $_FILES, $files_keys ), array( 'error' => 0 ) ); $files_size = array_sum( wp_list_pluck( $files, 'size' ) ); $files_size_max = wpforms_max_upload( true ); if ( $files_size > $files_size_max ) { // Add new header error preserving previous ones. $this->errors[ $form_id ]['header'] = ! empty( $this->errors[ $form_id ]['header'] ) ? $this->errors[ $form_id ]['header'] . '<br>' : ''; $this->errors[ $form_id ]['header'] .= esc_html__( 'Uploaded files combined size exceeds allowed maximum.', 'wpforms-lite' ); } } } /** * Validate the form return hash. * * @since 1.0.0 * * @param string $hash Base64-encoded hash of form and entry IDs. * * @return array|false False for invalid or form id. */ public function validate_return_hash( $hash = '' ) { $query_args = base64_decode( $hash ); parse_str( $query_args, $output ); // Verify hash matches. if ( wp_hash( $output['form_id'] . ',' . $output['entry_id'] ) !== $output['hash'] ) { return false; } // Get lead and verify it is attached to the form we received with it. $entry = wpforms()->entry->get( $output['entry_id'] ); if ( $output['form_id'] != $entry->form_id ) { return false; } return array( 'form_id' => absint( $output['form_id'] ), 'entry_id' => absint( $output['form_id'] ), 'fields' => null !== $entry && isset( $entry->fields ) ? $entry->fields : array(), ); } /** * Redirect user to a page or URL specified in the form confirmation settings. * * @since 1.0.0 * * @param array $form_data Form data and settings. * @param string $hash Base64-encoded hash of form and entry IDs. */ public function entry_confirmation_redirect( $form_data = array(), $hash = '' ) { // Maybe process return hash. if ( ! empty( $hash ) ) { $hash_data = $this->validate_return_hash( $hash ); if ( ! $hash_data || ! is_array( $hash_data ) ) { return; } $this->valid_hash = true; $this->entry_id = absint( $hash_data['entry_id'] ); $this->fields = json_decode( $hash_data['fields'], true ); $this->form_data = wpforms()->form->get( absint( $hash_data['form_id'] ), array( 'content_only' => true, ) ); } else { $this->form_data = $form_data; } // Backward compatibility. if ( empty( $this->form_data['settings']['confirmations'] ) ) { $this->form_data['settings']['confirmations'][1]['type'] = ! empty( $this->form_data['settings']['confirmation_type'] ) ? $this->form_data['settings']['confirmation_type'] : 'message'; $this->form_data['settings']['confirmations'][1]['message'] = ! empty( $this->form_data['settings']['confirmation_message'] ) ? $this->form_data['settings']['confirmation_message'] : esc_html__( 'Thanks for contacting us! We will be in touch with you shortly.', 'wpforms-lite' ); $this->form_data['settings']['confirmations'][1]['message_scroll'] = ! empty( $this->form_data['settings']['confirmation_message_scroll'] ) ? $this->form_data['settings']['confirmation_message_scroll'] : 1; $this->form_data['settings']['confirmations'][1]['page'] = ! empty( $this->form_data['settings']['confirmation_page'] ) ? $this->form_data['settings']['confirmation_page'] : ''; $this->form_data['settings']['confirmations'][1]['redirect'] = ! empty( $this->form_data['settings']['confirmation_redirect'] ) ? $this->form_data['settings']['confirmation_redirect'] : ''; } if ( empty( $this->form_data['settings']['confirmations'] ) || ! is_array( $this->form_data['settings']['confirmations'] ) ) { return; } $confirmations = $this->form_data['settings']['confirmations']; // Reverse sort confirmations by id to process newer ones first. krsort( $confirmations ); $default_confirmation_key = min( array_keys( $confirmations ) ); foreach ( $confirmations as $confirmation_id => $confirmation ) { // Last confirmation should execute in any case. if ( $default_confirmation_key === $confirmation_id ) { break; } $process_confirmation = apply_filters( 'wpforms_entry_confirmation_process', true, $this->fields, $form_data, $confirmation_id ); if ( $process_confirmation ) { break; } } $url = ''; // Redirect if needed, to either a page or URL, after form processing. if ( ! empty( $confirmations[ $confirmation_id ]['type'] ) && 'message' !== $confirmations[ $confirmation_id ]['type'] ) { if ( 'redirect' === $confirmations[ $confirmation_id ]['type'] ) { add_filter( 'wpforms_field_smart_tag_value', 'rawurlencode' ); $url = apply_filters( 'wpforms_process_smart_tags', $confirmations[ $confirmation_id ]['redirect'], $this->form_data, $this->fields, $this->entry_id ); } if ( 'page' === $confirmations[ $confirmation_id ]['type'] ) { $url = get_permalink( (int) $confirmations[ $confirmation_id ]['page'] ); } } if ( ! empty( $url ) ) { $url = apply_filters( 'wpforms_process_redirect_url', $url, $this->form_data['id'], $this->fields, $this->form_data, $this->entry_id ); if ( wpforms_is_amp() ) { /** This filter is documented in wp-includes/pluggable.php */ $url = apply_filters( 'wp_redirect', $url, 302 ); $url = wp_sanitize_redirect( $url ); header( sprintf( 'AMP-Redirect-To: %s', $url ) ); header( 'Access-Control-Expose-Headers: AMP-Redirect-To', false ); wp_send_json( array( 'message' => __( 'Redirecting…', 'wpforms-lite' ), 'redirecting' => true, ), 200 ); } else { wp_redirect( esc_url_raw( $url ) ); // phpcs:ignore } do_action( 'wpforms_process_redirect', $this->form_data['id'] ); do_action( "wpforms_process_redirect_{$this->form_data['id']}", $this->form_data['id'] ); exit; } // Pass a message to a frontend if no redirection happened. if ( ! empty( $confirmations[ $confirmation_id ]['type'] ) && 'message' === $confirmations[ $confirmation_id ]['type'] ) { $this->confirmation_message = $confirmations[ $confirmation_id ]['message']; if ( ! empty( $confirmations[ $confirmation_id ]['message_scroll'] ) ) { wpforms()->frontend->confirmation_message_scroll = true; } } } /** * Get confirmation message. * * @since 1.5.3 * * @param array $form_data Form data and settings. * @param array $fields Sanitized field data. * @param int $entry_id Entry id. * * @return string Confirmation message. */ public function get_confirmation_message( $form_data, $fields, $entry_id ) { if ( empty( $this->confirmation_message ) ) { return ''; } $confirmation_message = apply_filters( 'wpforms_process_smart_tags', $this->confirmation_message, $form_data, $fields, $entry_id ); $confirmation_message = apply_filters( 'wpforms_frontend_confirmation_message', wpautop( $confirmation_message ), $form_data, $fields, $entry_id ); return $confirmation_message; } /** * Catch the post_max_size overflow. * * @since 1.5.2 * * @return bool */ public function post_max_size_overflow() { if ( empty( $_SERVER['CONTENT_LENGTH'] ) || empty( $_GET['wpforms_form_id'] ) ) { // phpcs:ignore return false; } $form_id = (int) $_GET['wpforms_form_id']; $total_size = (int) $_SERVER['CONTENT_LENGTH']; $post_max_size = wpforms_size_to_bytes( ini_get( 'post_max_size' ) ); if ( ! ( $total_size > $post_max_size && empty( $_POST ) && $form_id > 0 ) ) { return false; } $total_size = number_format( $total_size / 1048576, 3 ); $post_max_size = number_format( $post_max_size / 1048576, 3 ); $error_msg = esc_html__( 'Form has not been submitted, please see the errors below.', 'wpforms-lite' ); $error_msg .= '<br>' . esc_html__( 'The total size of the selected files {totalSize} Mb exceeds the allowed limit {maxSize} Mb.', 'wpforms-lite' ); $error_msg = str_replace( '{totalSize}', $total_size, $error_msg ); $error_msg = str_replace( '{maxSize}', $post_max_size, $error_msg ); $this->errors[ $form_id ]['header'] = $error_msg; return true; } /** * Send entry email notifications. * * @since 1.0.0 * * @param array $fields List of fields. * @param array $entry Submitted form entry. * @param array $form_data Form data and settings. * @param int $entry_id Saved entry id. * @param string $context In which context this email is sent. */ public function entry_email( $fields, $entry, $form_data, $entry_id, $context = '' ) { // Check that the form was configured for email notifications. if ( empty( $form_data['settings']['notification_enable'] ) || '1' != $form_data['settings']['notification_enable'] ) { return; } // Provide the opportunity to override via a filter. if ( ! apply_filters( 'wpforms_entry_email', true, $fields, $entry, $form_data ) ) { return; } // Make sure we have and entry id. if ( empty( $this->entry_id ) ) { $this->entry_id = (int) $entry_id; } $fields = apply_filters( 'wpforms_entry_email_data', $fields, $entry, $form_data ); // Backwards compatibility for notifications before v1.4.3. if ( empty( $form_data['settings']['notifications'] ) ) { $notifications[1] = array( 'email' => $form_data['settings']['notification_email'], 'subject' => $form_data['settings']['notification_subject'], 'sender_name' => $form_data['settings']['notification_fromname'], 'sender_address' => $form_data['settings']['notification_fromaddress'], 'replyto' => $form_data['settings']['notification_replyto'], 'message' => '{all_fields}', ); } else { $notifications = $form_data['settings']['notifications']; } foreach ( $notifications as $notification_id => $notification ) : if ( empty( $notification['email'] ) ) { continue; } $process_email = apply_filters( 'wpforms_entry_email_process', true, $fields, $form_data, $notification_id, $context ); if ( ! $process_email ) { continue; } $email = array(); // Setup email properties. /* translators: %s - form name. */ $email['subject'] = ! empty( $notification['subject'] ) ? $notification['subject'] : sprintf( esc_html__( 'New %s Entry', 'wpforms-lite' ), $form_data['settings']['form_title'] ); $email['address'] = explode( ',', apply_filters( 'wpforms_process_smart_tags', $notification['email'], $form_data, $fields, $this->entry_id ) ); $email['address'] = array_map( 'sanitize_email', $email['address'] ); $email['sender_address'] = ! empty( $notification['sender_address'] ) ? $notification['sender_address'] : get_option( 'admin_email' ); $email['sender_name'] = ! empty( $notification['sender_name'] ) ? $notification['sender_name'] : get_bloginfo( 'name' ); $email['replyto'] = ! empty( $notification['replyto'] ) ? $notification['replyto'] : false; $email['message'] = ! empty( $notification['message'] ) ? $notification['message'] : '{all_fields}'; $email = apply_filters( 'wpforms_entry_email_atts', $email, $fields, $entry, $form_data, $notification_id ); // Create new email. $emails = new WPForms_WP_Emails(); $emails->__set( 'form_data', $form_data ); $emails->__set( 'fields', $fields ); $emails->__set( 'notification_id', $notification_id ); $emails->__set( 'entry_id', $this->entry_id ); $emails->__set( 'from_name', $email['sender_name'] ); $emails->__set( 'from_address', $email['sender_address'] ); $emails->__set( 'reply_to', $email['replyto'] ); // Maybe include CC. if ( ! empty( $notification['carboncopy'] ) && wpforms_setting( 'email-carbon-copy', false ) ) { $emails->__set( 'cc', $notification['carboncopy'] ); } $emails = apply_filters( 'wpforms_entry_email_before_send', $emails ); // Go. foreach ( $email['address'] as $address ) { $emails->send( trim( $address ), $email['subject'], $email['message'] ); } endforeach; } /** * Save entry to database. * * @since 1.0.0 * * @param array $fields List of form fields. * @param array $entry User submitted data. * @param int $form_id Form ID. * @param array $form_data Prepared form settings. * * @return int */ public function entry_save( $fields, $entry, $form_id, $form_data = array() ) { do_action( 'wpforms_process_entry_save', $fields, $entry, $form_id, $form_data ); return $this->entry_id; } /** * Process AJAX form submit. * * @since 1.5.3 */ public function ajax_submit() { $form_id = isset( $_POST['wpforms']['id'] ) ? absint( $_POST['wpforms']['id'] ) : 0; // phpcs:ignore if ( empty( $form_id ) ) { wp_send_json_error(); } add_filter( 'wp_redirect', array( $this, 'ajax_process_redirect' ), 999 ); do_action( 'wpforms_ajax_submit_before_processing', $form_id ); // If redirect happens in listen(), ajax_process_redirect() gets executed because of the filter on `wp_redirect`. // The code, that is below listen(), runs only if no redirect happened. $this->listen(); $form_data = $this->form_data; if ( empty( $form_data ) ) { $form_data = wpforms()->form->get( $form_id, array( 'content_only' => true ) ); $form_data = apply_filters( 'wpforms_frontend_form_data', $form_data ); } if ( ! empty( $this->errors[ $form_id ] ) ) { $this->ajax_process_errors( $form_id, $form_data ); wp_send_json_error(); } ob_start(); wpforms()->frontend->confirmation( $form_data ); $response = apply_filters( 'wpforms_ajax_submit_success_response', array( 'confirmation' => ob_get_clean() ), $form_id, $form_data ); do_action( 'wpforms_ajax_submit_completed', $form_id, $response ); wp_send_json_success( $response ); } /** * Process AJAX errors. * * @since 1.5.3 * @todo This should be re-used/combined for AMP verify-xhr requests. * * @param int $form_id Form ID. * @param array $form_data Form data and settings. */ protected function ajax_process_errors( $form_id, $form_data ) { $errors = isset( $this->errors[ $form_id ] ) ? $this->errors[ $form_id ] : array(); $errors = apply_filters( 'wpforms_ajax_submit_errors', $errors, $form_id, $form_data ); if ( empty( $errors ) ) { wp_send_json_error(); } // General errors are errors that cannot be populated with jQuery Validate plugin. $general_errors = array_intersect_key( $errors, array_flip( array( 'header', 'footer', 'recaptcha' ) ) ); foreach ( $general_errors as $key => $error ) { ob_start(); wpforms()->frontend->form_error( $key, $error ); $general_errors[ $key ] = ob_get_clean(); } $fields = isset( $form_data['fields'] ) ? $form_data['fields'] : array(); // Get registered fields errors only. $field_errors = array_intersect_key( $errors, $fields ); // Transform field ids to field names for jQuery Validate plugin. foreach ( $field_errors as $key => $error ) { $props = wpforms()->frontend->get_field_properties( $fields[ $key ], $form_data ); $name = isset( $props['inputs']['primary']['attr']['name'] ) ? $props['inputs']['primary']['attr']['name'] : ''; if ( $name ) { $field_errors[ $name ] = $error; } unset( $field_errors[ $key ] ); } $response = array(); if ( $general_errors ) { $response['errors']['general'] = $general_errors; } if ( $field_errors ) { $response['errors']['field'] = $field_errors; } $response = apply_filters( 'wpforms_ajax_submit_errors_response', $response, $form_id, $form_data ); do_action( 'wpforms_ajax_submit_completed', $form_id, $response ); wp_send_json_error( $response ); } /** * Process AJAX redirect. * * @since 1.5.3 * * @param string $url Redirect URL. */ public function ajax_process_redirect( $url ) { $form_id = isset( $_POST['wpforms']['id'] ) ? absint( $_POST['wpforms']['id'] ) : 0; // phpcs:ignore WordPress.Security.NonceVerification if ( empty( $form_id ) ) { wp_send_json_error(); } $response = array( 'form_id' => $form_id, 'redirect_url' => $url, ); $response = apply_filters( 'wpforms_ajax_submit_redirect', $response, $form_id, $url ); do_action( 'wpforms_ajax_submit_completed', $form_id, $response ); wp_send_json_success( $response ); } } class-logging.php 0000666 00000017757 15213301444 0010030 0 ustar 00 <?php /** * Class for logging events and errors * * This class is forked from Easy Digital Downloads / Pippin Williamson. * * @link https://github.com/easydigitaldownloads/Easy-Digital-Downloads/blob/master/includes/class-edd-logging.php * * @since 1.0.0 */ class WPForms_Logging { /** * Set up the logging class. * * @since 1.0.0 */ public function __construct() { // Create the log post type add_action( 'init', array( $this, 'register_post_type' ), 1 ); // Create types taxonomy and default types add_action( 'init', array( $this, 'register_taxonomy' ), 1 ); } /** * Register the log post type. * * @since 1.0.0 */ public function register_post_type() { $log_args = array( 'labels' => array( 'name' => esc_html__( 'WPForms Logs', 'wpforms-lite' ), 'menu_name' => esc_html__( 'Logs', 'wpforms-lite' ) ), 'public' => false, 'exclude_from_search' => true, 'publicly_queryable' => false, 'show_ui' => false, 'query_var' => false, 'rewrite' => false, 'supports' => array( 'title', 'editor' ), 'can_export' => false, 'show_in_menu' => 'wpforms-overview', 'show_in_admin_bar' => false, 'capability_type' => 'wpforms_log', ); if ( wpforms_debug() ) { $log_args['show_ui'] = true; } register_post_type( 'wpforms_log', apply_filters( 'wpforms_log_cpt', $log_args ) ); } /** * Register the Log Type taxonomy. * * @since 1.0.0 */ public function register_taxonomy() { register_taxonomy( 'wpforms_log_type', 'wpforms_log', array( 'public' => false ) ); } /** * Log types. * * @since 1.0.0 * @return array */ public function log_types() { $terms = array( 'payment', 'provider', 'spam', 'entry', 'error', 'conditional_logic' ); return apply_filters( 'wpforms_log_types', $terms ); } /** * Check if a log type is valid. * * @since 1.0.0 * @param string $type * @return bool */ function valid_type( $type ) { return in_array( $type, $this->log_types() ); } /** * Create new log entry. * * This is just a simple and fast way to log something. Use $this->insert_log() * if you need to store custom meta data * * @since 1.0.0 * @param string $title Log entry title * @param string $message Log entry message * @param int $parent Log entry parent * @param string $type Log type (default: null) * @return int Log ID */ public function add( $title = '', $message = '', $parent = 0, $type = null, $meta = '' ) { $log_data = array( 'post_title' => $title, 'post_content' => $message, 'post_parent' => $parent, 'log_type' => $type ); return $this->insert_log( $log_data, $meta ); } /** * Easily retrieves log items for a particular object ID. * * @since 1.0.0 * @param int $object_id (default: 0) * @param string $type Log type (default: null) * @param int $paged Page number (default: null) * @return array Array of the connected logs */ public function get_logs( $object_id = 0, $type = null, $paged = null ) { return $this->get_connected_logs( array( 'post_parent' => $object_id, 'paged' => $paged, 'log_type' => $type ) ); } /** * Store a log entry. * * @since 1.0.0 * @param array $log_data Log entry data * @param array $log_meta Log entry meta * @return int The ID of the newly created log item */ function insert_log( $log_data = array(), $log_meta = array() ) { $defaults = array( 'post_type' => 'wpforms_log', 'post_status' => 'publish', 'post_parent' => 0, 'post_content' => '', 'log_type' => false ); $args = wp_parse_args( $log_data, $defaults ); do_action( 'wpforms_pre_insert_log', $log_data, $log_meta ); // Store the log entry $log_id = wp_insert_post( $args ); // Set the log type, if any if ( $log_data['log_type'] && $this->valid_type( $log_data['log_type'] ) ) { wp_set_object_terms( $log_id, $log_data['log_type'], 'wpforms_log_type', false ); } // Set log meta, if any if ( $log_id && ! empty( $log_meta ) ) { foreach ( (array) $log_meta as $key => $meta ) { update_post_meta( $log_id, '_wpforms_log_' . sanitize_key( $key ), $meta ); } } do_action( 'wpforms_post_insert_log', $log_id, $log_data, $log_meta ); return $log_id; } /** * Update and existing log item. * * @since 1.0.0 * @param array $log_data Log entry data * @param array $log_meta Log entry meta * @return bool True if successful, false otherwise */ public function update_log( $log_data = array(), $log_meta = array() ) { do_action( 'wpforms_pre_update_log', $log_data, $log_meta ); $defaults = array( 'post_type' => 'wpforms_log', 'post_status' => 'publish', 'post_parent' => 0 ); $args = wp_parse_args( $log_data, $defaults ); // Store the log entry $log_id = wp_update_post( $args ); if ( $log_id && ! empty( $log_meta ) ) { foreach ( (array) $log_meta as $key => $meta ) { if ( ! empty( $meta ) ) update_post_meta( $log_id, '_wpforms_log_' . sanitize_key( $key ), $meta ); } } do_action( 'wpforms_post_update_log', $log_id, $log_data, $log_meta ); } /** * Retrieve all connected logs. * * Used for retrieving logs related to particular items, such as a specific purchase. * * @since 1.0.0 * @param array $args Query arguments * @return mixed array if logs were found, false otherwise */ public function get_connected_logs( $args = array() ) { $defaults = array( 'post_type' => 'wpforms_log', 'posts_per_page' => 20, 'post_status' => 'publish', 'paged' => get_query_var( 'paged' ), 'log_type' => false ); $query_args = wp_parse_args( $args, $defaults ); if ( $query_args['log_type'] && $this->valid_type( $query_args['log_type'] ) ) { $query_args['tax_query'] = array( array( 'taxonomy' => 'wpforms_log_type', 'field' => 'slug', 'terms' => $query_args['log_type'] ) ); } $logs = get_posts( $query_args ); if ( $logs ) return $logs; // No logs found return false; } /** * Retrieve number of log entries connected to particular object ID * * @since 1.0.0 * @param int $object_id (default: 0) * @param string $type Log type (default: null) * @param array $meta_query Log meta query (default: null) * @param array $date_query Log data query (default: null) (since 1.9) * @return int Log count */ public function get_log_count( $object_id = 0, $type = null, $meta_query = null, $date_query = null ) { global $pagenow, $typenow; $query_args = array( 'post_parent' => $object_id, 'post_type' => 'wpforms_log', 'posts_per_page' => -1, 'post_status' => 'publish', 'fields' => 'ids', ); if ( ! empty( $type ) && $this->valid_type( $type ) ) { $query_args['tax_query'] = array( array( 'taxonomy' => 'wpforms_log_type', 'field' => 'slug', 'terms' => $type ) ); } if ( ! empty( $meta_query ) ) { $query_args['meta_query'] = $meta_query; } if ( ! empty( $date_query ) ) { $query_args['date_query'] = $date_query; } $logs = new WP_Query( $query_args ); return (int) $logs->post_count; } /** * Delete a log. * * @since 1.0.0 * @param int $object_id (default: 0) * @param string $type Log type (default: null) * @param array $meta_query Log meta query (default: null) */ public function delete_logs( $object_id = 0, $type = null, $meta_query = null ) { $query_args = array( 'post_parent' => $object_id, 'post_type' => 'wpforms_log', 'posts_per_page' => -1, 'post_status' => 'publish', 'fields' => 'ids' ); if ( ! empty( $type ) && $this->valid_type( $type ) ) { $query_args['tax_query'] = array( array( 'taxonomy' => 'wpforms_log_type', 'field' => 'slug', 'terms' => $type, ) ); } if ( ! empty( $meta_query ) ) { $query_args['meta_query'] = $meta_query; } $logs = get_posts( $query_args ); if ( $logs ) { foreach ( $logs as $log ) { wp_delete_post( $log, true ); } } } } providers/class-base.php 0000666 00000102237 15213301444 0011315 0 ustar 00 <?php /** * Provider class. * * @since 1.0.0 */ abstract class WPForms_Provider { /** * Provider addon version. * * @since 1.0.0 * * @var string */ protected $version; /** * Provider name. * * @since 1.0.0 * * @var string */ public $name; /** * Provider name in slug format. * * @since 1.0.0 * * @var string */ public $slug; /** * Load priority. * * @since 1.0.0 * * @var int */ public $priority = 10; /** * Store the API connections. * * @since 1.0.0 * * @var mixed */ public $api = false; /** * Service icon. * * @since 1.0.0 * * @var string */ public $icon; /** * Service icon. * * @since 1.2.3 * * @var string */ public $type; /** * Form data and settings. * * @since 1.2.3 * * @var array */ public $form_data; /** * Primary class constructor. * * @since 1.0.0 */ public function __construct() { $this->type = esc_html__( 'Connection', 'wpforms-lite' ); $this->init(); // Add to list of available providers. add_filter( 'wpforms_providers_available', array( $this, 'register_provider' ), $this->priority, 1 ); // Process builder AJAX requests. add_action( "wp_ajax_wpforms_provider_ajax_{$this->slug}", array( $this, 'process_ajax' ) ); // Process entry. add_action( 'wpforms_process_complete', array( $this, 'process_entry' ), 5, 4 ); // Fetch and store the current form data when in the builder. add_action( 'wpforms_builder_init', array( $this, 'builder_form_data' ) ); // Output builder sidebar. add_action( 'wpforms_providers_panel_sidebar', array( $this, 'builder_sidebar' ), $this->priority ); // Output builder content. add_action( 'wpforms_providers_panel_content', array( $this, 'builder_output' ), $this->priority ); // Remove provider from Settings Integrations tab. add_action( "wp_ajax_wpforms_settings_provider_disconnect_{$this->slug}", array( $this, 'integrations_tab_disconnect' ) ); // Add new provider from Settings Integrations tab. add_action( "wp_ajax_wpforms_settings_provider_add_{$this->slug}", array( $this, 'integrations_tab_add' ) ); // Add providers sections to the Settings Integrations tab. add_action( 'wpforms_settings_providers', array( $this, 'integrations_tab_options' ), $this->priority, 2 ); } /** * All systems go. Used by subclasses. * * @since 1.0.0 */ public function init() { } /** * Add to list of registered providers. * * @since 1.0.0 * * @param array $providers Array of all active providers. * * @return array */ public function register_provider( $providers = array() ) { $providers[ $this->slug ] = $this->name; return $providers; } /** * Process the Builder AJAX requests. * * @since 1.0.0 */ public function process_ajax() { // Run a security check. check_ajax_referer( 'wpforms-builder', 'nonce' ); // Check for permissions. if ( ! wpforms_current_user_can( 'edit_forms' ) ) { wp_send_json_error( array( 'error' => esc_html__( 'You do not have permission', 'wpforms-lite' ), ) ); } $name = ! empty( $_POST['name'] ) ? sanitize_text_field( wp_unslash( $_POST['name'] ) ) : ''; $task = ! empty( $_POST['task'] ) ? sanitize_text_field( wp_unslash( $_POST['task'] ) ) : ''; $id = ! empty( $_POST['id'] ) ? sanitize_text_field( wp_unslash( $_POST['id'] ) ) : ''; $connection_id = ! empty( $_POST['connection_id'] ) ? sanitize_text_field( wp_unslash( $_POST['connection_id'] ) ) : ''; $account_id = ! empty( $_POST['account_id'] ) ? sanitize_text_field( wp_unslash( $_POST['account_id'] ) ) : ''; $list_id = ! empty( $_POST['list_id'] ) ? sanitize_text_field( wp_unslash( $_POST['list_id'] ) ) : ''; $data = ! empty( $_POST['data'] ) ? array_map( 'sanitize_text_field', wp_parse_args( wp_unslash( $_POST['data'] ) ) ) : array(); //phpcs:ignore /* * Create new connection. */ if ( 'new_connection' === $task ) { $connection = $this->output_connection( '', array( 'connection_name' => $name, ), $id ); wp_send_json_success( array( 'html' => $connection, ) ); } /* * Create new Provider account. */ if ( 'new_account' === $task ) { $auth = $this->api_auth( $data, $id ); if ( is_wp_error( $auth ) ) { wp_send_json_error( array( 'error' => $auth->get_error_message(), ) ); } else { $accounts = $this->output_accounts( $connection_id, array( 'account_id' => $auth, ) ); wp_send_json_success( array( 'html' => $accounts, ) ); } } /* * Select/Toggle Provider accounts. */ if ( 'select_account' === $task ) { $lists = $this->output_lists( $connection_id, array( 'account_id' => $account_id, ) ); if ( is_wp_error( $lists ) ) { wp_send_json_error( array( 'error' => $lists->get_error_message(), ) ); } else { wp_send_json_success( array( 'html' => $lists, ) ); } } /* * Select/Toggle Provider account lists. */ if ( 'select_list' === $task ) { $fields = $this->output_fields( $connection_id, array( 'account_id' => $account_id, 'list_id' => $list_id, ), $id ); if ( is_wp_error( $fields ) ) { wp_send_json_error( array( 'error' => $fields->get_error_message(), ) ); } else { $groups = $this->output_groups( $connection_id, array( 'account_id' => $account_id, 'list_id' => $list_id, ) ); $conditionals = $this->output_conditionals( $connection_id, array( 'account_id' => $account_id, 'list_id' => $list_id, ), array( 'id' => absint( $_POST['form_id'] ), //phpcs:ignore ) ); $options = $this->output_options( $connection_id, array( 'account_id' => $account_id, 'list_id' => $list_id, ) ); wp_send_json_success( array( 'html' => $groups . $fields . $conditionals . $options, ) ); } } die(); } /** * Process and submit entry to provider. * * @since 1.0.0 * * @param array $fields List of fields in a form. * @param array $entry Submitted entry values. * @param array $form_data Form data and settings. * @param int $entry_id Saved entry ID. */ public function process_entry( $fields, $entry, $form_data, $entry_id ) { } /** * Process conditional fields. * * @since 1.0.0 * * @param array $fields List of fields with their data and settings. * @param array $entry Submitted entry values. * @param array $form_data Form data and settings. * @param array $connection List of connection settings. * * @return bool */ public function process_conditionals( $fields, $entry, $form_data, $connection ) { if ( empty( $connection['conditional_logic'] ) || empty( $connection['conditionals'] ) ) { return true; } $process = wpforms_conditional_logic()->process( $fields, $form_data, $connection['conditionals'] ); if ( ! empty( $connection['conditional_type'] ) && 'stop' === $connection['conditional_type'] ) { $process = ! $process; } return $process; } /** * Retrieve all available forms in a field. * * Not all fields should be available for merge tags so we compare against a * white-list. Also some fields, such as Name, should have additional * variations. * * @since 1.0.0 * * @param object|bool $form * @param array $whitelist * * @return bool|array */ public function get_form_fields( $form = false, $whitelist = array() ) { // Accept form (post) object or form ID. if ( is_object( $form ) ) { $form = wpforms_decode( $form->post_content ); } elseif ( is_numeric( $form ) ) { $form = wpforms()->form->get( $form, array( 'content_only' => true, ) ); } if ( ! is_array( $form ) || empty( $form['fields'] ) ) { return false; } // White list of field types to allow. $allowed_form_fields = array( 'text', 'textarea', 'select', 'radio', 'checkbox', 'email', 'address', 'url', 'name', 'hidden', 'date-time', 'phone', 'number', ); $allowed_form_fields = apply_filters( 'wpforms_providers_fields', $allowed_form_fields ); $whitelist = ! empty( $whitelist ) ? $whitelist : $allowed_form_fields; $form_fields = $form['fields']; foreach ( $form_fields as $id => $form_field ) { if ( ! in_array( $form_field['type'], $whitelist, true ) ) { unset( $form_fields[ $id ] ); } } return $form_fields; } /** * Get form fields ready for select list options. * * In this function we also do the logic to limit certain fields to certain * provider field types. * * @since 1.0.0 * * @param array $form_fields * @param string $form_field_type * * @return array */ public function get_form_field_select( $form_fields = array(), $form_field_type = '' ) { if ( empty( $form_fields ) || empty( $form_field_type ) ) { return array(); } $formatted = array(); // Include only specific field types. foreach ( $form_fields as $id => $form_field ) { // Email. if ( 'email' === $form_field_type && ! in_array( $form_field['type'], array( 'text', 'email' ), true ) ) { unset( $form_fields[ $id ] ); } // Address. if ( 'address' === $form_field_type && ! in_array( $form_field['type'], array( 'address' ), true ) ) { unset( $form_fields[ $id ] ); } } // Format. foreach ( $form_fields as $id => $form_field ) { // Complex Name field. if ( 'name' === $form_field['type'] ) { // Full Name. $formatted[] = array( 'id' => $form_field['id'], 'key' => 'value', 'type' => $form_field['type'], 'subtype' => '', 'provider_type' => $form_field_type, 'label' => sprintf( /* translators: %s - Name field label. */ esc_html__( '%s (Full)', 'wpforms-lite' ), $form_field['label'] ), ); // First Name. if ( strpos( $form_field['format'], 'first' ) !== false ) { $formatted[] = array( 'id' => $form_field['id'], 'key' => 'first', 'type' => $form_field['type'], 'subtype' => 'first', 'provider_type' => $form_field_type, 'label' => sprintf( /* translators: %s - Name field label. */ esc_html__( '%s (First)', 'wpforms-lite' ), $form_field['label'] ), ); } // Middle Name. if ( strpos( $form_field['format'], 'middle' ) !== false ) { $formatted[] = array( 'id' => $form_field['id'], 'key' => 'middle', 'type' => $form_field['type'], 'subtype' => 'middle', 'provider_type' => $form_field_type, 'label' => sprintf( /* translators: %s - Name field label. */ esc_html__( '%s (Middle)', 'wpforms-lite' ), $form_field['label'] ), ); } // Last Name. if ( strpos( $form_field['format'], 'last' ) !== false ) { $formatted[] = array( 'id' => $form_field['id'], 'key' => 'last', 'type' => $form_field['type'], 'subtype' => 'last', 'provider_type' => $form_field_type, 'label' => sprintf( /* translators: %s - Name field label. */ esc_html__( '%s (Last)', 'wpforms-lite' ), $form_field['label'] ), ); } } else { // All other fields. $formatted[] = array( 'id' => $form_field['id'], 'key' => 'value', 'type' => $form_field['type'], 'subtype' => '', 'provider_type' => $form_field_type, 'label' => $form_field['label'], ); } } return $formatted; } /************************************************************************ * API methods - these methods interact directly with the provider API. * ************************************************************************/ /** * Authenticate with the provider API. * * @since 1.0.0 * * @param array $data * @param string $form_id * * @return mixed id or error object */ public function api_auth( $data = array(), $form_id = '' ) { } /** * Establish connection object to provider API. * * @since 1.0.0 * * @param string $account_id * * @return mixed array or error object */ public function api_connect( $account_id ) { } /** * Retrieve provider account lists. * * @since 1.0.0 * * @param string $connection_id * @param string $account_id * * @return mixed array or error object */ public function api_lists( $connection_id = '', $account_id = '' ) { } /** * Retrieve provider account list groups. * * @since 1.0.0 * * @param string $connection_id * @param string $account_id * @param string $list_id * * @return mixed array or error object */ public function api_groups( $connection_id = '', $account_id = '', $list_id = '' ) { } /** * Retrieve provider account list fields. * * @since 1.0.0 * * @param string $connection_id * @param string $account_id * @param string $list_id * * @return mixed array or error object */ public function api_fields( $connection_id = '', $account_id = '', $list_id = '' ) { } /************************************************************************* * Output methods - these methods generally return HTML for the builder. * *************************************************************************/ /** * Connection HTML. * * This method compiles all the HTML necessary for a connection to a provider. * * @since 1.0.0 * * @param string $connection_id * @param array $connection * @param mixed $form Form id or form data. * * @return string */ public function output_connection( $connection_id = '', $connection = array(), $form = '' ) { if ( empty( $connection_id ) ) { $connection_id = 'connection_' . uniqid(); } if ( empty( $connection ) || empty( $form ) ) { return ''; } $output = sprintf( '<div class="wpforms-provider-connection" data-provider="%s" data-connection_id="%s">', $this->slug, $connection_id ); $output .= $this->output_connection_header( $connection_id, $connection ); $output .= $this->output_auth(); $output .= $this->output_accounts( $connection_id, $connection ); $lists = $this->output_lists( $connection_id, $connection ); $output .= ! is_wp_error( $lists ) ? $lists : ''; $output .= $this->output_groups( $connection_id, $connection ); $fields = $this->output_fields( $connection_id, $connection, $form ); $output .= ! is_wp_error( $fields ) ? $fields : ''; $output .= $this->output_conditionals( $connection_id, $connection, $form ); $output .= $this->output_options( $connection_id, $connection ); $output .= '</div>'; return $output; } /** * Connection header HTML. * * @since 1.0.0 * * @param string $connection_id * @param array $connection * * @return string */ public function output_connection_header( $connection_id = '', $connection = array() ) { if ( empty( $connection_id ) || empty( $connection ) ) { return ''; } $output = '<div class="wpforms-provider-connection-header">'; $output .= sprintf( '<span>%s</span>', sanitize_text_field( $connection['connection_name'] ) ); $output .= '<button class="wpforms-provider-connection-delete"><i class="fa fa-times-circle"></i></button>'; $output .= sprintf( '<input type="hidden" name="providers[%s][%s][connection_name]" value="%s">', $this->slug, $connection_id, esc_attr( $connection['connection_name'] ) ); $output .= '</div>'; return $output; } /** * Provider account authorize fields HTML. * * @since 1.0.0 * * @return mixed */ public function output_auth() { } /** * Provider account select HTML. * * @since 1.0.0 * * @param string $connection_id Unique connection ID. * @param array $connection Array of connection data. * * @return string */ public function output_accounts( $connection_id = '', $connection = array() ) { if ( empty( $connection_id ) || empty( $connection ) ) { return ''; } $providers = wpforms_get_providers_options(); if ( empty( $providers[ $this->slug ] ) ) { return ''; } $output = '<div class="wpforms-provider-accounts wpforms-connection-block">'; $output .= sprintf( '<h4>%s</h4>', esc_html__( 'Select Account', 'wpforms-lite' ) ); $output .= sprintf( '<select name="providers[%s][%s][account_id]">', $this->slug, $connection_id ); foreach ( $providers[ $this->slug ] as $key => $provider_details ) { $selected = ! empty( $connection['account_id'] ) ? $connection['account_id'] : ''; $output .= sprintf( '<option value="%s" %s>%s</option>', $key, selected( $selected, $key, false ), esc_html( $provider_details['label'] ) ); } $output .= sprintf( '<option value="">%s</a>', esc_html__( 'Add New Account', 'wpforms-lite' ) ); $output .= '</select>'; $output .= '</div>'; return $output; } /** * Provider account lists HTML. * * @since 1.0.0 * * @param string $connection_id * @param array $connection * * @return WP_Error|string */ public function output_lists( $connection_id = '', $connection = array() ) { if ( empty( $connection_id ) || empty( $connection['account_id'] ) ) { return ''; } $lists = $this->api_lists( $connection_id, $connection['account_id'] ); $selected = ! empty( $connection['list_id'] ) ? $connection['list_id'] : ''; if ( is_wp_error( $lists ) ) { return $lists; } $output = '<div class="wpforms-provider-lists wpforms-connection-block">'; $output .= sprintf( '<h4>%s</h4>', esc_html__( 'Select List', 'wpforms-lite' ) ); $output .= sprintf( '<select name="providers[%s][%s][list_id]">', $this->slug, $connection_id ); if ( ! empty( $lists ) ) { foreach ( $lists as $list ) { $output .= sprintf( '<option value="%s" %s>%s</option>', esc_attr( $list['id'] ), selected( $selected, $list['id'], false ), esc_attr( $list['name'] ) ); } } $output .= '</select>'; $output .= '</div>'; return $output; } /** * Provider account list groups HTML. * * @since 1.0.0 * * @param string $connection_id * @param array $connection * * @return string */ public function output_groups( $connection_id = '', $connection = array() ) { if ( empty( $connection_id ) || empty( $connection['account_id'] ) || empty( $connection['list_id'] ) ) { return ''; } $groupsets = $this->api_groups( $connection_id, $connection['account_id'], $connection['list_id'] ); if ( is_wp_error( $groupsets ) ) { return ''; } $output = '<div class="wpforms-provider-groups wpforms-connection-block">'; $output .= sprintf( '<h4>%s</h4>', esc_html__( 'Select Groups', 'wpforms-lite' ) ); $output .= sprintf( '<p>%s</p>', esc_html__( 'We also noticed that you have some segments in your list. You can select specific list segments below if needed. This is optional.', 'wpforms-lite' ) ); $output .= '<div class="wpforms-provider-groups-list">'; foreach ( $groupsets as $groupset ) { $output .= sprintf( '<p>%s</p>', esc_html( $groupset['name'] ) ); foreach ( $groupset['groups'] as $group ) { $selected = ! empty( $connection['groups'] ) && ! empty( $connection['groups'][ $groupset['id'] ] ) ? in_array( $group['name'], $connection['groups'][ $groupset['id'] ], true ) : false; $output .= sprintf( '<span><input id="group_%s" type="checkbox" value="%s" name="providers[%s][%s][groups][%s][%s]" %s><label for="group_%s">%s</label></span>', esc_attr( $group['id'] ), esc_attr( $group['name'] ), $this->slug, $connection_id, $groupset['id'], $group['id'], checked( $selected, true, false ), esc_attr( $group['id'] ), esc_attr( $group['name'] ) ); } } $output .= '</div>'; $output .= '</div>'; return $output; } /** * Provider account list fields HTML. * * @since 1.0.0 * * @param string $connection_id * @param array $connection * @param mixed $form * * @return WP_Error|string */ public function output_fields( $connection_id = '', $connection = array(), $form = '' ) { if ( empty( $connection_id ) || empty( $connection['account_id'] ) || empty( $connection['list_id'] ) || empty( $form ) ) { return ''; } $provider_fields = $this->api_fields( $connection_id, $connection['account_id'], $connection['list_id'] ); $form_fields = $this->get_form_fields( $form ); if ( is_wp_error( $provider_fields ) ) { return $provider_fields; } $output = '<div class="wpforms-provider-fields wpforms-connection-block">'; $output .= sprintf( '<h4>%s</h4>', esc_html__( 'List Fields', 'wpforms-lite' ) ); // Table with all the fields. $output .= '<table>'; $output .= sprintf( '<thead><tr><th>%s</th><th>%s</th></thead>', esc_html__( 'List Fields', 'wpforms-lite' ), esc_html__( 'Available Form Fields', 'wpforms-lite' ) ); $output .= '<tbody>'; foreach ( $provider_fields as $provider_field ) : $output .= '<tr>'; $output .= '<td>'; $output .= esc_html( $provider_field['name'] ); if ( ! empty( $provider_field['req'] ) && $provider_field['req'] == '1' ) { $output .= '<span class="required">*</span>'; } $output .= '<td>'; $output .= sprintf( '<select name="providers[%s][%s][fields][%s]">', $this->slug, $connection_id, esc_attr( $provider_field['tag'] ) ); $output .= '<option value=""></option>'; $options = $this->get_form_field_select( $form_fields, $provider_field['field_type'] ); foreach ( $options as $option ) { $value = sprintf( '%d.%s.%s', $option['id'], $option['key'], $option['provider_type'] ); $selected = ! empty( $connection['fields'][ $provider_field['tag'] ] ) ? selected( $connection['fields'][ $provider_field['tag'] ], $value, false ) : ''; $output .= sprintf( '<option value="%s" %s>%s</option>', esc_attr( $value ), $selected, esc_html( $option['label'] ) ); } $output .= '</select>'; $output .= '</td>'; $output .= '</tr>'; endforeach; $output .= '</tbody>'; $output .= '</table>'; $output .= '</div>'; return $output; } /** * Provider connection conditional options HTML * * @since 1.0.0 * * @param string $connection_id * @param array $connection * @param string|array $form * * @return string */ public function output_conditionals( $connection_id = '', $connection = array(), $form = '' ) { if ( empty( $connection['account_id'] ) ) { return ''; } return wpforms_conditional_logic()->builder_block( array( 'form' => $this->form_data, 'type' => 'panel', 'panel' => $this->slug, 'parent' => 'providers', 'subsection' => $connection_id, 'reference' => esc_html__( 'Marketing provider connection', 'wpforms-lite' ), ), false ); } /** * Provider account list options HTML. * * @since 1.0.0 * * @param string $connection_id * @param array $connection * * @return string */ public function output_options( $connection_id = '', $connection = array() ) { } /******************************************************** * Builder methods - these methods _build_ the Builder. * ********************************************************/ /** * Fetch and store the current form data when in the builder. * * @since 1.2.3 */ public function builder_form_data() { if ( ! empty( $_GET['form_id'] ) && empty( $this->form_data ) ) { $this->form_data = wpforms()->form->get( absint( $_GET['form_id'] ), array( 'content_only' => true, ) ); } } /** * Display content inside the panel content area. * * @since 1.0.0 */ public function builder_content() { $form_data = $this->form_data; $providers = wpforms_get_providers_options(); if ( ! empty( $form_data['providers'][ $this->slug ] ) && ! empty( $providers[ $this->slug ] ) ) { foreach ( $form_data['providers'][ $this->slug ] as $connection_id => $connection ) { foreach ( $providers[ $this->slug ] as $account_id => $connections ) { if ( ! empty( $connection['account_id'] ) && $connection['account_id'] === $account_id ) { echo $this->output_connection( $connection_id, $connection, $form_data ); } } } } } /** * Display content inside the panel sidebar area. * * @since 1.0.0 */ public function builder_sidebar() { $form_data = $this->form_data; $configured = ! empty( $form_data['providers'][ $this->slug ] ) ? 'configured' : ''; $configured = apply_filters( 'wpforms_providers_' . $this->slug . '_configured', $configured ); echo '<a href="#" class="wpforms-panel-sidebar-section icon ' . esc_attr( $configured ) . ' wpforms-panel-sidebar-section-' . esc_attr( $this->slug ) . '" data-section="' . esc_attr( $this->slug ) . '">'; echo '<img src="' . esc_url( $this->icon ) . '">'; echo esc_html( $this->name ); echo '<i class="fa fa-angle-right wpforms-toggle-arrow"></i>'; if ( ! empty( $configured ) ) { echo '<i class="fa fa-check-circle-o"></i>'; } echo '</a>'; } /** * Wrap the builder content with the required markup. * * @since 1.0.0 */ public function builder_output() { ?> <div class="wpforms-panel-content-section wpforms-panel-content-section-<?php echo esc_attr( $this->slug ); ?>" id="<?php echo esc_attr( $this->slug ); ?>-provider"> <?php $this->builder_output_before(); ?> <div class="wpforms-panel-content-section-title"> <?php echo $this->name; ?> <button class="wpforms-provider-connections-add" data-form_id="<?php echo absint( $_GET['form_id'] ); ?>" data-provider="<?php echo esc_attr( $this->slug ); ?>" data-type="<?php echo esc_attr( strtolower( $this->type ) ); ?>"> <?php printf( /* translators: %s - Provider type. */ esc_html__( 'Add New %s', 'wpforms-lite' ), esc_html( $this->type ) ); ?> </button> </div> <div class="wpforms-provider-connections-wrap wpforms-clear"> <div class="wpforms-provider-connections"> <?php $this->builder_content(); ?> </div> </div> <?php $this->builder_output_after(); ?> </div> <?php } /** * Optionally output content before the main builder output. * * @since 1.3.6 */ public function builder_output_before() { } /** * Optionally output content after the main builder output. * * @since 1.3.6 */ public function builder_output_after() { } /************************************************************************* * Integrations tab methods - these methods relate to the settings page. * *************************************************************************/ /** * Form fields to add a new provider account. * * @since 1.0.0 */ public function integrations_tab_new_form() { } /** * AJAX to disconnect a provider from the settings integrations tab. * * @since 1.0.0 */ public function integrations_tab_disconnect() { // Run a security check. check_ajax_referer( 'wpforms-admin', 'nonce' ); // Check for permissions. if ( ! wpforms_current_user_can() ) { wp_send_json_error( array( 'error' => esc_html__( 'You do not have permission', 'wpforms-lite' ), ) ); } if ( empty( $_POST['provider'] ) || empty( $_POST['key'] ) ) { wp_send_json_error( array( 'error' => esc_html__( 'Missing data', 'wpforms-lite' ), ) ); } $providers = wpforms_get_providers_options(); if ( ! empty( $providers[ $_POST['provider'] ][ $_POST['key'] ] ) ) { unset( $providers[ $_POST['provider'] ][ $_POST['key'] ] ); update_option( 'wpforms_providers', $providers ); wp_send_json_success(); } else { wp_send_json_error( array( 'error' => esc_html__( 'Connection missing', 'wpforms-lite' ), ) ); } } /** * AJAX to add a provider from the settings integrations tab. * * @since 1.0.0 */ public function integrations_tab_add() { if ( $_POST['provider'] !== $this->slug ) { //phpcs:ignore return; } // Run a security check. check_ajax_referer( 'wpforms-admin', 'nonce' ); // Check for permissions. if ( ! wpforms_current_user_can() ) { wp_send_json_error( array( 'error' => esc_html__( 'You do not have permission', 'wpforms-lite' ), ) ); } if ( empty( $_POST['data'] ) ) { wp_send_json_error( array( 'error' => esc_html__( 'Missing data', 'wpforms-lite' ), ) ); } $data = wp_parse_args( $_POST['data'], array() ); $auth = $this->api_auth( $data, '' ); if ( is_wp_error( $auth ) ) { wp_send_json_error( array( 'error' => esc_html__( 'Could not connect to the provider.', 'wpforms-lite' ), 'error_msg' => $auth->get_error_message(), ) ); } else { $account = '<li class="wpforms-clear">'; $account .= '<span class="label">' . sanitize_text_field( $data['label'] ) . '</span>'; /* translators: %s - Connection date. */ $account .= '<span class="date">' . sprintf( esc_html__( 'Connected on: %s', 'wpforms-lite' ), date_i18n( get_option( 'date_format', time() ) ) ) . '</span>'; $account .= '<span class="remove"><a href="#" data-provider="' . $this->slug . '" data-key="' . esc_attr( $auth ) . '">' . esc_html__( 'Disconnect', 'wpforms-lite' ) . '</a></span>'; $account .= '</li>'; wp_send_json_success( array( 'html' => $account, ) ); } } /** * Add provider to the Settings Integrations tab. * * @since 1.0.0 * * @param array $active Array of active connections. * @param array $settings Array of all connections settings. */ public function integrations_tab_options( $active, $settings ) { $connected = ! empty( $active[ $this->slug ] ); $accounts = ! empty( $settings[ $this->slug ] ) ? $settings[ $this->slug ] : array(); $class = $connected && $accounts ? 'connected' : ''; $arrow = 'right'; /* translators: %s - provider name. */ $title_connect_to = sprintf( esc_html__( 'Connect to %s', 'wpforms-lite' ), esc_html( $this->name ) ); // This lets us highlight a specific service by a special link. if ( ! empty( $_GET['wpforms-integration'] ) ) { //phpcs:ignore if ( $this->slug === $_GET['wpforms-integration'] ) { //phpcs:ignore $class .= ' focus-in'; $arrow = 'down'; } else { $class .= ' focus-out'; } } ?> <div id="wpforms-integration-<?php echo esc_attr( $this->slug ); ?>" class="wpforms-settings-provider wpforms-clear <?php echo esc_attr( $this->slug ); ?> <?php echo esc_attr( $class ); ?>"> <div class="wpforms-settings-provider-header wpforms-clear" data-provider="<?php echo esc_attr( $this->slug ); ?>"> <div class="wpforms-settings-provider-logo"> <i title="<?php esc_attr_e( 'Show Accounts', 'wpforms-lite' ); ?>" class="fa fa-chevron-<?php echo esc_attr( $arrow ); ?>"></i> <img src="<?php echo esc_url( $this->icon ); ?>"> </div> <div class="wpforms-settings-provider-info"> <h3><?php echo esc_html( $this->name ); ?></h3> <p> <?php /* translators: %s - provider name. */ printf( esc_html__( 'Integrate %s with WPForms', 'wpforms-lite' ), esc_html( $this->name ) ); ?> </p> <span class="connected-indicator green"><i class="fa fa-check-circle-o"></i> <?php esc_html_e( 'Connected', 'wpforms-lite' ); ?></span> </div> </div> <div class="wpforms-settings-provider-accounts" id="provider-<?php echo esc_attr( $this->slug ); ?>"> <div class="wpforms-settings-provider-accounts-list"> <ul> <?php if ( ! empty( $accounts ) ) { foreach ( $accounts as $key => $account ) { echo '<li class="wpforms-clear">'; echo '<span class="label">' . esc_html( $account['label'] ) . '</span>'; /* translators: %s - Connection date. */ echo '<span class="date">' . sprintf( esc_html__( 'Connected on: %s', 'wpforms-lite' ), date_i18n( get_option( 'date_format' ), intval( $account['date'] ) ) ) . '</span>'; echo '<span class="remove"><a href="#" data-provider="' . esc_attr( $this->slug ) . '" data-key="' . esc_attr( $key ) . '">' . esc_html__( 'Disconnect', 'wpforms-lite' ) . '</a></span>'; echo '</li>'; } } ?> </ul> </div> <p class="wpforms-settings-provider-accounts-toggle"> <a class="wpforms-btn wpforms-btn-md wpforms-btn-light-grey" href="#" data-provider="<?php echo esc_attr( $this->slug ); ?>"> <i class="fa fa-plus"></i> <?php esc_html_e( 'Add New Account', 'wpforms-lite' ); ?> </a> </p> <div class="wpforms-settings-provider-accounts-connect"> <form> <p><?php esc_html_e( 'Please fill out all of the fields below to add your new provider account.', 'wpforms-lite' ); ?></span></p> <p class="wpforms-settings-provider-accounts-connect-fields"> <?php $this->integrations_tab_new_form(); ?> </p> <button type="submit" class="wpforms-btn wpforms-btn-md wpforms-btn-orange wpforms-settings-provider-connect" data-provider="<?php echo esc_attr( $this->slug ); ?>" title="<?php echo esc_attr( $title_connect_to ); ?>"> <?php echo esc_html( $title_connect_to ); ?> </button> </form> </div> </div> </div> <?php } /** * Error wrapper for WP_Error. * * @since 1.0.0 * * @param string $message * @param string $parent * * @return WP_Error */ public function error( $message = '', $parent = '0' ) { return new WP_Error( $this->slug . '-error', $message ); } } providers/class-constant-contact.php 0000666 00000072570 15213301444 0013673 0 ustar 00 <?php /** * Constant Contact integration. * * @since 1.3.6 */ class WPForms_Constant_Contact extends WPForms_Provider { /** * Provider access token. * * @since 1.3.6 * @var string */ public $access_token; /** * Provider API key. * * @since 1.3.6 * @var string */ public $api_key = 'c58xq3r27udz59h9rrq7qnvf'; /** * Sign up link. * * @since 1.3.6 * @var string */ public $sign_up = 'https://constant-contact.evyy.net/c/11535/341874/3411?sharedid=wpforms'; /** * Initialize. * * @since 1.3.6 */ public function init() { $this->version = '1.3.6'; $this->name = 'Constant Contact'; $this->slug = 'constant-contact'; $this->priority = 14; $this->icon = WPFORMS_PLUGIN_URL . 'assets/images/icon-provider-constant-contact.png'; if ( is_admin() ) { // Admin notice requesting connecting. add_action( 'admin_notices', array( $this, 'connect_request' ) ); add_action( 'wp_ajax_wpforms_constant_contact_dismiss', array( $this, 'connect_dismiss' ) ); add_action( 'wpforms_admin_page', array( $this, 'learn_more_page' ) ); // Provide option to override sign up link. $sign_up = get_option( 'wpforms_constant_contact_signup', false ); if ( $sign_up ) { $this->sign_up = esc_html( $sign_up ); } } } /** * Process and submit entry to provider. * * @since 1.3.6 * * @param array $fields List of fields with their data and settings. * @param array $entry Submitted entry values. * @param array $form_data Form data and settings. * @param int $entry_id Saved entry ID. * * @return void */ public function process_entry( $fields, $entry, $form_data, $entry_id = 0 ) { // Only run if this form has a connections for this provider. if ( empty( $form_data['providers'][ $this->slug ] ) ) { return; } /* * Fire for each connection. */ foreach ( $form_data['providers'][ $this->slug ] as $connection ) : // Before proceeding make sure required fields are configured. if ( empty( $connection['fields']['email'] ) ) { continue; } // Setup basic data. $list_id = $connection['list_id']; $account_id = $connection['account_id']; $email_data = explode( '.', $connection['fields']['email'] ); $email_id = $email_data[0]; $email = $fields[ $email_id ]['value']; $this->api_connect( $account_id ); // Email is required and Access token are required. if ( empty( $email ) || empty( $this->access_token ) ) { continue; } // Check for conditionals. $pass = $this->process_conditionals( $fields, $entry, $form_data, $connection ); if ( ! $pass ) { wpforms_log( esc_html__( 'Constant Contact Subscription stopped by conditional logic', 'wpforms-lite' ), $fields, array( 'type' => array( 'provider', 'conditional_logic' ), 'parent' => $entry_id, 'form_id' => $form_data['id'], ) ); continue; } // Check to see if the lead already exists in Constant Contact. $response = wp_remote_get( 'https://api.constantcontact.com/v2/contacts?api_key=' . $this->api_key . '&access_token=' . $this->access_token . '&email=' . $email ); $contact = json_decode( wp_remote_retrieve_body( $response ), true ); // Return early if there was a problem. if ( isset( $contact['error_key'] ) ) { wpforms_log( esc_html__( 'Constant Contact API Error', 'wpforms-lite' ), $contact->get_error_message(), array( 'type' => array( 'provider', 'error' ), 'parent' => $entry_id, 'form_id' => $form_data['id'], ) ); continue; } /* * Setup Merge Vars */ $merge_vars = array(); foreach ( $connection['fields'] as $name => $merge_var ) { // Don't include Email or Full name fields. if ( 'email' === $name ) { continue; } // Check if merge var is mapped. if ( empty( $merge_var ) ) { continue; } $merge_var = explode( '.', $merge_var ); $id = $merge_var[0]; $key = ! empty( $merge_var[1] ) ? $merge_var[1] : 'value'; // Check if mapped form field has a value. if ( empty( $fields[ $id ][ $key ] ) ) { continue; } $value = $fields[ $id ][ $key ]; // Constant Contact doesn't native URL field so it has to be // stored in a custom field. if ( 'url' === $name ) { $merge_vars['custom_fields'] = array( array( 'name' => 'custom_field_1', 'value' => $value, ), ); continue; } // Constant Contact stores name in two fields, so we have to // separate it. if ( 'full_name' === $name ) { $names = explode( ' ', $value ); if ( ! empty( $names[0] ) ) { $merge_vars['first_name'] = $names[0]; } if ( ! empty( $names[1] ) ) { $merge_vars['last_name'] = $names[1]; } continue; } // Constant Contact stores address in multiple fields, so we // have to separate it. if ( 'address' === $name ) { // Only support Address fields. if ( 'address' !== $fields[ $id ]['type'] ) { continue; } // Postal code may be in extended US format. $postal = array( 'code' => '', 'subcode' => '', ); if ( ! empty( $fields[ $id ]['postal'] ) ) { $p = explode( '-', $fields[ $id ]['postal'] ); $postal['code'] = ! empty( $p[0] ) ? $p[0] : ''; $postal['subcode'] = ! empty( $p[1] ) ? $p[1] : ''; } $merge_vars['addresses'] = array( array( 'address_type' => 'BUSINESS', 'city' => ! empty( $fields[ $id ]['city'] ) ? $fields[ $id ]['city'] : '', 'country_code' => ! empty( $fields[ $id ]['country'] ) ? $fields[ $id ]['country'] : '', 'line1' => ! empty( $fields[ $id ]['address1'] ) ? $fields[ $id ]['address1'] : '', 'line2' => ! empty( $fields[ $id ]['address2'] ) ? $fields[ $id ]['address2'] : '', 'postal_code' => $postal['code'], 'state' => ! empty( $fields[ $id ]['state'] ) ? $fields[ $id ]['state'] : '', 'sub_postal_code' => $postal['subcode'], ), ); continue; } $merge_vars[ $name ] = $value; } /* * Process in API */ // If we have a previous contact, only update the list association. if ( ! empty( $contact['results'] ) ) { $data = $contact['results'][0]; // Check if they are already assigned to lists. if ( ! empty( $data['lists'] ) ) { foreach ( $data['lists'] as $list ) { // If they are already assigned to this list, return early. if ( isset( $list['id'] ) && $list_id == $list['id'] ) { return; } } // Otherwise, add them to the list. $data['lists'][ count( $data['lists'] ) ] = array( 'id' => $list_id, 'status' => 'ACTIVE', ); } else { // Add the contact to the list. $data['lists'][0] = array( 'id' => $list_id, 'status' => 'ACTIVE', ); } // Combine merge vars into data before sending. $data = array_merge( $data, $merge_vars ); // Args to use. $args = array( 'body' => wp_json_encode( $data ), 'method' => 'PUT', 'headers' => array( 'Content-Type' => 'application/json', ), ); $update = wp_remote_request( 'https://api.constantcontact.com/v2/contacts/' . $data['id'] . '?api_key=' . $this->api_key . '&access_token=' . $this->access_token . '&action_by=ACTION_BY_VISITOR', $args ); $res = json_decode( wp_remote_retrieve_body( $update ), true ); } else { // Add a new contact. $data = array( 'email_addresses' => array( array( 'email_address' => $email ) ), 'lists' => array( array( 'id' => $list_id ) ), ); // Combine merge vars into data before sending. $data = array_merge( $data, $merge_vars ); // Args to use. $args = array( 'body' => wp_json_encode( $data ), 'headers' => array( 'Content-Type' => 'application/json', ), ); $add = wp_remote_post( 'https://api.constantcontact.com/v2/contacts?api_key=' . $this->api_key . '&access_token=' . $this->access_token . '&action_by=ACTION_BY_VISITOR', $args ); $res = json_decode( wp_remote_retrieve_body( $add ), true ); } // Check for errors. if ( isset( $res['error_key'] ) ) { wpforms_log( esc_html__( 'Constant Contact API Error', 'wpforms-lite' ), $res->get_error_message(), array( 'type' => array( 'provider', 'error' ), 'parent' => $entry_id, 'form_id' => $form_data['id'], ) ); } endforeach; } /************************************************************************ * API methods - these methods interact directly with the provider API. * ************************************************************************/ /** * Authenticate with the API. * * @since 1.3.6 * * @param array $data * @param string $form_id * * @return mixed id or error object */ public function api_auth( $data = array(), $form_id = '' ) { $id = uniqid(); $providers = wpforms_get_providers_options(); $providers[ $this->slug ][ $id ] = array( 'access_token' => sanitize_text_field( $data['authcode'] ), 'label' => sanitize_text_field( $data['label'] ), 'date' => time(), ); update_option( 'wpforms_providers', $providers ); return $id; } /** * Establish connection object to API. * * @since 1.3.6 * * @param string $account_id * * @return mixed array or error object. */ public function api_connect( $account_id ) { if ( ! empty( $this->api[ $account_id ] ) ) { return $this->api[ $account_id ]; } else { $providers = wpforms_get_providers_options(); if ( ! empty( $providers[ $this->slug ][ $account_id ] ) ) { $this->api[ $account_id ] = true; $this->access_token = $providers[ $this->slug ][ $account_id ]['access_token']; } else { return $this->error( 'API error' ); } } } /** * Retrieve provider account lists. * * @since 1.3.6 * * @param string $connection_id * @param string $account_id * * @return mixed array or error object */ public function api_lists( $connection_id = '', $account_id = '' ) { $this->api_connect( $account_id ); $request = wp_remote_get( 'https://api.constantcontact.com/v2/lists?api_key=' . $this->api_key . '&access_token=' . $this->access_token ); $lists = json_decode( wp_remote_retrieve_body( $request ), true ); if ( empty( $lists ) ) { wpforms_log( esc_html__( 'Constant Contact API Error', 'wpforms-lite' ), '', array( 'type' => array( 'provider', 'error' ), ) ); return $this->error( esc_html__( 'API list error: Constant API error', 'wpforms-lite' ) ); } return $lists; } /** * Retrieve provider account list fields. * * @since 1.3.6 * * @param string $connection_id * @param string $account_id * @param string $list_id * * @return mixed array or error object */ public function api_fields( $connection_id = '', $account_id = '', $list_id = '' ) { $provider_fields = array( array( 'name' => 'Email', 'field_type' => 'email', 'req' => '1', 'tag' => 'email', ), array( 'name' => 'Full Name', 'field_type' => 'name', 'tag' => 'full_name', ), array( 'name' => 'First Name', 'field_type' => 'first', 'tag' => 'first_name', ), array( 'name' => 'Last Name', 'field_type' => 'last', 'tag' => 'last_name', ), array( 'name' => 'Phone', 'field_type' => 'text', 'tag' => 'work_phone', ), array( 'name' => 'Website', 'field_type' => 'text', 'tag' => 'url', ), array( 'name' => 'Address', 'field_type' => 'address', 'tag' => 'address', ), array( 'name' => 'Job Title', 'field_type' => 'text', 'tag' => 'job_title', ), array( 'name' => 'Company', 'field_type' => 'text', 'tag' => 'company_name', ), ); return $provider_fields; } /************************************************************************* * Output methods - these methods generally return HTML for the builder. * *************************************************************************/ /** * Provider account authorize fields HTML. * * @since 1.3.6 * @return string */ public function output_auth() { $providers = wpforms_get_providers_options(); $class = ! empty( $providers[ $this->slug ] ) ? 'hidden' : ''; $output = '<div class="wpforms-provider-account-add ' . $class . ' wpforms-connection-block">'; $output .= sprintf( '<h4>%s</h4>', esc_html__( 'Add New Account', 'wpforms-lite' ) ); $output .= '<p>'; $output .= esc_html__( 'Please fill out all of the fields below to register your new Constant Contact account.', 'wpforms-lite' ); $output .= '<br><a href="https://wpforms.com/docs/how-to-connect-constant-contact-with-wpforms/" target="_blank" rel="noopener noreferrer">'; $output .= esc_html__( 'Click here for documentation on connecting WPForms with Constant Contact.', 'wpforms-lite' ); $output .= '</a>'; $output .= '</p>'; $output .= '<p class="wpforms-alert wpforms-alert-warning">'; $output .= esc_html__( 'Because Constant Contact requires external authentication, you will need to register WPForms with Constant Contact before you can proceed.', 'wpforms-lite' ); $output .= '</p>'; $output .= '<p class=""><strong><a onclick="window.open(this.href,\'\',\'resizable=yes,location=no,width=750,height=500,status\'); return false" href="https://oauth2.constantcontact.com/oauth2/oauth/siteowner/authorize?response_type=code&client_id=c58xq3r27udz59h9rrq7qnvf&redirect_uri=https://wpforms.com/oauth/constant-contact/" class="btn">'; $output .= esc_html__( 'Click here to register with Constant Contact', 'wpforms-lite' ); $output .= '</a></strong></p>'; $output .= sprintf( '<input type="text" data-name="authcode" placeholder="%s %s" class="wpforms-required">', $this->name, esc_html__( 'Authorization Code', 'wpforms-lite' ) ); $output .= sprintf( '<input type="text" data-name="label" placeholder="%s %s" class="wpforms-required">', $this->name, esc_html__( 'Account Nickname', 'wpforms-lite' ) ); $output .= sprintf( '<button data-provider="%s">%s</button>', $this->slug, esc_html__( 'Connect', 'wpforms-lite' ) ); $output .= '</div>'; return $output; } /** * Provider account list groups HTML. * * @since 1.3.6 * * @param string $connection_id * @param array $connection * * @return string */ public function output_groups( $connection_id = '', $connection = array() ) { // No groups or segments for this provider. return ''; } /** * Output content after the main builder output. * * @since 1.3.6 */ public function builder_output_after() { // Only display if Constant Contact account has not been setup. $providers = wpforms_get_providers_options(); if ( ! empty( $providers[ $this->slug ] ) ) { return; } ?> <div class="wpforms-alert wpforms-alert-info"> <p> <?php echo wp_kses( __( 'Get the most out of <strong>WPForms</strong> — use it with an active Constant Contact account.', 'wpforms-lite' ), array( 'strong' => array(), ) ); ?> </p> <p> <a href="<?php echo esc_url( $this->sign_up ); ?>" style="margin-right: 10px;" class="button-primary" target="_blank" rel="noopener noreferrer"> <?php esc_html_e( 'Try Constant Contact for Free', 'wpforms-lite' ); ?> </a> <?php printf( wp_kses( /* translators: %s - WPForms Constant Contact internal URL. */ __( 'Learn More about the <a href="%s" target="_blank" rel="noopener noreferrer">power of email marketing</a>', 'wpforms-lite' ), array( 'a' => array( 'href' => array(), 'target' => array(), 'rel' => array(), ), ) ), esc_url( admin_url( 'admin.php?page=wpforms-page&wpforms-page=constant-contact' ) ) ); ?> </p> </div> <?php } /************************************************************************* * Integrations tab methods - these methods relate to the settings page. * *************************************************************************/ /** * Form fields to add a new provider account. * * @since 1.3.6 */ public function integrations_tab_new_form() { $output = '<p>'; $output .= '<a href="https://wpforms.com/docs/how-to-connect-constant-contact-with-wpforms/" target="_blank" rel="noopener noreferrer">'; $output .= esc_html__( 'Click here for documentation on connecting WPForms with Constant Contact.', 'wpforms-lite' ); $output .= '</a>'; $output .= '</p>'; $output .= '<p class="wpforms-alert wpforms-alert-warning">'; $output .= esc_html__( 'Because Constant Contact requires external authentication, you will need to register WPForms with Constant Contact before you can proceed.', 'wpforms-lite' ); $output .= '</p>'; $output .= '<p class=""><strong><a onclick="window.open(this.href,\'\',\'resizable=yes,location=no,width=800,height=600,status\'); return false" href="https://oauth2.constantcontact.com/oauth2/oauth/siteowner/authorize?response_type=code&client_id=c58xq3r27udz59h9rrq7qnvf&redirect_uri=https://wpforms.com/oauth/constant-contact/" class="btn">'; $output .= esc_html__( 'Click here to register with Constant Contact', 'wpforms-lite' ); $output .= '</a></strong></p>'; $output .= sprintf( '<input type="text" name="authcode" placeholder="%s %s" class="wpforms-required">', $this->name, esc_html__( 'Authorization Code', 'wpforms-lite' ) ); $output .= sprintf( '<input type="text" name="label" placeholder="%s %s" class="wpforms-required">', $this->name, esc_html__( 'Account Nickname', 'wpforms-lite' ) ); echo $output; } /************************ * Other functionality. * ************************/ /** * Add admin notices to connect to Constant Contact. * * @since 1.3.6 */ public function connect_request() { // Only consider showing the review request to admin users. if ( ! is_super_admin() ) { return; } // Don't display on WPForms admin content pages. if ( ! empty( $_GET['wpforms-page'] ) ) { return; } // Don't display if user is about to connect via Settings page. if ( ! empty( $_GET['wpforms-integration'] ) && $this->slug === $_GET['wpforms-integration'] ) { return; } // Only display the notice is the Constant Contact option is set and // there are previous Constant Contact connections created. $cc_notice = get_option( 'wpforms_constant_contact', false ); $providers = wpforms_get_providers_options(); if ( ! $cc_notice || ! empty( $providers[ $this->slug ] ) ) { return; } // Output the notice message. $connect = admin_url( 'admin.php?page=wpforms-settings&wpforms-integration=constant-contact#!wpforms-tab-providers' ); $learn_more = admin_url( 'admin.php?page=wpforms-page&wpforms-page=constant-contact' ); ?> <div class="notice notice-info is-dismissible wpforms-constant-contact-notice"> <p> <?php echo wp_kses( __( 'Get the most out of the <strong>WPForms</strong> plugin — use it with an active Constant Contact account.', 'wpforms-lite' ), array( 'strong' => array(), ) ); ?> </p> <p> <a href="<?php echo esc_url( $this->sign_up ); ?>" class="button-primary" target="_blank" rel="noopener noreferrer"> <?php esc_html_e( 'Try Constant Contact for Free', 'wpforms-lite' ); ?> </a> <a href="<?php echo esc_url( $connect ); ?>" class="button-secondary"> <?php esc_html_e( 'Connect your existing account', 'wpforms-lite' ); ?> </a> <?php printf( wp_kses( /* translators: %s - WPForms Constant Contact internal URL. */ __( 'Learn More about the <a href="%s">power of email marketing</a>', 'wpforms-lite' ), array( 'a' => array( 'href' => array(), ), ) ), esc_url( $learn_more ) ); ?> </p> </div> <style type="text/css"> .wpforms-constant-contact-notice { border-left-color: #1a5285; } .wpforms-constant-contact-notice p:first-of-type { margin: 16px 0 8px; } .wpforms-constant-contact-notice p:last-of-type { margin: 8px 0 16px; } .wpforms-constant-contact-notice .button-primary, .wpforms-constant-contact-notice .button-secondary { display: inline-block; margin: 0 10px 0 0; } </style> <script type="text/javascript"> jQuery( function ( $ ) { $( document ).on( 'click', '.wpforms-constant-contact-notice button', function ( event ) { event.preventDefault(); $.post( ajaxurl, { action: 'wpforms_constant_contact_dismiss' } ); $( '.wpforms-constant-contact-notice' ).remove(); } ); } ); </script> <?php } /** * Dismiss the Constant Contact admin notice. * * @since 1.3.6 */ public function connect_dismiss() { delete_option( 'wpforms_constant_contact' ); wp_send_json_success(); } /** * Constant Contact "Learn More" admin page. * * @since 1.3.6 */ public function learn_more_page() { if ( empty( $_GET['page'] ) || empty( $_GET['wpforms-page'] ) || 'wpforms-page' !== $_GET['page'] || 'constant-contact' !== $_GET['wpforms-page'] ) { return; } $more = 'http://www.wpbeginner.com/beginners-guide/why-you-should-start-building-your-email-list-right-away'; ?> <div class="wrap about-wrap"> <h1><?php esc_html_e( 'Grow Your Website with WPForms + Email Marketing', 'wpforms-lite' ); ?></h1> <p><?php esc_html_e( 'Wondering if email marketing is really worth your time?', 'wpforms-lite' ); ?></p> <p><?php echo wp_kses( __( 'Email is hands-down the most effective way to nurture leads and turn them into customers, with a return on investment (ROI) of <strong>$44 back for every $1 spent</strong> according to DMA.', 'wpforms-lite' ), array( 'strong' => array() ) ); ?></p> <p><?php esc_html_e( 'Here are 3 big reasons why every smart business in the world has an email list:', 'wpforms-lite' ); ?></p> <a href="<?php echo esc_url( $this->sign_up ); ?>" target="_blank" rel="noopener noreferrer"> <img src="<?php echo WPFORMS_PLUGIN_URL; ?>assets/images/cc-about-logo.png" class="logo"> </a> <ol class="reasons"> <li><?php echo wp_kses( __( '<strong>Email is still #1</strong> - At least 91% of consumers check their email on a daily basis. You get direct access to your subscribers, without having to play by social media's rules and algorithms.', 'wpforms-lite' ), array( 'strong' => array() ) ); ?></li> <li><?php echo wp_kses( __( '<strong>You own your email list</strong> - Unlike with social media, your list is your property and no one can revoke your access to it.', 'wpforms-lite' ), array( 'strong' => array() ) ); ?></li> <li><?php echo wp_kses( __( '<strong>Email converts</strong> - People who buy products marketed through email spend 138% more than those who don't receive email offers.', 'wpforms-lite' ), array( 'strong' => array() ) ); ?></li> </ol> <p><?php esc_html_e( 'That's why it's crucial to start collecting email addresses and building your list as soon as possible.', 'wpforms-lite' ); ?></p> <p> <?php printf( wp_kses( /* translators: %s - WPBeginners.com Guide to Email Lists URL. */ __( 'For more details, see this guide on <a href="%s" target="_blank" rel="noopener noreferrer">why building your email list is so important</a>.', 'wpforms-lite' ), array( 'a' => array( 'href' => array(), 'target' => array(), 'rel' => array(), ), ) ), $more ); ?> </p> <hr/> <h2><?php esc_html_e( 'You've Already Started - Here's the Next Step (It's Easy)', 'wpforms-lite' ); ?></h2> <p><?php esc_html_e( 'Here are the 3 things you need to build an email list:', 'wpforms-lite' ); ?></p> <ol> <li><?php esc_html_e( 'A Website or Blog', 'wpforms-lite' ); ?> <span class="dashicons dashicons-yes"></span></li> <li><?php esc_html_e( 'High-Converting Form Builder', 'wpforms-lite' ); ?> <span class="dashicons dashicons-yes"></span></li> <li><strong><?php esc_html_e( 'The Best Email Marketing Service', 'wpforms-lite' ); ?></strong></li> </ol> <p><?php esc_html_e( 'With a powerful email marketing service like Constant Contact, you can instantly send out mass notifications and beautifully designed newsletters to engage your subscribers.', 'wpforms-lite' ); ?></p> <p> <a href="<?php echo esc_url( $this->sign_up ); ?>" class="button" target="_blank" rel="noopener noreferrer"> <?php esc_html_e( 'Get Started with Constant Contact for Free', 'wpforms-lite' ); ?> </a> </p> <p><?php esc_html_e( 'WPForms plugin makes it fast and easy to capture all kinds of visitor information right from your WordPress site - even if you don't have a Constant Contact account.', 'wpforms-lite' ); ?></p> <p><?php esc_html_e( 'But when you combine WPForms with Constant Contact, you can nurture your contacts and engage with them even after they leave your website. When you use Constant Contact + WPForms together, you can:', 'wpforms-lite' ); ?></p> <ul> <li><?php esc_html_e( 'Seamlessly add new contacts to your email list', 'wpforms-lite' ); ?></li> <li><?php esc_html_e( 'Create and send professional email newsletters', 'wpforms-lite' ); ?></li> <li><?php esc_html_e( 'Get expert marketing and support', 'wpforms-lite' ); ?></li> </ul> <p> <a href="<?php echo esc_url( $this->sign_up ); ?>" target="_blank" rel="noopener noreferrer"> <strong><?php esc_html_e( 'Try Constant Contact Today', 'wpforms-lite' ); ?></strong> </a> </p> <hr/> <h2><?php esc_html_e( 'WPForms Makes List Building Easy', 'wpforms-lite' ); ?></h2> <p><?php esc_html_e( 'When creating WPForms, our goal was to make a WordPress forms plugin that's both EASY and POWERFUL.', 'wpforms-lite' ); ?></p> <p><?php esc_html_e( 'We made the form creation process extremely intuitive, so you can create a form to start capturing emails within 5 minutes or less.', 'wpforms-lite' ); ?></p> <p><?php esc_html_e( 'Here's how it works.', 'wpforms-lite' ); ?></p> <div class="steps"> <div class="step1 step"> <img src="<?php echo WPFORMS_PLUGIN_URL; ?>assets/images/cc-about-step1.png"> <p><?php esc_html_e( '1. Select from our pre-built templates, or create a form from scratch.', 'wpforms-lite' ); ?></p> </div> <div class="step2 step"> <img src="<?php echo WPFORMS_PLUGIN_URL; ?>assets/images/cc-about-step2.png"> <p><?php esc_html_e( '2. Drag and drop any field you want onto your signup form.', 'wpforms-lite' ); ?></p> </div> <div class="step3 step"> <img src="<?php echo WPFORMS_PLUGIN_URL; ?>assets/images/cc-about-step3.png"> <p><?php esc_html_e( '3. Connect your Constant Contact email list.', 'wpforms-lite' ); ?></p> </div> <div class="step4 step"> <img src="<?php echo WPFORMS_PLUGIN_URL; ?>assets/images/cc-about-step4.png"> <p><?php esc_html_e( '4. Add your new form to any post, page, or sidebar.', 'wpforms-lite' ); ?></p> </div> </div> <p><?php esc_html_e( 'It doesn't matter what kind of business you run, what kind of website you have, or what industry you are in - you need to start building your email list today.', 'wpforms-lite' ); ?></p> <p><?php esc_html_e( 'With Constant Contact + WPForms, growing your list is easy.', 'wpforms-lite' ); ?></p> </div> <style type="text/css"> .notice { display: none; } .about-wrap { padding: 15px; max-width: 970px; } .about-wrap h1 { color: #1a5285; font-size: 30px; margin: 0 0 15px 0; } .about-wrap h2 { color: #1a5285; font-size: 26px; margin: 0 0 15px 0; text-align: left; } .about-wrap p { font-size: 16px; font-weight: 300; color: #333; margin: 1.2em 0; } .about-wrap ul, .about-wrap ol { margin: 1.6em 2.5em 2em; line-height: 1.5; font-size: 16px; font-weight: 300; } .about-wrap ul { list-style: disc; } .about-wrap li { margin-bottom: 0.8em; } .about-wrap hr { margin: 2.2em 0; } .about-wrap .logo { float: right; margin-top: 0.8em; width: auto; } .about-wrap .reasons { margin: 2.2em 400px 2.2em 2em; } .about-wrap .reasons li { margin-bottom: 1.4em; } .about-wrap .steps { clear: both; overflow: hidden; } .about-wrap .step { width: 46%; float: left; } .about-wrap .step { margin-bottom: 1.4em; } .about-wrap .step2, .about-wrap .step4 { float: right; } .about-wrap .step3 { clear: both; } .about-wrap .dashicons-yes { color: #19BE19; font-size: 26px; } .about-wrap .button { background-color: #0078C3; border: 1px solid #005990; border-radius: 4px; color: #fff; font-size: 16px; font-weight: 600; height: auto; line-height: 1; margin-bottom: 10px; padding: 14px 30px; text-align: center; } .about-wrap .button:hover, .about-wrap .button:focus { background-color: #005990; color: #fff } @media only screen and (max-width: 767px) { .about-wrap { padding: 0; } .about-wrap h1 { font-size: 26px; } .about-wrap h2 { font-size: 22px; } .about-wrap p { font-size: 14px; } .about-wrap ul, .about-wrap ol { font-size: 14px; } .about-wrap .logo { width: 120px; } .about-wrap .reasons { margin-right: 150px; } } </style> <?php } } new WPForms_Constant_Contact; integrations.php 0000666 00000005661 15213301445 0007775 0 ustar 00 <?php /** * Register and setup WPForms as a Visual Composer element. * * @since 1.3.0 */ function wpforms_visual_composer_shortcode() { if ( ! is_user_logged_in() ) { return; } $wpf = wpforms()->form->get( '', array( 'orderby' => 'title', ) ); if ( ! empty( $wpf ) ) { $forms = array( esc_html__( 'Select a form to display', 'wpforms-lite' ) => '', ); foreach ( $wpf as $form ) { $forms[ $form->post_title ] = $form->ID; } } else { $forms = array( esc_html__( 'No forms found', 'wpforms-lite' ) => '', ); } vc_map( array( 'name' => esc_html__( 'WPForms', 'wpforms-lite' ), 'base' => 'wpforms', 'icon' => WPFORMS_PLUGIN_URL . 'assets/images/sullie-vc.png', 'category' => esc_html__( 'Content', 'wpforms-lite' ), 'description' => esc_html__( 'Add your form', 'wpforms-lite' ), 'params' => array( array( 'type' => 'dropdown', 'heading' => esc_html__( 'Form', 'wpforms-lite' ), 'param_name' => 'id', 'value' => $forms, 'save_always' => true, 'description' => esc_html__( 'Select a form to add it to your post or page.', 'wpforms-lite' ), 'admin_label' => true, ), array( 'type' => 'dropdown', 'heading' => esc_html__( 'Display Form Name', 'wpforms-lite' ), 'param_name' => 'title', 'value' => array( esc_html__( 'No', 'wpforms-lite' ) => 'false', esc_html__( 'Yes', 'wpforms-lite' ) => 'true', ), 'save_always' => true, 'description' => esc_html__( 'Would you like to display the forms name?', 'wpforms-lite' ), 'dependency' => array( 'element' => 'id', 'not_empty' => true, ), ), array( 'type' => 'dropdown', 'heading' => esc_html__( 'Display Form Description', 'wpforms-lite' ), 'param_name' => 'description', 'value' => array( esc_html__( 'No', 'wpforms-lite' ) => 'false', esc_html__( 'Yes', 'wpforms-lite' ) => 'true', ), 'save_always' => true, 'description' => esc_html__( 'Would you like to display the form description?', 'wpforms-lite' ), 'dependency' => array( 'element' => 'id', 'not_empty' => true, ), ), ), ) ); } add_action( 'vc_before_init', 'wpforms_visual_composer_shortcode' ); /** * Load our basic CSS when in Visual Composer's frontend editor. * * @since 1.3.0 */ function wpforms_visual_composer_shortcode_css() { // Load CSS per global setting. if ( wpforms_setting( 'disable-css', '1' ) === '1' ) { wp_enqueue_style( 'wpforms-full', WPFORMS_PLUGIN_URL . 'assets/css/wpforms-full.css', array(), WPFORMS_VERSION ); } if ( wpforms_setting( 'disable-css', '1' ) === '2' ) { wp_enqueue_style( 'wpforms-base', WPFORMS_PLUGIN_URL . 'assets/css/wpforms-base.css', array(), WPFORMS_VERSION ); } } add_action( 'vc_load_iframe_jscss', 'wpforms_visual_composer_shortcode_css' ); deprecated.php 0000666 00000001021 15213301445 0007351 0 ustar 00 <?php /** * To be compatible with both WP 4.9 (that can run on PHP 5.2+) and WP 5.3+ (PHP 5.6+) * we need to rewrite some core WP classes and tweak our own skins to not use PHP 5.6 splat operator (...$args) * that were introduced in WP 5.3 in \WP_Upgrader_Skin::feedback(). * This alias is a safeguard to those developers who decided to use our internal class WPForms_Install_Silent_Skin, * which we deleted. * * @since 1.5.6.1 */ class_alias( 'WPForms\Helpers\PluginSilentUpgraderSkin', 'WPForms_Install_Silent_Skin' ); class-providers.php 0000666 00000001646 15213301445 0010406 0 ustar 00 <?php /** * Load the providers. * * @since 1.3.6 */ class WPForms_Providers { /** * Primary class constructor. * * @since 1.3.6 */ public function __construct() { $this->init(); } /** * Load and init the base provider class. * * @since 1.3.6 */ public function init() { // Parent class template. require_once WPFORMS_PLUGIN_DIR . 'includes/providers/class-base.php'; // Load default templates on WP init. add_action( 'wpforms_loaded', array( $this, 'load' ) ); } /** * Load default marketing providers. * * @since 1.3.6 */ public function load() { $providers = array( 'constant-contact', ); $providers = apply_filters( 'wpforms_load_providers', $providers ); foreach ( $providers as $provider ) { $provider = sanitize_file_name( $provider ); require_once WPFORMS_PLUGIN_DIR . 'includes/providers/class-' . $provider . '.php'; } } } new WPForms_Providers; functions.php 0000666 00000165164 15213301445 0007304 0 ustar 00 <?php /** * Helper function to trigger displaying a form. * * @since 1.0.2 * * @param mixed $form_id Form ID. * @param bool $title Form title. * @param bool $desc Form description. */ function wpforms_display( $form_id = false, $title = false, $desc = false ) { wpforms()->frontend->output( $form_id, $title, $desc ); } /** * Perform json_decode and unslash. * * @since 1.0.0 * * @param string $data Data to decode. * * @return array|bool */ function wpforms_decode( $data ) { if ( ! $data || empty( $data ) ) { return false; } return wp_unslash( json_decode( $data, true ) ); } /** * Perform json_encode and wp_slash. * * @since 1.3.1.3 * * @param mixed $data Data to encode. * * @return string */ function wpforms_encode( $data = false ) { if ( empty( $data ) ) { return false; } return wp_slash( wp_json_encode( $data ) ); } /** * Check if a string is a valid URL. * * @since 1.0.0 * @since 1.5.8 Changed the pattern used to validate the URL. * * @param string $url Input URL. * * @return bool */ function wpforms_is_url( $url ) { // The pattern taken from https://gist.github.com/dperini/729294. // It is the best choice according to the https://mathiasbynens.be/demo/url-regex. $pattern = '%^(?:(?:(?:https?|ftp):)?\/\/)(?:\S+(?::\S*)?@)?(?:(?!(?:10|127)(?:\.\d{1,3}){3})(?!(?:169\.254|192\.168)(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z0-9\x{00a1}-\x{ffff}][a-z0-9\x{00a1}-\x{ffff}_-]{0,62})?[a-z0-9\x{00a1}-\x{ffff}]\.)+(?:[a-z\x{00a1}-\x{ffff}]{2,}\.?))(?::\d{2,5})?(?:[/?#]\S*)?$%iu'; if ( preg_match( $pattern, trim( $url ) ) ) { return true; } return false; } /** * Get the current URL. * * @since 1.0.0 * * @return string */ function wpforms_current_url() { $url = ( ! empty( $_SERVER['HTTPS'] ) ) ? 'https://' . $_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI'] : 'http://' . $_SERVER['SERVER_NAME'] . $_SERVER['REQUEST_URI']; return esc_url_raw( $url ); } /** * Convert object to an array. * * @since 1.1.7 * * @param object $object Object to convert. * * @return mixed */ function wpforms_object_to_array( $object ) { if ( ! is_object( $object ) && ! is_array( $object ) ) { return $object; } if ( is_object( $object ) ) { $object = get_object_vars( $object ); } return array_map( 'wpforms_object_to_array', $object ); } /** * Get the value of a specific WPForms setting. * * @since 1.0.0 * * @param string $key * @param mixed $default * @param string $option * * @return mixed */ function wpforms_setting( $key, $default = false, $option = 'wpforms_settings' ) { $key = wpforms_sanitize_key( $key ); $options = get_option( $option, false ); $value = is_array( $options ) && ! empty( $options[ $key ] ) ? wp_unslash( $options[ $key ] ) : $default; return $value; } /** * Sanitize key, primarily used for looking up options. * * @since 1.3.9 * * @param string $key * * @return string */ function wpforms_sanitize_key( $key = '' ) { return preg_replace( '/[^a-zA-Z0-9_\-\.\:\/]/', '', $key ); } /** * Check if form provided contains the specified field type. * * @since 1.0.5 * * @param array|string $type * @param array|object $form * @param bool $multiple * * @return bool */ function wpforms_has_field_type( $type, $form, $multiple = false ) { $form_data = ''; $field = false; $type = (array) $type; if ( $multiple ) { foreach ( $form as $single_form ) { $field = wpforms_has_field_type( $type, $single_form ); if ( $field ) { break; } } return $field; } if ( is_object( $form ) && ! empty( $form->post_content ) ) { $form_data = wpforms_decode( $form->post_content ); } elseif ( is_array( $form ) ) { $form_data = $form; } if ( empty( $form_data['fields'] ) ) { return false; } foreach ( $form_data['fields'] as $single_field ) { if ( in_array( $single_field['type'], $type, true ) ) { $field = true; break; } } return $field; } /** * Check if form provided contains a field which a specific setting. * * @since 1.4.5 * * @param string $setting * @param object|array $form * @param bool $multiple * * @return bool */ function wpforms_has_field_setting( $setting, $form, $multiple = false ) { $form_data = ''; $field = false; if ( $multiple ) { foreach ( $form as $single_form ) { $field = wpforms_has_field_setting( $setting, $single_form ); if ( $field ) { break; } } return $field; } if ( is_object( $form ) && ! empty( $form->post_content ) ) { $form_data = wpforms_decode( $form->post_content ); } elseif ( is_array( $form ) ) { $form_data = $form; } if ( empty( $form_data['fields'] ) ) { return false; } foreach ( $form_data['fields'] as $single_field ) { if ( ! empty( $single_field[ $setting ] ) ) { $field = true; break; } } return $field; } /** * Check if form provided contains page breaks, if so give details. * * @since 1.0.0 * * @param mixed $form * * @return mixed */ function wpforms_has_pagebreak( $form = false ) { $form_data = ''; $pagebreak = false; $pages = 1; if ( is_object( $form ) && ! empty( $form->post_content ) ) { $form_data = wpforms_decode( $form->post_content ); } elseif ( is_array( $form ) ) { $form_data = $form; } if ( empty( $form_data['fields'] ) ) { return false; } $fields = $form_data['fields']; foreach ( $fields as $field ) { if ( 'pagebreak' === $field['type'] && empty( $field['position'] ) ) { $pagebreak = true; $pages ++; } } if ( $pagebreak ) { return $pages; } return false; } /** * Try to find and return a top or bottom pagebreak. * * @since 1.2.1 * * @param mixed $form * @param mixed $type * * @return array|bool */ function wpforms_get_pagebreak( $form = false, $type = false ) { $form_data = ''; if ( is_object( $form ) && ! empty( $form->post_content ) ) { $form_data = wpforms_decode( $form->post_content ); } elseif ( is_array( $form ) ) { $form_data = $form; } if ( empty( $form_data['fields'] ) ) { return false; } $fields = $form_data['fields']; $pages = array(); foreach ( $fields as $field ) { if ( 'pagebreak' === $field['type'] ) { $position = ! empty( $field['position'] ) ? $field['position'] : false; if ( 'pages' === $type && 'bottom' !== $position ) { $pages[] = $field; } elseif ( $position === $type ) { return $field; } } } if ( ! empty( $pages ) ) { return $pages; } return false; } /** * Return information about pages if the form has multiple pages. * * @since 1.3.7 * * @param mixed $form * * @return mixed false or an array */ function wpforms_get_pagebreak_details( $form = false ) { $form_data = ''; $details = array(); $pages = 1; if ( is_object( $form ) && ! empty( $form->post_content ) ) { $form_data = wpforms_decode( $form->post_content ); } elseif ( is_array( $form ) ) { $form_data = $form; } if ( empty( $form_data['fields'] ) ) { return false; } foreach ( $form_data['fields'] as $field ) { if ( 'pagebreak' === $field['type'] ) { if ( empty( $field['position'] ) ) { $pages ++; $details['total'] = $pages; $details['pages'][] = $field; } elseif ( 'top' === $field['position'] ) { $details['top'] = $field; } elseif ( 'bottom' === $field['position'] ) { $details['bottom'] = $field; } } } if ( ! empty( $details ) ) { if ( empty( $details['top'] ) ) { $details['top'] = array(); } if ( empty( $details['bottom'] ) ) { $details['bottom'] = array(); } $details['current'] = 1; return $details; } return false; } /** * Format, sanitize, and return/echo HTML element ID, classes, attributes, * and data attributes. * * @since 1.3.7 * * @param string $id * @param array $class * @param array $datas * @param array $atts * @param bool $echo * * @return string */ function wpforms_html_attributes( $id = '', $class = array(), $datas = array(), $atts = array(), $echo = false ) { $id = trim( $id ); $parts = array(); if ( ! empty( $id ) ) { $id = sanitize_html_class( $id ); if ( ! empty( $id ) ) { $parts[] = 'id="' . $id . '"'; } } if ( ! empty( $class ) ) { $class = wpforms_sanitize_classes( $class, true ); if ( ! empty( $class ) ) { $parts[] = 'class="' . $class . '"'; } } if ( ! empty( $datas ) ) { foreach ( $datas as $data => $val ) { $parts[] = 'data-' . sanitize_html_class( $data ) . '="' . esc_attr( $val ) . '"'; } } if ( ! empty( $atts ) ) { foreach ( $atts as $att => $val ) { if ( '0' == $val || ! empty( $val ) ) { if ( '[' === $att[0] ) { // Handle special case for bound attributes in AMP. $escaped_att = '[' . sanitize_html_class( trim( $att, '[]' ) ) . ']'; } else { $escaped_att = sanitize_html_class( $att ); } $parts[] = $escaped_att . '="' . esc_attr( $val ) . '"'; } } } $output = implode( ' ', $parts ); if ( $echo ) { echo trim( $output ); // phpcs:ignore } else { return trim( $output ); } } /** * Sanitize string of CSS classes. * * @since 1.2.1 * * @param array|string $classes * @param bool $convert True will convert strings to array and vice versa. * * @return string|array */ function wpforms_sanitize_classes( $classes, $convert = false ) { $array = is_array( $classes ); $css = array(); if ( ! empty( $classes ) ) { if ( ! $array ) { $classes = explode( ' ', trim( $classes ) ); } foreach ( $classes as $class ) { if ( ! empty( $class ) ) { $css[] = sanitize_html_class( $class ); } } } if ( $array ) { return $convert ? implode( ' ', $css ) : $css; } return $convert ? $css : implode( ' ', $css ); } /** * Convert a file size provided, such as "2M", to bytes. * * @link http://stackoverflow.com/a/22500394 * * @since 1.0.0 * * @param string $size * * @return int */ function wpforms_size_to_bytes( $size ) { if ( is_numeric( $size ) ) { return $size; } $suffix = substr( $size, - 1 ); $value = substr( $size, 0, - 1 ); switch ( strtoupper( $suffix ) ) { case 'P': $value *= 1024; case 'T': $value *= 1024; case 'G': $value *= 1024; case 'M': $value *= 1024; case 'K': $value *= 1024; break; } return $value; } /** * Convert bytes to megabytes (or in some cases KB). * * @since 1.0.0 * * @param int $bytes Bytes to convert to a readable format. * * @return string */ function wpforms_size_to_megabytes( $bytes ) { if ( $bytes < 1048676 ) { return number_format( $bytes / 1024, 1 ) . ' KB'; } return round( number_format( $bytes / 1048576, 1 ) ) . ' MB'; } /** * Convert a file size provided, such as "2M", to bytes. * * @link http://stackoverflow.com/a/22500394 * * @since 1.0.0 * * @param bool $bytes * * @return mixed */ function wpforms_max_upload( $bytes = false ) { $max = wp_max_upload_size(); if ( $bytes ) { return $max; } return wpforms_size_to_megabytes( $max ); } /** * Retrieve actual fields from a form. * * Non-posting elements such as section divider, page break, and HTML are * automatically excluded. Optionally a white list can be provided. * * @since 1.0.0 * * @param mixed $form * @param array $whitelist * * @return mixed boolean or array */ function wpforms_get_form_fields( $form = false, $whitelist = array() ) { // Accept form (post) object or form ID. if ( is_object( $form ) ) { $form = wpforms_decode( $form->post_content ); } elseif ( is_numeric( $form ) ) { $form = wpforms()->form->get( $form, array( 'content_only' => true, ) ); } if ( ! is_array( $form ) || empty( $form['fields'] ) ) { return false; } // White list of field types to allow. $allowed_form_fields = array( 'text', 'textarea', 'number-slider', 'select', 'radio', 'checkbox', 'gdpr-checkbox', 'email', 'address', 'url', 'name', 'hidden', 'date-time', 'phone', 'number', 'file-upload', 'rating', 'likert_scale', 'signature', 'payment-single', 'payment-multiple', 'payment-checkbox', 'payment-select', 'payment-total', 'net_promoter_score', ); $allowed_form_fields = apply_filters( 'wpforms_get_form_fields_allowed', $allowed_form_fields ); $whitelist = ! empty( $whitelist ) ? $whitelist : $allowed_form_fields; $form_fields = $form['fields']; foreach ( $form_fields as $id => $form_field ) { if ( ! in_array( $form_field['type'], $whitelist, true ) ) { unset( $form_fields[ $id ] ); } } return $form_fields; } /** * Conditional logic form fields supported. * * @since 1.5.2 * * @return array */ function wpforms_get_conditional_logic_form_fields_supported() { $fields_supported = array( 'text', 'textarea', 'number-slider', 'select', 'radio', 'email', 'url', 'checkbox', 'number', 'payment-multiple', 'payment-checkbox', 'payment-select', 'hidden', 'rating', 'net_promoter_score', ); return apply_filters( 'wpforms_get_conditional_logic_form_fields_supported', $fields_supported ); } /** * Get meta key value for a form field. * * @since 1.1.9 * * @param int|string $id Field ID. * @param string $key Meta key. * @param mixed $form_data Form data array. * * @return string */ function wpforms_get_form_field_meta( $id = '', $key = '', $form_data = '' ) { if ( empty( $id ) || empty( $key ) || empty( $form_data ) ) { return ''; } if ( ! empty( $form_data['fields'][ $id ]['meta'][ $key ] ) ) { return $form_data['fields'][ $id ]['meta'][ $key ]; } return ''; } /** * Get meta key value for a form field. * * @since 1.3.1 * @since 1.5.0 More strict parameters. Always return an array. * * @param string $key Meta key. * @param string $value Meta value to check against. * @param array $form_data Form data array. * * @return array|bool Empty array, when no data is found. */ function wpforms_get_form_fields_by_meta( $key, $value, $form_data ) { $found = array(); if ( empty( $key ) || empty( $value ) || empty( $form_data['fields'] ) ) { return $found; } foreach ( $form_data['fields'] as $id => $field ) { if ( ! empty( $field['meta'][ $key ] ) && $value === $field['meta'][ $key ] ) { $found[ $id ] = $field; } } return $found; } /** * US States. * * @since 1.0.0 * * @return array */ function wpforms_us_states() { $states = array( 'AL' => esc_html__( 'Alabama', 'wpforms-lite' ), 'AK' => esc_html__( 'Alaska', 'wpforms-lite' ), 'AZ' => esc_html__( 'Arizona', 'wpforms-lite' ), 'AR' => esc_html__( 'Arkansas', 'wpforms-lite' ), 'CA' => esc_html__( 'California', 'wpforms-lite' ), 'CO' => esc_html__( 'Colorado', 'wpforms-lite' ), 'CT' => esc_html__( 'Connecticut', 'wpforms-lite' ), 'DE' => esc_html__( 'Delaware', 'wpforms-lite' ), 'DC' => esc_html__( 'District of Columbia', 'wpforms-lite' ), 'FL' => esc_html__( 'Florida', 'wpforms-lite' ), 'GA' => esc_html_x( 'Georgia', 'US State', 'wpforms-lite' ), 'HI' => esc_html__( 'Hawaii', 'wpforms-lite' ), 'ID' => esc_html__( 'Idaho', 'wpforms-lite' ), 'IL' => esc_html__( 'Illinois', 'wpforms-lite' ), 'IN' => esc_html__( 'Indiana', 'wpforms-lite' ), 'IA' => esc_html__( 'Iowa', 'wpforms-lite' ), 'KS' => esc_html__( 'Kansas', 'wpforms-lite' ), 'KY' => esc_html__( 'Kentucky', 'wpforms-lite' ), 'LA' => esc_html__( 'Louisiana', 'wpforms-lite' ), 'ME' => esc_html__( 'Maine', 'wpforms-lite' ), 'MD' => esc_html__( 'Maryland', 'wpforms-lite' ), 'MA' => esc_html__( 'Massachusetts', 'wpforms-lite' ), 'MI' => esc_html__( 'Michigan', 'wpforms-lite' ), 'MN' => esc_html__( 'Minnesota', 'wpforms-lite' ), 'MS' => esc_html__( 'Mississippi', 'wpforms-lite' ), 'MO' => esc_html__( 'Missouri', 'wpforms-lite' ), 'MT' => esc_html__( 'Montana', 'wpforms-lite' ), 'NE' => esc_html__( 'Nebraska', 'wpforms-lite' ), 'NV' => esc_html__( 'Nevada', 'wpforms-lite' ), 'NH' => esc_html__( 'New Hampshire', 'wpforms-lite' ), 'NJ' => esc_html__( 'New Jersey', 'wpforms-lite' ), 'NM' => esc_html__( 'New Mexico', 'wpforms-lite' ), 'NY' => esc_html__( 'New York', 'wpforms-lite' ), 'NC' => esc_html__( 'North Carolina', 'wpforms-lite' ), 'ND' => esc_html__( 'North Dakota', 'wpforms-lite' ), 'OH' => esc_html__( 'Ohio', 'wpforms-lite' ), 'OK' => esc_html__( 'Oklahoma', 'wpforms-lite' ), 'OR' => esc_html__( 'Oregon', 'wpforms-lite' ), 'PA' => esc_html__( 'Pennsylvania', 'wpforms-lite' ), 'RI' => esc_html__( 'Rhode Island', 'wpforms-lite' ), 'SC' => esc_html__( 'South Carolina', 'wpforms-lite' ), 'SD' => esc_html__( 'South Dakota', 'wpforms-lite' ), 'TN' => esc_html__( 'Tennessee', 'wpforms-lite' ), 'TX' => esc_html__( 'Texas', 'wpforms-lite' ), 'UT' => esc_html__( 'Utah', 'wpforms-lite' ), 'VT' => esc_html__( 'Vermont', 'wpforms-lite' ), 'VA' => esc_html__( 'Virginia', 'wpforms-lite' ), 'WA' => esc_html__( 'Washington', 'wpforms-lite' ), 'WV' => esc_html__( 'West Virginia', 'wpforms-lite' ), 'WI' => esc_html__( 'Wisconsin', 'wpforms-lite' ), 'WY' => esc_html__( 'Wyoming', 'wpforms-lite' ), ); return apply_filters( 'wpforms_us_states', $states ); } /** * Countries. * * @since 1.0.0 * * @return array */ function wpforms_countries() { $countries = array( 'AF' => esc_html__( 'Afghanistan', 'wpforms-lite' ), 'AX' => esc_html__( 'Åland Islands', 'wpforms-lite' ), 'AL' => esc_html__( 'Albania', 'wpforms-lite' ), 'DZ' => esc_html__( 'Algeria', 'wpforms-lite' ), 'AS' => esc_html__( 'American Samoa', 'wpforms-lite' ), 'AD' => esc_html__( 'Andorra', 'wpforms-lite' ), 'AO' => esc_html__( 'Angola', 'wpforms-lite' ), 'AI' => esc_html__( 'Anguilla', 'wpforms-lite' ), 'AQ' => esc_html__( 'Antarctica', 'wpforms-lite' ), 'AG' => esc_html__( 'Antigua and Barbuda', 'wpforms-lite' ), 'AR' => esc_html__( 'Argentina', 'wpforms-lite' ), 'AM' => esc_html__( 'Armenia', 'wpforms-lite' ), 'AW' => esc_html__( 'Aruba', 'wpforms-lite' ), 'AU' => esc_html__( 'Australia', 'wpforms-lite' ), 'AT' => esc_html__( 'Austria', 'wpforms-lite' ), 'AZ' => esc_html__( 'Azerbaijan', 'wpforms-lite' ), 'BS' => esc_html__( 'Bahamas', 'wpforms-lite' ), 'BH' => esc_html__( 'Bahrain', 'wpforms-lite' ), 'BD' => esc_html__( 'Bangladesh', 'wpforms-lite' ), 'BB' => esc_html__( 'Barbados', 'wpforms-lite' ), 'BY' => esc_html__( 'Belarus', 'wpforms-lite' ), 'BE' => esc_html__( 'Belgium', 'wpforms-lite' ), 'BZ' => esc_html__( 'Belize', 'wpforms-lite' ), 'BJ' => esc_html__( 'Benin', 'wpforms-lite' ), 'BM' => esc_html__( 'Bermuda', 'wpforms-lite' ), 'BT' => esc_html__( 'Bhutan', 'wpforms-lite' ), 'BO' => esc_html__( 'Bolivia (Plurinational State of)', 'wpforms-lite' ), 'BA' => esc_html__( 'Bosnia and Herzegovina', 'wpforms-lite' ), 'BW' => esc_html__( 'Botswana', 'wpforms-lite' ), 'BV' => esc_html__( 'Bouvet Island', 'wpforms-lite' ), 'BR' => esc_html__( 'Brazil', 'wpforms-lite' ), 'IO' => esc_html__( 'British Indian Ocean Territory', 'wpforms-lite' ), 'BN' => esc_html__( 'Brunei Darussalam', 'wpforms-lite' ), 'BG' => esc_html__( 'Bulgaria', 'wpforms-lite' ), 'BF' => esc_html__( 'Burkina Faso', 'wpforms-lite' ), 'BI' => esc_html__( 'Burundi', 'wpforms-lite' ), 'CV' => esc_html__( 'Cabo Verde', 'wpforms-lite' ), 'KH' => esc_html__( 'Cambodia', 'wpforms-lite' ), 'CM' => esc_html__( 'Cameroon', 'wpforms-lite' ), 'CA' => esc_html__( 'Canada', 'wpforms-lite' ), 'KY' => esc_html__( 'Cayman Islands', 'wpforms-lite' ), 'CF' => esc_html__( 'Central African Republic', 'wpforms-lite' ), 'TD' => esc_html__( 'Chad', 'wpforms-lite' ), 'CL' => esc_html__( 'Chile', 'wpforms-lite' ), 'CN' => esc_html__( 'China', 'wpforms-lite' ), 'CX' => esc_html__( 'Christmas Island', 'wpforms-lite' ), 'CC' => esc_html__( 'Cocos (Keeling) Islands', 'wpforms-lite' ), 'CO' => esc_html__( 'Colombia', 'wpforms-lite' ), 'KM' => esc_html__( 'Comoros', 'wpforms-lite' ), 'CG' => esc_html__( 'Congo', 'wpforms-lite' ), 'CD' => esc_html__( 'Congo (Democratic Republic of the)', 'wpforms-lite' ), 'CK' => esc_html__( 'Cook Islands', 'wpforms-lite' ), 'CR' => esc_html__( 'Costa Rica', 'wpforms-lite' ), 'CI' => esc_html__( 'Côte d\'Ivoire', 'wpforms-lite' ), 'HR' => esc_html__( 'Croatia', 'wpforms-lite' ), 'CU' => esc_html__( 'Cuba', 'wpforms-lite' ), 'CW' => esc_html__( 'Curaçao', 'wpforms-lite' ), 'CY' => esc_html__( 'Cyprus', 'wpforms-lite' ), 'CZ' => esc_html__( 'Czech Republic', 'wpforms-lite' ), 'DK' => esc_html__( 'Denmark', 'wpforms-lite' ), 'DJ' => esc_html__( 'Djibouti', 'wpforms-lite' ), 'DM' => esc_html__( 'Dominica', 'wpforms-lite' ), 'DO' => esc_html__( 'Dominican Republic', 'wpforms-lite' ), 'EC' => esc_html__( 'Ecuador', 'wpforms-lite' ), 'EG' => esc_html__( 'Egypt', 'wpforms-lite' ), 'SV' => esc_html__( 'El Salvador', 'wpforms-lite' ), 'GQ' => esc_html__( 'Equatorial Guinea', 'wpforms-lite' ), 'ER' => esc_html__( 'Eritrea', 'wpforms-lite' ), 'EE' => esc_html__( 'Estonia', 'wpforms-lite' ), 'ET' => esc_html__( 'Ethiopia', 'wpforms-lite' ), 'FK' => esc_html__( 'Falkland Islands (Malvinas)', 'wpforms-lite' ), 'FO' => esc_html__( 'Faroe Islands', 'wpforms-lite' ), 'FJ' => esc_html__( 'Fiji', 'wpforms-lite' ), 'FI' => esc_html__( 'Finland', 'wpforms-lite' ), 'FR' => esc_html__( 'France', 'wpforms-lite' ), 'GF' => esc_html__( 'French Guiana', 'wpforms-lite' ), 'PF' => esc_html__( 'French Polynesia', 'wpforms-lite' ), 'TF' => esc_html__( 'French Southern Territories', 'wpforms-lite' ), 'GA' => esc_html__( 'Gabon', 'wpforms-lite' ), 'GM' => esc_html__( 'Gambia', 'wpforms-lite' ), 'GE' => esc_html_x( 'Georgia', 'Country', 'wpforms-lite' ), 'DE' => esc_html__( 'Germany', 'wpforms-lite' ), 'GH' => esc_html__( 'Ghana', 'wpforms-lite' ), 'GI' => esc_html__( 'Gibraltar', 'wpforms-lite' ), 'GR' => esc_html__( 'Greece', 'wpforms-lite' ), 'GL' => esc_html__( 'Greenland', 'wpforms-lite' ), 'GD' => esc_html__( 'Grenada', 'wpforms-lite' ), 'GP' => esc_html__( 'Guadeloupe', 'wpforms-lite' ), 'GU' => esc_html__( 'Guam', 'wpforms-lite' ), 'GT' => esc_html__( 'Guatemala', 'wpforms-lite' ), 'GG' => esc_html__( 'Guernsey', 'wpforms-lite' ), 'GN' => esc_html__( 'Guinea', 'wpforms-lite' ), 'GW' => esc_html__( 'Guinea-Bissau', 'wpforms-lite' ), 'GY' => esc_html__( 'Guyana', 'wpforms-lite' ), 'HT' => esc_html__( 'Haiti', 'wpforms-lite' ), 'HM' => esc_html__( 'Heard Island and McDonald Islands', 'wpforms-lite' ), 'HN' => esc_html__( 'Honduras', 'wpforms-lite' ), 'HK' => esc_html__( 'Hong Kong', 'wpforms-lite' ), 'HU' => esc_html__( 'Hungary', 'wpforms-lite' ), 'IS' => esc_html__( 'Iceland', 'wpforms-lite' ), 'IN' => esc_html__( 'India', 'wpforms-lite' ), 'ID' => esc_html__( 'Indonesia', 'wpforms-lite' ), 'IR' => esc_html__( 'Iran (Islamic Republic of)', 'wpforms-lite' ), 'IQ' => esc_html__( 'Iraq', 'wpforms-lite' ), 'IE' => esc_html__( 'Ireland (Republic of)', 'wpforms-lite' ), 'IM' => esc_html__( 'Isle of Man', 'wpforms-lite' ), 'IL' => esc_html__( 'Israel', 'wpforms-lite' ), 'IT' => esc_html__( 'Italy', 'wpforms-lite' ), 'JM' => esc_html__( 'Jamaica', 'wpforms-lite' ), 'JP' => esc_html__( 'Japan', 'wpforms-lite' ), 'JE' => esc_html__( 'Jersey', 'wpforms-lite' ), 'JO' => esc_html__( 'Jordan', 'wpforms-lite' ), 'KZ' => esc_html__( 'Kazakhstan', 'wpforms-lite' ), 'KE' => esc_html__( 'Kenya', 'wpforms-lite' ), 'KI' => esc_html__( 'Kiribati', 'wpforms-lite' ), 'KP' => esc_html__( 'Korea (Democratic People\'s Republic of)', 'wpforms-lite' ), 'KR' => esc_html__( 'Korea (Republic of)', 'wpforms-lite' ), 'KW' => esc_html__( 'Kuwait', 'wpforms-lite' ), 'KG' => esc_html__( 'Kyrgyzstan', 'wpforms-lite' ), 'LA' => esc_html__( 'Lao People\'s Democratic Republic', 'wpforms-lite' ), 'LV' => esc_html__( 'Latvia', 'wpforms-lite' ), 'LB' => esc_html__( 'Lebanon', 'wpforms-lite' ), 'LS' => esc_html__( 'Lesotho', 'wpforms-lite' ), 'LR' => esc_html__( 'Liberia', 'wpforms-lite' ), 'LY' => esc_html__( 'Libya', 'wpforms-lite' ), 'LI' => esc_html__( 'Liechtenstein', 'wpforms-lite' ), 'LT' => esc_html__( 'Lithuania', 'wpforms-lite' ), 'LU' => esc_html__( 'Luxembourg', 'wpforms-lite' ), 'MO' => esc_html__( 'Macao', 'wpforms-lite' ), 'MK' => esc_html__( 'Macedonia (Republic of)', 'wpforms-lite' ), 'MG' => esc_html__( 'Madagascar', 'wpforms-lite' ), 'MW' => esc_html__( 'Malawi', 'wpforms-lite' ), 'MY' => esc_html__( 'Malaysia', 'wpforms-lite' ), 'MV' => esc_html__( 'Maldives', 'wpforms-lite' ), 'ML' => esc_html__( 'Mali', 'wpforms-lite' ), 'MT' => esc_html__( 'Malta', 'wpforms-lite' ), 'MH' => esc_html__( 'Marshall Islands', 'wpforms-lite' ), 'MQ' => esc_html__( 'Martinique', 'wpforms-lite' ), 'MR' => esc_html__( 'Mauritania', 'wpforms-lite' ), 'MU' => esc_html__( 'Mauritius', 'wpforms-lite' ), 'YT' => esc_html__( 'Mayotte', 'wpforms-lite' ), 'MX' => esc_html__( 'Mexico', 'wpforms-lite' ), 'FM' => esc_html__( 'Micronesia (Federated States of)', 'wpforms-lite' ), 'MD' => esc_html__( 'Moldova (Republic of)', 'wpforms-lite' ), 'MC' => esc_html__( 'Monaco', 'wpforms-lite' ), 'MN' => esc_html__( 'Mongolia', 'wpforms-lite' ), 'ME' => esc_html__( 'Montenegro', 'wpforms-lite' ), 'MS' => esc_html__( 'Montserrat', 'wpforms-lite' ), 'MA' => esc_html__( 'Morocco', 'wpforms-lite' ), 'MZ' => esc_html__( 'Mozambique', 'wpforms-lite' ), 'MM' => esc_html__( 'Myanmar', 'wpforms-lite' ), 'NA' => esc_html__( 'Namibia', 'wpforms-lite' ), 'NR' => esc_html__( 'Nauru', 'wpforms-lite' ), 'NP' => esc_html__( 'Nepal', 'wpforms-lite' ), 'NL' => esc_html__( 'Netherlands', 'wpforms-lite' ), 'NC' => esc_html__( 'New Caledonia', 'wpforms-lite' ), 'NZ' => esc_html__( 'New Zealand', 'wpforms-lite' ), 'NI' => esc_html__( 'Nicaragua', 'wpforms-lite' ), 'NE' => esc_html__( 'Niger', 'wpforms-lite' ), 'NG' => esc_html__( 'Nigeria', 'wpforms-lite' ), 'NU' => esc_html__( 'Niue', 'wpforms-lite' ), 'NF' => esc_html__( 'Norfolk Island', 'wpforms-lite' ), 'MP' => esc_html__( 'Northern Mariana Islands', 'wpforms-lite' ), 'NO' => esc_html__( 'Norway', 'wpforms-lite' ), 'OM' => esc_html__( 'Oman', 'wpforms-lite' ), 'PK' => esc_html__( 'Pakistan', 'wpforms-lite' ), 'PW' => esc_html__( 'Palau', 'wpforms-lite' ), 'PS' => esc_html__( 'Palestine (State of)', 'wpforms-lite' ), 'PA' => esc_html__( 'Panama', 'wpforms-lite' ), 'PG' => esc_html__( 'Papua New Guinea', 'wpforms-lite' ), 'PY' => esc_html__( 'Paraguay', 'wpforms-lite' ), 'PE' => esc_html__( 'Peru', 'wpforms-lite' ), 'PH' => esc_html__( 'Philippines', 'wpforms-lite' ), 'PN' => esc_html__( 'Pitcairn', 'wpforms-lite' ), 'PL' => esc_html__( 'Poland', 'wpforms-lite' ), 'PT' => esc_html__( 'Portugal', 'wpforms-lite' ), 'PR' => esc_html__( 'Puerto Rico', 'wpforms-lite' ), 'QA' => esc_html__( 'Qatar', 'wpforms-lite' ), 'RE' => esc_html__( 'Réunion', 'wpforms-lite' ), 'RO' => esc_html__( 'Romania', 'wpforms-lite' ), 'RU' => esc_html__( 'Russian Federation', 'wpforms-lite' ), 'RW' => esc_html__( 'Rwanda', 'wpforms-lite' ), 'BL' => esc_html__( 'Saint Barthélemy', 'wpforms-lite' ), 'SH' => esc_html__( 'Saint Helena, Ascension and Tristan da Cunha', 'wpforms-lite' ), 'KN' => esc_html__( 'Saint Kitts and Nevis', 'wpforms-lite' ), 'LC' => esc_html__( 'Saint Lucia', 'wpforms-lite' ), 'MF' => esc_html__( 'Saint Martin (French part)', 'wpforms-lite' ), 'PM' => esc_html__( 'Saint Pierre and Miquelon', 'wpforms-lite' ), 'VC' => esc_html__( 'Saint Vincent and the Grenadines', 'wpforms-lite' ), 'WS' => esc_html__( 'Samoa', 'wpforms-lite' ), 'SM' => esc_html__( 'San Marino', 'wpforms-lite' ), 'ST' => esc_html__( 'Sao Tome and Principe', 'wpforms-lite' ), 'SA' => esc_html__( 'Saudi Arabia', 'wpforms-lite' ), 'SN' => esc_html__( 'Senegal', 'wpforms-lite' ), 'RS' => esc_html__( 'Serbia', 'wpforms-lite' ), 'SC' => esc_html__( 'Seychelles', 'wpforms-lite' ), 'SL' => esc_html__( 'Sierra Leone', 'wpforms-lite' ), 'SG' => esc_html__( 'Singapore', 'wpforms-lite' ), 'SX' => esc_html__( 'Sint Maarten (Dutch part)', 'wpforms-lite' ), 'SK' => esc_html__( 'Slovakia', 'wpforms-lite' ), 'SI' => esc_html__( 'Slovenia', 'wpforms-lite' ), 'SB' => esc_html__( 'Solomon Islands', 'wpforms-lite' ), 'SO' => esc_html__( 'Somalia', 'wpforms-lite' ), 'ZA' => esc_html__( 'South Africa', 'wpforms-lite' ), 'GS' => esc_html__( 'South Georgia and the South Sandwich Islands', 'wpforms-lite' ), 'SS' => esc_html__( 'South Sudan', 'wpforms-lite' ), 'ES' => esc_html__( 'Spain', 'wpforms-lite' ), 'LK' => esc_html__( 'Sri Lanka', 'wpforms-lite' ), 'SD' => esc_html__( 'Sudan', 'wpforms-lite' ), 'SR' => esc_html__( 'Suriname', 'wpforms-lite' ), 'SJ' => esc_html__( 'Svalbard and Jan Mayen', 'wpforms-lite' ), 'SZ' => esc_html__( 'Swaziland', 'wpforms-lite' ), 'SE' => esc_html__( 'Sweden', 'wpforms-lite' ), 'CH' => esc_html__( 'Switzerland', 'wpforms-lite' ), 'SY' => esc_html__( 'Syrian Arab Republic', 'wpforms-lite' ), 'TW' => esc_html__( 'Taiwan, Province of China', 'wpforms-lite' ), 'TJ' => esc_html__( 'Tajikistan', 'wpforms-lite' ), 'TZ' => esc_html__( 'Tanzania (United Republic of)', 'wpforms-lite' ), 'TH' => esc_html__( 'Thailand', 'wpforms-lite' ), 'TL' => esc_html__( 'Timor-Leste', 'wpforms-lite' ), 'TG' => esc_html__( 'Togo', 'wpforms-lite' ), 'TK' => esc_html__( 'Tokelau', 'wpforms-lite' ), 'TO' => esc_html__( 'Tonga', 'wpforms-lite' ), 'TT' => esc_html__( 'Trinidad and Tobago', 'wpforms-lite' ), 'TN' => esc_html__( 'Tunisia', 'wpforms-lite' ), 'TR' => esc_html__( 'Turkey', 'wpforms-lite' ), 'TM' => esc_html__( 'Turkmenistan', 'wpforms-lite' ), 'TC' => esc_html__( 'Turks and Caicos Islands', 'wpforms-lite' ), 'TV' => esc_html__( 'Tuvalu', 'wpforms-lite' ), 'UG' => esc_html__( 'Uganda', 'wpforms-lite' ), 'UA' => esc_html__( 'Ukraine', 'wpforms-lite' ), 'AE' => esc_html__( 'United Arab Emirates', 'wpforms-lite' ), 'GB' => esc_html__( 'United Kingdom of Great Britain and Northern Ireland', 'wpforms-lite' ), 'US' => esc_html__( 'United States of America', 'wpforms-lite' ), 'UM' => esc_html__( 'United States Minor Outlying Islands', 'wpforms-lite' ), 'UY' => esc_html__( 'Uruguay', 'wpforms-lite' ), 'UZ' => esc_html__( 'Uzbekistan', 'wpforms-lite' ), 'VU' => esc_html__( 'Vanuatu', 'wpforms-lite' ), 'VA' => esc_html__( 'Vatican City State', 'wpforms-lite' ), 'VE' => esc_html__( 'Venezuela (Bolivarian Republic of)', 'wpforms-lite' ), 'VN' => esc_html__( 'Viet Nam', 'wpforms-lite' ), 'VG' => esc_html__( 'Virgin Islands (British)', 'wpforms-lite' ), 'VI' => esc_html__( 'Virgin Islands (U.S.)', 'wpforms-lite' ), 'WF' => esc_html__( 'Wallis and Futuna', 'wpforms-lite' ), 'EH' => esc_html__( 'Western Sahara', 'wpforms-lite' ), 'YE' => esc_html__( 'Yemen', 'wpforms-lite' ), 'ZM' => esc_html__( 'Zambia', 'wpforms-lite' ), 'ZW' => esc_html__( 'Zimbabwe', 'wpforms-lite' ), ); return apply_filters( 'wpforms_countries', $countries ); } /** * Calendar Months. * * @since 1.3.7 * * @return array */ function wpforms_months() { $months = array( 'Jan' => esc_html__( 'January', 'wpforms-lite' ), 'Feb' => esc_html__( 'February', 'wpforms-lite' ), 'Mar' => esc_html__( 'March', 'wpforms-lite' ), 'Apr' => esc_html__( 'April', 'wpforms-lite' ), 'May' => esc_html__( 'May', 'wpforms-lite' ), 'Jun' => esc_html__( 'June', 'wpforms-lite' ), 'Jul' => esc_html__( 'July', 'wpforms-lite' ), 'Aug' => esc_html__( 'August', 'wpforms-lite' ), 'Sep' => esc_html__( 'September', 'wpforms-lite' ), 'Oct' => esc_html__( 'October', 'wpforms-lite' ), 'Nov' => esc_html__( 'November', 'wpforms-lite' ), 'Dec' => esc_html__( 'December', 'wpforms-lite' ), ); return apply_filters( 'wpforms_months', $months ); } /** * Calendar Days. * * @since 1.3.7 * * @return array */ function wpforms_days() { $days = array( 'Sun' => esc_html__( 'Sunday', 'wpforms-lite' ), 'Mon' => esc_html__( 'Monday', 'wpforms-lite' ), 'Tue' => esc_html__( 'Tuesday', 'wpforms-lite' ), 'Wed' => esc_html__( 'Wednesday', 'wpforms-lite' ), 'Thu' => esc_html__( 'Thursday', 'wpforms-lite' ), 'Fri' => esc_html__( 'Friday', 'wpforms-lite' ), 'Sat' => esc_html__( 'Saturday', 'wpforms-lite' ), ); return apply_filters( 'wpforms_days', $days ); } /** * Lookup user IP. * * There are many ways to do this, but we prefer the way EDD does it. * https://github.com/easydigitaldownloads/easy-digital-downloads/blob/master/includes/misc-functions.php#L163 * * @since 1.2.5 * * @return string */ function wpforms_get_ip() { $ip = false; if ( ! empty( $_SERVER['HTTP_X_REAL_IP'] ) ) { $ip = filter_var( wp_unslash( $_SERVER['HTTP_X_REAL_IP'] ), FILTER_VALIDATE_IP ); } elseif ( ! empty( $_SERVER['HTTP_CLIENT_IP'] ) ) { // Check ip from share internet. $ip = filter_var( wp_unslash( $_SERVER['HTTP_CLIENT_IP'] ), FILTER_VALIDATE_IP ); } elseif ( ! empty( $_SERVER['HTTP_X_FORWARDED_FOR'] ) ) { // To check ip is pass from proxy. // Can include more than 1 ip, first is the public one. // WPCS: sanitization ok. // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized $ips = explode( ',', wp_unslash( $_SERVER['HTTP_X_FORWARDED_FOR'] ) ); if ( is_array( $ips ) ) { $ip = filter_var( $ips[0], FILTER_VALIDATE_IP ); } } elseif ( ! empty( $_SERVER['REMOTE_ADDR'] ) ) { $ip = filter_var( wp_unslash( $_SERVER['REMOTE_ADDR'] ), FILTER_VALIDATE_IP ); } $ip = false !== $ip ? $ip : '127.0.0.1'; $ip_array = explode( ',', $ip ); $ip_array = array_map( 'trim', $ip_array ); return sanitize_text_field( apply_filters( 'wpforms_get_ip', $ip_array[0] ) ); } /** * Sanitize hex color. * * @since 1.2.1 * * @param string $color * * @return string */ function wpforms_sanitize_hex_color( $color ) { if ( empty( $color ) ) { return ''; } // 3 or 6 hex digits, or the empty string. if ( preg_match( '|^#([A-Fa-f0-9]{3}){1,2}$|', $color ) ) { return $color; } return ''; } /** * Sanitize error message, primarily used during form frontend output. * * @since 1.3.7 * * @param string $error * * @return string */ function wpforms_sanitize_error( $error = '' ) { $allow = array( 'a' => array( 'href' => array(), 'title' => array(), ), 'br' => array(), 'em' => array(), 'strong' => array(), 'p' => array(), ); return wp_kses( $error, $allow ); } /** * Sanitize a string, that can be a multiline. * * @uses wpforms_sanitize_text_deeply() * * @since 1.4.1 * * @param string $string String to deeply sanitize. * * @return string Sanitized string, or empty string if not a string provided. */ function wpforms_sanitize_textarea_field( $string ) { return wpforms_sanitize_text_deeply( $string, true ); } /** * Deeply sanitize the string, preserve newlines if needed. * Prevent maliciously prepared strings from containing HTML tags. * * @since 1.6.0 * * @param string $string String to deeply sanitize. * @param bool $keep_newlines Whether to keep newlines. Default: false. * * @return string Sanitized string, or empty string if not a string provided. */ function wpforms_sanitize_text_deeply( $string, $keep_newlines = false ) { if ( is_object( $string ) || is_array( $string ) ) { return ''; } $string = (string) $string; $keep_newlines = (bool) $keep_newlines; $new_value = _sanitize_text_fields( $string, $keep_newlines ); if ( strlen( $new_value ) !== strlen( $string ) ) { $new_value = wpforms_sanitize_text_deeply( $new_value, $keep_newlines ); } return $new_value; } /** * Sanitize an array, that consists of values as strings. * After that - merge all array values into multiline string. * * @since 1.4.1 * * @param array $array * * @return mixed If not an array is passed (or empty var) - return unmodified var. Otherwise - a merged array into multiline string. */ function wpforms_sanitize_array_combine( $array ) { if ( empty( $array ) || ! is_array( $array ) ) { return $array; } return implode( "\n", array_map( 'sanitize_text_field', $array ) ); } /** * Detect if we should use a light or dark color based on the color given. * * @since 1.2.5 * @link https://docs.woocommerce.com/wc-apidocs/source-function-wc_light_or_dark.html#608-627 * * @param mixed $color * @param string $dark (default: '#000000'). * @param string $light (default: '#FFFFFF'). * * @return string */ function wpforms_light_or_dark( $color, $dark = '#000000', $light = '#FFFFFF' ) { $hex = str_replace( '#', '', $color ); $c_r = hexdec( substr( $hex, 0, 2 ) ); $c_g = hexdec( substr( $hex, 2, 2 ) ); $c_b = hexdec( substr( $hex, 4, 2 ) ); $brightness = ( ( $c_r * 299 ) + ( $c_g * 587 ) + ( $c_b * 114 ) ) / 1000; return $brightness > 155 ? $dark : $light; } /** * Build and return either a taxonomy or post type object that is * nested to accommodate any hierarchy. * * @since 1.3.9 * @since 1.5.0 Return array only. Empty array of no data. * * @param array $args Object arguments to pass to data retrieval function. * @param bool $flat Preserve hierarchy or not. False by default - preserve it. * * @return array */ function wpforms_get_hierarchical_object( $args = array(), $flat = false ) { if ( empty( $args['taxonomy'] ) && empty( $args['post_type'] ) ) { return array(); } $children = array(); $parents = array(); $ref_parent = ''; $ref_name = ''; if ( ! empty( $args['post_type'] ) ) { $defaults = array( 'posts_per_page' => - 1, 'orderby' => 'title', 'order' => 'ASC', ); $args = wp_parse_args( $args, $defaults ); $items = get_posts( $args ); $ref_parent = 'post_parent'; $ref_id = 'ID'; $ref_name = 'post_title'; } elseif ( ! empty( $args['taxonomy'] ) ) { $defaults = array( 'hide_empty' => false, ); $args = wp_parse_args( $args, $defaults ); $items = get_terms( $args ); $ref_parent = 'parent'; $ref_id = 'term_id'; $ref_name = 'name'; } if ( empty( $items ) || is_wp_error( $items ) ) { return array(); } foreach ( $items as $item ) { if ( $item->{$ref_parent} ) { $children[ $item->{$ref_id} ] = $item; $children[ $item->{$ref_id} ]->ID = (int) $item->{$ref_id}; } else { $parents[ $item->{$ref_id} ] = $item; $parents[ $item->{$ref_id} ]->ID = (int) $item->{$ref_id}; } } $children_count = count( $children ); while ( $children_count >= 1 ) { foreach ( $children as $child ) { _wpforms_get_hierarchical_object_search( $child, $parents, $children, $ref_parent ); // $children is modified by reference, so we need to recount to make sure we met the limits. $children_count = count( $children ); } } if ( $flat ) { $parents_flat = array(); _wpforms_get_hierarchical_object_flatten( $parents, $parents_flat, $ref_name ); return $parents_flat; } return $parents; } /** * Search a given array and find the parent of the provided object. * * @since 1.3.9 * * @param object $child Current child. * @param array $parents Parents list. * @param array $children Children list. * @param string $ref_parent Parent reference. */ function _wpforms_get_hierarchical_object_search( $child, &$parents, &$children, $ref_parent ) { foreach ( $parents as $id => $parent ) { if ( $parent->ID === $child->{$ref_parent} ) { if ( empty( $parent->children ) ) { $parents[ $id ]->children = array( $child->ID => $child, ); } else { $parents[ $id ]->children[ $child->ID ] = $child; } unset( $children[ $child->ID ] ); } elseif ( ! empty( $parent->children ) && is_array( $parent->children ) ) { _wpforms_get_hierarchical_object_search( $child, $parent->children, $children, $ref_parent ); } } } /** * Flatten a hierarchical object. * * @since 1.3.9 * * @param array $array Array to process. * @param array $output Processed output. * @param string $ref_name Name reference. * @param int $level Nesting level. */ function _wpforms_get_hierarchical_object_flatten( $array, &$output, $ref_name = 'name', $level = 0 ) { foreach ( $array as $key => $item ) { $indicator = apply_filters( 'wpforms_hierarchical_object_indicator', '—' ); $item->{$ref_name} = str_repeat( $indicator, $level ) . ' ' . $item->{$ref_name}; $item->depth = $level + 1; $output[ $item->ID ] = $item; if ( ! empty( $item->children ) ) { _wpforms_get_hierarchical_object_flatten( $item->children, $output, $ref_name, $level + 1 ); unset( $output[ $item->ID ]->children ); } } } /** * Return field choice properties for field configured with dynamic choices. * * @since 1.4.5 * * @param array $field Field settings. * @param int $form_id Form ID. * @param array $form_data Form data and settings. * * @return false|array */ function wpforms_get_field_dynamic_choices( $field, $form_id, $form_data = array() ) { if ( empty( $field['dynamic_choices'] ) ) { return false; } $choices = array(); if ( 'post_type' === $field['dynamic_choices'] ) { if ( empty( $field['dynamic_post_type'] ) ) { return false; } $posts = wpforms_get_hierarchical_object( apply_filters( 'wpforms_dynamic_choice_post_type_args', array( 'post_type' => $field['dynamic_post_type'], 'posts_per_page' => -1, 'orderby' => 'title', 'order' => 'ASC', ), $field, $form_id ), true ); foreach ( $posts as $post ) { $choices[] = array( 'value' => $post->ID, 'label' => $post->post_title, 'depth' => isset( $post->depth ) ? absint( $post->depth ) : 1, ); } } elseif ( 'taxonomy' === $field['dynamic_choices'] ) { if ( empty( $field['dynamic_taxonomy'] ) ) { return false; } $terms = wpforms_get_hierarchical_object( apply_filters( 'wpforms_dynamic_choice_taxonomy_args', array( 'taxonomy' => $field['dynamic_taxonomy'], 'hide_empty' => false, ), $field, $form_data ), true ); foreach ( $terms as $term ) { $choices[] = array( 'value' => $term->term_id, 'label' => $term->name, 'depth' => isset( $term->depth ) ? absint( $term->depth ) : 1, ); } } return $choices; } /** * Insert an array into another array before/after a certain key. * * @link https://gist.github.com/scribu/588429 * * @since 1.3.9 * * @param array $array The initial array. * @param array $pairs The array to insert. * @param string $key The certain key. * @param string $position Where to insert the array - before or after the key. * * @return array */ function wpforms_array_insert( $array, $pairs, $key, $position = 'after' ) { $key_pos = array_search( $key, array_keys( $array ), true ); if ( 'after' === $position ) { $key_pos ++; } if ( false !== $key_pos ) { $result = array_slice( $array, 0, $key_pos ); $result = array_merge( $result, $pairs ); $result = array_merge( $result, array_slice( $array, $key_pos ) ); } else { $result = array_merge( $array, $pairs ); } return $result; } /** * Recursively remove empty strings from an array. * * @since 1.3.9.1 * * @param array $data * * @return array */ function wpforms_array_remove_empty_strings( $data ) { foreach ( $data as $key => $value ) { if ( is_array( $value ) ) { $data[ $key ] = wpforms_array_remove_empty_strings( $data[ $key ] ); } if ( '' === $data[ $key ] ) { unset( $data[ $key ] ); } } return $data; } /** * Check whether plugin works in a debug mode. * * @since 1.2.3 * * @return bool */ function wpforms_debug() { $debug = false; if ( ( defined( 'WPFORMS_DEBUG' ) && true === WPFORMS_DEBUG ) && is_super_admin() ) { $debug = true; } $debug_option = get_option( 'wpforms_debug' ); if ( $debug_option ) { $current_user = wp_get_current_user(); if ( $current_user->user_login === $debug_option ) { $debug = true; } } return apply_filters( 'wpforms_debug', $debug ); } /** * Helper function to display debug data. * * @since 1.0.0 * * @param mixed $data What to dump, can be any type. * @param bool $echo Whether to print or return. Default is to print. * * @return string */ function wpforms_debug_data( $data, $echo = true ) { if ( wpforms_debug() ) { $output = '<div><textarea style="background:#fff;margin: 20px 0;width:100%;height:500px;font-size:12px;font-family: Consolas,Monaco,monospace;direction: ltr;unicode-bidi: embed;line-height: 1.4;padding: 4px 6px 1px;" readonly>'; $output .= "=================== WPFORMS DEBUG ===================\n\n"; if ( is_array( $data ) || is_object( $data ) ) { $output .= print_r( $data, true ); // phpcs:ignore } else { $output .= $data; } $output .= '</textarea></div>'; if ( $echo ) { echo $output; // phpcs:ignore } else { return $output; } } } /** * Log helper. * * @since 1.0.0 * * @param string $title Title of a log message. * @param mixed $message Content of a log message. * @param array $args Expected keys: form_id, meta, parent. */ function wpforms_log( $title = '', $message = '', $args = array() ) { // Require log title. if ( empty( $title ) ) { return; } // Force logging everything when in debug mode. if ( ! wpforms_debug() ) { /** * Compare error levels to determine if we should log. * Current supported levels: * - Errors (error) * - Spam (spam) * - Entries (entry) * - Payments (payment) * - Providers (provider) * - Conditional Logic (conditional_logic) */ $type = ! empty( $args['type'] ) ? (array) $args['type'] : array( 'error' ); $levels = array_intersect( $type, get_option( 'wpforms_logging', array() ) ); if ( empty( $levels ) ) { return; } } // Meta. if ( ! empty( $args['form_id'] ) ) { $meta = array( 'form' => absint( $args['form_id'] ), ); } elseif ( ! empty( $args['meta'] ) ) { $meta = $args['meta']; } else { $meta = ''; } // Parent element. $parent = ! empty( $args['parent'] ) ? $args['parent'] : 0; // Make arrays and objects look nice. if ( is_array( $message ) || is_object( $message ) ) { $message = '<pre>' . print_r( $message, true ) . '</pre>'; // phpcs:ignore } // Create log entry. wpforms()->logs->add( $title, $message, $parent, $parent, $meta ); } /** * Check whether the current page is in AMP mode or not. * We need to check for specific functions, as there is no special AMP header. * * @since 1.4.1 * * @param bool $check_theme_support Whether theme support should be checked. Defaults to true. * * @return bool */ function wpforms_is_amp( $check_theme_support = true ) { $is_amp = false; if ( // AMP by Automattic; ampforwp. ( function_exists( 'is_amp_endpoint' ) && is_amp_endpoint() ) || // Better AMP. ( function_exists( 'is_better_amp' ) && is_better_amp() ) ) { $is_amp = true; } if ( $is_amp && $check_theme_support ) { $is_amp = current_theme_supports( 'amp' ); } return apply_filters( 'wpforms_is_amp', $is_amp ); } /** * Decode special characters, both alpha- (<) and numeric-based ('). * Sanitize recursively, preserve new lines. * Handle all the possible mixed variations of < and `<` that can be processed into tags. * * @since 1.4.1 * @since 1.6.0 Sanitize recursively, preserve new lines. * * @param string $string Raw string to decode. * * @return string */ function wpforms_decode_string( $string ) { if ( ! is_string( $string ) ) { return $string; } /* * Sanitization should be done first, so tags are stripped and < is converted to < etc. * This iteration may do nothing when the string already comes with < and > only. */ $string = wpforms_sanitize_text_deeply( $string, true ); // Now we need to convert the string without tags: < back to < (same for quotes). $string = wp_kses_decode_entities( html_entity_decode( $string, ENT_QUOTES ) ); // And now we need to sanitize AGAIN, to avoid unwanted tags that appeared after decoding. return wpforms_sanitize_text_deeply( $string, true ); } /** * Get a suffix for assets, `.min` if debug is disabled. * * @since 1.4.1 * * @return string */ function wpforms_get_min_suffix() { return wpforms_debug() ? '' : '.min'; } /** * Get the required label text, with a filter. * * @since 1.4.4 * * @return string */ function wpforms_get_required_label() { return apply_filters( 'wpforms_required_label', esc_html__( 'This field is required.', 'wpforms-lite' ) ); } /** * Get the required field label HTML, with a filter. * * @since 1.4.8 * * @return string */ function wpforms_get_field_required_label() { $label_html = apply_filters_deprecated( 'wpforms_field_required_label', array( ' <span class="wpforms-required-label">*</span>' ), '1.4.8 of WPForms plugin', 'wpforms_get_field_required_label' ); return apply_filters( 'wpforms_get_field_required_label', $label_html ); } /** * Get the default capability to manage everything for WPForms. * * @since 1.4.4 * * @return string */ function wpforms_get_capability_manage_options() { return apply_filters( 'wpforms_manage_cap', 'manage_options' ); } /** * Check WPForms permissions for currently logged in user. * Both short (e.g. 'view_own_forms') or long (e.g. 'wpforms_view_own_forms') capability name can be used. * Only WPForms capabilities get processed. * * @since 1.4.4 * * @param array|string $caps Capability name(s). * @param int $id ID of the specific object to check against if `$capability` is a "meta" cap. * "Meta" capabilities, e.g. 'edit_post', 'edit_user', etc., are capabilities used * by map_meta_cap() to map to other "primitive" capabilities, e.g. 'edit_posts', * 'edit_others_posts', etc. Accessed via func_get_args() and passed to WP_User::has_cap(), * then map_meta_cap(). * * @return bool */ function wpforms_current_user_can( $caps = array(), $id = 0 ) { $user_can = wpforms()->get( 'access' )->current_user_can( $caps , $id ); return apply_filters( 'wpforms_current_user_can', $user_can, $caps, $id ); } /** * Get the certain date of a specified day in a specified format. * * @since 1.4.4 * * @param string $period Supported values: start, end. * @param string $timestamp Default is the current timestamp, if left empty. * @param string $format Default is a MySQL format. * * @return string */ function wpforms_get_day_period_date( $period, $timestamp = '', $format = 'Y-m-d H:i:s' ) { $date = ''; if ( empty( $timestamp ) ) { $timestamp = time(); } switch ( $period ) { case 'start_of_day': $date = date( $format, strtotime( 'today', $timestamp ) ); break; case 'end_of_day': $date = date( $format, strtotime( 'tomorrow', $timestamp ) - 1 ); break; } return $date; } /** * Get an array of all possible provider addons. * * @since 1.5.5 * * @return array */ function wpforms_get_providers_all() { return [ [ 'name' => 'ActiveCampaign', 'slug' => 'activecampaign', 'img' => 'addon-icon-activecampaign.png', 'plugin' => 'wpforms-activecampaign/wpforms-activecampaign.php', 'plugin_slug' => 'wpforms-activecampaign', 'license' => 'elite', ], [ 'name' => 'AWeber', 'slug' => 'aweber', 'img' => 'addon-icon-aweber.png', 'plugin' => 'wpforms-aweber/wpforms-aweber.php', 'plugin_slug' => 'wpforms-aweber', 'license' => 'pro', ], [ 'name' => 'Campaign Monitor', 'slug' => 'campaign-monitor', 'img' => 'addon-icon-campaign-monitor.png', 'plugin' => 'wpforms-campaign-monitor/wpforms-campaign-monitor.php', 'plugin_slug' => 'wpforms-campaign-monitor', 'license' => 'pro', ], [ 'name' => 'Drip', 'slug' => 'drip', 'img' => 'addon-icon-drip.png', 'plugin' => 'wpforms-drip/wpforms-drip.php', 'plugin_slug' => 'wpforms-drip', 'license' => 'pro', ], [ 'name' => 'GetResponse', 'slug' => 'getresponse', 'img' => 'addon-icon-getresponse.png', 'plugin' => 'wpforms-getresponse/wpforms-getresponse.php', 'plugin_slug' => 'wpforms-getresponse', 'license' => 'pro', ], [ 'name' => 'Mailchimp', 'slug' => 'mailchimp', 'img' => 'addon-icon-mailchimp.png', 'plugin' => 'wpforms-mailchimp/wpforms-mailchimp.php', 'plugin_slug' => 'wpforms-mailchimp', 'license' => 'pro', ], [ 'name' => 'Zapier', 'slug' => 'zapier', 'img' => 'addon-icon-zapier.png', 'plugin' => 'wpforms-zapier/wpforms-zapier.php', 'plugin_slug' => 'wpforms-zapier', 'license' => 'pro', ], ]; } /** * Get an array of all the active provider addons. * * @since 1.4.7 * * @return array */ function wpforms_get_providers_available() { return (array) apply_filters( 'wpforms_providers_available', array() ); } /** * Get options for all providers. * * @since 1.4.7 * * @param string $provider Define a single provider to get options for this one only. * * @return array */ function wpforms_get_providers_options( $provider = '' ) { $options = get_option( 'wpforms_providers', array() ); $provider = sanitize_key( $provider ); $data = $options; if ( ! empty( $provider ) && isset( $options[ $provider ] ) ) { $data = $options[ $provider ]; } return (array) apply_filters( 'wpforms_get_providers_options', $data, $provider ); } /** * Update options for all providers. * * @since 1.4.7 * * @param string $provider Provider slug. * @param array|false $options If false is passed - provider will be removed. Otherwise saved. * @param string $key Optional key to identify which connection to update. If empty - generate a new one. */ function wpforms_update_providers_options( $provider, $options, $key = '' ) { $providers = wpforms_get_providers_options(); $id = ! empty( $key ) ? $key : uniqid(); $provider = sanitize_key( $provider ); if ( $options ) { $providers[ $provider ][ $id ] = (array) $options; } else { unset( $providers[ $provider ] ); } update_option( 'wpforms_providers', $providers ); } /** * Helper function to determine if loading an WPForms related admin page. * * Here we determine if the current administration page is owned/created by * WPForms. This is done in compliance with WordPress best practices for * development, so that we only load required WPForms CSS and JS files on pages * we create. As a result we do not load our assets admin wide, where they might * conflict with other plugins needlessly, also leading to a better, faster user * experience for our users. * * @since 1.3.9 * * @param string $slug Slug identifier for a specific WPForms admin page. * @param string $view Slug identifier for a specific WPForms admin page view ("subpage"). * * @return bool */ function wpforms_is_admin_page( $slug = '', $view = '' ) { // phpcs:disable WordPress.Security.NonceVerification.Recommended // Check against basic requirements. if ( ! is_admin() || empty( $_REQUEST['page'] ) || strpos( $_REQUEST['page'], 'wpforms' ) === false ) { return false; } // Check against page slug identifier. if ( ( ! empty( $slug ) && 'wpforms-' . $slug !== $_REQUEST['page'] ) || ( empty( $slug ) && 'wpforms-builder' === $_REQUEST['page'] ) ) { return false; } // Check against sub-level page view. if ( ! empty( $view ) && ( empty( $_REQUEST['view'] ) || $view !== $_REQUEST['view'] ) ) { return false; } // phpcs:enable return true; } /** * Get the ISO 639-2 Language Code from user/site locale. * * @see http://www.loc.gov/standards/iso639-2/php/code_list.php * * @since 1.5.0 * * @return string */ function wpforms_get_language_code() { $default_lang = 'en'; $locale = get_user_locale(); if ( ! empty( $locale ) ) { $lang = explode( '_', $locale ); if ( ! empty( $lang ) && is_array( $lang ) ) { $default_lang = strtolower( $lang[0] ); } } return $default_lang; } /** * Determine if we should show the "Show Values" toggle for checkbox, radio, or * select fields in form builder. Legacy. * * @since 1.5.0 * * @return bool */ function wpforms_show_fields_options_setting() { return apply_filters( 'wpforms_fields_show_options_setting', false ); } /** * Check if a string is empty. * * @since 1.5.0 * * @param string $string String to test. * * @return bool */ function wpforms_is_empty_string( $string ) { return is_string( $string ) && '' === $string; } /** * Return URL to form preview page. * * @since 1.5.1 * * @param int $form_id Form ID. * @param bool $new_window New window flag. * * @return string */ function wpforms_get_form_preview_url( $form_id, $new_window = false ) { $url = add_query_arg( array( 'wpforms_form_preview' => absint( $form_id ), ), home_url() ); if ( $new_window ) { $url = add_query_arg( array( 'new_window' => 1, ), $url ); } return $url; } /** * Include a template - alias to \WPForms\Helpers\Template::get_html. * Use 'require' if $args are passed or 'load_template' if not. * * @since 1.5.6 * * @param string $template_name Template name. * @param array $args Arguments. * @param bool $extract Extract arguments. * * @throws \RuntimeException If extract() tries to modify the scope. * * @return string Compiled HTML. */ function wpforms_render( $template_name, $args = array(), $extract = false ) { return \WPForms\Helpers\Templates::get_html( $template_name, $args, $extract ); } /** * Chain monad, useful for chaining certain array or string related functions. * * @since 1.5.6 * * @param mixed $value Any data. * * @return \WPForms\Helpers\Chain */ function wpforms_chain( $value ) { return \WPForms\Helpers\Chain::of( $value ); } /** * Get the current installation license type (always lowercase). * * @since 1.5.6 * * @return string|false */ function wpforms_get_license_type() { $type = \wpforms_setting( 'type', '', 'wpforms_license' ); if ( empty( $type ) || ! \wpforms()->pro ) { return false; } return strtolower( $type ); } /** * Get when WPForms was first installed. * * @since 1.6.0 * * @param string $type Specific install type to check for. * * @return int|false */ function wpforms_get_activated_timestamp( $type = '' ) { $activated = get_option( 'wpforms_activated', [] ); $types = ! empty( $type ) ? [ $type ] : [ 'lite', 'pro' ]; foreach ( $types as $type ) { if ( ! empty( $activated[ $type ] ) ) { return absint( $activated[ $type ] ); } } return false; } /** * Detect if AJAX frontend form submit is being processed. * * @since 1.5.8.2 * * @return bool */ function wpforms_is_frontend_ajax() { // It's an AJAX request. if ( ! wp_doing_ajax() ) { return false; } // It targets admin-ajax.php. if ( isset( $_SERVER['SCRIPT_FILENAME'] ) && basename( sanitize_text_field( wp_unslash( $_SERVER['SCRIPT_FILENAME'] ) ) ) !== 'admin-ajax.php' ) { return false; } $ref = wp_get_referer(); if ( ! $ref ) { return false; } $path = wp_parse_url( $ref, PHP_URL_PATH ); $admin_path = wp_parse_url( admin_url(), PHP_URL_PATH ); // It does not contain an admin path. if ( strpos( $path, $admin_path ) !== false ) { return false; } $action = isset( $_POST['action'] ) ? sanitize_key( $_POST['action'] ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Missing // It's a WPForms request. if ( strpos( $action, 'wpforms' ) !== 0 ) { return false; } return true; } class-install.php 0000666 00000010022 15213301445 0010023 0 ustar 00 <?php /** * Handle plugin installation upon activation. * * @since 1.0.0 */ class WPForms_Install { /** * Primary class constructor. * * @since 1.0.0 */ public function __construct() { // When activated, trigger install method. register_activation_hook( WPFORMS_PLUGIN_FILE, array( $this, 'install' ) ); register_deactivation_hook( WPFORMS_PLUGIN_FILE, array( $this, 'deactivate' ) ); // Watch for new multisite blogs. add_action( 'wpmu_new_blog', array( $this, 'new_multisite_blog' ), 10, 6 ); // Watch for delayed admin install. add_action( 'admin_init', array( $this, 'admin' ) ); } /** * Perform certain actions on plugin activation. * * @since 1.0.0 * * @param bool $network_wide Whether to enable the plugin for all sites in the network * or just the current site. Multisite only. Default is false. */ public function install( $network_wide = false ) { // Check if we are on multisite and network activating. if ( is_multisite() && $network_wide ) { // Multisite - go through each subsite and run the installer. if ( function_exists( 'get_sites' ) && class_exists( 'WP_Site_Query', false ) ) { // WP 4.6+. $sites = get_sites(); foreach ( $sites as $site ) { switch_to_blog( $site->blog_id ); $this->run(); restore_current_blog(); } } else { $sites = wp_get_sites( array( 'limit' => 0 ) ); foreach ( $sites as $site ) { switch_to_blog( $site['blog_id'] ); $this->run(); restore_current_blog(); } } } else { // Normal single site. $this->run(); } // Abort so we only set the transient for single site installs. if ( is_network_admin() || isset( $_GET['activate-multi'] ) ) { return; } // Add transient to trigger redirect to the Welcome screen. set_transient( 'wpforms_activation_redirect', true, 30 ); } /** * Run manual installation. * * @since 1.5.4.2 * * @param bool $silent Silent install, disables welcome page. */ public function manual( $silent = false ) { $this->install( is_plugin_active_for_network( plugin_basename( WPFORMS_PLUGIN_FILE ) ) ); if ( $silent ) { delete_transient( 'wpforms_activation_redirect' ); } } /** * Perform certain actions on plugin deactivation. * * @since 1.5.9 */ public function deactivate() { // Unschedule all ActionScheduler actions by group. wpforms()->get( 'tasks' )->cancel_all(); } /** * Watch for delayed install procedure from WPForms admin. * * @since 1.5.4.2 */ public function admin() { if ( ! is_admin() ) { return; } $install = get_option( 'wpforms_install', false ); if ( empty( $install ) ) { return; } $this->manual( true ); delete_option( 'wpforms_install' ); } /** * Run the actual installer. * * @since 1.5.4.2 */ protected function run() { // Hook for Pro users. do_action( 'wpforms_install' ); // Set current version, to be referenced in future updates. update_option( 'wpforms_version', WPFORMS_VERSION ); // Store the date when the initial activation was performed. $type = class_exists( 'WPForms_Lite', false ) ? 'lite' : 'pro'; $activated = get_option( 'wpforms_activated', array() ); if ( empty( $activated[ $type ] ) ) { $activated[ $type ] = time(); update_option( 'wpforms_activated', $activated ); } } /** * When a new site is created in multisite, see if we are network activated, * and if so run the installer. * * @since 1.3.0 * * @param int $blog_id Blog ID. * @param int $user_id User ID. * @param string $domain Site domain. * @param string $path Site path. * @param int $site_id Site ID. Only relevant on multi-network installs. * @param array $meta Meta data. Used to set initial site options. */ public function new_multisite_blog( $blog_id, $user_id, $domain, $path, $site_id, $meta ) { if ( is_plugin_active_for_network( plugin_basename( WPFORMS_PLUGIN_FILE ) ) ) { switch_to_blog( $blog_id ); $this->run(); restore_current_blog(); } } } new WPForms_Install(); admin/class-editor.php 0000666 00000022047 15213301445 0010745 0 ustar 00 <?php /** * Functionality related to the admin TinyMCE editor. * * @since 1.0.0 */ class WPForms_Admin_Editor { /** * Primary class constructor. * * @since 1.0.0 */ public function __construct() { add_action( 'media_buttons', array( $this, 'media_button' ), 15 ); } /** * Allow easy shortcode insertion via a custom media button. * * @since 1.0.0 * * @param string $editor_id */ public function media_button( $editor_id ) { if ( ! \wpforms_current_user_can( 'view_forms' ) ) { return; } // Provide the ability to conditionally disable the button, so it can be // disabled for custom fields or front-end use such as bbPress. We default // to only showing within the admin panel. if ( ! apply_filters( 'wpforms_display_media_button', is_admin(), $editor_id ) ) { return; } // Setup the icon - currently using a dashicon. $icon = '<span class="wp-media-buttons-icon wpforms-menu-icon" style="font-size:16px;margin-top:-2px;"><svg width="18" height="18" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><path d="M643 911v128h-252v-128h252zm0-255v127h-252v-127h252zm758 511v128h-341v-128h341zm0-256v128h-672v-128h672zm0-255v127h-672v-127h672zm135 860v-1240q0-8-6-14t-14-6h-32l-378 256-210-171-210 171-378-256h-32q-8 0-14 6t-6 14v1240q0 8 6 14t14 6h1240q8 0 14-6t6-14zm-855-1110l185-150h-406zm430 0l221-150h-406zm553-130v1240q0 62-43 105t-105 43h-1240q-62 0-105-43t-43-105v-1240q0-62 43-105t105-43h1240q62 0 105 43t43 105z" fill="#82878c"/></svg></span>'; printf( '<a href="#" class="button wpforms-insert-form-button" data-editor="%s" title="%s">%s %s</a>', esc_attr( $editor_id ), esc_attr__( 'Add Form', 'wpforms-lite' ), $icon, __( 'Add Form', 'wpforms-lite' ) ); // If we have made it this far then load the JS. wp_enqueue_script( 'wpforms-editor', WPFORMS_PLUGIN_URL . 'assets/js/admin-editor.js', array( 'jquery' ), WPFORMS_VERSION, true ); add_action( 'admin_footer', array( $this, 'shortcode_modal' ) ); } /** * Modal window for inserting the form shortcode into TinyMCE. * * Thickbox is old and busted so we don't use that. Creating a custom view in * Backbone would make me pull my hair out. So instead we offer a small clean * modal that is based off of the WordPress insert link modal. * * @since 1.0.0 */ public function shortcode_modal() { ?> <div id="wpforms-modal-backdrop" style="display: none"></div> <div id="wpforms-modal-wrap" style="display: none"> <form id="wpforms-modal" tabindex="-1"> <div id="wpforms-modal-title"> <?php esc_html_e( 'Insert Form', 'wpforms-lite' ); ?> <button type="button" id="wpforms-modal-close"><span class="screen-reader-text"><?php esc_html_e( 'Close', 'wpforms-lite' ); ?></span></button> </div> <div id="wpforms-modal-inner"> <div id="wpforms-modal-options"> <?php echo '<p id="wpforms-modal-notice">'; printf( wp_kses( /* translators: %s - WPForms documentation link. */ __( 'Heads up! Don\'t forget to test your form. <a href="%s" target="_blank" rel="noopener noreferrer">Check out our complete guide</a>!', 'wpforms-lite' ), array( 'a' => array( 'href' => array(), 'rel' => array(), 'target' => array(), ), ) ), 'https://wpforms.com/docs/how-to-properly-test-your-wordpress-forms-before-launching-checklist/' ); echo '</p>'; $args = apply_filters( 'wpforms_modal_select', array() ); $forms = wpforms()->form->get( '', $args ); if ( ! empty( $forms ) ) { printf( '<p><label for="wpforms-modal-select-form">%s</label></p>', esc_html__( 'Select a form below to insert', 'wpforms-lite' ) ); echo '<select id="wpforms-modal-select-form">'; foreach ( $forms as $form ) { printf( '<option value="%d">%s</option>', $form->ID, esc_html( $form->post_title ) ); } echo '</select><br>'; printf( '<p class="wpforms-modal-inline"><input type="checkbox" id="wpforms-modal-checkbox-title"><label for="wpforms-modal-checkbox-title">%s</label></p>', esc_html__( 'Show form name', 'wpforms-lite' ) ); printf( '<p class="wpforms-modal-inline"><input type="checkbox" id="wpforms-modal-checkbox-description"><label for="wpforms-modal-checkbox-description">%s</label></p>', esc_html__( 'Show form description', 'wpforms-lite' ) ); } else { echo '<p>'; printf( wp_kses( /* translators: %s - WPForms Builder page. */ __( 'Whoops, you haven\'t created a form yet. Want to <a href="%s">give it a go</a>?', 'wpforms-lite' ), array( 'a' => array( 'href' => array(), ), ) ), admin_url( 'admin.php?page=wpforms-builder' ) ); echo '</p>'; } ?> </div> </div> <div class="submitbox"> <div id="wpforms-modal-cancel"> <a class="submitdelete deletion" href="#"><?php esc_html_e( 'Cancel', 'wpforms-lite' ); ?></a> </div> <?php if ( ! empty( $forms ) ) : ?> <div id="wpforms-modal-update"> <button class="button button-primary" id="wpforms-modal-submit"><?php esc_html_e( 'Add Form', 'wpforms-lite' ); ?></button> </div> <?php endif; ?> </div> </form> </div> <style type="text/css"> #wpforms-modal-wrap { display: none; background-color: #fff; -webkit-box-shadow: 0 3px 6px rgba(0, 0, 0, 0.3); box-shadow: 0 3px 6px rgba(0, 0, 0, 0.3); width: 500px; height: 285px; overflow: hidden; margin-left: -250px; margin-top: -125px; position: fixed; top: 50%; left: 50%; z-index: 100105; -webkit-transition: height 0.2s, margin-top 0.2s; transition: height 0.2s, margin-top 0.2s; } #wpforms-modal-backdrop { display: none; position: fixed; top: 0; left: 0; right: 0; bottom: 0; min-height: 360px; background: #000; opacity: 0.7; filter: alpha(opacity=70); z-index: 100100; } #wpforms-modal { position: relative; height: 100%; } #wpforms-modal-title { background: #fcfcfc; border-bottom: 1px solid #dfdfdf; height: 36px; font-size: 18px; font-weight: 600; line-height: 36px; padding: 0 36px 0 16px; top: 0; right: 0; left: 0; } #wpforms-modal-close { color: #666; padding: 0; position: absolute; top: 0; right: 0; width: 36px; height: 36px; text-align: center; background: none; border: none; cursor: pointer; } #wpforms-modal-close:before { font: normal 20px/36px 'dashicons'; vertical-align: top; speak: none; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; width: 36px; height: 36px; content: '\f158'; } #wpforms-modal-close:hover, #wpforms-modal-close:focus { color: #2ea2cc; } #wpforms-modal-close:focus { outline: none; -webkit-box-shadow: 0 0 0 1px #5b9dd9, 0 0 2px 1px rgba(30, 140, 190, .8); box-shadow: 0 0 0 1px #5b9dd9, 0 0 2px 1px rgba(30, 140, 190, .8); } #wpforms-modal-inner { padding: 0 16px 50px; } #wpforms-modal-search-toggle:after { display: inline-block; font: normal 20px/1 'dashicons'; vertical-align: top; speak: none; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; content: '\f140'; } #wpforms-modal-notice { background-color: #d9edf7; border: 1px solid #bce8f1; color: #31708f; padding: 10px; } #wpforms-modal #wpforms-modal-options { padding: 8px 0 12px; } #wpforms-modal #wpforms-modal-options .wpforms-modal-inline { display: inline-block; margin: 0; padding: 0 20px 0 0; } #wpforms-modal-select-form { margin-bottom: 1em; max-width: 100%; } #wpforms-modal .submitbox { padding: 8px 16px; background: #fcfcfc; border-top: 1px solid #dfdfdf; position: absolute; bottom: 0; left: 0; right: 0; } #wpforms-modal-cancel { line-height: 25px; float: left; } #wpforms-modal-update { line-height: 23px; float: right; } #wpforms-modal-submit { float: right; margin-bottom: 0; } @media screen and ( max-width: 782px ) { #wpforms-modal-wrap { height: 280px; margin-top: -140px; } #wpforms-modal-inner { padding: 0 16px 60px; } #wpforms-modal-cancel { line-height: 32px; } } @media screen and ( max-width: 520px ) { #wpforms-modal-wrap { width: auto; margin-left: 0; left: 10px; right: 10px; max-width: 500px; } } @media screen and ( max-height: 520px ) { #wpforms-modal-wrap { -webkit-transition: none; transition: none; } } @media screen and ( max-height: 290px ) { #wpforms-modal-wrap { height: auto; margin-top: 0; top: 10px; bottom: 10px; } #wpforms-modal-inner { overflow: auto; height: -webkit-calc(100% - 92px); height: calc(100% - 92px); padding-bottom: 2px; } } </style> <?php } } new WPForms_Admin_Editor; admin/class-tools.php 0000666 00000104411 15213301445 0010613 0 ustar 00 <?php /** * Tools admin page class. * * @since 1.3.9 */ class WPForms_Tools { /** * The current active tab. * * @since 1.3.9 * * @var string */ public $view; /** * Template code if generated. * * @since 1.3.9 * * @var string */ private $template = false; /** * Registered importers. * * @since 1.4.2 * * @var array */ public $importers = array(); /** * Available forms for a specific importer. * * @since 1.4.2 * * @var array */ public $importer_forms = array(); /** * The available forms. * * @since 1.3.9 * * @var array */ public $forms = false; /** * The core views. * * @since 1.4.3 * * @var array */ public $views = array(); /** * Primary class constructor. * * @since 1.3.9 */ public function __construct() { // Maybe load tools page. add_action( 'admin_init', array( $this, 'init' ) ); } /** * Determining if the user is viewing the tools page, if so, party on. * * @since 1.3.9 */ public function init() { // Check what page we are on. $page = isset( $_GET['page'] ) ? $_GET['page'] : ''; // Only load if we are actually on the settings page. if ( 'wpforms-tools' !== $page ) { return; } $views = array(); if ( wpforms_current_user_can( 'create_forms' ) ) { $views[ esc_html__( 'Import', 'wpforms-lite' ) ] = array( 'import', 'importer' ); } if ( wpforms_current_user_can( array( 'view_forms', 'view_entries' ) ) ) { $views[ esc_html__( 'Export', 'wpforms-lite' ) ] = array( 'export' ); } if ( wpforms_current_user_can() ) { $views[ esc_html__( 'System Info', 'wpforms-lite' ) ] = array( 'system' ); } // Define the core views for the tools tab. $this->views = apply_filters( 'wpforms_tools_views', $views ); $view_ids = call_user_func_array( 'array_merge', $views ); // Determine the current active settings tab. $this->view = ! empty( $_GET['view'] ) ? esc_html( $_GET['view'] ) : 'import'; // If the user tries to load an invalid view - fallback to the first available. if ( ! in_array( $this->view, $view_ids, true ) && ! has_action( 'wpforms_tools_display_tab_' . sanitize_key( $this->view ) ) ) { $this->view = reset( $view_ids ); } if ( empty( $this->view ) ) { return; } if ( in_array( $this->view, array( 'import', 'importer' ), true ) ) { // If we're on the an import related tab, then build a list of // all available importers. $this->importers = apply_filters( 'wpforms_importers', $this->importers ); // Get all forms for the previous form provider. if ( ! empty( $_GET['provider'] ) ) { $provider = sanitize_key( $_GET['provider'] ); $this->importer_forms = apply_filters( "wpforms_importer_forms_{$provider}", $this->importer_forms ); } // Load the Underscores templates for importers. add_action( 'admin_print_scripts', array( $this, 'importer_templates' ) ); } // Retrieve available forms. $this->forms = wpforms()->form->get( '', array( 'orderby' => 'title' ) ); add_action( 'wpforms_tools_init', array( $this, 'import_export_process' ) ); add_action( 'wpforms_admin_page', array( $this, 'output' ) ); // Hook for addons. do_action( 'wpforms_tools_init' ); } /** * Build the output for the Tools admin page. * * @since 1.3.9 */ public function output() { $show_nav = false; foreach ( $this->views as $view ) { if ( in_array( $this->view, (array) $view, true ) ) { $show_nav = true; break; } } ?> <div id="wpforms-tools" class="wrap wpforms-admin-wrap"> <?php if ( $show_nav ) { echo '<ul class="wpforms-admin-tabs">'; foreach ( $this->views as $label => $view ) { $view = (array) $view; $class = in_array( $this->view, $view, true ) ? ' class="active"' : ''; echo '<li>'; printf( '<a href="%s"%s>%s</a>', admin_url( 'admin.php?page=wpforms-tools&view=' . sanitize_key( $view[0] ) ), $class, esc_html( $label ) ); echo '</li>'; } echo '</ul>'; } ?> <h1 class="wpforms-h1-placeholder"></h1> <?php if ( isset( $_GET['wpforms_notice'] ) && 'forms-imported' === $_GET['wpforms_notice'] ) { ?> <div class="updated notice is-dismissible"> <p> <?php printf( wp_kses( /* translators: %s - Forms list page URL. */ __( 'Import was successfully finished. You can go and <a href="%s">check your forms</a>.', 'wpforms-lite' ), array( 'a' => array( 'href' => array(), ), ) ), admin_url( 'admin.php?page=wpforms-overview' ) ); ?> </p> </div> <?php } ?> <div class="wpforms-admin-content wpforms-admin-settings"> <?php switch ( $this->view ) { case 'system': $this->system_info_tab(); break; case 'export': $this->export_tab(); break; case 'importer': $this->importer_tab(); break; case 'import': $this->import_tab(); break; default: do_action( 'wpforms_tools_display_tab_' . sanitize_key( $this->view ) ); break; } ?> </div> </div> <?php } /** * Import tab contents. * * @since 1.4.2 */ public function import_tab() { ?> <div class="wpforms-setting-row tools"> <h3><?php esc_html_e( 'WPForms Import', 'wpforms-lite' ); ?></h3> <p><?php esc_html_e( 'Select a WPForms export file.', 'wpforms-lite' ); ?></p> <form method="post" enctype="multipart/form-data" action="<?php echo esc_url( admin_url( 'admin.php?page=wpforms-tools&view=import' ) ); ?>"> <div class="wpforms-file-upload"> <input type="file" name="file" id="wpforms-tools-form-import" class="inputfile" data-multiple-caption="{count} <?php esc_attr_e( 'files selected', 'wpforms-lite' ); ?>" accept=".json" /> <label for="wpforms-tools-form-import"> <span class="fld"><span class="placeholder"><?php esc_html_e( 'No file chosen', 'wpforms-lite' ); ?></span></span> <strong class="wpforms-btn wpforms-btn-md wpforms-btn-light-grey"> <i class="fa fa-upload" aria-hidden="true"></i> <?php esc_html_e( 'Choose a file…', 'wpforms-lite' ); ?> </strong> </label> </div> <br> <input type="hidden" name="action" value="import_form"> <button type="submit" name="submit-importexport" class="wpforms-btn wpforms-btn-md wpforms-btn-orange"><?php esc_html_e( 'Import', 'wpforms-lite' ); ?></button> <?php wp_nonce_field( 'wpforms_import_nonce', 'wpforms-tools-importexport-nonce' ); ?> </form> </div> <div class="wpforms-setting-row tools" id="wpforms-importers"> <h3><?php esc_html_e( 'Import from Other Form Plugins', 'wpforms-lite' ); ?></h3> <p><?php esc_html_e( 'Not happy with other WordPress contact form plugins?', 'wpforms-lite' ); ?></p> <p><?php esc_html_e( 'WPForms makes it easy for you to switch by allowing you import your third-party forms with a single click.', 'wpforms-lite' ); ?></p> <div class="wpforms-importers-wrap"> <?php if ( empty( $this->importers ) ) { ?> <p><?php esc_html_e( 'No form importers are currently enabled.', 'wpforms-lite' ); ?> </p> <?php } else { ?> <form method="get" action="<?php echo esc_url( admin_url( 'admin.php' ) ); ?>"> <span class="choicesjs-select-wrap"> <select class="choicesjs-select" name="provider" required> <option value=""><?php esc_html_e( 'Select previous contact form plugin...', 'wpforms-lite' ); ?></option> <?php foreach ( $this->importers as $importer ) { $status = ''; if ( empty( $importer['installed'] ) ) { $status = esc_html__( 'Not Installed', 'wpforms-lite' ); } elseif ( empty( $importer['active'] ) ) { $status = esc_html__( 'Not Active', 'wpforms-lite' ); } printf( '<option value="%s" %s>%s %s</option>', esc_attr( $importer['slug'] ), ! empty( $status ) ? 'disabled' : '', esc_html( $importer['name'] ), ! empty( $status ) ? '(' . $status . ')' : '' ); } ?> </select> </span> <br /> <input type="hidden" name="page" value="wpforms-tools"> <input type="hidden" name="view" value="importer"> <button type="submit" class="wpforms-btn wpforms-btn-md wpforms-btn-orange"><?php esc_html_e( 'Import', 'wpforms-lite' ); ?></button> </form> <?php } ?> </div> </div> <?php } /** * Importer tab contents. * * @since 1.4.2 */ public function importer_tab() { $slug = ! empty( $_GET['provider'] ) ? sanitize_key( $_GET['provider'] ) : ''; $provider = $this->importers[ $slug ]; ?> <div class="wpforms-setting-row tools wpforms-clear section-heading no-desc"> <div class="wpforms-setting-field"> <h4><?php esc_html_e( 'Form Import', 'wpforms-lite' ); ?></h4> </div> </div> <div id="wpforms-importer-forms"> <div class="wpforms-setting-row tools"> <p><?php esc_html_e( 'Select the forms you would like to import.', 'wpforms-lite' ); ?></p> <div class="checkbox-multiselect-columns"> <div class="first-column"> <h5 class="header"><?php esc_html_e( 'Available Forms', 'wpforms-lite' ); ?></h5> <ul> <?php if ( empty( $this->importer_forms ) ) { echo '<li>' . esc_html__( 'No forms found.', 'wpforms-lite' ) . '</li>'; } else { foreach ( $this->importer_forms as $id => $form ) { printf( '<li><label><input type="checkbox" name="forms[]" value="%s">%s</label></li>', esc_attr( $id ), sanitize_text_field( $form ) ); } } ?> </ul> <?php if ( ! empty( $this->importer_forms ) ) : ?> <a href="#" class="all"><?php esc_html_e( 'Select All', 'wpforms-lite' ); ?></a> <?php endif; ?> </div> <div class="second-column"> <h5 class="header"><?php esc_html_e( 'Forms to Import', 'wpforms-lite' ); ?></h5> <ul></ul> </div> </div> </div> <?php if ( ! empty( $this->importer_forms ) ) : ?> <p class="submit"> <button class="wpforms-btn wpforms-btn-md wpforms-btn-orange" id="wpforms-importer-forms-submit"><?php esc_html_e( 'Import', 'wpforms-lite' ); ?></button> </p> <?php endif; ?> </div> <div id="wpforms-importer-analyze"> <p class="process-analyze"> <i class="fa fa-spinner fa-spin" aria-hidden="true"></i> <?php printf( /* translators: %1$s - current forms counter; %2$s - total forms counter; %3$s - provider name. */ esc_html__( 'Analyzing %1$s of %2$s forms from %3$s.', 'wpforms-lite' ), '<span class="form-current">1</span>', '<span class="form-total">0</span>', sanitize_text_field( $provider['name'] ) ); ?> </p> <div class="upgrade"> <h5><?php esc_html_e( 'Heads Up!', 'wpforms-lite' ); ?></h5> <p><?php esc_html_e( 'One or more of your forms contain fields that are not available in WPForms Lite. To properly import these fields, we recommend upgrading to WPForms Pro.', 'wpforms-lite' ); ?></p> <p><?php esc_html_e( 'You can continue with the import without upgrading, and we will do our best to match the fields. However, some of them will be omitted due to compatibility issues.', 'wpforms-lite' ); ?></p> <p> <a href="<?php echo esc_url( wpforms_admin_upgrade_link( 'tools-import' ) ); ?>" target="_blank" rel="noopener noreferrer" class="wpforms-btn wpforms-btn-md wpforms-btn-orange wpforms-upgrade-modal"><?php esc_html_e( 'Upgrade to WPForms Pro', 'wpforms-lite' ); ?></a> <a href="#" class="wpforms-btn wpforms-btn-md wpforms-btn-light-grey" id="wpforms-importer-continue-submit"><?php esc_html_e( 'Continue Import without Upgrading', 'wpforms-lite' ); ?></a> </p> <hr> <p><?php esc_html_e( 'Below is the list of form fields that may be impacted:', 'wpforms-lite' ); ?></p> </div> </div> <div id="wpforms-importer-process"> <p class="process-count"> <i class="fa fa-spinner fa-spin" aria-hidden="true"></i> <?php printf( /* translators: %1$s - current forms counter; %2$s - total forms counter; %3$s - provider name. */ esc_html__( 'Importing %1$s of %2$s forms from %3$s.', 'wpforms-lite' ), '<span class="form-current">1</span>', '<span class="form-total">0</span>', sanitize_text_field( $provider['name'] ) ); ?> </p> <p class="process-completed"> <?php printf( /* translators: %s - number of imported forms. */ esc_html__( 'Congrats, the import process has finished! We have successfully imported %s forms. You can review the results below.', 'wpforms-lite' ), '<span class="forms-completed"></span>' ); ?> </p> <div class="status"></div> </div> <?php } /** * Various Underscores templates for form importing. * * @since 1.4.2 */ public function importer_templates() { ?> <script type="text/html" id="tmpl-wpforms-importer-upgrade"> <# _.each( data, function( item, key ) { #> <ul> <li class="form">{{ item.name }}</li> <# _.each( item.fields, function( val, key ) { #> <li>{{ val }}</li> <# }) #> </ul> <# }) #> </script> <script type="text/html" id="tmpl-wpforms-importer-status-error"> <div class="item"> <div class="wpforms-clear"> <span class="name"> <i class="status-icon fa fa-times" aria-hidden="true"></i> {{ data.name }} </span> </div> <p>{{ data.msg }}</p> </div> </script> <script type="text/html" id="tmpl-wpforms-importer-status-update"> <div class="item"> <div class="wpforms-clear"> <span class="name"> <# if ( ! _.isEmpty( data.upgrade_omit ) ) { #> <i class="status-icon fa fa-exclamation-circle" aria-hidden="true"></i> <# } else if ( ! _.isEmpty( data.upgrade_plain ) ) { #> <i class="status-icon fa fa-exclamation-triangle" aria-hidden="true"></i> <# } else if ( ! _.isEmpty( data.unsupported ) ) { #> <i class="status-icon fa fa-info-circle" aria-hidden="true"></i> <# } else { #> <i class="status-icon fa fa-check" aria-hidden="true"></i> <# } #> {{ data.name }} </span> <span class="actions"> <a href="{{ data.edit }}" target="_blank"><?php esc_html_e( 'Edit', 'wpforms-lite' ); ?></a> <span class="sep">|</span> <a href="{{ data.preview }}" target="_blank"><?php esc_html_e( 'Preview', 'wpforms-lite' ); ?></a> </span> </div> <# if ( ! _.isEmpty( data.upgrade_omit ) ) { #> <p><?php esc_html_e( 'The following fields are available in PRO and were not imported:', 'wpforms-lite' ); ?></p> <ul> <# _.each( data.upgrade_omit, function( val, key ) { #> <li>{{ val }}</li> <# }) #> </ul> <# } #> <# if ( ! _.isEmpty( data.upgrade_plain ) ) { #> <p><?php esc_html_e( 'The following fields are available in PRO and were imported as text fields:', 'wpforms-lite' ); ?></p> <ul> <# _.each( data.upgrade_plain, function( val, key ) { #> <li>{{ val }}</li> <# }) #> </ul> <# } #> <# if ( ! _.isEmpty( data.unsupported ) ) { #> <p><?php esc_html_e( 'The following fields are not supported and were not imported:', 'wpforms-lite' ); ?></p> <ul> <# _.each( data.unsupported, function( val, key ) { #> <li>{{ val }}</li> <# }) #> </ul> <# } #> <# if ( ! _.isEmpty( data.upgrade_plain ) || ! _.isEmpty( data.upgrade_omit ) ) { #> <p> <?php esc_html_e( 'Upgrade to the PRO plan to import these fields.' ); ?><br><br> <a href="<?php echo esc_url( wpforms_admin_upgrade_link( 'tools-import' ) ); ?>" class="wpforms-btn wpforms-btn-orange wpforms-btn-md wpforms-upgrade-modal" target="_blank" rel="noopener noreferrer"> <?php esc_html_e( 'Upgrade Now', 'wpforms-lite' ); ?> </a> </p> <# } #> </div> </script> <?php } /** * Export tab contents. * * @since 1.4.2 */ public function export_tab() { do_action( 'wpforms_admin_tools_export_top' ); if ( $this->forms ) { $this->export_tab_html(); } do_action( 'wpforms_admin_tools_export_bottom' ); } /** * Export tab contents. * * @since 1.5.8 */ public function export_tab_html() { ?> <div class="wpforms-setting-row tools"> <h3 id="form-export"><?php esc_html_e( 'Form Export', 'wpforms-lite' ); ?></h3> <p><?php esc_html_e( 'Form exports files can be used to create a backup of your forms or to import forms into another site.', 'wpforms-lite' ); ?></p> <form method="post" action="<?php echo esc_url( admin_url( 'admin.php?page=wpforms-tools&view=export' ) ); ?>"> <?php if ( ! empty( $this->forms ) ) { echo '<span class="choicesjs-select-wrap">'; echo '<select id="wpforms-tools-form-export" class="choicesjs-select" name="forms[]" multiple data-placeholder="' . esc_attr__( 'Select form(s)', 'wpforms-lite' ) . '">'; foreach ( $this->forms as $form ) { printf( '<option value="%d">%s</option>', absint( $form->ID ), esc_html( $form->post_title ) ); } echo '</select>'; echo '</span>'; } else { echo '<p>' . esc_html__( 'You need to create a form before you can use form export.', 'wpforms-lite' ) . '</p>'; } ?> <br> <input type="hidden" name="action" value="export_form"> <?php wp_nonce_field( 'wpforms_import_nonce', 'wpforms-tools-importexport-nonce' ); ?> <button type="submit" name="submit-importexport" class="wpforms-btn wpforms-btn-md wpforms-btn-orange"><?php esc_html_e( 'Export', 'wpforms-lite' ); ?></button> </form> </div> <div class="wpforms-setting-row tools"> <h3 id="template-export"><?php esc_html_e( 'Form Template Export', 'wpforms-lite' ); ?></h3> <?php if ( $this->template ) { echo '<p>' . esc_html__( 'The following code can be used to register your custom form template. Copy and paste the following code to your theme\'s functions.php file or include it within an external file.', 'wpforms-lite' ) . '<p>'; echo '<p>' . sprintf( wp_kses( /* translators: %s - WPForms.com docs URL. */ __( 'For more information <a href="%s" target="_blank" rel="noopener noreferrer">see our documentation</a>.', 'wpforms-lite' ), array( 'a' => array( 'href' => array(), 'target' => array(), 'rel' => array(), ), ) ), 'https://wpforms.com/docs/how-to-create-a-custom-form-template/' ) . '<p>'; echo '<textarea class="info-area" readonly>' . esc_textarea( $this->template ) . '</textarea><br>'; } ?> <p><?php esc_html_e( 'Select a form to generate PHP code that can be used to register a custom form template.', 'wpforms-lite' ); ?></p> <form method="post" action="<?php echo esc_url( admin_url( 'admin.php?page=wpforms-tools&view=export#template-export' ) ); ?>"> <?php if ( ! empty( $this->forms ) ) { echo '<span class="choicesjs-select-wrap">'; echo '<select id="wpforms-tools-form-template" class="choicesjs-select" name="form">'; foreach ( $this->forms as $form ) { printf( '<option value="%d">%s</option>', absint( $form->ID ), esc_html( $form->post_title ) ); } echo '</select>'; echo '</span>'; } else { echo '<p>' . esc_html__( 'You need to create a form before you can generate a template.', 'wpforms-lite' ) . '</p>'; } ?> <br> <input type="hidden" name="action" value="export_template"> <?php wp_nonce_field( 'wpforms_import_nonce', 'wpforms-tools-importexport-nonce' ); ?> <button type="submit" name="submit-importexport" class="wpforms-btn wpforms-btn-md wpforms-btn-orange"><?php esc_html_e( 'Export Template', 'wpforms-lite' ); ?></button> </form> </div> <?php } /** * System Info tab contents. * * @since 1.3.9 */ public function system_info_tab() { if ( ! wpforms_current_user_can() ) { return; } ?> <div class="wpforms-setting-row tools"> <h3 id="form-export"><?php esc_html_e( 'System Information', 'wpforms-lite' ); ?></h3> <textarea readonly="readonly" class="info-area"><?php echo $this->get_system_info(); ?></textarea> </div> <div class="wpforms-setting-row tools"> <h3 id="ssl-verify"><?php esc_html_e( 'Test SSL Connections', 'wpforms-lite' ); ?></h3> <p><?php esc_html_e( 'Click the button below to verify your web server can perform SSL connections successfully.', 'wpforms-lite' ); ?></p> <button type="button" id="wpforms-ssl-verify" class="wpforms-btn wpforms-btn-md wpforms-btn-orange"><?php esc_html_e( 'Test Connection', 'wpforms-lite' ); ?></button> </div> <?php } /** * Import/Export processing. * * @since 1.3.9 */ public function import_export_process() { // Check for triggered save. if ( empty( $_POST['wpforms-tools-importexport-nonce'] ) || empty( $_POST['action'] ) || ! isset( $_POST['submit-importexport'] ) ) { return; } // Check for valid nonce and permission. if ( ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['wpforms-tools-importexport-nonce'] ) ), 'wpforms_import_nonce' ) ) { return; } // Import Form(s). if ( 'import_form' === $_POST['action'] && ! empty( $_FILES['file']['tmp_name'] ) ) { $this->import_process(); } // Export Form(s). if ( 'export_form' === $_POST['action'] && ! empty( $_POST['forms'] ) ) { $this->export_process(); } // Export form template. if ( 'export_template' === $_POST['action'] && ! empty( $_POST['form'] ) ) { $this->export_template_process(); } } /** * Import processing. * * @since 1.5.8 */ protected function import_process() { if ( ! wpforms_current_user_can( 'create_forms' ) ) { return; } // Add filter of the link rel attr to avoid JSON damage. add_filter( 'wp_targeted_link_rel', '__return_empty_string', 50, 1 ); $ext = isset( $_FILES['file']['name'] ) ? strtolower( pathinfo( sanitize_text_field( wp_unslash( $_FILES['file']['name'] ) ), PATHINFO_EXTENSION ) ) : ''; if ( 'json' !== $ext ) { wp_die( esc_html__( 'Please upload a valid .json form export file.', 'wpforms-lite' ), esc_html__( 'Error', 'wpforms-lite' ), array( 'response' => 400, ) ); } $tmp_name = isset( $_FILES['file']['tmp_name'] ) ? sanitize_text_field( $_FILES['file']['tmp_name'] ) : ''; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash -- wp_unslash() breaks upload on Windows. $forms = json_decode( file_get_contents( $tmp_name ), true ); if ( empty( $forms ) || ! is_array( $forms ) ) { wp_die( esc_html__( 'Form data cannot be imported.', 'wpforms-lite' ), esc_html__( 'Error', 'wpforms-lite' ), array( 'response' => 400, ) ); } foreach ( $forms as $form ) { $title = ! empty( $form['settings']['form_title'] ) ? $form['settings']['form_title'] : ''; $desc = ! empty( $form['settings']['form_desc'] ) ? $form['settings']['form_desc'] : ''; $new_id = wp_insert_post( array( 'post_title' => $title, 'post_status' => 'publish', 'post_type' => 'wpforms', 'post_excerpt' => $desc, ) ); if ( $new_id ) { $form['id'] = $new_id; wp_update_post( array( 'ID' => $new_id, 'post_content' => wpforms_encode( $form ), ) ); } } wp_safe_redirect( admin_url( 'admin.php?page=wpforms-tools&view=importexport&wpforms_notice=forms-imported' ) ); exit; } /** * Export processing. * * @since 1.5.8 */ protected function export_process() { if ( ! wpforms_current_user_can( 'create_forms' ) ) { return; } $export = array(); $forms = get_posts( array( 'post_type' => 'wpforms', 'no_found_rows' => true, 'nopaging' => true, 'post__in' => isset( $_POST['forms'] ) ? array_map( 'intval', $_POST['forms'] ) : array(), // phpcs:ignore WordPress.Security.NonceVerification.Missing ) ); foreach ( $forms as $form ) { $export[] = wpforms_decode( $form->post_content ); } ignore_user_abort( true ); if ( ! in_array( 'set_time_limit', explode( ',', ini_get( 'disable_functions' ) ), true ) ) { set_time_limit( 0 ); } nocache_headers(); header( 'Content-Type: application/json; charset=utf-8' ); header( 'Content-Disposition: attachment; filename=wpforms-form-export-' . current_time( 'm-d-Y' ) . '.json' ); header( 'Expires: 0' ); echo wp_json_encode( $export ); exit; } /** * Export template processing. * * @since 1.5.8 */ protected function export_template_process() { if ( ! wpforms_current_user_can( 'create_forms' ) ) { return; } if ( ! isset( $_POST['form'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing return; } $form_data = wpforms()->form->get( absint( $_POST['form'] ), // phpcs:ignore WordPress.Security.NonceVerification.Missing array( 'content_only' => true ) ); if ( ! $form_data ) { return; } // Define basic data. $name = sanitize_text_field( $form_data['settings']['form_title'] ); $desc = sanitize_text_field( $form_data['settings']['form_desc'] ); $slug = sanitize_key( str_replace( ' ', '_', $form_data['settings']['form_title'] ) ); $class = 'WPForms_Template_' . $slug; // Format template field and settings data. $data = $form_data; $data['meta']['template'] = $slug; $data['fields'] = wpforms_array_remove_empty_strings( $data['fields'] ); $data['settings'] = wpforms_array_remove_empty_strings( $data['settings'] ); unset( $data['id'] ); $data = var_export( $data, true ); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_var_export $data = str_replace( ' ', "\t", $data ); $data = preg_replace( '/([\t\r\n]+?)array/', 'array', $data ); // Build the final template string. $this->template = <<<EOT if ( class_exists( 'WPForms_Template', false ) ) : /** * {$name} * Template for WPForms. */ class {$class} extends WPForms_Template { /** * Primary class constructor. * * @since 1.0.0 */ public function init() { // Template name \$this->name = '{$name}'; // Template slug \$this->slug = '{$slug}'; // Template description \$this->description = '{$desc}'; // Template field and settings \$this->data = {$data}; } } new {$class}; endif; EOT; } /** * Get system information. * * Based on a function from Easy Digital Downloads by Pippin Williamson. * * @link https://github.com/easydigitaldownloads/easy-digital-downloads/blob/master/includes/admin/tools.php#L470 * * @since 1.3.9 * * @return string */ public function get_system_info() { global $wpdb; // Get theme info. $theme_data = wp_get_theme(); $theme = $theme_data->Name . ' ' . $theme_data->Version; $return = '### Begin System Info ###' . "\n\n"; // WPForms info. $activated = get_option( 'wpforms_activated', array() ); $return .= '-- WPForms Info' . "\n\n"; if ( ! empty( $activated['pro'] ) ) { $date = $activated['pro'] + ( get_option( 'gmt_offset' ) * 3600 ); $return .= 'Pro: ' . date_i18n( esc_html__( 'M j, Y @ g:ia' ), $date ) . "\n"; } if ( ! empty( $activated['lite'] ) ) { $date = $activated['lite'] + ( get_option( 'gmt_offset' ) * 3600 ); $return .= 'Lite: ' . date_i18n( esc_html__( 'M j, Y @ g:ia' ), $date ) . "\n"; } // Now the basics... $return .= "\n" . '-- Site Info' . "\n\n"; $return .= 'Site URL: ' . site_url() . "\n"; $return .= 'Home URL: ' . home_url() . "\n"; $return .= 'Multisite: ' . ( is_multisite() ? 'Yes' : 'No' ) . "\n"; // WordPress configuration. $return .= "\n" . '-- WordPress Configuration' . "\n\n"; $return .= 'Version: ' . get_bloginfo( 'version' ) . "\n"; $return .= 'Language: ' . ( defined( 'WPLANG' ) && WPLANG ? WPLANG : 'en_US' ) . "\n"; $return .= 'Permalink Structure: ' . ( get_option( 'permalink_structure' ) ? get_option( 'permalink_structure' ) : 'Default' ) . "\n"; $return .= 'Active Theme: ' . $theme . "\n"; $return .= 'Show On Front: ' . get_option( 'show_on_front' ) . "\n"; // Only show page specs if front page is set to 'page'. if ( get_option( 'show_on_front' ) === 'page' ) { $front_page_id = get_option( 'page_on_front' ); $blog_page_id = get_option( 'page_for_posts' ); $return .= 'Page On Front: ' . ( 0 != $front_page_id ? get_the_title( $front_page_id ) . ' (#' . $front_page_id . ')' : 'Unset' ) . "\n"; $return .= 'Page For Posts: ' . ( 0 != $blog_page_id ? get_the_title( $blog_page_id ) . ' (#' . $blog_page_id . ')' : 'Unset' ) . "\n"; } $return .= 'ABSPATH: ' . ABSPATH . "\n"; $return .= 'Table Prefix: ' . 'Length: ' . strlen( $wpdb->prefix ) . ' Status: ' . ( strlen( $wpdb->prefix ) > 16 ? 'ERROR: Too long' : 'Acceptable' ) . "\n"; $return .= 'WP_DEBUG: ' . ( defined( 'WP_DEBUG' ) ? WP_DEBUG ? 'Enabled' : 'Disabled' : 'Not set' ) . "\n"; $return .= 'WPFORMS_DEBUG: ' . ( defined( 'WPFORMS_DEBUG' ) ? WPFORMS_DEBUG ? 'Enabled' : 'Disabled' : 'Not set' ) . "\n"; $return .= 'Memory Limit: ' . WP_MEMORY_LIMIT . "\n"; $return .= 'Registered Post Stati: ' . implode( ', ', get_post_stati() ) . "\n"; // @todo WPForms configuration/specific details. $return .= "\n" . '-- WordPress Uploads/Constants' . "\n\n"; $return .= 'WP_CONTENT_DIR: ' . ( defined( 'WP_CONTENT_DIR' ) ? WP_CONTENT_DIR ? WP_CONTENT_DIR : 'Disabled' : 'Not set' ) . "\n"; $return .= 'WP_CONTENT_URL: ' . ( defined( 'WP_CONTENT_URL' ) ? WP_CONTENT_URL ? WP_CONTENT_URL : 'Disabled' : 'Not set' ) . "\n"; $return .= 'UPLOADS: ' . ( defined( 'UPLOADS' ) ? UPLOADS ? UPLOADS : 'Disabled' : 'Not set' ) . "\n"; $uploads_dir = wp_upload_dir(); $return .= 'wp_uploads_dir() path: ' . $uploads_dir['path'] . "\n"; $return .= 'wp_uploads_dir() url: ' . $uploads_dir['url'] . "\n"; $return .= 'wp_uploads_dir() basedir: ' . $uploads_dir['basedir'] . "\n"; $return .= 'wp_uploads_dir() baseurl: ' . $uploads_dir['baseurl'] . "\n"; // Get plugins that have an update. $updates = get_plugin_updates(); // Must-use plugins. // NOTE: MU plugins can't show updates! $muplugins = get_mu_plugins(); if ( count( $muplugins ) > 0 && ! empty( $muplugins ) ) { $return .= "\n" . '-- Must-Use Plugins' . "\n\n"; foreach ( $muplugins as $plugin => $plugin_data ) { $return .= $plugin_data['Name'] . ': ' . $plugin_data['Version'] . "\n"; } } // WordPress active plugins. $return .= "\n" . '-- WordPress Active Plugins' . "\n\n"; $plugins = get_plugins(); $active_plugins = get_option( 'active_plugins', array() ); foreach ( $plugins as $plugin_path => $plugin ) { if ( ! in_array( $plugin_path, $active_plugins, true ) ) { continue; } $update = ( array_key_exists( $plugin_path, $updates ) ) ? ' (needs update - ' . $updates[ $plugin_path ]->update->new_version . ')' : ''; $return .= $plugin['Name'] . ': ' . $plugin['Version'] . $update . "\n"; } // WordPress inactive plugins. $return .= "\n" . '-- WordPress Inactive Plugins' . "\n\n"; foreach ( $plugins as $plugin_path => $plugin ) { if ( in_array( $plugin_path, $active_plugins, true ) ) { continue; } $update = ( array_key_exists( $plugin_path, $updates ) ) ? ' (needs update - ' . $updates[ $plugin_path ]->update->new_version . ')' : ''; $return .= $plugin['Name'] . ': ' . $plugin['Version'] . $update . "\n"; } if ( is_multisite() ) { // WordPress Multisite active plugins. $return .= "\n" . '-- Network Active Plugins' . "\n\n"; $plugins = wp_get_active_network_plugins(); $active_plugins = get_site_option( 'active_sitewide_plugins', array() ); foreach ( $plugins as $plugin_path ) { $plugin_base = plugin_basename( $plugin_path ); if ( ! array_key_exists( $plugin_base, $active_plugins ) ) { continue; } $update = ( array_key_exists( $plugin_path, $updates ) ) ? ' (needs update - ' . $updates[ $plugin_path ]->update->new_version . ')' : ''; $plugin = get_plugin_data( $plugin_path ); $return .= $plugin['Name'] . ': ' . $plugin['Version'] . $update . "\n"; } } // Server configuration (really just versions). $return .= "\n" . '-- Webserver Configuration' . "\n\n"; $return .= 'PHP Version: ' . PHP_VERSION . "\n"; $return .= 'MySQL Version: ' . $wpdb->db_version() . "\n"; $return .= 'Webserver Info: ' . $_SERVER['SERVER_SOFTWARE'] . "\n"; // PHP configs... now we're getting to the important stuff. $return .= "\n" . '-- PHP Configuration' . "\n\n"; $return .= 'Memory Limit: ' . ini_get( 'memory_limit' ) . "\n"; $return .= 'Upload Max Size: ' . ini_get( 'upload_max_filesize' ) . "\n"; $return .= 'Post Max Size: ' . ini_get( 'post_max_size' ) . "\n"; $return .= 'Upload Max Filesize: ' . ini_get( 'upload_max_filesize' ) . "\n"; $return .= 'Time Limit: ' . ini_get( 'max_execution_time' ) . "\n"; $return .= 'Max Input Vars: ' . ini_get( 'max_input_vars' ) . "\n"; $return .= 'Display Errors: ' . ( ini_get( 'display_errors' ) ? 'On (' . ini_get( 'display_errors' ) . ')' : 'N/A' ) . "\n"; // PHP extensions and such. $return .= "\n" . '-- PHP Extensions' . "\n\n"; $return .= 'cURL: ' . ( function_exists( 'curl_init' ) ? 'Supported' : 'Not Supported' ) . "\n"; $return .= 'fsockopen: ' . ( function_exists( 'fsockopen' ) ? 'Supported' : 'Not Supported' ) . "\n"; $return .= 'SOAP Client: ' . ( class_exists( 'SoapClient', false ) ? 'Installed' : 'Not Installed' ) . "\n"; $return .= 'Suhosin: ' . ( extension_loaded( 'suhosin' ) ? 'Installed' : 'Not Installed' ) . "\n"; // Session stuff. $return .= "\n" . '-- Session Configuration' . "\n\n"; $return .= 'Session: ' . ( isset( $_SESSION ) ? 'Enabled' : 'Disabled' ) . "\n"; // The rest of this is only relevant if session is enabled. if ( isset( $_SESSION ) ) { $return .= 'Session Name: ' . esc_html( ini_get( 'session.name' ) ) . "\n"; $return .= 'Cookie Path: ' . esc_html( ini_get( 'session.cookie_path' ) ) . "\n"; $return .= 'Save Path: ' . esc_html( ini_get( 'session.save_path' ) ) . "\n"; $return .= 'Use Cookies: ' . ( ini_get( 'session.use_cookies' ) ? 'On' : 'Off' ) . "\n"; $return .= 'Use Only Cookies: ' . ( ini_get( 'session.use_only_cookies' ) ? 'On' : 'Off' ) . "\n"; } $return .= "\n" . '### End System Info ###'; return $return; } } new WPForms_Tools(); admin/admin.php 0000666 00000037023 15213301445 0007444 0 ustar 00 <?php /** * Global admin related items and functionality. * * @since 1.3.9 */ /** * Load styles for all WPForms-related admin screens. * * @since 1.3.9 */ function wpforms_admin_styles() { if ( ! wpforms_is_admin_page() ) { return; } $min = wpforms_get_min_suffix(); // jQuery confirm. wp_enqueue_style( 'jquery-confirm', WPFORMS_PLUGIN_URL . 'assets/css/jquery-confirm.min.css', array(), '3.3.2' ); // Minicolors (color picker). wp_enqueue_style( 'minicolors', WPFORMS_PLUGIN_URL . 'assets/css/jquery.minicolors.css', array(), '2.2.6' ); // FontAwesome. wp_enqueue_style( 'wpforms-font-awesome', WPFORMS_PLUGIN_URL . 'assets/css/font-awesome.min.css', null, '4.7.0' ); // Main admin styles. wp_enqueue_style( 'wpforms-admin', WPFORMS_PLUGIN_URL . "assets/css/admin{$min}.css", array(), WPFORMS_VERSION ); } add_action( 'admin_enqueue_scripts', 'wpforms_admin_styles' ); /** * Load scripts for all WPForms-related admin screens. * * @since 1.3.9 */ function wpforms_admin_scripts() { if ( ! wpforms_is_admin_page() ) { return; } $min = wpforms_get_min_suffix(); wp_enqueue_media(); // jQuery confirm. wp_enqueue_script( 'jquery-confirm', WPFORMS_PLUGIN_URL . 'assets/js/jquery.jquery-confirm.min.js', array( 'jquery' ), '3.3.2', false ); // Minicolors (color picker). wp_enqueue_script( 'minicolors', WPFORMS_PLUGIN_URL . 'assets/js/jquery.minicolors.min.js', array( 'jquery' ), '2.2.6', false ); // Choices.js. wp_enqueue_script( 'choicesjs', WPFORMS_PLUGIN_URL . 'assets/js/choices.min.js', array(), '9.0.1', false ); // jQuery Conditionals. wp_enqueue_script( 'jquery-conditionals', WPFORMS_PLUGIN_URL . 'assets/js/jquery.conditionals.min.js', array( 'jquery' ), '1.0.1', false ); // Main admin script. wp_enqueue_script( 'wpforms-admin', WPFORMS_PLUGIN_URL . "assets/js/admin{$min}.js", array( 'jquery' ), WPFORMS_VERSION, false ); $strings = array( 'addon_activate' => esc_html__( 'Activate', 'wpforms-lite' ), 'addon_activated' => esc_html__( 'Activated', 'wpforms-lite' ), 'addon_active' => esc_html__( 'Active', 'wpforms-lite' ), 'addon_deactivate' => esc_html__( 'Deactivate', 'wpforms-lite' ), 'addon_inactive' => esc_html__( 'Inactive', 'wpforms-lite' ), 'addon_install' => esc_html__( 'Install Addon', 'wpforms-lite' ), 'addon_error' => esc_html__( 'Could not install addon. Please download from wpforms.com and install manually.', 'wpforms-lite' ), 'plugin_error' => esc_html__( 'Could not install a plugin. Please download from WordPress.org and install manually.', 'wpforms-lite' ), 'addon_search' => esc_html__( 'Searching Addons', 'wpforms-lite' ), 'ajax_url' => admin_url( 'admin-ajax.php' ), 'cancel' => esc_html__( 'Cancel', 'wpforms-lite' ), 'close' => esc_html__( 'Close', 'wpforms-lite' ), 'entry_delete_confirm' => esc_html__( 'Are you sure you want to delete this entry?', 'wpforms-lite' ), 'entry_delete_all_confirm' => esc_html__( 'Are you sure you want to delete ALL entries?', 'wpforms-lite' ), 'entry_empty_fields_hide' => esc_html__( 'Hide Empty Fields', 'wpforms-lite' ), 'entry_empty_fields_show' => esc_html__( 'Show Empty Fields', 'wpforms-lite' ), 'entry_field_columns' => esc_html__( 'Entries Field Columns', 'wpforms-lite' ), 'entry_note_delete_confirm' => esc_html__( 'Are you sure you want to delete this note?', 'wpforms-lite' ), 'entry_unstar' => esc_html__( 'Unstar entry', 'wpforms-lite' ), 'entry_star' => esc_html__( 'Star entry', 'wpforms-lite' ), 'entry_read' => esc_html__( 'Mark entry read', 'wpforms-lite' ), 'entry_unread' => esc_html__( 'Mark entry unread', 'wpforms-lite' ), 'form_delete_confirm' => esc_html__( 'Are you sure you want to delete this form?', 'wpforms-lite' ), 'form_duplicate_confirm' => esc_html__( 'Are you sure you want to duplicate this form?', 'wpforms-lite' ), 'heads_up' => esc_html__( 'Heads up!', 'wpforms-lite' ), 'importer_forms_required' => esc_html__( 'Please select at least one form to import.', 'wpforms-lite' ), 'isPro' => wpforms()->pro, 'nonce' => wp_create_nonce( 'wpforms-admin' ), 'almost_done' => esc_html__( 'Almost Done', 'wpforms-lite' ), 'oops' => esc_html__( 'Oops!', 'wpforms-lite' ), 'ok' => esc_html__( 'OK', 'wpforms-lite' ), 'plugin_install_activate_btn' => esc_html__( 'Install and Activate', 'wpforms-lite' ), 'plugin_install_activate_confirm' => esc_html__( 'needs to be installed and activated to import its forms. Would you like us to install and activate it for you?', 'wpforms-lite' ), 'plugin_activate_btn' => esc_html__( 'Activate', 'wpforms-lite' ), 'plugin_activate_confirm' => esc_html__( 'needs to be activated to import its forms. Would you like us to activate it for you?', 'wpforms-lite' ), 'provider_delete_confirm' => esc_html__( 'Are you sure you want to disconnect this account?', 'wpforms-lite' ), 'provider_auth_error' => esc_html__( 'Could not authenticate with the provider.', 'wpforms-lite' ), 'save_refresh' => esc_html__( 'Save and Refresh', 'wpforms-lite' ), 'server_error' => esc_html__( 'Unfortunately, there was an server connection error.', 'wpforms-lite' ), 'settings_form_style_base' => sprintf( wp_kses( /* translators: %s - WPForms.com docs page URL. */ __( 'You\'ve selected <strong>Base Styling Only</strong>, which may result in styling issues. <a href="%s" target="_blank" rel="noopener noreferrer">Please check out our tutorial</a> for common issues and recommendations.', 'wpforms-lite' ), array( 'strong' => array(), 'a' => array( 'href' => array(), 'target' => array(), 'rel' => array(), ), ) ), 'https://wpforms.com/docs/how-to-choose-an-include-form-styling-setting/' ), 'settings_form_style_none' => sprintf( wp_kses( /* translators: %s - WPForms.com docs page URL. */ __( 'You\'ve selected <strong>No Styling</strong>, which will likely result in significant styling issues and is recommended only for developers. <a href="%s" target="_blank" rel="noopener noreferrer">Please check out our tutorial</a> for more details and recommendations.', 'wpforms-lite' ), array( 'strong' => array(), 'a' => array( 'href' => array(), 'target' => array(), 'rel' => array(), ), ) ), 'https://wpforms.com/docs/how-to-choose-an-include-form-styling-setting/' ), 'testing' => esc_html__( 'Testing', 'wpforms-lite' ), 'upgrade_completed' => esc_html__( 'Upgrade was successfully completed!', 'wpforms-lite' ), 'upload_image_title' => esc_html__( 'Upload or Choose Your Image', 'wpforms-lite' ), 'upload_image_button' => esc_html__( 'Use Image', 'wpforms-lite' ), 'upgrade_modal' => wpforms_get_upgrade_modal_text(), 'choicesjs_fields_select' => esc_html__( 'Select fields', 'wpforms-lite' ), 'choicesjs_loading' => esc_html__( 'Loading...', 'wpforms-lite' ), 'choicesjs_no_results' => esc_html__( 'No results found', 'wpforms-lite' ), 'choicesjs_no_choices' => esc_html__( 'No choices to choose from', 'wpforms-lite' ), 'choicesjs_item_select' => esc_html__( 'Press to select', 'wpforms-lite' ), ); $strings = apply_filters( 'wpforms_admin_strings', $strings ); wp_localize_script( 'wpforms-admin', 'wpforms_admin', $strings ); } add_action( 'admin_enqueue_scripts', 'wpforms_admin_scripts' ); /** * Add body class to WPForms admin pages for easy reference. * * @since 1.3.9 * * @param string $classes CSS classes, space separated. * * @return string */ function wpforms_admin_body_class( $classes ) { if ( ! wpforms_is_admin_page() ) { return $classes; } return "$classes wpforms-admin-page"; } add_filter( 'admin_body_class', 'wpforms_admin_body_class', 10, 1 ); /** * Output the WPForms admin header. * * @since 1.3.9 */ function wpforms_admin_header() { // Bail if we're not on a WPForms screen or page (also exclude form builder). if ( ! wpforms_is_admin_page() ) { return; } if ( ! apply_filters( 'wpforms_admin_header', true ) ) { return; } // Omit header from Welcome activation screen. if ( 'wpforms-getting-started' === $_REQUEST['page'] ) { return; } do_action( 'wpforms_admin_header_before' ); ?> <div id="wpforms-header-temp"></div> <div id="wpforms-header" class="wpforms-header"> <img class="wpforms-header-logo" src="<?php echo WPFORMS_PLUGIN_URL; ?>assets/images/logo.png" alt="WPForms Logo"/> </div> <?php do_action( 'wpforms_admin_header_after' ); } add_action( 'in_admin_header', 'wpforms_admin_header', 100 ); /** * Remove non-WPForms notices from WPForms pages. * * @since 1.3.9 */ function wpforms_admin_hide_unrelated_notices() { // Bail if we're not on a WPForms screen or page. if ( empty( $_REQUEST['page'] ) || strpos( $_REQUEST['page'], 'wpforms' ) === false ) { return; } // Extra banned classes and callbacks from third-party plugins. $blacklist = array( 'classes' => array(), 'callbacks' => array( 'wpformsdb_admin_notice', // 'Database for WPforms' plugin. ), ); global $wp_filter; foreach ( array( 'user_admin_notices', 'admin_notices', 'all_admin_notices' ) as $notices_type ) { if ( empty( $wp_filter[ $notices_type ]->callbacks ) || ! is_array( $wp_filter[ $notices_type ]->callbacks ) ) { continue; } foreach ( $wp_filter[ $notices_type ]->callbacks as $priority => $hooks ) { foreach ( $hooks as $name => $arr ) { if ( is_object( $arr['function'] ) && $arr['function'] instanceof Closure ) { unset( $wp_filter[ $notices_type ]->callbacks[ $priority ][ $name ] ); continue; } $class = ! empty( $arr['function'][0] ) && is_object( $arr['function'][0] ) ? strtolower( get_class( $arr['function'][0] ) ) : ''; if ( ! empty( $class ) && strpos( $class, 'wpforms' ) !== false && ! in_array( $class, $blacklist['classes'], true ) ) { continue; } if ( ! empty( $name ) && ( strpos( $name, 'wpforms' ) === false || in_array( $class, $blacklist['classes'], true ) || in_array( $name, $blacklist['callbacks'], true ) ) ) { unset( $wp_filter[ $notices_type ]->callbacks[ $priority ][ $name ] ); } } } } } add_action( 'admin_print_scripts', 'wpforms_admin_hide_unrelated_notices' ); /** * Upgrade link used within the various admin pages. * * Previously was only included as a method in wpforms-lite.php, but made * available globally in 1.3.9. * * @since 1.3.9 * * @param string $medium utm_medium URL parameter. * @param string $content utm_content URL parameter. * * @return string. */ function wpforms_admin_upgrade_link( $medium = 'link', $content = '' ) { $upgrade = add_query_arg( array( 'discount' => 'LITEUPGRADE', 'utm_source' => 'WordPress', 'utm_campaign' => 'liteplugin', 'utm_medium' => apply_filters( 'wpforms_upgrade_link_medium', $medium ), ), 'https://wpforms.com/lite-upgrade/' ); if ( ! empty( $content ) ) { $upgrade = add_query_arg( 'utm_content', $content, $upgrade ); } return apply_filters( 'wpforms_upgrade_link', $upgrade ); } /** * Check the current PHP version and display a notice if on unsupported PHP. * * @since 1.4.0.1 * @since 1.5.0 Raising this awareness of old PHP version message from 5.2 to 5.3. */ function wpforms_check_php_version() { // Display for PHP below 5.6 if ( version_compare( PHP_VERSION, '5.5', '>=' ) ) { return; } // Display for admins only. if ( ! is_super_admin() ) { return; } // Display on Dashboard page only. if ( isset( $GLOBALS['pagenow'] ) && 'index.php' !== $GLOBALS['pagenow'] ) { return; } // Display the notice, finally. WPForms_Admin_Notice::error( '<p>' . sprintf( wp_kses( /* translators: %1$s - WPForms plugin name; %2$s - WPForms.com URL to a related doc. */ __( 'Your site is running an outdated version of PHP that is no longer supported and may cause issues with %1$s. <a href="%2$s" target="_blank" rel="noopener noreferrer">Read more</a> for additional information.', 'wpforms-lite' ), array( 'a' => array( 'href' => array(), 'target' => array(), 'rel' => array(), ), ) ), '<strong>WPForms</strong>', 'https://wpforms.com/docs/supported-php-version/' ) . '<br><br><em>' . wp_kses( __( '<strong>Please Note:</strong> Support for PHP 5.5 will be discontinued in 2020. After this, if no further action is taken, WPForms functionality will be disabled.', 'wpforms-lite' ), array( 'strong' => array(), 'em' => array(), ) ) . '</em></p>' ); } add_action( 'admin_init', 'wpforms_check_php_version' ); /** * Get an upgrade modal text. * * @since 1.4.4 * * @param string $type Either "pro" or "elite". Default is "pro". * * @return string */ function wpforms_get_upgrade_modal_text( $type = 'pro' ) { switch ( $type ) { case 'elite': $level = 'WPForms Elite'; break; case 'pro': default: $level = 'WPForms Pro'; } return '<p>' . sprintf( /* translators: %s - license level, WPForms Pro or WPForms Elite. */ esc_html__( 'Thanks for your interest in %s!', 'wpforms-lite' ), $level ) . '<br>' . sprintf( wp_kses( /* translators: %s - WPForms.com contact page URL. */ __( 'If you have any questions or issues just <a href="%s" target="_blank" rel="noopener noreferrer">let us know</a>.', 'wpforms-lite' ), array( 'a' => array( 'href' => array(), 'target' => array(), 'rel' => array(), ), ) ), 'https://wpforms.com/contact/' ) . '</p>' . '<p>' . sprintf( wp_kses( /* translators: %s - license level, WPForms Pro or WPForms Elite. */ __( 'After purchasing a license,<br>just <strong>enter your license key on the WPForms Settings page</strong>.<br>This will let your site automatically upgrade to %s!', 'wpforms-lite' ), [ 'strong' => [], 'br' => [], ] ), $level ) . '<br>' . esc_html__( '(Don\'t worry, all your forms and settings will be preserved.)', 'wpforms-lite' ) . '</p>' . '<p>' . sprintf( wp_kses( /* translators: %s - WPForms.com upgrade from Lite to paid docs page URL. */ __( 'Check out <a href="%s" target="_blank" rel="noopener noreferrer">our documentation</a> for step-by-step instructions.', 'wpforms-lite' ), array( 'a' => array( 'href' => array(), 'target' => array(), 'rel' => array(), ), ) ), 'https://wpforms.com/docs/upgrade-wpforms-lite-paid-license/?utm_source=WordPress&utm_medium=link&utm_campaign=liteplugin' ) . '</p>'; } /** * Hide the wp-admin area "Version x.x" in footer on WPForms pages. * * @since 1.5.7 * * @param string $text Default "Version x.x" or "Get Version x.x" text. * * @return string */ function wpforms_admin_hide_wp_version( $text ) { // Reset text if we're not on a WPForms screen or page. if ( wpforms_is_admin_page() ) { return ''; } return $text; } add_filter( 'update_footer', 'wpforms_admin_hide_wp_version', PHP_INT_MAX ); admin/class-install-skin.php 0000666 00000001126 15213301445 0012062 0 ustar 00 <?php use WPForms\Helpers\PluginSilentUpgraderSkin; /** * Skin for on-the-fly addon installations. * * @since 1.0.0 * @since 1.5.6.1 Extend PluginSilentUpgraderSkin and clean up the class. */ class WPForms_Install_Skin extends PluginSilentUpgraderSkin { /** * Instead of outputting HTML for errors, json_encode the errors and send them * back to the Ajax script for processing. * * @since 1.0.0 * * @param array $errors Array of errors with the install process. */ public function error( $errors ) { if ( ! empty( $errors ) ) { wp_send_json_error( $errors ); } } } admin/builder/class-builder.php 0000666 00000054116 15213301445 0012535 0 ustar 00 <?php /** * Form builder that contains magic. * * @since 1.0.0 */ class WPForms_Builder { /** * One is the loneliest number that you'll ever do. * * @since 1.4.4.1 * * @var object */ private static $instance; /** * Current view (panel). * * @since 1.0.0 * @var string */ public $view; /** * Available panels. * * @since 1.0.0 * @var array */ public $panels; /** * Current form. * * @since 1.0.0 * @var object */ public $form; /** * Form data and settings. * * @since 1.4.4.1 * @var array */ public $form_data; /** * Current template information. * * @since 1.0.0 * @var array */ public $template; /** * Main Instance. * * @since 1.4.4.1 * * @return WPForms_Builder */ public static function instance() { if ( ! isset( self::$instance ) && ! ( self::$instance instanceof WPForms_Builder ) ) { self::$instance = new WPForms_Builder(); add_action( 'admin_init', array( self::$instance, 'init' ), 10 ); } return self::$instance; } /** * Determine if the user is viewing the builder, if so, party on. * * @since 1.0.0 */ public function init() { // Check what page we are on. $page = isset( $_GET['page'] ) ? $_GET['page'] : ''; // Only load if we are actually on the builder. if ( 'wpforms-builder' === $page ) { // Load form if found. $form_id = isset( $_GET['form_id'] ) ? absint( $_GET['form_id'] ) : false; if ( $form_id ) { // Default view for with an existing form is fields panel. $this->view = isset( $_GET['view'] ) ? $_GET['view'] : 'fields'; } else { // Default view for new field is the setup panel. $this->view = isset( $_GET['view'] ) ? $_GET['view'] : 'setup'; } if ( 'setup' === $this->view && ! wpforms_current_user_can( 'create_forms' ) ) { wp_die( esc_html__( 'Sorry, you are not allowed to create new forms.', 'wpforms-lite' ), 403 ); } if ( 'fields' === $this->view && ! wpforms_current_user_can( 'edit_form_single', $form_id ) ) { wp_die( esc_html__( 'Sorry, you are not allowed to edit this form.', 'wpforms-lite' ), 403 ); } // Fetch form. $this->form = wpforms()->form->get( $form_id ); $this->form_data = $this->form ? wpforms_decode( $this->form->post_content ) : false; // Fetch template information. $this->template = apply_filters( 'wpforms_builder_template_active', array(), $this->form ); // Load builder panels. $this->load_panels(); add_action( 'admin_head', array( $this, 'admin_head' ) ); add_action( 'admin_enqueue_scripts', array( $this, 'enqueues' ) ); add_action( 'admin_print_footer_scripts', array( $this, 'footer_scripts' ) ); add_action( 'wpforms_admin_page', array( $this, 'output' ) ); // Provide hook for addons. do_action( 'wpforms_builder_init', $this->view ); add_filter( 'teeny_mce_plugins', array( $this, 'tinymce_buttons' ) ); } } /** * Define TinyMCE buttons to use with our fancy editor instances. * * @since 1.0.3 * * @param array $buttons List of default buttons. * * @return array */ public function tinymce_buttons( $buttons ) { $buttons = array( 'colorpicker', 'lists', 'wordpress', 'wpeditimage', 'wplink' ); return $buttons; } /** * Load panels. * * @since 1.0.0 */ public function load_panels() { // Base class and functions. require_once WPFORMS_PLUGIN_DIR . 'includes/admin/builder/panels/class-base.php'; $this->panels = apply_filters( 'wpforms_builder_panels', array( 'setup', 'fields', 'settings', 'providers', 'payments', ) ); foreach ( $this->panels as $panel ) { $panel = sanitize_file_name( $panel ); if ( file_exists( WPFORMS_PLUGIN_DIR . 'includes/admin/builder/panels/class-' . $panel . '.php' ) ) { require_once WPFORMS_PLUGIN_DIR . 'includes/admin/builder/panels/class-' . $panel . '.php'; } elseif ( file_exists( WPFORMS_PLUGIN_DIR . 'pro/includes/admin/builder/panels/class-' . $panel . '.php' ) ) { require_once WPFORMS_PLUGIN_DIR . 'pro/includes/admin/builder/panels/class-' . $panel . '.php'; } } } /** * Admin head area inside the form builder. * * @since 1.4.6 */ public function admin_head() { do_action( 'wpforms_builder_admin_head', $this->view ); } /** * Enqueue assets for the builder. * * @since 1.0.0 */ public function enqueues() { // Remove conflicting scripts. wp_deregister_script( 'serialize-object' ); wp_deregister_script( 'wpclef-ajax-settings' ); do_action( 'wpforms_builder_enqueues_before', $this->view ); $min = wpforms_get_min_suffix(); /* * CSS. */ wp_enqueue_style( 'wpforms-font-awesome', WPFORMS_PLUGIN_URL . 'assets/css/font-awesome.min.css', null, '4.7.0' ); wp_enqueue_style( 'tooltipster', WPFORMS_PLUGIN_URL . 'assets/css/tooltipster.css', null, '4.2.6' ); wp_enqueue_style( 'jquery-confirm', WPFORMS_PLUGIN_URL . 'assets/css/jquery-confirm.min.css', null, '3.3.2' ); wp_enqueue_style( 'minicolors', WPFORMS_PLUGIN_URL . 'assets/css/jquery.minicolors.css', null, '2.2.6' ); wp_enqueue_style( 'wpforms-builder-legacy', WPFORMS_PLUGIN_URL . 'assets/css/admin-builder.css', null, WPFORMS_VERSION ); wp_enqueue_style( 'wpforms-builder', WPFORMS_PLUGIN_URL . "assets/css/builder{$min}.css", null, WPFORMS_VERSION ); /* * JavaScript. */ wp_enqueue_media(); wp_enqueue_script( 'jquery-ui-sortable' ); wp_enqueue_script( 'jquery-ui-draggable' ); wp_enqueue_script( 'wp-util' ); wp_enqueue_script( 'tooltipster', WPFORMS_PLUGIN_URL . 'assets/js/jquery.tooltipster.min.js', array( 'jquery' ), '4.2.6' ); wp_enqueue_script( 'jquery-confirm', WPFORMS_PLUGIN_URL . 'assets/js/jquery.jquery-confirm.min.js', array( 'jquery' ), '3.3.2' ); wp_enqueue_script( 'matchheight', WPFORMS_PLUGIN_URL . 'assets/js/jquery.matchHeight-min.js', array( 'jquery' ), '0.7.0' ); wp_enqueue_script( 'insert-at-caret', WPFORMS_PLUGIN_URL . 'assets/js/jquery.insert-at-caret.min.js', array( 'jquery' ), '1.1.4' ); wp_enqueue_script( 'minicolors', WPFORMS_PLUGIN_URL . 'assets/js/jquery.minicolors.min.js', array( 'jquery' ), '2.2.6' ); wp_enqueue_script( 'conditionals', WPFORMS_PLUGIN_URL . 'assets/js/jquery.conditionals.min.js', array( 'jquery' ), '1.0.0' ); wp_enqueue_script( 'listjs', WPFORMS_PLUGIN_URL . 'assets/js/list.min.js', array( 'jquery' ), '1.5.0' ); wp_enqueue_script( 'dom-purify', WPFORMS_PLUGIN_URL . 'assets/js/purify.min.js', array(), '2.0.8' ); wp_enqueue_script( 'wpforms-utils', WPFORMS_PLUGIN_URL . 'assets/js/admin-utils.js', array( 'jquery', 'dom-purify' ), WPFORMS_VERSION ); wp_enqueue_script( 'wpforms-builder', WPFORMS_PLUGIN_URL . 'assets/js/admin-builder.js', array( 'wpforms-utils', 'wpforms-admin-builder-templates', 'jquery-ui-sortable', 'jquery-ui-draggable', 'tooltipster', 'jquery-confirm' ), WPFORMS_VERSION ); wp_enqueue_script( 'wpforms-admin-builder-templates', WPFORMS_PLUGIN_URL . "assets/js/components/admin/builder/templates{$min}.js", array( 'wp-util' ), WPFORMS_VERSION, true ); $strings = array( 'and' => esc_html__( 'AND', 'wpforms-lite' ), 'ajax_url' => admin_url( 'admin-ajax.php' ), 'bulk_add_button' => esc_html__( 'Add New Choices', 'wpforms-lite' ), 'bulk_add_show' => esc_html__( 'Bulk Add', 'wpforms-lite' ), 'are_you_sure_to_close' => esc_html__( 'Are you sure you want to leave? You have unsaved changes', 'wpforms-lite' ), 'bulk_add_hide' => esc_html__( 'Hide Bulk Add', 'wpforms-lite' ), 'bulk_add_heading' => esc_html__( 'Add Choices (one per line)', 'wpforms-lite' ), 'bulk_add_placeholder' => esc_html__( "Blue\nRed\nGreen", 'wpforms-lite' ), 'bulk_add_presets_show' => esc_html__( 'Show presets', 'wpforms-lite' ), 'bulk_add_presets_hide' => esc_html__( 'Hide presets', 'wpforms-lite' ), 'date_select_day' => 'DD', 'date_select_month' => 'MM', 'debug' => wpforms_debug(), 'dynamic_choice_limit' => esc_html__( 'The {source} {type} contains over {limit} items ({total}). This may make the field difficult for your visitors to use and/or cause the form to be slow.', 'wpforms-lite' ), 'cancel' => esc_html__( 'Cancel', 'wpforms-lite' ), 'ok' => esc_html__( 'OK', 'wpforms-lite' ), 'close' => esc_html__( 'Close', 'wpforms-lite' ), 'conditionals_change' => esc_html__( 'Due to form changes, conditional logic rules have been removed or updated:', 'wpforms-lite' ), 'conditionals_disable' => esc_html__( 'Are you sure you want to disable conditional logic? This will remove the rules for this field or setting.', 'wpforms-lite' ), 'field' => esc_html__( 'Field', 'wpforms-lite' ), 'field_locked' => esc_html__( 'Field Locked', 'wpforms-lite' ), 'field_locked_msg' => esc_html__( 'This field cannot be deleted or duplicated.', 'wpforms-lite' ), 'fields_available' => esc_html__( 'Available Fields', 'wpforms-lite' ), 'fields_unavailable' => esc_html__( 'No fields available', 'wpforms-lite' ), 'heads_up' => esc_html__( 'Heads up!', 'wpforms-lite' ), 'image_placeholder' => WPFORMS_PLUGIN_URL . 'assets/images/placeholder-200x125.png', 'nonce' => wp_create_nonce( 'wpforms-builder' ), 'no_email_fields' => esc_html__( 'No email fields', 'wpforms-lite' ), 'notification_delete' => esc_html__( 'Are you sure you want to delete this notification?', 'wpforms-lite' ), 'notification_prompt' => esc_html__( 'Enter a notification name', 'wpforms-lite' ), 'notification_ph' => esc_html__( 'Eg: User Confirmation', 'wpforms-lite' ), 'notification_error' => esc_html__( 'You must provide a notification name', 'wpforms-lite' ), 'notification_error2' => esc_html__( 'Form must contain one notification. To disable all notifications use the Notifications dropdown setting.', 'wpforms-lite' ), 'notification_def_name' => esc_html__( 'Default Notification', 'wpforms-lite' ), 'confirmation_delete' => esc_html__( 'Are you sure you want to delete this confirmation?', 'wpforms-lite' ), 'confirmation_prompt' => esc_html__( 'Enter a confirmation name', 'wpforms-lite' ), 'confirmation_ph' => esc_html__( 'Eg: Alternative Confirmation', 'wpforms-lite' ), 'confirmation_error' => esc_html__( 'You must provide a confirmation name', 'wpforms-lite' ), 'confirmation_error2' => esc_html__( 'Form must contain at least one confirmation.', 'wpforms-lite' ), 'confirmation_def_name' => esc_html__( 'Default Confirmation', 'wpforms-lite' ), 'save' => esc_html__( 'Save', 'wpforms-lite' ), 'saving' => esc_html__( 'Saving ...', 'wpforms-lite' ), 'saved' => esc_html__( 'Saved!', 'wpforms-lite' ), 'save_exit' => esc_html__( 'Save and Exit', 'wpforms-lite' ), 'saved_state' => '', 'layout_selector_show' => esc_html__( 'Show Layouts', 'wpforms-lite' ), 'layout_selector_hide' => esc_html__( 'Hide Layouts', 'wpforms-lite' ), 'layout_selector_layout' => esc_html__( 'Select your layout', 'wpforms-lite' ), 'layout_selector_column' => esc_html__( 'Select your column', 'wpforms-lite' ), 'loading' => esc_html__( 'Loading', 'wpforms-lite' ), 'template_name' => ! empty( $this->template['name'] ) ? $this->template['name'] : '', 'template_slug' => ! empty( $this->template['slug'] ) ? $this->template['slug'] : '', 'template_modal_title' => ! empty( $this->template['modal']['title'] ) ? $this->template['modal']['title'] : '', 'template_modal_msg' => ! empty( $this->template['modal']['message'] ) ? $this->template['modal']['message'] : '', 'template_modal_display' => ! empty( $this->template['modal_display'] ) ? $this->template['modal_display'] : '', 'template_select' => esc_html__( 'Use Template', 'wpforms-lite' ), 'template_confirm' => esc_html__( 'Changing templates on an existing form will DELETE existing form fields. Are you sure you want apply the new template?', 'wpforms-lite' ), 'embed_modal' => esc_html__( 'You are almost done. To embed this form on your site, please paste the following shortcode inside a post or page.', 'wpforms-lite' ), 'embed_modal_2' => esc_html__( 'Or you can follow the instructions in this video.', 'wpforms-lite' ), 'exit' => esc_html__( 'Exit', 'wpforms-lite' ), 'exit_url' => wpforms_current_user_can( 'view_forms' ) ? admin_url( 'admin.php?page=wpforms-overview' ) : admin_url(), 'exit_confirm' => esc_html__( 'If you exit without saving, your changes will be lost.', 'wpforms-lite' ), 'delete_confirm' => esc_html__( 'Are you sure you want to delete this field?', 'wpforms-lite' ), 'duplicate_confirm' => esc_html__( 'Are you sure you want to duplicate this field?', 'wpforms-lite' ), 'duplicate_copy' => esc_html__( '(copy)', 'wpforms-lite' ), 'error_title' => esc_html__( 'Please enter a form name.', 'wpforms-lite' ), 'error_choice' => esc_html__( 'This item must contain at least one choice.', 'wpforms-lite' ), 'off' => esc_html__( 'Off', 'wpforms-lite' ), 'on' => esc_html__( 'On', 'wpforms-lite' ), 'or' => esc_html__( 'or', 'wpforms-lite' ), 'other' => esc_html__( 'Other', 'wpforms-lite' ), 'operator_is' => esc_html__( 'is', 'wpforms-lite' ), 'operator_is_not' => esc_html__( 'is not', 'wpforms-lite' ), 'operator_empty' => esc_html__( 'empty', 'wpforms-lite' ), 'operator_not_empty' => esc_html__( 'not empty', 'wpforms-lite' ), 'operator_contains' => esc_html__( 'contains', 'wpforms-lite' ), 'operator_not_contains' => esc_html__( 'does not contain', 'wpforms-lite' ), 'operator_starts' => esc_html__( 'starts with', 'wpforms-lite' ), 'operator_ends' => esc_html__( 'ends with', 'wpforms-lite' ), 'operator_greater_than' => esc_html__( 'greater than', 'wpforms-lite' ), 'operator_less_than' => esc_html__( 'less than', 'wpforms-lite' ), 'payments_entries_off' => esc_html__( 'Entry storage is currently disabled, but is required to accept payments. Please enable in your form settings.', 'wpforms-lite' ), 'payments_on_entries_off' => esc_html__( 'This form is currently accepting payments. Entry storage is required to accept payments. To disable entry storage, please first disable payments.', 'wpforms-lite' ), 'previous' => esc_html__( 'Previous', 'wpforms-lite' ), 'provider_required_flds' => esc_html__( "In order to complete your form's {provider} integration, please check that the dropdowns for all required (*) List Fields have been filled out.", 'wpforms-lite' ), 'rule_create' => esc_html__( 'Create new rule', 'wpforms-lite' ), 'rule_create_group' => esc_html__( 'Add new group', 'wpforms-lite' ), 'rule_delete' => esc_html__( 'Delete rule', 'wpforms-lite' ), 'smart_tags' => wpforms()->smart_tags->get(), 'smart_tags_disabled_for_fields' => array( 'entry_id' ), 'smart_tags_show' => esc_html__( 'Show Smart Tags', 'wpforms-lite' ), 'smart_tags_hide' => esc_html__( 'Hide Smart Tags', 'wpforms-lite' ), 'select_field' => esc_html__( '--- Select Field ---', 'wpforms-lite' ), 'select_choice' => esc_html__( '--- Select Choice ---', 'wpforms-lite' ), 'upload_image_title' => esc_html__( 'Upload or Choose Your Image', 'wpforms-lite' ), 'upload_image_button' => esc_html__( 'Use Image', 'wpforms-lite' ), 'upload_image_remove' => esc_html__( 'Remove Image', 'wpforms-lite' ), 'provider_add_new_acc_btn' => esc_html__( 'Add', 'wpforms-lite' ), 'pro' => wpforms()->pro, 'is_gutenberg' => version_compare( get_bloginfo( 'version' ), '5.0', '>=' ) && ! is_plugin_active( 'classic-editor/classic-editor.php' ), 'cl_fields_supported' => wpforms_get_conditional_logic_form_fields_supported(), 'redirect_url_field_error' => esc_html__( 'You should enter a valid absolute address to the Confirmation Redirect URL field.', 'wpforms-lite' ), ); $strings = apply_filters( 'wpforms_builder_strings', $strings, $this->form ); // phpcs:disable WordPress.Security.NonceVerification.Recommended if ( ! empty( $_GET['form_id'] ) ) { $form_id = (int) $_GET['form_id']; $strings['preview_url'] = esc_url( add_query_arg( 'new_window', 1, wpforms_get_form_preview_url( $form_id ) ) ); $strings['entries_url'] = esc_url( admin_url( 'admin.php?page=wpforms-entries&view=list&form_id=' . $form_id ) ); } // phpcs:enable wp_localize_script( 'wpforms-builder', 'wpforms_builder', $strings ); // Hook for addons. do_action( 'wpforms_builder_enqueues', $this->view ); } /** * Footer JavaScript. * * @since 1.3.7 */ public function footer_scripts() { $choices = array( 'countries' => array( 'name' => esc_html__( 'Countries', 'wpforms-lite' ), 'choices' => array_values( wpforms_countries() ), ), 'countries_postal' => array( 'name' => esc_html__( 'Countries Postal Code', 'wpforms-lite' ), 'choices' => array_keys( wpforms_countries() ), ), 'states' => array( 'name' => esc_html__( 'States', 'wpforms-lite' ), 'choices' => array_values( wpforms_us_states() ), ), 'states_postal' => array( 'name' => esc_html__( 'States Postal Code', 'wpforms-lite' ), 'choices' => array_keys( wpforms_us_states() ), ), 'months' => array( 'name' => esc_html__( 'Months', 'wpforms-lite' ), 'choices' => array_values( wpforms_months() ), ), 'days' => array( 'name' => esc_html__( 'Days', 'wpforms-lite' ), 'choices' => array_values( wpforms_days() ), ), ); $choices = apply_filters( 'wpforms_builder_preset_choices', $choices ); echo '<script type="text/javascript">wpforms_preset_choices=' . wp_json_encode( $choices ) . '</script>'; do_action( 'wpforms_builder_print_footer_scripts' ); } /** * Load the appropriate files to build the page. * * @since 1.0.0 */ public function output() { if ( ! (bool) apply_filters( 'wpforms_builder_output', true ) ) { return; } $form_id = $this->form ? absint( $this->form->ID ) : ''; $field_id = ! empty( $this->form_data['field_id'] ) ? $this->form_data['field_id'] : ''; ?> <div id="wpforms-builder" class="wpforms-admin-page"> <div id="wpforms-builder-mobile-notice"> <img src="<?php echo esc_url( WPFORMS_PLUGIN_URL . 'assets/images/sullie-builder-mobile.png' ); ?>" alt="<?php esc_attr_e( 'Sullie the WPForms mascot', 'wpforms-lite' ); ?>"> <h3><?php esc_html_e( 'Oh, hi there!', 'wpforms-lite' ); ?></h3> <p><?php esc_html_e( 'Our form builder is optimized for desktop computers and tablets. Please manage your forms on a different device.', 'wpforms-lite' ); ?></p> <button type="button"><?php esc_html_e( 'Go back', 'wpforms-lite' ); ?></button> </div> <div id="wpforms-builder-overlay"> <div class="wpforms-builder-overlay-content"> <i class="fa fa-cog fa-spin"></i> <span class="msg"><?php esc_html_e( 'Loading', 'wpforms-lite' ); ?></span> </div> </div> <form name="wpforms-builder" id="wpforms-builder-form" method="post" data-id="<?php echo esc_attr( $form_id ); ?>"> <input type="hidden" name="id" value="<?php echo esc_attr( $form_id ); ?>"> <input type="hidden" value="<?php echo absint( $field_id ); ?>" name="field_id" id="wpforms-field-id"> <!-- Toolbar --> <div class="wpforms-toolbar"> <div class="wpforms-left"> <img src="<?php echo esc_url( WPFORMS_PLUGIN_URL . 'assets/images/sullie-alt.png' ); ?>" alt="<?php esc_attr_e( 'Sullie the WPForms mascot', 'wpforms-lite' ); ?>"> </div> <div class="wpforms-center"> <?php if ( $this->form ) : ?> <?php esc_html_e( 'Now editing', 'wpforms-lite' ); ?> <span class="wpforms-center-form-name wpforms-form-name"><?php echo esc_html( $this->form->post_title ); ?></span> <?php endif; ?> </div> <div class="wpforms-right"> <?php if ( $this->form ) : ?> <a href="#" id="wpforms-embed" title="<?php esc_attr_e( 'Embed Form', 'wpforms-lite' ); ?>"> <i class="fa fa-code"></i> <span class="text"><?php esc_html_e( 'Embed', 'wpforms-lite' ); ?></span> </a> <a href="#" id="wpforms-save" title="<?php esc_attr_e( 'Save Form', 'wpforms-lite' ); ?>"> <i class="fa fa-check"></i> <span class="text"><?php esc_html_e( 'Save', 'wpforms-lite' ); ?></span> </a> <?php endif; ?> <a href="#" id="wpforms-exit" title="<?php esc_attr_e( 'Exit', 'wpforms-lite' ); ?>"> <i class="fa fa-times"></i> </a> </div> </div> <!-- Panel toggle buttons. --> <div class="wpforms-panels-toggle" id="wpforms-panels-toggle"> <?php do_action( 'wpforms_builder_panel_buttons', $this->form, $this->view ); ?> </div> <div class="wpforms-panels"> <?php do_action( 'wpforms_builder_panels', $this->form, $this->view ); ?> </div> </form> </div> <?php } } WPForms_Builder::instance(); admin/builder/functions.php 0000666 00000026570 15213301445 0012017 0 ustar 00 <?php /** * Output fields to be used on panels (settings etc). * * @since 1.0.0 * * @param string $option * @param string $panel * @param string $field * @param array $form_data * @param string $label * @param array $args * @param bool $echo * * @return string */ function wpforms_panel_field( $option, $panel, $field, $form_data, $label, $args = array(), $echo = true ) { // Required params. if ( empty( $option ) || empty( $panel ) || empty( $field ) ) { return ''; } // Setup basic vars. $panel = esc_attr( $panel ); $field = esc_attr( $field ); $panel_id = sanitize_html_class( $panel ); $parent = ! empty( $args['parent'] ) ? esc_attr( $args['parent'] ) : ''; $subsection = ! empty( $args['subsection'] ) ? esc_attr( $args['subsection'] ) : ''; $label = ! empty( $label ) ? esc_html( $label ) : ''; $class = ! empty( $args['class'] ) ? esc_attr( $args['class'] ) : ''; $input_class = ! empty( $args['input_class'] ) ? esc_attr( $args['input_class'] ) : ''; $default = isset( $args['default'] ) ? $args['default'] : ''; $placeholder = ! empty( $args['placeholder'] ) ? esc_attr( $args['placeholder'] ) : ''; $data_attr = ''; $output = ''; $input_id = sprintf( 'wpforms-panel-field-%s-%s', sanitize_html_class( $panel_id ), sanitize_html_class( $field ) ); if ( ! empty( $args['input_id'] ) ) { $input_id = esc_attr( $args['input_id'] ); } // Check if we should store values in a parent array. if ( ! empty( $parent ) ) { if ( ! empty( $subsection ) ) { $field_name = sprintf( '%s[%s][%s][%s]', $parent, $panel, $subsection, $field ); $value = isset( $form_data[ $parent ][ $panel ][ $subsection ][ $field ] ) ? $form_data[ $parent ][ $panel ][ $subsection ][ $field ] : $default; $input_id = sprintf( 'wpforms-panel-field-%s-%s-%s', sanitize_html_class( $panel_id ), sanitize_html_class( $subsection ), sanitize_html_class( $field ) ); $panel_id = sanitize_html_class( $panel . '-' . $subsection ); } else { $field_name = sprintf( '%s[%s][%s]', $parent, $panel, $field ); $value = isset( $form_data[ $parent ][ $panel ][ $field ] ) ? $form_data[ $parent ][ $panel ][ $field ] : $default; } } else { $field_name = sprintf( '%s[%s]', $panel, $field ); $value = isset( $form_data[ $panel ][ $field ] ) ? $form_data[ $panel ][ $field ] : $default; } if ( isset( $args['field_name'] ) ) { $field_name = $args['field_name']; } if ( isset( $args['value'] ) ) { $value = $args['value']; } // Check for data attributes. if ( ! empty( $args['data'] ) ) { foreach ( $args['data'] as $key => $val ) { if ( is_array( $val ) ) { $val = wp_json_encode( $val ); } $data_attr .= ' data-' . $key . '=\'' . $val . '\''; } } // Check for readonly inputs. if ( ! empty( $args['readonly' ] ) ) { $data_attr .= 'readonly'; } // Determine what field type to output. switch ( $option ) { // Text input. case 'text': $output = sprintf( '<input type="%s" id="%s" name="%s" value="%s" placeholder="%s" class="%s" %s>', ! empty( $args['type'] ) ? esc_attr( $args['type'] ) : 'text', $input_id, $field_name, esc_attr( $value ), $placeholder, $input_class, $data_attr ); break; // Textarea. case 'textarea': $output = sprintf( '<textarea id="%s" name="%s" rows="%d" placeholder="%s" class="%s" %s>%s</textarea>', $input_id, $field_name, ! empty( $args['rows'] ) ? (int) $args['rows'] : '3', $placeholder, $input_class, $data_attr, esc_textarea( $value ) ); break; // TinyMCE. case 'tinymce': $id = str_replace( '-', '_', $input_id ); $args['tinymce']['textarea_name'] = $field_name; $args['tinymce']['teeny'] = true; $args['tinymce'] = wp_parse_args( $args['tinymce'], array( 'media_buttons' => false, 'teeny' => true, ) ); ob_start(); wp_editor( $value, $id, $args['tinymce'] ); $output = ob_get_clean(); break; // Checkbox. case 'checkbox': $output = sprintf( '<input type="checkbox" id="%s" name="%s" value="1" class="%s" %s %s>', $input_id, $field_name, $input_class, checked( '1', $value, false ), $data_attr ); $output .= sprintf( '<label for="%s" class="inline">%s', $input_id, $label ); if ( ! empty( $args['tooltip'] ) ) { $output .= sprintf( ' <i class="fa fa-question-circle wpforms-help-tooltip" title="%s"></i>', esc_attr( $args['tooltip'] ) ); } $output .= '</label>'; break; // Radio. case 'radio': $options = $args['options']; $radio_counter = 1; $output = ''; foreach ( $options as $key => $item ) { if ( empty( $item['label'] ) ) { continue; } $item_value = ! empty( $item['value'] ) ? $item['value'] : $key; $output .= '<span class="row">'; if ( ! empty( $item['pre_label'] ) ) { $output .= '<label>' . $item['pre_label']; } $output .= sprintf( '<input type="radio" id="%s-%d" name="%s" value="%s" class="%s" %s %s>', $input_id, $radio_counter, $field_name, $item_value, $input_class, checked( $item_value, $value, false ), $data_attr ); if ( empty( $item['pre_label'] ) ) { $output .= sprintf( '<label for="%s-%d" class="inline">%s', $input_id, $radio_counter, $item['label'] ); } else { $output .= '<span class="wpforms-panel-field-radio-label">' . $item['label'] . '</span>'; } if ( ! empty( $item['tooltip'] ) ) { $output .= sprintf( ' <i class="fa fa-question-circle wpforms-help-tooltip" title="%s"></i>', esc_attr( $item['tooltip'] ) ); } $output .= '</label></span>'; $radio_counter ++; } if ( ! empty( $output ) ) { $output = '<div class="wpforms-panel-field-radio-container">' . $output . '</div>'; } break; // Select. case 'select': if ( empty( $args['options'] ) && empty( $args['field_map'] ) ) { return ''; } if ( ! empty( $args['field_map'] ) ) { $options = array(); $available_fields = wpforms_get_form_fields( $form_data, $args['field_map'] ); if ( ! empty( $available_fields ) ) { foreach ( $available_fields as $id => $available_field ) { $lbl = ! empty( $available_field['label'] ) ? esc_attr( $available_field['label'] ) : esc_html__( 'Field #' ) . $id; $options[ $id ] = $lbl; } } $input_class .= ' wpforms-field-map-select'; $data_attr .= ' data-field-map-allowed="' . implode( ' ', $args['field_map'] ) . '"'; if ( ! empty( $placeholder ) ) { $data_attr .= ' data-field-map-placeholder="' . esc_attr( $placeholder ) . '"'; } } else { $options = $args['options']; } $output = sprintf( '<select id="%s" name="%s" class="%s" %s>', $input_id, $field_name, $input_class, $data_attr ); if ( ! empty( $placeholder ) ) { $output .= '<option value="">' . $placeholder . '</option>'; } foreach ( $options as $key => $item ) { $output .= sprintf( '<option value="%s" %s>%s</option>', esc_attr( $key ), selected( $key, $value, false ), $item ); } $output .= '</select>'; break; } // Put the pieces together. $field_open = sprintf( '<div id="%s-wrap" class="wpforms-panel-field %s %s">', $input_id, $class, 'wpforms-panel-field-' . sanitize_html_class( $option ) ); $field_open .= ! empty( $args['before'] ) ? $args['before'] : ''; if ( 'checkbox' !== $option && ! empty( $label ) ) { $field_label = sprintf( '<label for="%s">%s', $input_id, $label ); if ( ! empty( $args['tooltip'] ) ) { $field_label .= sprintf( ' <i class="fa fa-question-circle wpforms-help-tooltip" title="%s"></i>', esc_attr( $args['tooltip'] ) ); } if ( ! empty( $args['after_tooltip'] ) ) { $field_label .= $args['after_tooltip']; } if ( ! empty( $args['smarttags'] ) ) { $type = ! empty( $args['smarttags']['type'] ) ? esc_attr( $args['smarttags']['type'] ) : 'fields'; $fields = ! empty( $args['smarttags']['fields'] ) ? esc_attr( $args['smarttags']['fields'] ) : ''; $field_label .= '<a href="#" class="toggle-smart-tag-display" data-type="' . $type . '" data-fields="' . $fields . '"><i class="fa fa-tags"></i> <span>' . esc_html__( 'Show Smart Tags', 'wpforms-lite' ) . '</span></a>'; } $field_label .= '</label>'; if ( ! empty( $args['after_label'] ) ) { $field_label .= $args['after_label']; } } else { $field_label = ''; } $field_close = ! empty( $args['after'] ) ? $args['after'] : ''; $field_close .= '</div>'; $output = $field_open . $field_label . $output . $field_close; // Wash our hands. if ( $echo ) { echo $output; } else { return $output; } } /** * Get notification state, whether it's opened or closed. * * @since 1.4.1 * @deprecated 1.4.8 * * @param int $form_id * @param int $notification_id * * @return string */ function wpforms_builder_notification_get_state( $form_id, $notification_id ) { _deprecated_function( __FUNCTION__, '1.4.8 of WPForms plugin', 'wpforms_builder_settings_block_get_state()' ); return wpforms_builder_settings_block_get_state( $form_id, $notification_id, 'notification' ); } /** * Get settings block state, whether it's opened or closed. * * @since 1.4.8 * * @param int $form_id * @param int $block_id * @param string $block_type * * @return string */ function wpforms_builder_settings_block_get_state( $form_id, $block_id, $block_type ) { $form_id = absint( $form_id ); $block_id = absint( $block_id ); $block_type = sanitize_key( $block_type ); $state = 'opened'; $all_states = get_user_meta( get_current_user_id(), 'wpforms_builder_settings_collapsable_block_states', true ); if ( empty( $all_states ) ) { return $state; } if ( is_array( $all_states ) && ! empty( $all_states[ $form_id ][ $block_type ][ $block_id ] ) && 'closed' === $all_states[ $form_id ][ $block_type ][ $block_id ] ) { $state = 'closed'; } // Backward compatibility for notifications. if ( 'notification' === $block_type && 'closed' !== $state ) { $notification_states = get_user_meta( get_current_user_id(), 'wpforms_builder_notification_states', true ); } if ( ! empty( $notification_states[ $form_id ][ $block_id ] ) && 'closed' === $notification_states[ $form_id ][ $block_id ] ) { $state = 'closed'; } if ( 'notification' === $block_type ) { // Backward compatibility for notifications. return apply_filters( 'wpforms_builder_notification_get_state', $state, $form_id, $block_id ); } return apply_filters( 'wpforms_builder_settings_block_get_state', $state, $form_id, $block_id, $block_type ); } /** * Get the list of allowed tags, used in pair with wp_kses() function. * This allows getting rid of all potentially harmful HTML tags and attributes. * * @since 1.5.9 * * @return array Allowed Tags. */ function wpforms_builder_preview_get_allowed_tags() { static $allowed_tags; if ( ! empty( $allowed_tags ) ) { return $allowed_tags; } $atts = [ 'align', 'class', 'type', 'id', 'for', 'style', 'src', 'rel', 'href', 'target', 'value', 'width', 'height' ]; $tags = [ 'label', 'iframe', 'style', 'button', 'strong', 'small', 'table', 'span', 'abbr', 'code', 'pre', 'div', 'img', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'ol', 'ul', 'li', 'em', 'hr', 'br', 'th', 'tr', 'td', 'p', 'a', 'b', 'i' ]; $allowed_atts = array_fill_keys( $atts, [] ); $allowed_tags = array_fill_keys( $tags, $allowed_atts ); return $allowed_tags; } admin/builder/panels/class-setup.php 0000666 00000013761 15213301445 0013532 0 ustar 00 <?php /** * Setup panel. * * @since 1.0.0 */ class WPForms_Builder_Panel_Setup extends WPForms_Builder_Panel { /** * All systems go. * * @since 1.0.0 */ public function init() { // Define panel information. $this->name = esc_html__( 'Setup', 'wpforms-lite' ); $this->slug = 'setup'; $this->icon = 'fa-cog'; $this->order = 5; } /** * Enqueue assets for the builder. * * @since 1.0.0 */ public function enqueues() { // CSS. wp_enqueue_style( 'wpforms-builder-setup', WPFORMS_PLUGIN_URL . 'assets/css/admin-builder-setup.css', null, WPFORMS_VERSION ); } /** * Output the Settings panel primary content. * * @since 1.0.0 */ public function panel_content() { $core_templates = apply_filters( 'wpforms_form_templates_core', array() ); $additional_templates = apply_filters( 'wpforms_form_templates', array() ); $additional_count = count( $additional_templates ); ?> <div id="wpforms-setup-form-name"> <span><?php esc_html_e( 'Form Name', 'wpforms-lite' ); ?></span> <input type="text" id="wpforms-setup-name" placeholder="<?php esc_attr_e( 'Enter your form name here…', 'wpforms-lite' ); ?>"> </div> <div class="wpforms-setup-title core"> <?php esc_html_e( 'Select a Template', 'wpforms-lite' ); ?> </div> <p class="wpforms-setup-desc core"> <?php echo wp_kses( __( 'To speed up the process, you can select from one of our pre-made templates or start with a <strong><a href="#" class="wpforms-trigger-blank">blank form.</a></strong>', 'wpforms-lite' ), array( 'strong' => array(), 'a' => array( 'href' => array(), 'class' => array(), ), ) ); ?> </p> <?php $this->template_select_options( $core_templates, 'core' ); ?> <div class="wpforms-setup-title additional"> <?php esc_html_e( 'Additional Templates', 'wpforms-lite' ); ?> <?php echo ! empty( $additional_count ) ? '<span class="count">(' . $additional_count . ')</span>' : ''; ?> </div> <?php if ( ! empty( $additional_count ) ) : ?> <p class="wpforms-setup-desc additional"> <?php printf( wp_kses( /* translators: %1$s - WPForms.com URL to a template suggestion, %2$s - WPForms.com URL to a doc about custom templates. */ __( 'Have a suggestion for a new template? <a href="%1$s" target="_blank" rel="noopener noreferrer">We\'d love to hear it</a>. Also, you can <a href="%2$s" target="_blank" rel="noopener noreferrer">create your own templates</a>!', 'wpforms-lite' ), array( 'a' => array( 'href' => array(), 'target' => array(), 'rel' => array(), ), ) ), 'https://wpforms.com/form-template-suggestion/', 'https://wpforms.com/docs/how-to-create-a-custom-form-template/' ); ?> </p> <div class="wpforms-setup-template-search-wrap"> <i class="fa fa-search" aria-hidden="true"></i> <input type="text" id="wpforms-setup-template-search" value="" placeholder="<?php esc_attr_e( 'Search additional templates...', 'wpforms-lite' ); ?>"> </div> <?php $this->template_select_options( $additional_templates, 'additional' ); ?> <?php else : ?> <p class="wpforms-setup-desc additional"> <?php printf( wp_kses( /* translators: %1$s - WPForms.com URL to an addon page, %2$s - WPForms.com URL to a docs article. */ __( 'More are available in the <a href="%1$s" target="_blank" rel="noopener noreferrer">Form Templates Pack addon</a> or by <a href="%2$s" target="_blank" rel="noopener noreferrer">creating your own</a>.', 'wpforms-lite' ), array( 'a' => array( 'href' => array(), 'target' => array(), 'rel' => array(), ), ) ), 'https://wpforms.com/addons/form-templates-pack-addon/', 'https://wpforms.com/docs/how-to-create-a-custom-form-template/' ); ?> </p> <?php endif; do_action( 'wpforms_setup_panel_after' ); } /** * Generate a block of templates to choose from. * * @since 1.4.0 * * @param array $templates * @param string $slug */ public function template_select_options( $templates, $slug ) { if ( ! empty( $templates ) ) { echo '<div id="wpforms-setup-templates-' . $slug . '" class="wpforms-setup-templates ' . $slug . ' wpforms-clear">'; echo '<div class="list">'; // Loop through each available template. foreach ( $templates as $template ) { $selected = ! empty( $this->form_data['meta']['template'] ) && $this->form_data['meta']['template'] === $template['slug'] ? true : false; ?> <div class="wpforms-template <?php echo $selected ? 'selected' : ''; ?>" id="wpforms-template-<?php echo sanitize_html_class( $template['slug'] ); ?>"> <div class="wpforms-template-inner"> <div class="wpforms-template-name wpforms-clear"> <?php echo esc_html( $template['name'] ); ?> <?php echo $selected ? '<span class="selected">' . esc_html__( 'Selected', 'wpforms-lite' ) . '</span>' : ''; ?> </div> <?php if ( ! empty( $template['description'] ) ) : ?> <div class="wpforms-template-details"> <p class="desc"><?php echo esc_html( $template['description'] ); ?></p> </div> <?php endif; ?> <?php $template_name = sprintf( /* translators: %s - Form template name. */ esc_html__( '%s template', 'wpforms-lite' ), $template['name'] ); ?> <div class="wpforms-template-overlay"> <a href="#" class="wpforms-template-select" data-template-name-raw="<?php echo esc_attr( $template['name'] ); ?>" data-template-name="<?php echo esc_attr( $template_name ); ?>" data-template="<?php echo esc_attr( $template['slug'] ); ?>"> <?php printf( /* translators: %s - Form template name. */ esc_html__( 'Create a %s', 'wpforms-lite' ), $template['name'] ); ?> </a> </div> </div> </div> <?php } echo '</div>'; echo '</div>'; } } } new WPForms_Builder_Panel_Setup; admin/builder/panels/class-base.php 0000666 00000010615 15213301445 0013277 0 ustar 00 <?php /** * Base panel class. * * @since 1.0.0 */ abstract class WPForms_Builder_Panel { /** * Full name of the panel. * * @since 1.0.0 * * @var string */ public $name; /** * Slug. * * @since 1.0.0 * * @var string */ public $slug; /** * Font Awesome Icon used for the editor button, eg "fa-list". * * @since 1.0.0 * * @var mixed */ public $icon = false; /** * Priority order the field button should show inside the "Add Fields" tab. * * @since 1.0.0 * * @var int */ public $order = 50; /** * If panel contains a sidebar element or is full width. * * @since 1.0.0 * * @var bool */ public $sidebar = false; /** * Contain form object if we have one. * * @since 1.0.0 * * @var object */ public $form; /** * Contain array of the form data (post_content). * * @since 1.0.0 * * @var array */ public $form_data; /** * Primary class constructor. * * @since 1.0.0 */ public function __construct() { // Load form if found. $form_id = isset( $_GET['form_id'] ) ? absint( $_GET['form_id'] ) : false; $this->form = wpforms()->form->get( $form_id ); $this->form_data = $this->form ? wpforms_decode( $this->form->post_content ) : false; // Bootstrap. $this->init(); // Load panel specific enqueues. add_action( 'admin_enqueue_scripts', array( $this, 'enqueues' ), 15 ); // Primary panel button. add_action( 'wpforms_builder_panel_buttons', array( $this, 'button' ), $this->order, 2 ); // Output. add_action( 'wpforms_builder_panels', array( $this, 'panel_output' ), $this->order, 2 ); } /** * All systems go. Used by children. * * @since 1.0.0 */ public function init() { } /** * Enqueue assets for the builder. Used by children. * * @since 1.0.0 */ public function enqueues() { } /** * Primary panel button in the left panel navigation. * * @since 1.0.0 * * @param mixed $form * @param string $view */ public function button( $form, $view ) { $active = $view === $this->slug ? 'active' : ''; ?> <button class="wpforms-panel-<?php echo esc_attr( $this->slug ); ?>-button <?php echo $active; ?>" data-panel="<?php echo esc_attr( $this->slug ); ?>"> <i class="fa <?php echo esc_attr( $this->icon ); ?>"></i> <span><?php echo esc_html( $this->name ); ?></span> </button> <?php } /** * Output the contents of the panel. * * @since 1.0.0 * * @param object $form * @param string $view */ public function panel_output( $form, $view ) { $active = $view === $this->slug ? 'active' : ''; $wrap = $this->sidebar ? 'wpforms-panel-sidebar-content' : 'wpforms-panel-full-content'; printf( '<div class="wpforms-panel %s" id="wpforms-panel-%s">', $active, esc_attr( $this->slug ) ); printf( '<div class="wpforms-panel-name">%s</div>', $this->name ); printf( '<div class="%s">', $wrap ); if ( true === $this->sidebar ) { echo '<div class="wpforms-panel-sidebar">'; do_action( 'wpforms_builder_before_panel_sidebar', $this->form, $this->slug ); $this->panel_sidebar(); do_action( 'wpforms_builder_after_panel_sidebar', $this->form, $this->slug ); echo '</div>'; } echo '<div class="wpforms-panel-content-wrap">'; echo '<div class="wpforms-panel-content">'; do_action( 'wpforms_builder_before_panel_content', $this->form, $this->slug ); $this->panel_content(); do_action( 'wpforms_builder_after_panel_content', $this->form, $this->slug ); echo '</div>'; echo '</div>'; echo '</div>'; echo '</div>'; } /** * Output the panel's sidebar if we have one. * * @since 1.0.0 */ public function panel_sidebar() { } /** * Output panel sidebar sections. * * @since 1.0.0 * * @param string $name * @param string $slug * @param string $icon */ public function panel_sidebar_section( $name, $slug, $icon = '' ) { $class = ''; $class .= $slug === 'default' ? ' default' : ''; $class .= ! empty( $icon ) ? ' icon' : ''; echo '<a href="#" class="wpforms-panel-sidebar-section wpforms-panel-sidebar-section-' . esc_attr( $slug ) . $class . '" data-section="' . esc_attr( $slug ) . '">'; if ( ! empty( $icon ) ) { echo '<img src="' . esc_url( $icon ) . '">'; } echo esc_html( $name ); echo '<i class="fa fa-angle-right wpforms-toggle-arrow"></i>'; echo '</a>'; } /** * Output the panel's primary content. * * @since 1.0.0 */ public function panel_content() { } } admin/builder/panels/class-fields.php 0000666 00000032636 15213301445 0013642 0 ustar 00 <?php /** * Fields management panel. * * @since 1.0.0 */ class WPForms_Builder_Panel_Fields extends WPForms_Builder_Panel { /** * All systems go. * * @since 1.0.0 */ public function init() { // Define panel information. $this->name = esc_html__( 'Fields', 'wpforms-lite' ); $this->slug = 'fields'; $this->icon = 'fa-list-alt'; $this->order = 10; $this->sidebar = true; if ( $this->form ) { add_action( 'wpforms_builder_fields', array( $this, 'fields' ) ); add_action( 'wpforms_builder_fields_options', array( $this, 'fields_options' ) ); add_action( 'wpforms_builder_preview', array( $this, 'preview' ) ); // Template for form builder previews. add_action( 'wpforms_builder_print_footer_scripts', array( $this, 'field_preview_templates' ) ); } } /** * Enqueue assets for the Fields panel. * * @since 1.0.0 */ public function enqueues() { // CSS. wp_enqueue_style( 'wpforms-builder-fields', WPFORMS_PLUGIN_URL . 'assets/css/admin-builder-fields.css', null, WPFORMS_VERSION ); } /** * Output the Field panel sidebar. * * @since 1.0.0 */ public function panel_sidebar() { // Sidebar contents are not valid unless we have a form. if ( ! $this->form ) { return; } ?> <ul class="wpforms-tabs wpforms-clear"> <li class="wpforms-tab" id="add-fields"> <a href="#" class="active"> <?php esc_html_e( 'Add Fields', 'wpforms-lite' ); ?> <i class="fa fa-angle-down"></i> </a> </li> <li class="wpforms-tab" id="field-options"> <a href="#"> <?php esc_html_e( 'Field Options', 'wpforms-lite' ); ?> <i class="fa fa-angle-right"></i> </a> </li> </ul> <div class="wpforms-add-fields wpforms-tab-content"> <?php do_action( 'wpforms_builder_fields', $this->form ); ?> </div> <div id="wpforms-field-options" class="wpforms-field-options wpforms-tab-content"> <?php do_action( 'wpforms_builder_fields_options', $this->form ); ?> </div> <?php } /** * Output the Field panel primary content. * * @since 1.0.0 */ public function panel_content() { // Check if there is a form created. if ( ! $this->form ) { echo '<div class="wpforms-alert wpforms-alert-info">'; echo wp_kses( __( 'You need to <a href="#" class="wpforms-panel-switch" data-panel="setup">setup your form</a> before you can manage the fields.', 'wpforms-lite' ), array( 'a' => array( 'href' => array(), 'class' => array(), 'data-panel' => array(), ), ) ); echo '</div>'; return; } ?> <div class="wpforms-preview-wrap"> <div class="wpforms-preview"> <div class="wpforms-title-desc"> <h2 class="wpforms-form-name"><?php echo esc_html( $this->form->post_title ); ?></h2> <span class="wpforms-form-desc"><?php echo wp_kses( $this->form->post_excerpt, wpforms_builder_preview_get_allowed_tags() ); ?></span> </div> <div class="wpforms-no-fields-holder wpforms-hidden"> <?php $this->no_fields_options(); ?> <?php $this->no_fields_preview(); ?> </div> <div class="wpforms-field-wrap"> <?php do_action( 'wpforms_builder_preview', $this->form ); ?> </div> <div class="wpforms-field-recaptcha"> <div class="wpforms-field-recaptcha-wrap"> <div class="wpforms-field-recaptcha-wrap-l"> <svg class="wpforms-field-recaptcha-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 28 27.918"><path d="M28 13.943l-.016-.607V2l-3.133 3.134a13.983 13.983 0 00-21.964.394l5.134 5.183a6.766 6.766 0 012.083-2.329A6.171 6.171 0 0114.025 7.1a1.778 1.778 0 01.492.066 6.719 6.719 0 015.17 3.119l-3.625 3.641 11.941.016" fill="#1c3aa9"/><path d="M13.943 0l-.607.016H2.018l3.133 3.133a13.969 13.969 0 00.377 21.964l5.183-5.134A6.766 6.766 0 018.382 17.9 6.171 6.171 0 017.1 13.975a1.778 1.778 0 01.066-.492 6.719 6.719 0 013.117-5.167l3.641 3.641L13.943 0" fill="#4285f4"/><path d="M0 13.975l.016.607v11.334l3.133-3.133a13.983 13.983 0 0021.964-.394l-5.134-5.183a6.766 6.766 0 01-2.079 2.33 6.171 6.171 0 01-3.92 1.279 1.778 1.778 0 01-.492-.066 6.719 6.719 0 01-5.167-3.117l3.641-3.641c-4.626 0-9.825.016-11.958-.016" fill="#ababab"/></svg> </div> <div class="wpforms-field-recaptcha-wrap-r"> <p class="wpforms-field-recaptcha-title"><?php esc_html_e( 'reCAPTCHA', 'wpforms-lite' ); ?></p> <p class="wpforms-field-recaptcha-desc"> <span class="wpforms-field-recaptcha-desc-txt"><?php esc_html_e( 'Enabled', 'wpforms-lite' ); ?></span> <svg class="wpforms-field-recaptcha-desc-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M512 256c0-37.7-23.7-69.9-57.1-82.4 14.7-32.4 8.8-71.9-17.9-98.6-26.7-26.7-66.2-32.6-98.6-17.9C325.9 23.7 293.7 0 256 0s-69.9 23.7-82.4 57.1c-32.4-14.7-72-8.8-98.6 17.9-26.7 26.7-32.6 66.2-17.9 98.6C23.7 186.1 0 218.3 0 256s23.7 69.9 57.1 82.4c-14.7 32.4-8.8 72 17.9 98.6 26.6 26.6 66.1 32.7 98.6 17.9 12.5 33.3 44.7 57.1 82.4 57.1s69.9-23.7 82.4-57.1c32.6 14.8 72 8.7 98.6-17.9 26.7-26.7 32.6-66.2 17.9-98.6 33.4-12.5 57.1-44.7 57.1-82.4zm-144.8-44.25L236.16 341.74c-4.31 4.28-11.28 4.25-15.55-.06l-75.72-76.33c-4.28-4.31-4.25-11.28.06-15.56l26.03-25.82c4.31-4.28 11.28-4.25 15.56.06l42.15 42.49 97.2-96.42c4.31-4.28 11.28-4.25 15.55.06l25.82 26.03c4.28 4.32 4.26 11.29-.06 15.56z"></path></svg> </p> </div> </div> </div> <?php $submit = ! empty( $this->form_data['settings']['submit_text'] ) ? $this->form_data['settings']['submit_text'] : esc_html__( 'Submit', 'wpforms-lite' ); printf( '<p class="wpforms-field-submit"><input type="submit" value="%s" class="wpforms-field-submit-button"></p>', esc_attr( $submit ) ); ?> <?php wpforms_debug_data( $this->form_data ); ?> </div> </div> <?php } /** * Builder field buttons. * * @since 1.0.0 */ public function fields() { $fields = array( 'standard' => array( 'group_name' => esc_html__( 'Standard Fields', 'wpforms-lite' ), 'fields' => array(), ), 'fancy' => array( 'group_name' => esc_html__( 'Fancy Fields', 'wpforms-lite' ), 'fields' => array(), ), 'payment' => array( 'group_name' => esc_html__( 'Payment Fields', 'wpforms-lite' ), 'fields' => array(), ), ); $fields = apply_filters( 'wpforms_builder_fields_buttons', $fields ); // Output the buttons. foreach ( $fields as $id => $group ) { usort( $group['fields'], array( $this, 'field_order' ) ); echo '<div class="wpforms-add-fields-group">'; echo '<a href="#" class="wpforms-add-fields-heading" data-group="' . esc_attr( $id ) . '">'; echo '<span>' . esc_html( $group['group_name'] ) . '</span>'; echo '<i class="fa fa-angle-down"></i>'; echo '</a>'; echo '<div class="wpforms-add-fields-buttons">'; foreach ( $group['fields'] as $field ) { $atts = apply_filters( 'wpforms_builder_field_button_attributes', array( 'id' => 'wpforms-add-fields-' . $field['type'], 'class' => array( 'wpforms-add-fields-button' ), 'data' => array( 'field-type' => $field['type'], ), 'atts' => array(), ), $field, $this->form_data ); if ( ! empty( $field['class'] ) ) { $atts['class'][] = $field['class']; } echo '<button ' . wpforms_html_attributes( $atts['id'], $atts['class'], $atts['data'], $atts['atts'] ) . '>'; if ( $field['icon'] ) { echo '<i class="fa ' . esc_attr( $field['icon'] ) . '"></i> '; } echo esc_html( $field['name'] ); echo '</button>'; } echo '</div>'; echo '</div>'; } } /** * Editor Field Options. * * @since 1.0.0 */ public function fields_options() { // Check to make sure the form actually has fields created already. if ( empty( $this->form_data['fields'] ) ) { $this->no_fields_options(); return; } $fields = $this->form_data['fields']; foreach ( $fields as $field ) { $class = apply_filters( 'wpforms_builder_field_option_class', '', $field ); printf( '<div class="wpforms-field-option wpforms-field-option-%s %s" id="wpforms-field-option-%d" data-field-id="%d">', sanitize_html_class( $field['type'] ), sanitize_html_class( $class ), (int) $field['id'], (int) $field['id'] ); printf( '<input type="hidden" name="fields[%d][id]" value="%d" class="wpforms-field-option-hidden-id">', $field['id'], $field['id'] ); printf( '<input type="hidden" name="fields[%d][type]" value="%s" class="wpforms-field-option-hidden-type">', $field['id'], esc_attr( $field['type'] ) ); do_action( "wpforms_builder_fields_options_{$field['type']}", $field ); echo '</div>'; } } /** * Editor preview (right pane). * * @since 1.0.0 */ public function preview() { // Check to make sure the form actually has fields created already. if ( empty( $this->form_data['fields'] ) ) { $this->no_fields_preview(); return; } $fields = $this->form_data['fields']; foreach ( $fields as $field ) { $css = ! empty( $field['size'] ) ? 'size-' . esc_attr( $field['size'] ) : ''; $css .= ! empty( $field['label_hide'] ) && $field['label_hide'] == '1' ? ' label_hide' : ''; $css .= ! empty( $field['sublabel_hide'] ) && $field['sublabel_hide'] == '1' ? ' sublabel_hide' : ''; $css .= ! empty( $field['required'] ) && $field['required'] == '1' ? ' required' : ''; $css .= ! empty( $field['input_columns'] ) && $field['input_columns'] === '2' ? ' wpforms-list-2-columns' : ''; $css .= ! empty( $field['input_columns'] ) && $field['input_columns'] === '3' ? ' wpforms-list-3-columns' : ''; $css .= ! empty( $field['input_columns'] ) && $field['input_columns'] === 'inline' ? ' wpforms-list-inline' : ''; $css .= isset( $field['meta']['delete'] ) && $field['meta']['delete'] === false ? ' no-delete' : ''; $css = apply_filters( 'wpforms_field_preview_class', $css, $field ); printf( '<div class="wpforms-field wpforms-field-%s %s" id="wpforms-field-%d" data-field-id="%d" data-field-type="%s">', $field['type'], $css, $field['id'], $field['id'], $field['type'] ); if ( apply_filters( 'wpforms_field_preview_display_duplicate_button', true, $field, $this->form_data ) ) { printf( '<a href="#" class="wpforms-field-duplicate" title="%s"><i class="fa fa-files-o" aria-hidden="true"></i></a>', esc_html__( 'Duplicate Field', 'wpforms-lite' ) ); } printf( '<a href="#" class="wpforms-field-delete" title="%s"><i class="fa fa-trash" aria-hidden="true"></i></a>', esc_html__( 'Delete Field', 'wpforms-lite' ) ); printf( '<span class="wpforms-field-helper">%s</span>', esc_html__( 'Click to edit. Drag to reorder.', 'wpforms-lite' ) ); do_action( "wpforms_builder_fields_previews_{$field['type']}", $field ); echo '</div>'; } } /** * No fields options markup. * * @since 1.6.0 */ public function no_fields_options() { printf( '<p class="no-fields">%s</p>', esc_html__( 'You don\'t have any fields yet.', 'wpforms-lite' ) ); } /** * No fields preview placeholder markup. * * @since 1.6.0 */ public function no_fields_preview() { printf( '<p class="no-fields-preview">%s</p>', esc_html__( 'You don\'t have any fields yet. Add some!', 'wpforms-lite' ) ); } /** * Sort Add Field buttons by order provided. * * @since 1.0.0 * * @param array $a * @param array $b * * @return array */ public function field_order( $a, $b ) { return $a['order'] - $b['order']; } /** * Template for form builder preview. * * @since 1.4.5 */ public function field_preview_templates() { // Checkbox, Radio, and Payment Multiple/Checkbox field choices. ?> <script type="text/html" id="tmpl-wpforms-field-preview-checkbox-radio-payment-multiple"> <# if ( data.settings.choices_images ) { #> <ul class="primary-input wpforms-image-choices wpforms-image-choices-{{ data.settings.choices_images_style }}"> <# _.each( data.order, function( choiceID, key ) { #> <li class="wpforms-image-choices-item<# if ( 1 === data.settings.choices[choiceID].default ) { print( ' wpforms-selected' ); } #>"> <label> <span class="wpforms-image-choices-image"> <# if ( ! _.isEmpty( data.settings.choices[choiceID].image ) ) { #> <img src="{{ data.settings.choices[choiceID].image }}" alt="{{ data.settings.choices[choiceID].label }}"<# if ( data.settings.choices[choiceID].label ) { print( ' title="{{ data.settings.choices[choiceID].label }}"' ); } #>> <# } else { #> <img src="{{ wpforms_builder.image_placeholder }}" alt="{{ data.settings.choices[choiceID].label }}"<# if ( data.settings.choices[choiceID].label ) { print( ' title="{{ data.settings.choices[choiceID].label }}"' ); } #>> <# } #> </span> <# if ( 'none' === data.settings.choices_images_style ) { #> <br> <input type="{{ data.type }}" disabled<# if ( 1 === data.settings.choices[choiceID].default ) { print( ' checked' ); } #>> <# } else { #> <input class="wpforms-screen-reader-element" type="{{ data.type }}" disabled<# if ( 1 === data.settings.choices[choiceID].default ) { print( ' checked' ); } #>> <# } #> <span class="wpforms-image-choices-label">{{{ data.settings.choices[choiceID].label }}}</span> </label> </li> <# }) #> </ul> <# } else { #> <ul class="primary-input"> <# _.each( data.order, function( choiceID, key ) { #> <li> <input type="{{ data.type }}" disabled<# if ( 1 === data.settings.choices[choiceID].default ) { print( ' checked' ); } #>>{{{ wpf.sanitizeHTML( data.settings.choices[choiceID].label ) }}} </li> <# }) #> </ul> <# } #> </script> <?php } } new WPForms_Builder_Panel_Fields(); admin/builder/panels/class-payments.php 0000666 00000007122 15213301445 0014224 0 ustar 00 <?php /** * Payments panel. * * @since 1.0.0 */ class WPForms_Builder_Panel_Payments extends WPForms_Builder_Panel { /** * All systems go. * * @since 1.0.0 */ public function init() { // Define panel information. $this->name = esc_html__( 'Payments', 'wpforms-lite' ); $this->slug = 'payments'; $this->icon = 'fa-usd'; $this->order = 10; $this->sidebar = true; } /** * Output the Payments panel sidebar. * * @since 1.0.0 */ public function panel_sidebar() { // Sidebar contents are not valid unless we have a form. if ( ! $this->form ) { return; } $this->panel_sidebar_section( esc_html__( 'Default', 'wpforms-lite' ), 'default' ); do_action( 'wpforms_payments_panel_sidebar', $this->form ); } /** * Output the Payments panel primary content. * * @since 1.0.0 */ public function panel_content() { // An array of all the active provider addons. $payments_active = apply_filters( 'wpforms_payments_available', array() ); if ( ! $this->form ) { // Check if there is a form created. When no form has been created // yet let the user know we need a form to setup a payment. echo '<div class="wpforms-alert wpforms-alert-info">'; echo wp_kses( __( 'You need to <a href="#" class="wpforms-panel-switch" data-panel="setup">setup your form</a> before you can manage these settings.', 'wpforms-lite' ), array( 'a' => array( 'href' => array(), 'class' => array(), 'data-panel' => array(), ), ) ); echo '</div>'; return; } if ( ! wpforms()->pro ) { // WPForms Lite users. echo '<div class="wpforms-panel-content-section wpforms-panel-content-section-info">'; echo '<p>Payment integrations are not available on your plan.</p>'; echo '<p>Please upgrade to PRO to unlock all the payment integrations and more awesome features.</p>'; echo '<a href="' . esc_url( wpforms_admin_upgrade_link( 'builder-payments' ) ) . '" class="wpforms-btn wpforms-btn-orange wpforms-btn-lg" target="_blank" rel="noopener noreferrer">' . esc_html__( 'Upgrade to PRO', 'wpforms-lite' ) . '</a>'; echo '</div>'; } elseif ( empty( $payments_active ) ) { // Check for active payment addons. When no payment addons are // activated let the user know they need to install/activate an // addon to setup a payment. echo '<div class="wpforms-panel-content-section wpforms-panel-content-section-info">'; echo '<h5>' . esc_html__( 'Install Your Payment Integration', 'wpforms-lite' ) . '</h5>'; echo '<p>' . sprintf( wp_kses( /* translators: %s - Addons page URL. */ __( 'It seems you do not have any payment addons activated. You can head over to the <a href="%s">Addons page</a> to install and activate the addon for your payment service.', 'wpforms-lite' ), array( 'a' => array( 'href' => array(), ), ) ), esc_url( admin_url( 'admin.php?page=wpforms-addons' ) ) ) . '</p>'; echo '</div>'; } else { // Everything is good - display default instructions. echo '<div class="wpforms-panel-content-section wpforms-panel-content-section-default">'; echo '<h5>' . esc_html__( 'Select Your Payment Integration', 'wpforms-lite' ) . '</h5>'; echo '<p>' . esc_html__( 'Select your payment provider from the options on the left. If you don\'t see your payment service listed, then let us know and we\'ll do our best to get it added as fast as possible.', 'wpforms-lite' ) . '</p>'; echo '</div>'; } do_action( 'wpforms_payments_panel_content', $this->form ); } } new WPForms_Builder_Panel_Payments(); admin/builder/panels/class-settings.php 0000666 00000013150 15213301445 0014222 0 ustar 00 <?php /** * Settings management panel. * * @since 1.0.0 */ class WPForms_Builder_Panel_Settings extends WPForms_Builder_Panel { /** * All systems go. * * @since 1.0.0 */ public function init() { // Define panel information. $this->name = esc_html__( 'Settings', 'wpforms-lite' ); $this->slug = 'settings'; $this->icon = 'fa-sliders'; $this->order = 10; $this->sidebar = true; } /** * Output the Settings panel sidebar. * * @since 1.0.0 */ public function panel_sidebar() { // Sidebar contents are not valid unless we have a form. if ( ! $this->form ) { return; } $sections = array( 'general' => esc_html__( 'General', 'wpforms-lite' ), 'notifications' => esc_html__( 'Notifications', 'wpforms-lite' ), 'confirmation' => esc_html__( 'Confirmations', 'wpforms-lite' ), ); $sections = apply_filters( 'wpforms_builder_settings_sections', $sections, $this->form_data ); foreach ( $sections as $slug => $section ) { $this->panel_sidebar_section( $section, $slug ); } } /** * Output the Settings panel primary content. * * @since 1.0.0 */ public function panel_content() { // Check if there is a form created. if ( ! $this->form ) { echo '<div class="wpforms-alert wpforms-alert-info">'; echo wp_kses( __( 'You need to <a href="#" class="wpforms-panel-switch" data-panel="setup">setup your form</a> before you can manage the settings.', 'wpforms-lite' ), array( 'a' => array( 'href' => array(), 'class' => array(), 'data-panel' => array(), ), ) ); echo '</div>'; return; } /* * General. */ echo '<div class="wpforms-panel-content-section wpforms-panel-content-section-general">'; echo '<div class="wpforms-panel-content-section-title">'; esc_html_e( 'General', 'wpforms-lite' ); echo '</div>'; wpforms_panel_field( 'text', 'settings', 'form_title', $this->form_data, esc_html__( 'Form Name', 'wpforms-lite' ), array( 'default' => $this->form->post_title, ) ); wpforms_panel_field( 'textarea', 'settings', 'form_desc', $this->form_data, esc_html__( 'Form Description', 'wpforms-lite' ) ); wpforms_panel_field( 'text', 'settings', 'form_class', $this->form_data, esc_html__( 'Form CSS Class', 'wpforms-lite' ), array( 'tooltip' => esc_html__( 'Enter CSS class names for the form wrapper. Multiple class names should be separated with spaces.', 'wpforms-lite' ), ) ); wpforms_panel_field( 'text', 'settings', 'submit_text', $this->form_data, esc_html__( 'Submit Button Text', 'wpforms-lite' ), array( 'default' => esc_html__( 'Submit', 'wpforms-lite' ), ) ); wpforms_panel_field( 'text', 'settings', 'submit_text_processing', $this->form_data, esc_html__( 'Submit Button Processing Text', 'wpforms-lite' ), array( 'tooltip' => esc_html__( 'Enter the submit button text you would like the button display while the form submit is processing.', 'wpforms-lite' ), ) ); wpforms_panel_field( 'text', 'settings', 'submit_class', $this->form_data, esc_html__( 'Submit Button CSS Class', 'wpforms-lite' ), array( 'tooltip' => esc_html__( 'Enter CSS class names for the form submit button. Multiple names should be separated with spaces.', 'wpforms-lite' ), ) ); wpforms_panel_field( 'checkbox', 'settings', 'honeypot', $this->form_data, esc_html__( 'Enable anti-spam honeypot', 'wpforms-lite' ) ); $recaptcha_key = wpforms_setting( 'recaptcha-site-key' ); $recaptcha_secret = wpforms_setting( 'recaptcha-secret-key' ); $recaptcha_type = wpforms_setting( 'recaptcha-type', 'v2' ); if ( ! empty( $recaptcha_key ) && ! empty( $recaptcha_secret ) ) { switch ( $recaptcha_type ) { case 'v2': $lbl = esc_html__( 'Enable Google Checkbox v2 reCAPTCHA', 'wpforms-lite' ); break; case 'invisible': $lbl = esc_html__( 'Enable Google Invisible v2 reCAPTCHA', 'wpforms-lite' ); break; case 'v3': $lbl = esc_html__( 'Enable Google v3 reCAPTCHA', 'wpforms-lite' ); break; } wpforms_panel_field( 'checkbox', 'settings', 'recaptcha', $this->form_data, $lbl ); } wpforms_panel_field( 'checkbox', 'settings', 'dynamic_population', $this->form_data, esc_html__( 'Enable dynamic fields population', 'wpforms-lite' ), array( 'tooltip' => '<a href="https://developers.wpforms.com/docs/enable-dynamic-field-population/" target="_blank" rel="noopener noreferrer">' . esc_html__( 'How to use Dynamic Field Population', 'wpforms-lite' ) . '</a>', ) ); wpforms_panel_field( 'checkbox', 'settings', 'ajax_submit', $this->form_data, esc_html__( 'Enable AJAX form submission', 'wpforms-lite' ), array( 'tooltip' => esc_html__( 'Enables form submission without page reload.', 'wpforms-lite' ), ) ); do_action( 'wpforms_form_settings_general', $this ); echo '</div>'; /* * Notifications. */ echo '<div class="wpforms-panel-content-section wpforms-panel-content-section-notifications">'; do_action( 'wpforms_form_settings_notifications', $this ); echo '</div>'; /* * Confirmations. */ echo '<div class="wpforms-panel-content-section wpforms-panel-content-section-confirmation">'; do_action( 'wpforms_form_settings_confirmations', $this ); echo '</div>'; /* * Custom panels can be added below. */ do_action( 'wpforms_form_settings_panel_content', $this ); } } new WPForms_Builder_Panel_Settings(); admin/builder/panels/class-providers.php 0000666 00000010310 15213301445 0014372 0 ustar 00 <?php /** * Providers panel. * * @since 1.0.0 */ class WPForms_Builder_Panel_Providers extends WPForms_Builder_Panel { /** * All systems go. * * @since 1.0.0 */ public function init() { // Define panel information. $this->name = esc_html__( 'Marketing', 'wpforms-lite' ); $this->slug = 'providers'; $this->icon = 'fa-bullhorn'; $this->order = 10; $this->sidebar = true; } /** * Enqueue assets for the Providers panel. * * @since 1.0.0 */ public function enqueues() { wp_enqueue_style( 'wpforms-builder-providers', WPFORMS_PLUGIN_URL . 'assets/css/admin-builder-providers.css', null, WPFORMS_VERSION ); wp_enqueue_script( 'wpforms-builder-providers', WPFORMS_PLUGIN_URL . 'assets/js/admin-builder-providers.js', array( 'jquery' ), WPFORMS_VERSION, false ); wp_localize_script( 'wpforms-builder-providers', 'wpforms_builder_providers', array( 'url' => esc_url( add_query_arg( array( 'view' => 'providers' ) ) ), 'confirm_save' => esc_html__( 'We need to save your progress to continue to the Marketing panel. Is that OK?', 'wpforms-lite' ), 'confirm_connection' => esc_html__( 'Are you sure you want to delete this connection?', 'wpforms-lite' ), 'prompt_connection' => esc_html__( 'Enter a %type% nickname', 'wpforms-lite' ), 'prompt_placeholder' => esc_html__( 'Eg: Newsletter Optin', 'wpforms-lite' ), 'error_name' => esc_html__( 'You must provide a connection nickname.', 'wpforms-lite' ), 'required_field' => esc_html__( 'Field required', 'wpforms-lite' ), ) ); } /** * Output the Provider panel sidebar. * * @since 1.0.0 */ public function panel_sidebar() { // Sidebar contents are not valid unless we have a form. if ( ! $this->form ) { return; } $this->panel_sidebar_section( 'Default', 'default' ); do_action( 'wpforms_providers_panel_sidebar', $this->form ); } /** * Output the Provider panel primary content. * * @since 1.0.0 */ public function panel_content() { if ( ! $this->form ) { // Check if there is a form created. When no form has been created // yet let the user know we need a form to setup a provider. echo '<div class="wpforms-alert wpforms-alert-info">'; echo wp_kses( __( 'You need to <a href="#" class="wpforms-panel-switch" data-panel="setup">setup your form</a> before you can manage these settings.', 'wpforms-lite' ), array( 'a' => array( 'href' => array(), 'class' => array(), 'data-panel' => array(), ), ) ); echo '</div>'; return; } // An array of all the active provider addons. $providers_active = wpforms_get_providers_available(); if ( empty( $providers_active ) ) { // Check for active provider addons. When no provider addons are // activated let the user know they need to install/activate an // addon to setup a provider. echo '<div class="wpforms-panel-content-section wpforms-panel-content-section-info">'; echo '<h5>' . esc_html__( 'Install Your Marketing Integration', 'wpforms-lite' ) . '</h5>'; echo '<p>' . sprintf( wp_kses( /* translators: %s - plugin admin area Addons page. */ __( 'It seems you do not have any marketing addons activated. You can head over to the <a href="%s">Addons page</a> to install and activate the addon for your provider.', 'wpforms-lite' ), array( 'a' => array( 'href' => array(), ), ) ), esc_url( admin_url( 'admin.php?page=wpforms-addons' ) ) ) . '</p>'; echo '</div>'; } else { // Everything is good - display default instructions. echo '<div class="wpforms-panel-content-section wpforms-panel-content-section-default">'; echo '<h5>' . esc_html__( 'Select Your Marketing Integration', 'wpforms-lite' ) . '</h5>'; echo '<p>' . esc_html__( 'Select your email marketing service provider or CRM from the options on the left. If you don\'t see your email marketing service listed, then let us know and we\'ll do our best to get it added as fast as possible.', 'wpforms-lite' ) . '</p>'; echo '</div>'; } do_action( 'wpforms_providers_panel_content', $this->form ); } } new WPForms_Builder_Panel_Providers(); admin/ajax-actions.php 0000666 00000034061 15213301445 0010734 0 ustar 00 <?php /** * Ajax actions used in by admin. * * @since 1.0.0 */ /** * Save a form. * * @since 1.0.0 */ function wpforms_save_form() { // Run a security check. check_ajax_referer( 'wpforms-builder', 'nonce' ); // Check for permissions. if ( ! wpforms_current_user_can( 'edit_forms' ) ) { die( esc_html__( 'You do not have permission.', 'wpforms-lite' ) ); } // Check for form data. if ( empty( $_POST['data'] ) ) { die( esc_html__( 'No data provided', 'wpforms-lite' ) ); } $form_post = json_decode( stripslashes( $_POST['data'] ) ); // phpcs:ignore $data = array(); if ( ! is_null( $form_post ) && $form_post ) { foreach ( $form_post as $post_input_data ) { // For input names that are arrays (e.g. `menu-item-db-id[3][4][5]`), // derive the array path keys via regex and set the value in $_POST. preg_match( '#([^\[]*)(\[(.+)\])?#', $post_input_data->name, $matches ); $array_bits = array( $matches[1] ); if ( isset( $matches[3] ) ) { $array_bits = array_merge( $array_bits, explode( '][', $matches[3] ) ); } $new_post_data = array(); // Build the new array value from leaf to trunk. for ( $i = count( $array_bits ) - 1; $i >= 0; $i -- ) { if ( $i === count( $array_bits ) - 1 ) { $new_post_data[ $array_bits[ $i ] ] = wp_slash( $post_input_data->value ); } else { $new_post_data = array( $array_bits[ $i ] => $new_post_data, ); } } $data = array_replace_recursive( $data, $new_post_data ); } } $form_id = wpforms()->form->update( $data['id'], $data ); do_action( 'wpforms_builder_save_form', $form_id, $data ); if ( ! $form_id ) { die( esc_html__( 'An error occurred and the form could not be saved', 'wpforms-lite' ) ); } wp_send_json_success( apply_filters( 'wpforms_builder_save_form_response_data', array( 'form_name' => esc_html( $data['settings']['form_title'] ), 'form_desc' => $data['settings']['form_desc'], 'redirect' => admin_url( 'admin.php?page=wpforms-overview' ), ), $form_id, $data ) ); } add_action( 'wp_ajax_wpforms_save_form', 'wpforms_save_form' ); /** * Create a new form * * @since 1.0.0 */ function wpforms_new_form() { // Run a security check. check_ajax_referer( 'wpforms-builder', 'nonce' ); // Check for form name. if ( empty( $_POST['title'] ) ) { die( esc_html__( 'No form name provided', 'wpforms-lite' ) ); } // Create form. $form_title = sanitize_text_field( $_POST['title'] ); $form_template = sanitize_text_field( $_POST['template'] ); $title_exists = get_page_by_title( $form_title, 'OBJECT', 'wpforms' ); $form_id = wpforms()->form->add( $form_title, array(), array( 'template' => $form_template, ) ); if ( null !== $title_exists ) { wp_update_post( array( 'ID' => $form_id, 'post_title' => $form_title . ' (ID #' . $form_id . ')', ) ); } if ( ! $form_id ) { die( esc_html__( 'Error creating form', 'wpforms-lite' ) ); } if ( wpforms_current_user_can( 'edit_form_single', $form_id ) ) { wp_send_json_success( array( 'id' => $form_id, 'redirect' => add_query_arg( array( 'view' => 'fields', 'form_id' => $form_id, 'newform' => '1', ), admin_url( 'admin.php?page=wpforms-builder' ) ), ) ); } if ( wpforms_current_user_can( 'view_forms' ) ) { wp_send_json_success( array( 'redirect' => admin_url( 'admin.php?page=wpforms-overview' ) ) ); } wp_send_json_success( array( 'redirect' => admin_url() ) ); } add_action( 'wp_ajax_wpforms_new_form', 'wpforms_new_form' ); /** * Update form template. * * @since 1.0.0 */ function wpforms_update_form_template() { // Run a security check. check_ajax_referer( 'wpforms-builder', 'nonce' ); // Check for form name. if ( empty( $_POST['form_id'] ) ) { die( esc_html__( 'No form ID provided', 'wpforms-lite' ) ); } $data = wpforms()->form->get( (int) $_POST['form_id'], array( 'content_only' => true, ) ); $form_id = wpforms()->form->update( (int) $_POST['form_id'], $data, array( 'template' => $_POST['template'], ) ); if ( $form_id ) { $data = array( 'id' => $form_id, 'redirect' => add_query_arg( array( 'view' => 'fields', 'form_id' => $form_id, ), admin_url( 'admin.php?page=wpforms-builder' ) ), ); wp_send_json_success( $data ); } else { die( esc_html__( 'Error updating form template', 'wpforms-lite' ) ); } } add_action( 'wp_ajax_wpforms_update_form_template', 'wpforms_update_form_template' ); /** * Form Builder update next field ID. * * @since 1.2.9 */ function wpforms_builder_increase_next_field_id() { // Run a security check. check_ajax_referer( 'wpforms-builder', 'nonce' ); // Check for permissions. if ( ! wpforms_current_user_can( 'edit_forms' ) ) { wp_send_json_error(); } // Check for required items. if ( empty( $_POST['form_id'] ) ) { wp_send_json_error(); } wpforms()->form->next_field_id( absint( $_POST['form_id'] ) ); wp_send_json_success(); } add_action( 'wp_ajax_wpforms_builder_increase_next_field_id', 'wpforms_builder_increase_next_field_id' ); /** * Form Builder Dynamic Choices option toggle. * * This can be triggered with select/radio/checkbox fields. * * @since 1.2.8 */ function wpforms_builder_dynamic_choices() { // Run a security check. check_ajax_referer( 'wpforms-builder', 'nonce' ); // Check for permissions. if ( ! wpforms_current_user_can( 'edit_forms' ) ) { wp_send_json_error(); } // Check for valid/required items. if ( ! isset( $_POST['field_id'] ) || empty( $_POST['type'] ) || ! in_array( $_POST['type'], array( 'post_type', 'taxonomy' ), true ) ) { wp_send_json_error(); } $type = esc_attr( $_POST['type'] ); $id = absint( $_POST['field_id'] ); // Fetch the option row HTML to be returned to the builder. $field = new WPForms_Field_Select( false ); $field_args = array( 'id' => $id, 'dynamic_choices' => $type, ); $option_row = $field->field_option( 'dynamic_choices_source', $field_args, array(), false ); wp_send_json_success( array( 'markup' => $option_row, ) ); } add_action( 'wp_ajax_wpforms_builder_dynamic_choices', 'wpforms_builder_dynamic_choices' ); /** * Form Builder Dynamic Choices Source option toggle. * * This can be triggered with select/radio/checkbox fields. * * @since 1.2.8 */ function wpforms_builder_dynamic_source() { // Run a security check. check_ajax_referer( 'wpforms-builder', 'nonce' ); // Check for permissions. if ( ! wpforms_current_user_can( 'edit_forms' ) ) { wp_send_json_error(); } // Check for required items. if ( ! isset( $_POST['field_id'] ) || empty( $_POST['form_id'] ) || empty( $_POST['type'] ) || empty( $_POST['source'] ) ) { wp_send_json_error(); } $type = esc_attr( $_POST['type'] ); $source = esc_attr( $_POST['source'] ); $id = absint( $_POST['field_id'] ); $form_id = absint( $_POST['form_id'] ); $items = array(); $total = 0; $source_name = ''; $type_name = ''; if ( 'post_type' === $type ) { $type_name = esc_html__( 'post type', 'wpforms-lite' ); $args = array( 'post_type' => $source, 'posts_per_page' => - 1, 'orderby' => 'title', 'order' => 'ASC', ); $posts = wpforms_get_hierarchical_object( apply_filters( 'wpforms_dynamic_choice_post_type_args', $args, array( 'id' => $id, ), $form_id ), true ); $total = wp_count_posts( $source ); $total = $total->publish; $pt = get_post_type_object( $source ); $source_name = ''; if ( null !== $pt ) { $source_name = $pt->labels->name; } foreach ( $posts as $post ) { $items[] = $post->post_title; } } elseif ( 'taxonomy' === $type ) { $type_name = esc_html__( 'taxonomy', 'wpforms-lite' ); $args = array( 'taxonomy' => $source, 'hide_empty' => false, ); $terms = wpforms_get_hierarchical_object( apply_filters( 'wpforms_dynamic_choice_taxonomy_args', $args, array( 'id' => $id, ), $form_id ), true ); $total = wp_count_terms( $source ); $tax = get_taxonomy( $source ); $source_name = $tax->labels->name; foreach ( $terms as $term ) { $items[] = $term->name; } } if ( empty( $items ) ) { $items = array( esc_html__( '(empty)', 'wpforms-lite' ), ); } wp_send_json_success( array( 'items' => $items, 'source' => $source, 'source_name' => $source_name, 'total' => $total, 'type' => $type, 'type_name' => $type_name, ) ); } add_action( 'wp_ajax_wpforms_builder_dynamic_source', 'wpforms_builder_dynamic_source' ); /** * Perform test connection to verify that the current web host can successfully * make outbound SSL connections. * * @since 1.4.5 */ function wpforms_verify_ssl() { // Run a security check. check_ajax_referer( 'wpforms-admin', 'nonce' ); // Check for permissions. if ( ! wpforms_current_user_can() ) { wp_send_json_error( array( 'msg' => esc_html__( 'You do not have permission to perform this operation.', 'wpforms-lite' ), ) ); } $response = wp_remote_post( 'https://wpforms.com/connection-test.php' ); if ( 200 === wp_remote_retrieve_response_code( $response ) ) { wp_send_json_success( array( 'msg' => esc_html__( 'Success! Your server can make SSL connections.', 'wpforms-lite' ), ) ); } wp_send_json_error( array( 'msg' => esc_html__( 'There was an error and the connection failed. Please contact your web host with the technical details below.', 'wpforms-lite' ), 'debug' => '<pre>' . print_r( map_deep( $response, 'wp_strip_all_tags' ), true ) . '</pre>', ) ); } add_action( 'wp_ajax_wpforms_verify_ssl', 'wpforms_verify_ssl' ); /** * Deactivate addon. * * @since 1.0.0 */ function wpforms_deactivate_addon() { // Run a security check. check_ajax_referer( 'wpforms-admin', 'nonce' ); // Check for permissions. if ( ! wpforms_current_user_can() ) { wp_send_json_error(); } $type = 'addon'; if ( ! empty( $_POST['type'] ) ) { $type = sanitize_key( $_POST['type'] ); } if ( isset( $_POST['plugin'] ) ) { deactivate_plugins( $_POST['plugin'] ); if ( 'plugin' === $type ) { wp_send_json_success( esc_html__( 'Plugin deactivated.', 'wpforms-lite' ) ); } else { wp_send_json_success( esc_html__( 'Addon deactivated.', 'wpforms-lite' ) ); } } wp_send_json_error( esc_html__( 'Could not deactivate the addon. Please deactivate from the Plugins page.', 'wpforms-lite' ) ); } add_action( 'wp_ajax_wpforms_deactivate_addon', 'wpforms_deactivate_addon' ); /** * Activate addon. * * @since 1.0.0 */ function wpforms_activate_addon() { // Run a security check. check_ajax_referer( 'wpforms-admin', 'nonce' ); // Check for permissions. if ( ! wpforms_current_user_can() ) { wp_send_json_error(); } if ( isset( $_POST['plugin'] ) ) { $type = 'addon'; if ( ! empty( $_POST['type'] ) ) { $type = sanitize_key( $_POST['type'] ); } $activate = activate_plugins( $_POST['plugin'] ); if ( ! is_wp_error( $activate ) ) { if ( 'plugin' === $type ) { wp_send_json_success( esc_html__( 'Plugin activated.', 'wpforms-lite' ) ); } else { wp_send_json_success( esc_html__( 'Addon activated.', 'wpforms-lite' ) ); } } } wp_send_json_error( esc_html__( 'Could not activate addon. Please activate from the Plugins page.', 'wpforms-lite' ) ); } add_action( 'wp_ajax_wpforms_activate_addon', 'wpforms_activate_addon' ); /** * Install addon. * * @since 1.0.0 */ function wpforms_install_addon() { // Run a security check. check_ajax_referer( 'wpforms-admin', 'nonce' ); // Check for permissions. if ( ! wpforms_current_user_can() ) { wp_send_json_error(); } $error = esc_html__( 'Could not install addon. Please download from wpforms.com and install manually.', 'wpforms-lite' ); if ( empty( $_POST['plugin'] ) ) { wp_send_json_error( $error ); } // Set the current screen to avoid undefined notices. set_current_screen( 'wpforms_page_wpforms-settings' ); // Prepare variables. $url = esc_url_raw( add_query_arg( array( 'page' => 'wpforms-addons', ), admin_url( 'admin.php' ) ) ); $creds = request_filesystem_credentials( $url, '', false, false, null ); // Check for file system permissions. if ( false === $creds ) { wp_send_json_error( $error ); } if ( ! WP_Filesystem( $creds ) ) { wp_send_json_error( $error ); } /* * We do not need any extra credentials if we have gotten this far, so let's install the plugin. */ require_once WPFORMS_PLUGIN_DIR . 'includes/admin/class-install-skin.php'; // Do not allow WordPress to search/download translations, as this will break JS output. remove_action( 'upgrader_process_complete', array( 'Language_Pack_Upgrader', 'async_upgrade' ), 20 ); // Create the plugin upgrader with our custom skin. $installer = new WPForms\Helpers\PluginSilentUpgrader( new WPForms_Install_Skin() ); // Error check. if ( ! method_exists( $installer, 'install' ) || empty( $_POST['plugin'] ) ) { wp_send_json_error( $error ); } $installer->install( $_POST['plugin'] ); // phpcs:ignore // Flush the cache and return the newly installed plugin basename. wp_cache_flush(); $plugin_basename = $installer->plugin_info(); if ( $plugin_basename ) { $type = 'addon'; if ( ! empty( $_POST['type'] ) ) { $type = sanitize_key( $_POST['type'] ); } // Activate the plugin silently. $activated = activate_plugin( $plugin_basename ); if ( ! is_wp_error( $activated ) ) { wp_send_json_success( array( 'msg' => 'plugin' === $type ? esc_html__( 'Plugin installed & activated.', 'wpforms-lite' ) : esc_html__( 'Addon installed & activated.', 'wpforms-lite' ), 'is_activated' => true, 'basename' => $plugin_basename, ) ); } else { wp_send_json_success( array( 'msg' => 'plugin' === $type ? esc_html__( 'Plugin installed.', 'wpforms-lite' ) : esc_html__( 'Addon installed.', 'wpforms-lite' ), 'is_activated' => false, 'basename' => $plugin_basename, ) ); } } wp_send_json_error( $error ); } add_action( 'wp_ajax_wpforms_install_addon', 'wpforms_install_addon' ); admin/class-about.php 0000666 00000133021 15213301445 0010564 0 ustar 00 <?php /** * About WPForms admin page class. * * @since 1.5.0 */ class WPForms_About { /** * Admin menu page slug. * * @since 1.5.0 * * @var string */ const SLUG = 'wpforms-about'; /** * Default view for a page. * * @since 1.5.0 * * @var string */ const DEFAULT_TAB = 'about'; /** * Array of license types, that are considered being top level and has no features difference. * * @since 1.5.0 * * @var array */ public static $licenses_top = array( 'pro', 'agency', 'ultimate', 'elite' ); /** * List of features that licenses are different with. * * @since 1.5.0 * * @var array */ public static $licenses_features = array(); /** * The current active tab. * * @since 1.5.0 * * @var string */ public $view; /** * The core views. * * @since 1.5.0 * * @var array */ public $views = array(); /** * Primary class constructor. * * @since 1.5.0 */ public function __construct() { // In old PHP we can't define this elsewhere. self::$licenses_features = array( 'entries' => esc_html__( 'Form Entries', 'wpforms-lite' ), 'fields' => esc_html__( 'Form Fields', 'wpforms-lite' ), 'templates' => esc_html__( 'Form Templates', 'wpforms-lite' ), 'conditionals' => esc_html__( 'Smart Conditional Logic', 'wpforms-lite' ), 'marketing' => esc_html__( 'Marketing Integrations', 'wpforms-lite' ), 'payments' => esc_html__( 'Payment Forms', 'wpforms-lite' ), 'surveys' => esc_html__( 'Surveys & Polls', 'wpforms-lite' ), 'advanced' => esc_html__( 'Advanced Form Features', 'wpforms-lite' ), 'addons' => esc_html__( 'WPForms Addons', 'wpforms-lite' ), 'support' => esc_html__( 'Customer Support', 'wpforms-lite' ), 'sites' => esc_html__( 'Number of Sites', 'wpforms-lite' ), ); // Maybe load tools page. add_action( 'admin_init', array( $this, 'init' ) ); } /** * Determining if the user is viewing the our page, if so, party on. * * @since 1.5.0 */ public function init() { // Check what page we are on. $page = isset( $_GET['page'] ) ? $_GET['page'] : ''; // Only load if we are actually on the settings page. if ( self::SLUG !== $page ) { return; } add_action( 'admin_enqueue_scripts', array( $this, 'enqueues' ) ); /* * Define the core views for the our tab. */ $this->views = apply_filters( 'wpforms_admin_about_views', array( esc_html__( 'About Us', 'wpforms-lite' ) => array( 'about' ), esc_html__( 'Getting Started', 'wpforms-lite' ) => array( 'getting-started' ), ) ); $license = $this->get_license_type(); if ( ( $license === 'pro' || ! in_array( $license, self::$licenses_top, true ) ) || wpforms_debug() ) { $vs_tab_name = sprintf( /* translators: %1$s - current license type, %2$s - suggested license type. */ esc_html__( '%1$s vs %2$s', 'wpforms-lite' ), ucfirst( $license ), $this->get_next_license( $license ) ); $this->views[ $vs_tab_name ] = array( 'versus' ); } // Determine the current active settings tab. $this->view = ! empty( $_GET['view'] ) ? esc_html( $_GET['view'] ) : self::DEFAULT_TAB; // If the user tries to load an invalid view - fallback to About Us. if ( ! in_array( $this->view, call_user_func_array( 'array_merge', $this->views ), true ) && ! has_action( 'wpforms_admin_about_display_tab_' . sanitize_key( $this->view ) ) ) { $this->view = self::DEFAULT_TAB; } add_action( 'wpforms_admin_page', array( $this, 'output' ) ); // Hook for addons. do_action( 'wpforms_admin_about_init' ); } /** * Enqueue assets for the the page. * * @since 1.5.0 */ public function enqueues() { wp_enqueue_script( 'jquery-matchheight', WPFORMS_PLUGIN_URL . 'assets/js/jquery.matchHeight-min.js', array( 'jquery' ), '0.7.0', false ); } /** * Output the basic page structure. * * @since 1.5.0 */ public function output() { $show_nav = false; foreach ( $this->views as $view ) { if ( in_array( $this->view, (array) $view, true ) ) { $show_nav = true; break; } } ?> <div id="wpforms-admin-about" class="wrap wpforms-admin-wrap"> <?php if ( $show_nav ) { $license = $this->get_license_type(); $next_license = $this->get_next_license( $license ); echo '<ul class="wpforms-admin-tabs">'; foreach ( $this->views as $label => $view ) { $class = in_array( $this->view, $view, true ) ? 'active' : ''; echo '<li>'; printf( '<a href="%s" class="%s">%s</a>', esc_url( admin_url( 'admin.php?page=' . self::SLUG . '&view=' . sanitize_key( $view[0] ) ) ), esc_attr( $class ), esc_html( $label ) ); echo '</li>'; } echo '</ul>'; } ?> <h1 class="wpforms-h1-placeholder"></h1> <?php switch ( $this->view ) { case 'about': $this->output_about(); break; case 'getting-started': $this->output_getting_started(); break; case 'versus': $this->output_versus(); break; default: do_action( 'wpforms_admin_about_display_tab_' . sanitize_key( $this->view ) ); break; } ?> </div> <?php } /** * Display the About tab content. * * @since 1.5.0 */ protected function output_about() { $this->output_about_info(); $this->output_about_addons(); } /** * Display the General Info section of About tab. * * @since 1.5.8 */ protected function output_about_info() { ?> <div class="wpforms-admin-about-section wpforms-admin-columns"> <div class="wpforms-admin-column-60"> <h3> <?php esc_html_e( 'Hello and welcome to WPForms, the most beginner friendly drag & drop WordPress forms plugin. At WPForms, we build software that helps you create beautiful responsive online forms for your website in minutes.', 'wpforms-lite' ); ?> </h3> <p> <?php esc_html_e( 'Over the years, we found that most WordPress contact form plugins were bloated, buggy, slow, and very hard to use. So we started with a simple goal: build a WordPress forms plugin that’s both easy and powerful.', 'wpforms-lite' ); ?> </p> <p> <?php esc_html_e( 'Our goal is to take the pain out of creating online forms and make it easy.', 'wpforms-lite' ); ?> </p> <p> <?php printf( wp_kses( /* translators: %1$s - WPBeginner URL, %2$s - OptinMonster URL, %3$s - MonsterInsights URL, %4$s - RafflePress URL. */ __( 'WPForms is brought to you by the same team that’s behind the largest WordPress resource site, <a href="%1$s" target="_blank" rel="noopener noreferrer">WPBeginner</a>, the most popular lead-generation software, <a href="%2$s" target="_blank" rel="noopener noreferrer">OptinMonster</a>, the best WordPress analytics plugin, <a href="%3$s" target="_blank" rel="noopener noreferrer">MonsterInsights</a>, and the most powerful WordPress contest plugin, <a href="%4$s" target="_blank" rel="noopener noreferrer">RafflePress</a>.', 'wpforms-lite' ), array( 'a' => array( 'href' => array(), 'rel' => array(), 'target' => array(), ), ) ), 'https://www.wpbeginner.com/?utm_source=wpformsplugin&utm_medium=pluginaboutpage&utm_campaign=aboutwpforms', 'https://optinmonster.com/?utm_source=wpformsplugin&utm_medium=pluginaboutpage&utm_campaign=aboutwpforms', 'https://www.monsterinsights.com/?utm_source=wpformsplugin&utm_medium=pluginaboutpage&utm_campaign=aboutwpforms', 'https://rafflepress.com/?utm_source=wpformsplugin&utm_medium=pluginaboutpage&utm_campaign=aboutwpforms' ); ?> </p> <p> <?php esc_html_e( 'Yup, we know a thing or two about building awesome products that customers love.', 'wpforms-lite' ); ?> </p> </div> <div class="wpforms-admin-column-40 wpforms-admin-column-last"> <figure> <img src="<?php echo WPFORMS_PLUGIN_URL; ?>assets/images/about/team.jpg" alt="<?php esc_attr_e( 'The WPForms Team photo', 'wpforms-lite' ); ?>"> <figcaption> <?php esc_html_e( 'The WPForms Team', 'wpforms-lite' ); ?><br> </figcaption> </figure> </div> </div> <?php } /** * Display the Addons section of About tab. * * @since 1.5.8 */ protected function output_about_addons() { if ( ! wpforms_current_user_can() ) { return; } $all_plugins = get_plugins(); $am_plugins = $this->get_am_plugins(); ?> <div id="wpforms-admin-addons"> <div class="addons-container"> <?php foreach ( $am_plugins as $plugin => $details ) : $plugin_data = $this->get_plugin_data( $plugin, $details, $all_plugins ); ?> <div class="addon-container"> <div class="addon-item"> <div class="details wpforms-clear"> <img src="<?php echo esc_url( $plugin_data['details']['icon'] ); ?>"> <h5 class="addon-name"> <?php echo esc_html( $plugin_data['details']['name'] ); ?> </h5> <p class="addon-desc"> <?php echo wp_kses_post( $plugin_data['details']['desc'] ); ?> </p> </div> <div class="actions wpforms-clear"> <div class="status"> <strong> <?php printf( /* translators: %s - addon status label. */ esc_html__( 'Status: %s', 'wpforms-lite' ), '<span class="status-label ' . esc_attr( $plugin_data['status_class'] ) . '">' . wp_kses_post( $plugin_data['status_text'] ) . '</span>' ); ?> </strong> </div> <div class="action-button"> <button class="<?php echo esc_attr( $plugin_data['action_class'] ); ?>" data-plugin="<?php echo esc_attr( $plugin_data['plugin_src'] ); ?>" data-type="plugin"> <?php echo wp_kses_post( $plugin_data['action_text'] ); ?> </button> </div> </div> </div> </div> <?php endforeach; ?> </div> </div> <?php } /** * Get AM plugin data to display in the Addons section of About tab. * * @since 1.5.8 * * @param string $plugin Plugin slug. * @param array $details Plugin details. * @param array $all_plugins List of all plugins. * * @return array */ protected function get_plugin_data( $plugin, $details, $all_plugins ) { $have_pro = ( ! empty( $details['pro'] ) && ! empty( $details['pro']['plug'] ) ); $show_pro = false; $plugin_data = array(); if ( $have_pro ) { if ( array_key_exists( $plugin, $all_plugins ) ) { if ( is_plugin_active( $plugin ) ) { $show_pro = true; } } if ( array_key_exists( $details['pro']['plug'], $all_plugins ) ) { $show_pro = true; } if ( $show_pro ) { $plugin = $details['pro']['plug']; $details = $details['pro']; } } if ( array_key_exists( $plugin, $all_plugins ) ) { if ( is_plugin_active( $plugin ) ) { // Status text/status. $plugin_data['status_class'] = 'status-active'; $plugin_data['status_text'] = esc_html__( 'Active', 'wpforms-lite' ); // Button text/status. $plugin_data['action_class'] = $plugin_data['status_class'] . ' button button-secondary disabled'; $plugin_data['action_text'] = esc_html__( 'Activated', 'wpforms-lite' ); $plugin_data['plugin_src'] = esc_attr( $plugin ); } else { // Status text/status. $plugin_data['status_class'] = 'status-inactive'; $plugin_data['status_text'] = esc_html__( 'Inactive', 'wpforms-lite' ); // Button text/status. $plugin_data['action_class'] = $plugin_data['status_class'] . ' button button-secondary'; $plugin_data['action_text'] = esc_html__( 'Activate', 'wpforms-lite' ); $plugin_data['plugin_src'] = esc_attr( $plugin ); } } else { // Doesn't exist, install. // Status text/status. $plugin_data['status_class'] = 'status-download'; if ( isset( $details['act'] ) && 'go-to-url' === $details['act'] ) { $plugin_data['status_class'] = 'status-go-to-url'; } $plugin_data['status_text'] = esc_html__( 'Not Installed', 'wpforms-lite' ); // Button text/status. $plugin_data['action_class'] = $plugin_data['status_class'] . ' button button-primary'; $plugin_data['action_text'] = esc_html__( 'Install Plugin', 'wpforms-lite' ); $plugin_data['plugin_src'] = esc_url( $details['url'] ); } $plugin_data['details'] = $details; return $plugin_data; } /** * Display the Getting Started tab content. * * @since 1.5.0 */ protected function output_getting_started() { $license = $this->get_license_type(); ?> <div class="wpforms-admin-about-section wpforms-admin-about-section-first-form" style="display:flex;"> <div class="wpforms-admin-about-section-first-form-text"> <h2> <?php esc_html_e( 'Creating Your First Form', 'wpforms-lite' ); ?> </h2> <p> <?php esc_html_e( 'Want to get started creating your first form with WPForms? By following the step by step instructions in this walkthrough, you can easily publish your first form on your site.', 'wpforms-lite' ); ?> </p> <p> <?php esc_html_e( 'To begin, you’ll need to be logged into the WordPress admin area. Once there, click on WPForms in the admin sidebar to go the Forms Overview page.', 'wpforms-lite' ); ?> </p> <p> <?php esc_html_e( 'In the Forms Overview page, the forms list will be empty because there are no forms yet. To create a new form, click on the Add New button, and this will launch the WPForms Form Builder.', 'wpforms-lite' ); ?> </p> <ul class="list-plain"> <li> <a href="https://wpforms.com/docs/creating-first-form/?utm_source=WordPress&utm_medium=wpforms-about-page&utm_campaign=gettingstarted#add-new" target="_blank" rel="noopener noreferrer"> <?php esc_html_e( 'How to Add a New Form', 'wpforms-lite' ); ?> </a> </li> <li> <a href="https://wpforms.com/docs/creating-first-form/?utm_source=WordPress&utm_medium=wpforms-about-page&utm_campaign=gettingstarted#customize-fields" target="_blank" rel="noopener noreferrer"> <?php esc_html_e( 'How to Customize Form Fields', 'wpforms-lite' ); ?> </a> </li> <li> <a href="https://wpforms.com/docs/creating-first-form/?utm_source=WordPress&utm_medium=wpforms-about-page&utm_campaign=gettingstarted#display-form" target="_blank" rel="noopener noreferrer"> <?php esc_html_e( 'How to Display Forms on Your Site', 'wpforms-lite' ); ?> </a> </li> </ul> </div> <div class="wpforms-admin-about-section-first-form-video"> <iframe src="https://www.youtube-nocookie.com/embed/o2nE1P74WxQ?rel=0" width="540" height="304" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe> </div> </div> <?php if ( ! in_array( $license, self::$licenses_top, true ) ) { ?> <div class="wpforms-admin-about-section wpforms-admin-about-section-hero"> <div class="wpforms-admin-about-section-hero-main"> <h2> <?php esc_html_e( 'Get WPForms Pro and Unlock all the Powerful Features', 'wpforms-lite' ); ?> </h2> <p class="bigger"> <?php echo wp_kses( __( 'Thanks for being a loyal WPForms Lite user. <strong>Upgrade to WPForms Pro</strong> to unlock all the awesome features and experience<br>why WPForms is consistently rated the best WordPress form builder.', 'wpforms-lite' ), array( 'br' => array(), 'strong' => array(), ) ); ?> </p> <p> <?php printf( wp_kses( /* translators: %s - stars. */ __( 'We know that you will truly love WPForms. It has over <strong>5000+ five star ratings</strong> (%s) and is active on over 1 million websites.', 'wpforms-lite' ), array( 'strong' => array(), ) ), '<i class="fa fa-star" aria-hidden="true"></i>' . '<i class="fa fa-star" aria-hidden="true"></i>' . '<i class="fa fa-star" aria-hidden="true"></i>' . '<i class="fa fa-star" aria-hidden="true"></i>' . '<i class="fa fa-star" aria-hidden="true"></i>' ); ?> </p> </div> <div class="wpforms-admin-about-section-hero-extra"> <div class="wpforms-admin-columns"> <div class="wpforms-admin-column-50"> <ul class="list-features list-plain"> <li> <i class="fa fa-check" aria-hidden="true"></i> <?php esc_html_e( 'Entry Management - view all leads in one place.', 'wpforms-lite' ); ?> </li> <li> <i class="fa fa-check" aria-hidden="true"></i> <?php esc_html_e( 'All form features like file upload, pagination, etc.', 'wpforms-lite' ); ?> </li> <li> <i class="fa fa-check" aria-hidden="true"></i> <?php esc_html_e( 'Create surveys & polls with the surveys addon.', 'wpforms-lite' ); ?> </li> <li> <i class="fa fa-check" aria-hidden="true"></i> <?php esc_html_e( 'WordPress user registration and login forms.', 'wpforms-lite' ); ?> </li> <li> <i class="fa fa-check" aria-hidden="true"></i> <?php esc_html_e( 'Create payment forms with Stripe and PayPal.', 'wpforms-lite' ); ?> </li> </ul> </div> <div class="wpforms-admin-column-50 wpforms-admin-column-last"> <ul class="list-features list-plain"> <li> <i class="fa fa-check" aria-hidden="true"></i> <?php esc_html_e( 'Powerful Conditional Logic so you can create smart forms.', 'wpforms-lite' ); ?> </li> <li> <i class="fa fa-check" aria-hidden="true"></i> <?php esc_html_e( '500+ integrations with different marketing & payment services.', 'wpforms-lite' ); ?> </li> <li> <i class="fa fa-check" aria-hidden="true"></i> <?php esc_html_e( 'Collect signatures, geo-location data, and more.', 'wpforms-lite' ); ?> </li> <li> <i class="fa fa-check" aria-hidden="true"></i> <?php esc_html_e( 'Accept user submitted content with Post Submissions addon.', 'wpforms-lite' ); ?> </li> <li> <i class="fa fa-check" aria-hidden="true"></i> <?php esc_html_e( 'Bonus form templates, form abandonment, and more.', 'wpforms-lite' ); ?> </li> </ul> </div> </div> <hr /> <h3 class="call-to-action"> <?php if ( 'lite' === $license ) { echo '<a href="' . wpforms_admin_upgrade_link( 'wpforms-about-page' ) . '" target="_blank" rel="noopener noreferrer">'; } else { echo '<a href="https://wpforms.com/pricing?utm_source=WordPress&utm_medium=wpforms-about-page&utm_campaign=gettingstarted" target="_blank" rel="noopener noreferrer">'; } esc_html_e( 'Get WPForms Pro Today and Unlock all the Powerful Features', 'wpforms-lite' ); ?> </a> </h3> <?php if ( 'lite' === $license ) { ?> <p> <?php echo wp_kses( __( 'Bonus: WPForms Lite users get <span class="price-20-off">50% off regular price</span>, automatically applied at checkout.', 'wpforms-lite' ), array( 'span' => array( 'class' => array(), ), ) ); ?> </p> <?php } ?> </div> </div> <?php } ?> <div class="wpforms-admin-about-section wpforms-admin-about-section-squashed wpforms-admin-about-section-post wpforms-admin-columns"> <div class="wpforms-admin-column-20"> <img src="<?php echo WPFORMS_PLUGIN_URL; ?>assets/images/about/how-choose-right-form-field.png" alt=""> </div> <div class="wpforms-admin-column-80"> <h2> <?php esc_html_e( 'How to Choose the Right Form Field', 'wpforms-lite' ); ?> </h2> <p> <?php esc_html_e( 'Are you wondering which form fields you have access to in WPForms and what each field does? WPForms has lots of field types to make creating and filling out forms easy. In this tutorial, we’ll cover all of the fields available in WPForms.', 'wpforms-lite' ); ?> </p> <a href="https://wpforms.com/docs/how-to-choose-the-right-form-field-for-your-forms/?utm_source=WordPress&utm_medium=wpforms-about-page&utm_campaign=gettingstarted" target="_blank" rel="noopener noreferrer" class="wpforms-admin-about-section-post-link"> <?php esc_html_e( 'Read Documentation', 'wpforms-lite' ); ?><i class="fa fa-external-link" aria-hidden="true"></i> </a> </div> </div> <div class="wpforms-admin-about-section wpforms-admin-about-section-squashed wpforms-admin-about-section-post wpforms-admin-columns"> <div class="wpforms-admin-column-20"> <img src="<?php echo WPFORMS_PLUGIN_URL; ?>assets/images/about/complete-guide-to-wpforms-settings.png" alt=""> </div> <div class="wpforms-admin-column-80"> <h2> <?php esc_html_e( 'A Complete Guide to WPForms Settings', 'wpforms-lite' ); ?> </h2> <p> <?php esc_html_e( 'Would you like to learn more about all of the settings available in WPForms? In addition to tons of customization options within the form builder, WPForms has an extensive list of plugin-wide options available. This includes choosing your currency, adding GDPR enhancements, setting up integrations.', 'wpforms-lite' ); ?> </p> <a href="https://wpforms.com/docs/a-complete-guide-to-wpforms-settings/?utm_source=WordPress&utm_medium=wpforms-about-page&utm_campaign=gettingstarted" target="_blank" rel="noopener noreferrer" class="wpforms-admin-about-section-post-link"> <?php esc_html_e( 'Read Documentation', 'wpforms-lite' ); ?><i class="fa fa-external-link" aria-hidden="true"></i> </a> </div> </div> <div class="wpforms-admin-about-section wpforms-admin-about-section-squashed wpforms-admin-about-section-post wpforms-admin-columns"> <div class="wpforms-admin-column-20"> <img src="<?php echo WPFORMS_PLUGIN_URL; ?>assets/images/about/how-create-gdpr-compliant-forms.png" alt=""> </div> <div class="wpforms-admin-column-80"> <h2> <?php esc_html_e( 'How to Create GDPR Compliant Forms', 'wpforms-lite' ); ?> </h2> <p> <?php esc_html_e( 'Do you need to check that your forms are compliant with the European Union’s General Data Protection Regulation? The best way to ensure GDPR compliance for your specific site is always to consult legal counsel. In this guide, we’ll discuss general considerations for GDPR compliance in your WordPress forms.', 'wpforms-lite' ); ?> </p> <a href="https://wpforms.com/docs/how-to-create-gdpr-compliant-forms/?utm_source=WordPress&utm_medium=wpforms-about-page&utm_campaign=gettingstarted" target="_blank" rel="noopener noreferrer" class="wpforms-admin-about-section-post-link"> <?php esc_html_e( 'Read Documentation', 'wpforms-lite' ); ?><i class="fa fa-external-link" aria-hidden="true"></i> </a> </div> </div> <div class="wpforms-admin-about-section wpforms-admin-about-section-squashed wpforms-admin-about-section-post wpforms-admin-columns"> <div class="wpforms-admin-column-20"> <img src="<?php echo WPFORMS_PLUGIN_URL; ?>assets/images/about/how-install-activate-wpforms-addons.png" alt=""> </div> <div class="wpforms-admin-column-80"> <h2> <?php esc_html_e( 'How to Install and Activate WPForms Addons', 'wpforms-lite' ); ?> </h2> <p> <?php esc_html_e( 'Would you like to access WPForms addons to extend the functionality of your forms? The first thing you need to do is install WPForms. Once that’s done, let’s go ahead and look at the process of activating addons.', 'wpforms-lite' ); ?> </p> <a href="https://wpforms.com/docs/install-activate-wpforms-addons/?utm_source=WordPress&utm_medium=wpforms-about-page&utm_campaign=gettingstarted" target="_blank" rel="noopener noreferrer" class="wpforms-admin-about-section-post-link"> <?php esc_html_e( 'Read Documentation', 'wpforms-lite' ); ?><i class="fa fa-external-link" aria-hidden="true"></i> </a> </div> </div> <?php } /** * Get the next license type. Helper for Versus tab content. * * @since 1.5.5 * * @param string $current Current license type slug. * * @return string Next license type slug. */ protected function get_next_license( $current ) { $current = ucfirst( $current ); $license_pairs = array( 'Lite' => 'Pro', 'Basic' => 'Pro', 'Plus' => 'Pro', 'Pro' => 'Elite', ); return ! empty( $license_pairs[ $current ] ) ? $license_pairs[ $current ] : 'Elite'; } /** * Display the Versus tab content. * * @since 1.5.0 */ protected function output_versus() { $license = $this->get_license_type(); $next_license = $this->get_next_license( $license ); ?> <div class="wpforms-admin-about-section wpforms-admin-about-section-squashed"> <h1 class="centered"> <strong><?php echo esc_html( ucfirst( $license ) ); ?></strong> vs <strong><?php echo esc_html( $next_license ); ?></strong> </h1> <p class="centered"> <?php esc_html_e( 'Get the most out of WPForms by upgrading to Pro and unlocking all of the powerful features.', 'wpforms-lite' ); ?> </p> </div> <div class="wpforms-admin-about-section wpforms-admin-about-section-squashed wpforms-admin-about-section-hero wpforms-admin-about-section-table"> <div class="wpforms-admin-about-section-hero-main wpforms-admin-columns"> <div class="wpforms-admin-column-33"> <h3 class="no-margin"> <?php esc_html_e( 'Feature', 'wpforms-lite' ); ?> </h3> </div> <div class="wpforms-admin-column-33"> <h3 class="no-margin"> <?php echo esc_html( ucfirst( $license ) ); ?> </h3> </div> <div class="wpforms-admin-column-33"> <h3 class="no-margin"> <?php echo esc_html( $next_license ); ?> </h3> </div> </div> <div class="wpforms-admin-about-section-hero-extra no-padding wpforms-admin-columns"> <table> <?php foreach ( self::$licenses_features as $slug => $name ) { $current = $this->get_license_data( $slug, $license ); $next = $this->get_license_data( $slug, strtolower( $next_license ) ); if ( empty( $current ) || empty( $next ) ) { continue; } $current_status = $current['status']; if ( $current['text'] !== $next['text'] && $current_status === 'full' ) { $current_status = 'partial'; } ?> <tr class="wpforms-admin-columns"> <td class="wpforms-admin-column-33"> <p><?php echo esc_html( $name ); ?></p> </td> <td class="wpforms-admin-column-33"> <?php if ( is_array( $current ) ) : ?> <p class="features-<?php echo esc_attr( $current_status ); ?>"> <?php echo wp_kses_post( implode( '<br>', $current['text'] ) ); ?> </p> <?php endif; ?> </td> <td class="wpforms-admin-column-33"> <?php if ( is_array( $current ) ) : ?> <p class="features-full"> <?php echo wp_kses_post( implode( '<br>', $next['text'] ) ); ?> </p> <?php endif; ?> </td> </tr> <?php } ?> </table> </div> </div> <div class="wpforms-admin-about-section wpforms-admin-about-section-hero"> <div class="wpforms-admin-about-section-hero-main no-border"> <h3 class="call-to-action centered"> <?php if ( 'lite' === $license ) { echo '<a href="' . esc_url( wpforms_admin_upgrade_link( 'wpforms-about-page' ) ) . '" target="_blank" rel="noopener noreferrer">'; } else { echo '<a href="https://wpforms.com/pricing?utm_source=WordPress&utm_medium=wpforms-about-page&utm_campaign=gettingstarted" target="_blank" rel="noopener noreferrer">'; } printf( /* translators: %s - next license level. */ esc_html__( 'Get WPForms %s Today and Unlock all the Powerful Features', 'wpforms-lite' ), esc_html( $next_license ) ); ?> </a> </h3> <?php if ( 'lite' === $license ) { ?> <p class="centered"> <?php echo wp_kses( __( 'Bonus: WPForms Lite users get <span class="price-20-off">50% off regular price</span>, automatically applied at checkout.', 'wpforms-lite' ), array( 'span' => array( 'class' => array(), ), ) ); ?> </p> <?php } ?> </div> </div> <?php } /** * List of AM plugins that we propose to install. * * @since 1.5.0 * * @return array */ protected function get_am_plugins() { $images_url = WPFORMS_PLUGIN_URL . 'assets/images/about/'; return array( 'google-analytics-for-wordpress/googleanalytics.php' => array( 'icon' => $images_url . 'plugin-mi.png', 'name' => esc_html__( 'MonsterInsights', 'wpforms-lite' ), 'desc' => esc_html__( 'MonsterInsights makes it “effortless” to properly connect your WordPress site with Google Analytics, so you can start making data-driven decisions to grow your business.', 'wpforms-lite' ), 'url' => 'https://downloads.wordpress.org/plugin/google-analytics-for-wordpress.zip', 'pro' => array( 'plug' => 'google-analytics-premium/googleanalytics-premium.php', 'icon' => $images_url . 'plugin-mi.png', 'name' => esc_html__( 'MonsterInsights Pro', 'wpforms-lite' ), 'desc' => esc_html__( 'MonsterInsights makes it “effortless” to properly connect your WordPress site with Google Analytics, so you can start making data-driven decisions to grow your business.', 'wpforms-lite' ), 'url' => 'https://www.monsterinsights.com/?utm_source=proplugin&utm_medium=pluginheader&utm_campaign=pluginurl&utm_content=7%2E0%2E0', 'act' => 'go-to-url', ), ), 'optinmonster/optin-monster-wp-api.php' => array( 'icon' => $images_url . 'plugin-om.png', 'name' => esc_html__( 'OptinMonster', 'wpforms-lite' ), 'desc' => esc_html__( 'Our high-converting optin forms like Exit-Intent® popups, Fullscreen Welcome Mats, and Scroll boxes help you dramatically boost conversions and get more email subscribers.', 'wpforms-lite' ), 'url' => 'https://downloads.wordpress.org/plugin/optinmonster.zip', ), 'wp-mail-smtp/wp_mail_smtp.php' => array( 'icon' => $images_url . 'plugin-smtp.png', 'name' => esc_html__( 'WP Mail SMTP', 'wpforms-lite' ), 'desc' => esc_html__( 'Make sure your website\'s emails reach the inbox. Our goal is to make email deliverability easy and reliable. Trusted by over 1 million websites.', 'wpforms-lite' ), 'url' => 'https://downloads.wordpress.org/plugin/wp-mail-smtp.zip', 'pro' => array( 'plug' => 'wp-mail-smtp-pro/wp_mail_smtp.php', 'icon' => $images_url . 'plugin-smtp.png', 'name' => esc_html__( 'WP Mail SMTP Pro', 'wpforms-lite' ), 'desc' => esc_html__( 'Make sure your website\'s emails reach the inbox. Our goal is to make email deliverability easy and reliable. Trusted by over 1 million websites.', 'wpforms-lite' ), 'url' => 'https://wpmailsmtp.com/pricing/', 'act' => 'go-to-url', ), ), 'rafflepress/rafflepress.php' => array( 'icon' => $images_url . 'plugin-rp.png', 'name' => esc_html__( 'RafflePress', 'wpforms-lite' ), 'desc' => esc_html__( 'Turn your visitors into brand ambassadors! Easily grow your email list, website traffic, and social media followers with powerful viral giveaways & contests.', 'wpforms-lite' ), 'url' => 'https://downloads.wordpress.org/plugin/rafflepress.zip', 'pro' => array( 'plug' => 'rafflepress-pro/rafflepress-pro.php', 'icon' => $images_url . 'plugin-rp.png', 'name' => esc_html__( 'RafflePress Pro', 'wpforms-lite' ), 'desc' => esc_html__( 'Turn your visitors into brand ambassadors! Easily grow your email list, website traffic, and social media followers with powerful viral giveaways & contests.', 'wpforms-lite' ), 'url' => 'https://rafflepress.com/pricing/', 'act' => 'go-to-url', ), ), ); } /** * Get the array of data that compared the license data. * * @since 1.5.0 * * @param string $feature Feature name. * @param string $license License type to get data for. * * @return array|false */ protected function get_license_data( $feature, $license ) { $data = array( 'entries' => array( 'lite' => array( 'status' => 'partial', 'text' => array( '<strong>' . esc_html__( 'Entries via Email Only', 'wpforms-lite' ) . '</strong>', ), ), 'basic' => array( 'status' => 'full', 'text' => array( '<strong>' . esc_html__( 'Complete Entry Management inside WordPress', 'wpforms-lite' ) . '</strong>', ), ), 'plus' => array( 'status' => 'full', 'text' => array( '<strong>' . esc_html__( 'Complete Entry Management inside WordPress', 'wpforms-lite' ) . '</strong>', ), ), 'pro' => array( 'status' => 'full', 'text' => array( '<strong>' . esc_html__( 'Complete Entry Management inside WordPress', 'wpforms-lite' ) . '</strong>', ), ), ), 'fields' => array( 'lite' => array( 'status' => 'partial', 'text' => array( '<strong>' . esc_html__( 'Standard Fields Only', 'wpforms-lite' ) . '</strong>', esc_html__( 'Name, Email, Single Line Text, Paragraph Text, Dropdown, Multiple Choice, Checkboxes, and Numbers', 'wpforms-lite' ), ), ), 'basic' => array( 'status' => 'full', 'text' => array( '<strong>' . esc_html__( 'Access to all Standard and Fancy Fields', 'wpforms-lite' ) . '</strong>', esc_html__( 'Address, Phone, Website URL, Date/Time, Password, File Upload, HTML, Pagebreaks, Section Dividers, Ratings, and Hidden Field', 'wpforms-lite' ), ), ), 'plus' => array( 'status' => 'full', 'text' => array( '<strong>' . esc_html__( 'Access to all Standard and Fancy Fields', 'wpforms-lite' ) . '</strong>', esc_html__( 'Address, Phone, Website URL, Date/Time, Password, File Upload, HTML, Pagebreaks, Section Dividers, Ratings, and Hidden Field', 'wpforms-lite' ), ), ), 'pro' => array( 'status' => 'full', 'text' => array( '<strong>' . esc_html__( 'Access to all Standard and Fancy Fields', 'wpforms-lite' ) . '</strong>', esc_html__( 'Address, Phone, Website URL, Date/Time, Password, File Upload, HTML, Pagebreaks, Section Dividers, Ratings, and Hidden Field', 'wpforms-lite' ), ), ), ), 'conditionals' => array( 'lite' => array( 'status' => 'none', 'text' => array( '<strong>' . esc_html__( 'Not available', 'wpforms-lite' ) . '</strong>', ), ), 'basic' => array( 'status' => 'full', 'text' => array( '<strong>' . esc_html__( 'Powerful Form Logic for Building Smart Forms', 'wpforms-lite' ) . '</strong>', ), ), 'plus' => array( 'status' => 'full', 'text' => array( '<strong>' . esc_html__( 'Powerful Form Logic for Building Smart Forms', 'wpforms-lite' ) . '</strong>', ), ), 'pro' => array( 'status' => 'full', 'text' => array( '<strong>' . esc_html__( 'Powerful Form Logic for Building Smart Forms', 'wpforms-lite' ) . '</strong>', ), ), ), 'templates' => array( 'lite' => array( 'status' => 'partial', 'text' => array( '<strong>' . esc_html__( 'Basic Form Templates', 'wpforms-lite' ) . '</strong>', ), ), 'basic' => array( 'status' => 'partial', 'text' => array( '<strong>' . esc_html__( 'Basic Form Templates', 'wpforms-lite' ) . '</strong>', ), ), 'plus' => array( 'status' => 'partial', 'text' => array( '<strong>' . esc_html__( 'Basic Form Templates', 'wpforms-lite' ) . '</strong>', ), ), 'pro' => array( 'status' => 'full', 'text' => array( '<strong>' . esc_html__( 'All Form Templates including Bonus 150+ pre-made form templates.', 'wpforms-lite' ) . '</strong>', ), ), ), 'marketing' => array( 'lite' => array( 'status' => 'partial', 'text' => array( '<strong>' . esc_html__( 'Limited Marketing Integration', 'wpforms-lite' ) . '</strong>', esc_html__( 'Constant Contact only', 'wpforms-lite' ), ), ), 'basic' => array( 'status' => 'partial', 'text' => array( '<strong>' . esc_html__( 'Limited Marketing Integration', 'wpforms-lite' ) . '</strong>', esc_html__( 'Constant Contact only', 'wpforms-lite' ), ), ), 'plus' => array( 'status' => 'partial', 'text' => array( '<strong>' . esc_html__( 'Additional Marketing Integrations', 'wpforms-lite' ) . '</strong>', esc_html__( 'Constant Contact, Mailchimp, AWeber, GetResponse, Campaign Monitor, and Drip', 'wpforms-lite' ), ), ), 'pro' => array( 'status' => 'full', 'text' => array( '<strong>' . esc_html__( 'Additional Marketing Integrations', 'wpforms-lite' ) . '</strong>', esc_html__( 'Constant Contact, Mailchimp, AWeber, GetResponse, Campaign Monitor, and Drip.', 'wpforms-lite' ), '', wp_kses( __( '<strong>Bonus:</strong> 500+ integrations with Zapier.', 'wpforms-lite' ), array( 'strong' => array(), ) ), ), ), 'elite' => array( 'status' => 'full', 'text' => array( '<strong>' . esc_html__( 'All Marketing Integrations', 'wpforms-lite' ) . '</strong>', esc_html__( 'ActiveCampaign, Constant Contact, Mailchimp, AWeber, GetResponse, Campaign Monitor, and Drip.', 'wpforms-lite' ), '', wp_kses( __( '<strong>Bonus:</strong> 500+ integrations with Zapier.', 'wpforms-lite' ), array( 'strong' => array(), ) ), ), ), 'ultimate' => array( 'status' => 'full', 'text' => array( '<strong>' . esc_html__( 'All Marketing Integrations', 'wpforms-lite' ) . '</strong>', esc_html__( 'ActiveCampaign, Constant Contact, Mailchimp, AWeber, GetResponse, Campaign Monitor, and Drip.', 'wpforms-lite' ), '', wp_kses( __( '<strong>Bonus:</strong> 500+ integrations with Zapier.', 'wpforms-lite' ), array( 'strong' => array(), ) ), ), ), 'agency' => array( 'status' => 'full', 'text' => array( '<strong>' . esc_html__( 'All Marketing Integrations', 'wpforms-lite' ) . '</strong>', esc_html__( 'ActiveCampaign, Constant Contact, Mailchimp, AWeber, GetResponse, Campaign Monitor, and Drip.', 'wpforms-lite' ), '', wp_kses( __( '<strong>Bonus:</strong> 500+ integrations with Zapier.', 'wpforms-lite' ), array( 'strong' => array(), ) ), ), ), ), 'payments' => array( 'lite' => array( 'status' => 'none', 'text' => array( '<strong>' . esc_html__( 'Not Available', 'wpforms-lite' ) . '</strong>', ), ), 'basic' => array( 'status' => 'none', 'text' => array( '<strong>' . esc_html__( 'Not Available', 'wpforms-lite' ) . '</strong>', ), ), 'plus' => array( 'status' => 'none', 'text' => array( '<strong>' . esc_html__( 'Not Available', 'wpforms-lite' ) . '</strong>', ), ), 'pro' => array( 'status' => 'full', 'text' => array( '<strong>' . esc_html__( 'Create Payment Forms', 'wpforms-lite' ) . '</strong>', esc_html__( 'Accept payments using Stripe (credit card) and PayPal', 'wpforms-lite' ), ), ), ), 'surveys' => array( 'lite' => array( 'status' => 'none', 'text' => array( '<strong>' . esc_html__( 'Not Available', 'wpforms-lite' ) . '</strong>', ), ), 'basic' => array( 'status' => 'none', 'text' => array( '<strong>' . esc_html__( 'Not Available', 'wpforms-lite' ) . '</strong>', ), ), 'plus' => array( 'status' => 'none', 'text' => array( '<strong>' . esc_html__( 'Not Available', 'wpforms-lite' ) . '</strong>', ), ), 'pro' => array( 'status' => 'full', 'text' => array( '<strong>' . esc_html__( 'Create interactive Surveys and Polls with beautiful reports', 'wpforms-lite' ) . '</strong>', ), ), ), 'advanced' => array( 'lite' => array( 'status' => 'none', 'text' => array( '<strong>' . esc_html__( 'No Advanced Features', 'wpforms-lite' ) . '</strong>', ), ), 'basic' => array( 'status' => 'partial', 'text' => array( '<strong>' . esc_html__( 'Limited Advanced Features', 'wpforms-lite' ) . '</strong>', esc_html__( 'Multi-page Forms, File Upload Forms, Multiple Form Notifications, Conditional Form Confirmation', 'wpforms-lite' ), ), ), 'plus' => array( 'status' => 'partial', 'text' => array( '<strong>' . esc_html__( 'Limited Advanced Features', 'wpforms-lite' ) . '</strong>', esc_html__( 'Multi-page Forms, File Upload Forms, Multiple Form Notifications, Conditional Form Confirmation', 'wpforms-lite' ), ), ), 'pro' => array( 'status' => 'full', 'text' => array( '<strong>' . esc_html__( 'All Advanced Features', 'wpforms-lite' ) . '</strong>', esc_html__( 'Multi-page Forms, File Upload Forms, Multiple Form Notifications, Conditional Form Confirmation, Custom CAPTCHA, Offline Forms, Signature Forms', 'wpforms-lite' ), ), ), ), 'addons' => array( 'lite' => array( 'status' => 'none', 'text' => array( '<strong>' . esc_html__( 'No Addons Included', 'wpforms-lite' ) . '</strong>', ), ), 'basic' => array( 'status' => 'partial', 'text' => array( '<strong>' . esc_html__( 'Custom Captcha Addon included', 'wpforms-lite' ) . '</strong>', ), ), 'plus' => array( 'status' => 'partial', 'text' => array( '<strong>' . esc_html__( 'Email Marketing Addons included', 'wpforms-lite' ) . '</strong>', ), ), 'pro' => array( 'status' => 'full', 'text' => array( '<strong>' . esc_html__( 'Pro Addons Included', 'wpforms-lite' ) . '</strong>', esc_html__( 'Form Abandonment, Front-end Post Submission, User Registration, Geo-location, and more (21 total)', 'wpforms-lite' ), ), ), 'elite' => array( 'status' => 'full', 'text' => array( '<strong>' . esc_html__( 'All Addons Included', 'wpforms-lite' ) . '</strong>', esc_html__( 'Form Abandonment, Front-end Post Submission, User Registration, Geo-location, and more (22 total)', 'wpforms-lite' ), ), ), 'ultimate' => array( 'status' => 'full', 'text' => array( '<strong>' . esc_html__( 'All Addons Included', 'wpforms-lite' ) . '</strong>', esc_html__( 'Form Abandonment, Front-end Post Submission, User Registration, Geo-location, and more (22 total)', 'wpforms-lite' ), ), ), 'agency' => array( 'status' => 'full', 'text' => array( '<strong>' . esc_html__( 'All Addons Included', 'wpforms-lite' ) . '</strong>', esc_html__( 'Form Abandonment, Front-end Post Submission, User Registration, Geo-location, and more (22 total)', 'wpforms-lite' ), ), ), ), 'support' => array( 'lite' => array( 'status' => 'none', 'text' => array( '<strong>' . esc_html__( 'Limited Support', 'wpforms-lite' ) . '</strong>', ), ), 'basic' => array( 'status' => 'partial', 'text' => array( '<strong>' . esc_html__( 'Standard Support', 'wpforms-lite' ) . '</strong>', ), ), 'plus' => array( 'status' => 'partial', 'text' => array( '<strong>' . esc_html__( 'Standard Support', 'wpforms-lite' ) . '</strong>', ), ), 'pro' => array( 'status' => 'full', 'text' => array( '<strong>' . esc_html__( 'Priority Support', 'wpforms-lite' ) . '</strong>', ), ), 'elite' => array( 'status' => 'full', 'text' => array( '<strong>' . esc_html__( 'Premium Support', 'wpforms-lite' ) . '</strong>', ), ), 'ultimate' => array( 'status' => 'full', 'text' => array( '<strong>' . esc_html__( 'Premium Support', 'wpforms-lite' ) . '</strong>', ), ), 'agency' => array( 'status' => 'full', 'text' => array( '<strong>' . esc_html__( 'Premium Support', 'wpforms-lite' ) . '</strong>', ), ), ), 'sites' => array( 'basic' => array( 'status' => 'partial', 'text' => array( '<strong>' . esc_html__( '1 Site', 'wpforms-lite' ) . '</strong>', ), ), 'plus' => array( 'status' => 'partial', 'text' => array( '<strong>' . esc_html__( '3 Sites', 'wpforms-lite' ) . '</strong>', ), ), 'pro' => array( 'status' => 'full', 'text' => array( '<strong>' . esc_html__( '5 Sites', 'wpforms-lite' ) . '</strong>', ), ), 'elite' => array( 'status' => 'full', 'text' => array( '<strong>' . esc_html__( 'Unlimited Sites', 'wpforms-lite' ) . '</strong>', ), ), 'ultimate' => array( 'status' => 'full', 'text' => array( '<strong>' . esc_html__( 'Unlimited Sites', 'wpforms-lite' ) . '</strong>', ), ), 'agency' => array( 'status' => 'full', 'text' => array( '<strong>' . esc_html__( 'Unlimited Sites', 'wpforms-lite' ) . '</strong>', ), ), ), ); // Wrong feature? if ( ! isset( $data[ $feature ] ) ) { return false; } // Is a top level license? $is_licenses_top = in_array( $license, self::$licenses_top, true ); // Wrong license type? if ( ! isset( $data[ $feature ][ $license ] ) && ! $is_licenses_top ) { return false; } // Some licenses have partial data. if ( isset( $data[ $feature ][ $license ] ) ) { return $data[ $feature ][ $license ]; } // Top level plans has no feature difference with `pro` plan in most cases. return $is_licenses_top ? $data[ $feature ]['pro'] : $data[ $feature ][ $license ]; } /** * Get the current installation license type (always lowercase). * * @since 1.5.0 * * @return string */ protected function get_license_type() { $type = wpforms_get_license_type(); if ( empty( $type ) ) { $type = 'lite'; } return $type; } } new WPForms_About(); admin/class-settings.php 0000666 00000055221 15213301445 0011317 0 ustar 00 <?php /** * Settings class. * * @since 1.0.0 */ class WPForms_Settings { /** * The current active tab. * * @since 1.3.9 * * @var string */ public $view; /** * Primary class constructor. * * @since 1.0.0 */ public function __construct() { // Maybe load settings page. add_action( 'admin_init', array( $this, 'init' ) ); } /** * Determine if the user is viewing the settings page, if so, party on. * * @since 1.0.0 */ public function init() { // 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'; // Watch for triggered save. $this->save_settings(); // Determine the current active settings tab. $this->view = isset( $_GET['view'] ) ? sanitize_key( wp_unslash( $_GET['view'] ) ) : 'general'; // phpcs:ignore WordPress.CSRF.NonceVerification add_action( 'admin_enqueue_scripts', array( $this, 'enqueues' ) ); add_action( 'wpforms_admin_page', array( $this, 'output' ) ); // Hook for addons. do_action( 'wpforms_settings_init', $this ); } /** * Sanitize and save settings. * * @since 1.3.9 */ public function save_settings() { // 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', array() ); // Views excluded from saving list. $exclude_views = apply_filters( 'wpforms_settings_exclude_view', array(), $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', array( 'content', 'license', 'providers' ) ); if ( empty( $field['type'] ) || in_array( $field['type'], $exclude, true ) ) { continue; } // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized $value = isset( $_POST[ $id ] ) ? trim( wp_unslash( $_POST[ $id ] ) ) : false; $value_prev = isset( $settings[ $id ] ) ? $settings[ $id ] : false; // Custom filter can be provided for sanitizing, otherwise use defaults. if ( ! empty( $field['filter'] ) && function_exists( $field['filter'] ) ) { $value = call_user_func( $field['filter'], $value, $id, $field, $value_prev ); } else { switch ( $field['type'] ) { case 'checkbox': $value = (bool) $value; break; case 'image': $value = esc_url_raw( $value ); break; case 'color': $value = wpforms_sanitize_hex_color( $value ); break; case 'number': $value = (float) $value; break; case 'text': case 'radio': case 'select': default: $value = sanitize_text_field( $value ); break; } } // Add to settings. $settings[ $id ] = $value; } // Save settings. update_option( 'wpforms_settings', $settings ); WPForms_Admin_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' ), ], 'email' => [ 'name' => esc_html__( 'Email', 'wpforms-lite' ), 'form' => true, 'submit' => esc_html__( 'Save Settings', 'wpforms-lite' ), ], 'recaptcha' => [ 'name' => esc_html__( 'reCAPTCHA', '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, ], '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 '<ul class="wpforms-admin-tabs">'; foreach ( $tabs as $id => $tab ) { $active = $id === $this->view ? 'active' : ''; $link = add_query_arg( 'view', $id, admin_url( 'admin.php?page=wpforms-settings' ) ); echo '<li><a href="' . esc_url_raw( $link ) . '" class="' . esc_attr( $active ) . '">' . esc_html( $tab['name'] ) . '</a></li>'; } echo '</ul>'; } /** * Return all the default registered settings fields. * * @since 1.3.9 * * @param string $view The current view (tab) on Settings page. * * @return array */ public function get_registered_settings( $view = '' ) { $defaults = [ // General Settings tab. 'general' => [ 'license-heading' => [ 'id' => 'license-heading', 'content' => '<h4>' . esc_html__( 'License', 'wpforms-lite' ) . '</h4><p>' . esc_html__( 'Your license key provides access to updates and addons.', 'wpforms-lite' ) . '</p>', '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' => '<h4>' . esc_html__( 'General', 'wpforms-lite' ) . '</h4>', 'type' => 'content', 'no_label' => true, 'class' => [ 'section-heading', 'no-desc' ], ], 'disable-css' => [ 'id' => 'disable-css', 'name' => esc_html__( 'Include Form Styling', 'wpforms-lite' ), 'desc' => sprintf( wp_kses( /* translators: %s - WPForms.com documentation URL. */ __( 'Determines which CSS files to load for the site (<a href="%s" target="_blank" rel="noopener noreferrer">please see our tutorial for full details</a>). Unless experienced with CSS or instructed by support, "Base and Form Theme Styling" is recommended.', 'wpforms-lite' ), [ 'a' => [ 'href' => [], 'target' => [], 'rel' => [], ], ] ), 'https://wpforms.com/docs/how-to-choose-an-include-form-styling-setting/' ), 'type' => 'select', 'choicesjs' => true, 'default' => 1, 'options' => [ 1 => esc_html__( 'Base and form theme styling', 'wpforms-lite' ), 2 => esc_html__( 'Base styling only', 'wpforms-lite' ), 3 => esc_html__( 'No styling', 'wpforms-lite' ), ], ], 'global-assets' => [ 'id' => 'global-assets', 'name' => esc_html__( 'Load Assets Globally', 'wpforms-lite' ), 'desc' => esc_html__( 'Check this if you would like to load WPForms assets site-wide. Only check if your site is having compatibility issues or instructed to by support.', 'wpforms-lite' ), 'type' => 'checkbox', ], 'gdpr-heading' => [ 'id' => 'GDPR', 'content' => '<h4>' . esc_html__( 'GDPR', 'wpforms-lite' ) . '</h4>', 'type' => 'content', 'no_label' => true, 'class' => [ 'section-heading', 'no-desc' ], ], 'gdpr' => [ 'id' => 'gdpr', 'name' => esc_html__( 'GDPR Enhancements', 'wpforms-lite' ), 'desc' => sprintf( wp_kses( /* translators: %s - WPForms.com GDPR documentation URL. */ __( 'Check this to turn on GDPR related features and enhancements. <a href="%s" target="_blank" rel="noopener noreferrer">Read our GDPR documentation</a> to learn more.', 'wpforms-lite' ), [ 'a' => [ 'href' => [], 'target' => [], 'rel' => [], ], ] ), 'https://wpforms.com/docs/how-to-create-gdpr-compliant-forms/' ), 'type' => 'checkbox', ], ], // Email settings tab. 'email' => [ 'email-heading' => [ 'id' => 'email-heading', 'content' => '<h4>' . esc_html__( 'Email', 'wpforms-lite' ) . '</h4>', 'type' => 'content', 'no_label' => true, 'class' => [ 'section-heading', 'no-desc' ], ], 'email-async' => [ 'id' => 'email-async', 'name' => esc_html__( 'Optimize Email Sending', 'wpforms-lite' ), 'desc' => esc_html__( 'Check this if you would like to enable sending emails asynchronously, which can make submission processing faster.', 'wpforms-lite' ), 'type' => 'checkbox', ], 'email-template' => [ 'id' => 'email-template', 'name' => esc_html__( 'Template', 'wpforms-lite' ), 'desc' => esc_html__( 'Determines how email notifications will be formatted. HTML Templates are the default.', 'wpforms-lite' ), 'type' => 'radio', 'default' => 'default', 'options' => [ 'default' => esc_html__( 'HTML Template', 'wpforms-lite' ), 'none' => esc_html__( 'Plain text', 'wpforms-lite' ), ], ], 'email-header-image' => [ 'id' => 'email-header-image', 'name' => esc_html__( 'Header Image', 'wpforms-lite' ), 'desc' => wp_kses( __( 'Upload or choose a logo to be displayed at the top of email notifications.<br>Recommended size is 300x100 or smaller for best support on all devices.', 'wpforms-lite' ), [ 'br' => [] ] ), 'type' => 'image', ], 'email-background-color' => [ 'id' => 'email-background-color', 'name' => esc_html__( 'Background Color', 'wpforms-lite' ), 'desc' => esc_html__( 'Customize the background color of the HTML email template.', 'wpforms-lite' ), 'type' => 'color', 'default' => '#e9eaec', ], 'email-carbon-copy' => [ 'id' => 'email-carbon-copy', 'name' => esc_html__( 'Carbon Copy', 'wpforms-lite' ), 'desc' => esc_html__( 'Check this if you would like to enable the ability to CC: email addresses in the form notification settings.', 'wpforms-lite' ), 'type' => 'checkbox', ], ], // Recaptcha settings tab. 'recaptcha' => [ 'recaptcha-heading' => [ 'id' => 'recaptcha-heading', 'content' => '<h4>' . esc_html__( 'reCAPTCHA', 'wpforms-lite' ) . '</h4>' . $this->get_recaptcha_field_desc(), 'type' => 'content', 'no_label' => true, 'class' => [ 'section-heading' ], ], 'recaptcha-type' => [ 'id' => 'recaptcha-type', 'name' => esc_html__( 'Type', 'wpforms-lite' ), 'type' => 'radio', 'default' => 'v2', 'options' => [ 'v2' => esc_html__( 'Checkbox reCAPTCHA v2', 'wpforms-lite' ), 'invisible' => esc_html__( 'Invisible reCAPTCHA v2', 'wpforms-lite' ), 'v3' => esc_html__( 'reCAPTCHA v3', 'wpforms-lite' ), ], ], 'recaptcha-site-key' => [ 'id' => 'recaptcha-site-key', 'name' => esc_html__( 'Site Key', 'wpforms-lite' ), 'type' => 'text', ], 'recaptcha-secret-key' => [ 'id' => 'recaptcha-secret-key', 'name' => esc_html__( 'Secret Key', 'wpforms-lite' ), 'type' => 'text', ], 'recaptcha-fail-msg' => [ 'id' => 'recaptcha-fail-msg', 'name' => esc_html__( 'Fail Message', 'wpforms-lite' ), 'desc' => esc_html__( 'The message displayed to users who fail the reCAPTCHA verification process.', 'wpforms-lite' ), 'type' => 'text', 'default' => esc_html__( 'Google reCAPTCHA verification failed, please try again later.', 'wpforms-lite' ), ], 'recaptcha-v3-threshold' => [ 'id' => 'recaptcha-v3-threshold', 'name' => esc_html__( 'Score Threshold', 'wpforms-lite' ), 'desc' => esc_html__( 'reCAPTCHA v3 returns a score (1.0 is very likely a good interaction, 0.0 is very likely a bot). If the score less than or equal to this threshold, the form submission will be blocked and the message above will be displayed.', 'wpforms-lite' ), 'type' => 'number', 'attr' => [ 'step' => '0.1', 'min' => '0.0', 'max' => '1.0', ], 'default' => esc_html__( '0.4', 'wpforms-lite' ), ], 'recaptcha-noconflict' => [ 'id' => 'recaptcha-noconflict', 'name' => esc_html__( 'No-Conflict Mode', 'wpforms-lite' ), 'desc' => esc_html__( 'When checked, other reCAPTCHA occurrences are forcefully removed, to prevent conflicts. Only check if your site is having compatibility issues or instructed to by support.', 'wpforms-lite' ), 'type' => 'checkbox', ], ], // Validation messages settings tab. 'validation' => [ 'validation-heading' => [ 'id' => 'validation-heading', 'content' => '<h4>' . esc_html__( 'Validation Messages', 'wpforms-lite' ) . '</h4><p>' . esc_html__( 'These messages are displayed to the users as they fill out a form in real-time.', 'wpforms-lite' ) . '</p>', '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-url' => [ 'id' => 'validation-url', 'name' => esc_html__( 'Website URL', 'wpforms-lite' ), 'type' => 'text', 'default' => esc_html__( 'Please enter a valid URL.', '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' => esc_html__( 'Did you mean {suggestion}?', '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-confirm' => [ 'id' => 'validation-confirm', 'name' => esc_html__( 'Confirm Value', 'wpforms-lite' ), 'type' => 'text', 'default' => esc_html__( 'Field values do not match.', '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' ), ], ], // Provider integrations settings tab. 'integrations' => [ 'integrations-heading' => [ 'id' => 'integrations-heading', 'content' => '<h4>' . esc_html__( 'Integrations', 'wpforms-lite' ) . '</h4><p>' . esc_html__( 'Manage integrations with popular providers such as Constant Contact, Mailchimp, Zapier, and more.', 'wpforms-lite' ) . '</p>', 'type' => 'content', 'no_label' => true, 'class' => [ 'section-heading' ], ], 'integrations-providers' => [ 'id' => 'integrations-providers', 'content' => '<h4>' . esc_html__( 'Integrations', 'wpforms-lite' ) . '</h4><p>' . esc_html__( 'Manage integrations with popular providers such as Constant Contact, Mailchimp, Zapier, and more.', 'wpforms-lite' ) . '</p>', 'type' => 'providers', 'wrap' => 'none', ], ], // Misc. settings tab. 'misc' => [ 'misc-heading' => [ 'id' => 'misc-heading', 'content' => '<h4>' . esc_html__( 'Misc', 'wpforms-lite' ) . '</h4>', 'type' => 'content', 'no_label' => true, 'class' => [ 'section-heading', 'no-desc' ], ], 'hide-announcements' => [ 'id' => 'hide-announcements', 'name' => esc_html__( 'Hide Announcements', 'wpforms-lite' ), 'desc' => esc_html__( 'Check this if you would like to hide plugin announcements and update details.', 'wpforms-lite' ), 'type' => 'checkbox', ], 'hide-admin-bar' => [ 'id' => 'hide-admin-bar', 'name' => esc_html__( 'Hide Admin Bar Menu', 'wpforms-lite' ), 'desc' => esc_html__( 'Check this if you would like to hide the WPForms admin bar menu.', 'wpforms-lite' ), 'type' => 'checkbox', ], 'uninstall-data' => [ 'id' => 'uninstall-data', 'name' => esc_html__( 'Uninstall WPForms', 'wpforms-lite' ), 'desc' => esc_html__( 'Check this if you would like to remove ALL WPForms data upon plugin deletion. All forms and settings will be unrecoverable.', 'wpforms-lite' ), 'type' => 'checkbox', ], ], ]; // TODO: move this to Pro. if ( wpforms()->pro ) { $defaults['misc']['uninstall-data']['desc'] = esc_html__( 'Check this if you would like to remove ALL WPForms data upon plugin deletion. All forms, entries, and uploaded files will be unrecoverable.', 'wpforms' ); } $defaults = apply_filters( 'wpforms_settings_defaults', $defaults ); // Take care of invalid views. if ( ! empty( $view ) && ! array_key_exists( $view, $defaults ) ) { $this->view = key( $defaults ); return reset( $defaults ); } return empty( $view ) ? $defaults : $defaults[ $view ]; } /** * Some heading descriptions, like for reCAPTCHA, are long so we define them separately. * * @since 1.6.0 * * @return string */ private function get_recaptcha_field_desc() { return '<p>' . esc_html__( 'reCAPTCHA is a free anti-spam service from Google which helps to protect your website from spam and abuse while letting real people pass through with ease.', 'wpforms-lite' ) . '</p>' . '<p>' . esc_html__( 'Google offers 3 versions of reCAPTCHA (all supported within WPForms):', 'wpforms-lite' ) . '</p>' . '<ul style="list-style: disc;margin-left: 20px;">' . '<li>' . wp_kses( __( '<strong>v2 Checkbox reCAPTCHA</strong>: Prompts users to check a box to prove they\'re human.', 'wpforms-lite' ), [ 'strong' => [] ] ) . '</li>' . '<li>' . wp_kses( __( '<strong>v2 Invisible reCAPTCHA</strong>: Uses advanced technology to detect real users without requiring any input.', 'wpforms-lite' ), [ 'strong' => [] ] ) . '</li>' . '<li>' . wp_kses( __( '<strong>v3 reCAPTCHA</strong>: Uses a behind-the-scenes scoring system to detect abusive traffic, and lets you decide the minimum passing score. Recommended for advanced use only (or if using Google AMP).', 'wpforms-lite' ), [ 'strong' => [] ] ) . '</li>' . '</ul>' . '<p>' . esc_html__( 'Sites already using one type of reCAPTCHA will need to create new site keys before switching to a different option.', 'wpforms-lite' ) . '</p>' . '<p>' . sprintf( wp_kses( /* translators: %s - WPForms.com Setup Captcha URL. */ __( '<a href="%s" target="_blank" rel="noopener noreferrer">Read our walk through</a> to learn more and for step-by-step directions.', 'wpforms-lite' ), [ 'a' => [ 'href' => [], 'target' => [], 'rel' => [], ], ] ), 'https://wpforms.com/docs/setup-captcha-wpforms/' ) . '</p></ul>'; } /** * Return array containing markup for all the appropriate settings fields. * * @since 1.3.9 * * @param string $view View slug. * * @return array */ public function get_settings_fields( $view = '' ) { $fields = array(); $settings = $this->get_registered_settings( $view ); foreach ( $settings as $id => $args ) { $fields[ $id ] = wpforms_settings_output_field( $args ); } return apply_filters( 'wpforms_settings_fields', $fields, $view ); } /** * Build the output for the plugin settings page. * * @since 1.0.0 */ public function output() { $tabs = $this->get_tabs(); $fields = $this->get_settings_fields( $this->view ); ?> <div id="wpforms-settings" class="wrap wpforms-admin-wrap"> <?php $this->tabs(); ?> <h1 class="wpforms-h1-placeholder"></h1> <?php if ( wpforms()->pro && class_exists( 'WPForms_License', false ) ) { wpforms()->license->notices( true ); } ?> <div class="wpforms-admin-content wpforms-admin-settings wpforms-admin-content-<?php echo esc_attr( $this->view ); ?> wpforms-admin-settings-<?php echo esc_attr( $this->view ); ?>"> <?php // Some tabs rely on AJAX and do not contain a form, such as Integrations. if ( ! empty( $tabs[ $this->view ]['form'] ) ) : ?> <form class="wpforms-admin-settings-form" method="post"> <input type="hidden" name="action" value="update-settings"> <input type="hidden" name="view" value="<?php echo esc_attr( $this->view ); ?>"> <input type="hidden" name="nonce" value="<?php echo esc_attr( wp_create_nonce( 'wpforms-settings-nonce' ) ); ?>"> <?php endif; ?> <?php do_action( 'wpforms_admin_settings_before', $this->view, $fields ); ?> <?php foreach ( $fields as $field ) { echo $field; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped } ?> <?php if ( ! empty( $tabs[ $this->view ]['submit'] ) ) : ?> <p class="submit"> <button type="submit" class="wpforms-btn wpforms-btn-md wpforms-btn-orange" name="wpforms-settings-submit"> <?php // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped echo $tabs[ $this->view ]['submit']; ?> </button> </p> <?php endif; ?> <?php do_action( 'wpforms_admin_settings_after', $this->view, $fields ); ?> <?php if ( ! empty( $tabs[ $this->view ]['form'] ) ) : ?> </form> <?php endif; ?> </div> </div> <?php } } new WPForms_Settings(); admin/class-importers.php 0000666 00000002403 15213301445 0011475 0 ustar 00 <?php /** * Load the different form importers. * * @since 1.4.2 */ class WPForms_Importers { /** * Primary class constructor. * * @since 1.4.2 */ public function __construct() { if ( wpforms_is_admin_page() || ( defined( 'DOING_AJAX' ) && DOING_AJAX ) ) { $this->init(); } } /** * Load and init the base importer class. * * @since 1.4.2 */ public function init() { // Interface with common methods. require_once WPFORMS_PLUGIN_DIR . 'includes/admin/importers/interface.php'; // Abstract class with common functionality. require_once WPFORMS_PLUGIN_DIR . 'includes/admin/importers/class-base.php'; // Load default importers on WP init. add_action( 'init', array( $this, 'load' ) ); } /** * Load default form importers. * * @since 1.4.2 */ public function load() { $importers = apply_filters( 'wpforms_load_importers', array( 'contact-form-7', 'ninja-forms', 'pirate-forms', ) ); foreach ( $importers as $importer ) { $importer = sanitize_file_name( $importer ); if ( file_exists( WPFORMS_PLUGIN_DIR . 'includes/admin/importers/class-' . $importer . '.php' ) ) { require_once WPFORMS_PLUGIN_DIR . 'includes/admin/importers/class-' . $importer . '.php'; } } } } new WPForms_Importers(); admin/class-review.php 0000666 00000016511 15213301445 0010757 0 ustar 00 <?php /** * Ask for some love. * * @since 1.3.2 */ class WPForms_Review { /** * Primary class constructor. * * @since 1.3.2 */ public function __construct() { // Admin notice requesting review. add_action( 'admin_notices', array( $this, 'review_request' ) ); add_action( 'wp_ajax_wpforms_review_dismiss', array( $this, 'review_dismiss' ) ); // Admin footer text. add_filter( 'admin_footer_text', array( $this, 'admin_footer' ), 1, 2 ); } /** * Add admin notices as needed for reviews. * * @since 1.3.2 */ public function review_request() { // Only consider showing the review request to admin users. if ( ! is_super_admin() ) { return; } // If the user has opted out of product announcement notifications, don't // display the review request. if ( wpforms_setting( 'hide-announcements', false ) ) { return; } // Verify that we can do a check for reviews. $review = get_option( 'wpforms_review' ); $time = time(); $load = false; if ( ! $review ) { $review = array( 'time' => $time, 'dismissed' => false, ); update_option( 'wpforms_review', $review ); } else { // Check if it has been dismissed or not. if ( ( isset( $review['dismissed'] ) && ! $review['dismissed'] ) && ( isset( $review['time'] ) && ( ( $review['time'] + DAY_IN_SECONDS ) <= $time ) ) ) { $load = true; } } // If we cannot load, return early. if ( ! $load ) { return; } // Logic is slightly different depending on what's at our disposal. if ( wpforms()->pro && class_exists( 'WPForms_Entry_Handler', false ) ) { $this->review(); } else { $this->review_lite(); } } /** * Maybe show review request. * * @since 1.3.9 */ public function review() { // Fetch total entries. $entries = wpforms()->entry->get_entries( array( 'number' => 50 ), true ); // Only show review request if the site has collected at least 50 entries. if ( empty( $entries ) || $entries < 50 ) { return; } // We have a candidate! Output a review message. ?> <div class="notice notice-info is-dismissible wpforms-review-notice"> <p><?php esc_html_e( 'Hey, I noticed you collected over 50 entries from WPForms - that’s awesome! Could you please do me a BIG favor and give it a 5-star rating on WordPress to help us spread the word and boost our motivation?', 'wpforms-lite' ); ?></p> <p><strong><?php echo wp_kses( __( '~ Syed Balkhi<br>Co-Founder of WPForms', 'wpforms-lite' ), array( 'br' => array() ) ); ?></strong></p> <p> <a href="https://wordpress.org/support/plugin/wpforms-lite/reviews/?filter=5#new-post" class="wpforms-dismiss-review-notice wpforms-review-out" target="_blank" rel="noopener"><?php esc_html_e( 'Ok, you deserve it', 'wpforms-lite' ); ?></a><br> <a href="#" class="wpforms-dismiss-review-notice" target="_blank" rel="noopener noreferrer"><?php esc_html_e( 'Nope, maybe later', 'wpforms-lite' ); ?></a><br> <a href="#" class="wpforms-dismiss-review-notice" target="_blank" rel="noopener noreferrer"><?php esc_html_e( 'I already did', 'wpforms-lite' ); ?></a> </p> </div> <script type="text/javascript"> jQuery( document ).ready( function ( $ ) { $( document ).on( 'click', '.wpforms-dismiss-review-notice, .wpforms-review-notice button', function ( event ) { if ( ! $( this ).hasClass( 'wpforms-review-out' ) ) { event.preventDefault(); } $.post( ajaxurl, { action: 'wpforms_review_dismiss' } ); $( '.wpforms-review-notice' ).remove(); } ); } ); </script> <?php } /** * Maybe show Lite review request. * * @since 1.3.9 */ public function review_lite() { // Fetch when plugin was initially installed. $activated = get_option( 'wpforms_activated', array() ); if ( ! empty( $activated['lite'] ) ) { // Only continue if plugin has been installed for at least 7 days. if ( ( $activated['lite'] + ( DAY_IN_SECONDS * 14 ) ) > time() ) { return; } } else { $activated['lite'] = time(); update_option( 'wpforms_activated', $activated ); return; } // Only proceed with displaying if the user created at least one form. $form_count = wp_count_posts( 'wpforms' ); if ( empty( $form_count->publish ) ) { return; } // Check if the Constant Contact notice is displaying. $cc = get_option( 'wpforms_constant_contact', false ); // If it's displaying don't ask for review until they configure CC or // dismiss the notice. if ( $cc ) { return; } // We have a candidate! Output a review message. ?> <div class="notice notice-info is-dismissible wpforms-review-notice"> <p><?php esc_html_e( 'Hey, I noticed you created a contact form with WPForms - that’s awesome! Could you please do me a BIG favor and give it a 5-star rating on WordPress to help us spread the word and boost our motivation?', 'wpforms-lite' ); ?></p> <p><strong><?php echo wp_kses( __( '~ Syed Balkhi<br>Co-Founder of WPForms', 'wpforms-lite' ), array( 'br' => array() ) ); ?></strong></p> <p> <a href="https://wordpress.org/support/plugin/wpforms-lite/reviews/?filter=5#new-post" class="wpforms-dismiss-review-notice wpforms-review-out" target="_blank" rel="noopener noreferrer"><?php esc_html_e( 'Ok, you deserve it', 'wpforms-lite' ); ?></a><br> <a href="#" class="wpforms-dismiss-review-notice" target="_blank" rel="noopener noreferrer"><?php esc_html_e( 'Nope, maybe later', 'wpforms-lite' ); ?></a><br> <a href="#" class="wpforms-dismiss-review-notice" target="_blank" rel="noopener noreferrer"><?php esc_html_e( 'I already did', 'wpforms-lite' ); ?></a> </p> </div> <script type="text/javascript"> jQuery( document ).ready( function ( $ ) { $( document ).on( 'click', '.wpforms-dismiss-review-notice, .wpforms-review-notice button', function ( event ) { if ( ! $( this ).hasClass( 'wpforms-review-out' ) ) { event.preventDefault(); } $.post( ajaxurl, { action: 'wpforms_review_dismiss' } ); $( '.wpforms-review-notice' ).remove(); } ); } ); </script> <?php } /** * Dismiss the review admin notice * * @since 1.3.2 */ public function review_dismiss() { $review = get_option( 'wpforms_review', array() ); $review['time'] = time(); $review['dismissed'] = true; update_option( 'wpforms_review', $review ); die; } /** * When user is on a WPForms related admin page, display footer text * that graciously asks them to rate us. * * @since 1.3.2 * * @param string $text * * @return string */ public function admin_footer( $text ) { global $current_screen; if ( ! empty( $current_screen->id ) && strpos( $current_screen->id, 'wpforms' ) !== false ) { $url = 'https://wordpress.org/support/plugin/wpforms-lite/reviews/?filter=5#new-post'; $text = sprintf( wp_kses( /* translators: $1$s - WPForms plugin name; $2$s - WP.org review link; $3$s - WP.org review link. */ __( 'Please rate %1$s <a href="%2$s" target="_blank" rel="noopener noreferrer">★★★★★</a> on <a href="%3$s" target="_blank" rel="noopener">WordPress.org</a> to help us spread the word. Thank you from the WPForms team!', 'wpforms-lite' ), array( 'a' => array( 'href' => array(), 'target' => array(), 'rel' => array(), ), ) ), '<strong>WPForms</strong>', $url, $url ); } return $text; } } new WPForms_Review; admin/class-notices.php 0000666 00000004742 15213301445 0011125 0 ustar 00 <?php /** * Admin notices, on the fly. * * @example * WPForms_Admin_Notice::success( 'All is good!' ); * * @example * WPForms_Admin_Notice::warning( 'Do something please.' ); * * @todo Persistent, dismissible notices. * @link https://gist.github.com/monkeymonk/2ea17e2260daaecd0049c46c8d6c85fd * * @since 1.3.9 */ class WPForms_Admin_Notice { /** * Single instance holder. * * @since 1.3.9 * @var mixed */ private static $_instance = null; /** * Added notices. * * @since 1.3.9 * @var array */ public $notices = array(); /** * Get the instance. * * @since 1.3.9 * @return WPForms_Admin_Notice */ public static function getInstance() { if ( is_null( self::$_instance ) ) { self::$_instance = new WPForms_Admin_Notice(); } return self::$_instance; } /** * Hook when called. * * @since 1.3.9 */ public function __construct() { add_action( 'admin_notices', array( &$this, 'display' ) ); } /** * Display the notices. * * @since 1.3.9 */ public function display() { // At least one WPForms capability is needed to see admin notices. if ( ! wpforms_current_user_can( 'any' ) ) { return; } echo implode( ' ', $this->notices ); } /** * Add notice to instance property. * * @since 1.3.9 * * @param string $message Message to display. * @param string $type Type of the notice (default: ''). */ public static function add( $message, $type = '' ) { $instance = self::getInstance(); $id = 'wpforms-notice-' . ( count( $instance->notices ) + 1 ); $type = ! empty( $type ) ? 'notice-' . $type : ''; $notice = sprintf( '<div class="notice wpforms-notice %s" id="%s">%s</div>', $type, $id, wpautop( $message ) ); $instance->notices[] = $notice; } /** * Add Info notice. * * @since 1.3.9 * * @param string $message Message to display. */ public static function info( $message ) { self::add( $message, 'info' ); } /** * Add Error notice. * * @since 1.3.9 * * @param string $message Message to display. */ public static function error( $message ) { self::add( $message, 'error' ); } /** * Add Success notice. * * @since 1.3.9 * * @param string $message Message to display. */ public static function success( $message ) { self::add( $message, 'success' ); } /** * Add Warning notice. * * @since 1.3.9 * * @param string $message Message to display. */ public static function warning( $message ) { self::add( $message, 'warning' ); } } admin/overview/class-overview.php 0000666 00000020073 15213301445 0013170 0 ustar 00 <?php /** * Primary overview page inside the admin which lists all forms. * * @since 1.0.0 */ class WPForms_Overview { /** * Primary class constructor. * * @since 1.0.0 */ public function __construct() { // Maybe load overview page. add_action( 'admin_init', array( $this, 'init' ) ); // Setup screen options. Needs to be here as admin_init hook it too late. add_action( 'load-toplevel_page_wpforms-overview', array( $this, 'screen_options' ) ); add_filter( 'set-screen-option', array( $this, 'screen_options_set' ), 10, 3 ); } /** * Determine if the user is viewing the overview page, if so, party on. * * @since 1.0.0 */ public function init() { // Only load if we are actually on the overview page. if ( ! wpforms_is_admin_page( 'overview' ) ) { return; } // Bulk actions. add_action( 'load-toplevel_page_wpforms-overview', array( $this, 'notices' ) ); add_action( 'load-toplevel_page_wpforms-overview', array( $this, 'process_bulk_actions' ) ); add_filter( 'removable_query_args', array( $this, 'removable_query_args' ) ); // The overview page leverages WP_List_Table so we must load it. if ( ! class_exists( 'WP_List_Table', false ) ) { require_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php'; } // Load the class that builds the overview table. require_once WPFORMS_PLUGIN_DIR . 'includes/admin/overview/class-overview-table.php'; add_action( 'admin_enqueue_scripts', array( $this, 'enqueues' ) ); add_action( 'wpforms_admin_page', array( $this, 'output' ) ); // Provide hook for addons. do_action( 'wpforms_overview_init' ); } /** * Add per-page screen option to the Forms table. * * @since 1.0.0 */ public function screen_options() { $screen = get_current_screen(); if ( null === $screen || 'toplevel_page_wpforms-overview' !== $screen->id ) { return; } add_screen_option( 'per_page', array( 'label' => esc_html__( 'Number of forms per page:', 'wpforms-lite' ), 'option' => 'wpforms_forms_per_page', 'default' => apply_filters( 'wpforms_overview_per_page', 20 ), ) ); } /** * Form table per-page screen option value. * * @since 1.0.0 * * @param bool $keep Whether to save or skip saving the screen option value. Default false. * @param string $option The option name. * @param int $value The number of rows to use. * * @return mixed */ public function screen_options_set( $keep, $option, $value ) { if ( 'wpforms_forms_per_page' === $option ) { return $value; } return $keep; } /** * Enqueue assets for the overview page. * * @since 1.0.0 */ public function enqueues() { // Hook for addons. do_action( 'wpforms_overview_enqueue' ); } /** * Build the output for the overview page. * * @since 1.0.0 */ public function output() { ?> <div id="wpforms-overview" class="wrap wpforms-admin-wrap"> <h1 class="page-title"> <?php esc_html_e( 'Forms Overview', 'wpforms-lite' ); ?> <?php if ( wpforms_current_user_can( 'create_forms' ) ) : ?> <a href="<?php echo esc_url( admin_url( 'admin.php?page=wpforms-builder&view=setup' ) ); ?>" class="add-new-h2 wpforms-btn-orange"> <?php esc_html_e( 'Add New', 'wpforms-lite' ); ?> </a> <?php endif; ?> </h1> <?php $overview_table = new WPForms_Overview_Table(); $overview_table->prepare_items(); ?> <div class="wpforms-admin-content"> <?php do_action( 'wpforms_admin_overview_before_table' ); ?> <form id="wpforms-overview-table" method="get" action="<?php echo esc_url( admin_url( 'admin.php?page=wpforms-overview' ) ); ?>"> <input type="hidden" name="post_type" value="wpforms" /> <input type="hidden" name="page" value="wpforms-overview" /> <?php $overview_table->views(); ?> <?php $overview_table->display(); ?> </form> </div> </div> <?php } /** * Add admin action notices and process bulk actions. * * @since 1.5.7 */ public function notices() { $deleted = ! empty( $_REQUEST['deleted'] ) ? sanitize_key( $_REQUEST['deleted'] ) : false; // phpcs:ignore WordPress.Security.NonceVerification $duplicated = ! empty( $_REQUEST['duplicated'] ) ? sanitize_key( $_REQUEST['duplicated'] ) : false; // phpcs:ignore WordPress.Security.NonceVerification $notice = array(); if ( $deleted && 'error' !== $deleted ) { $notice = array( 'type' => 'info', /* translators: %s - Deleted forms count. */ 'msg' => sprintf( _n( '%s form was successfully deleted.', '%s forms were successfully deleted.', $deleted, 'wpforms-lite' ), $deleted ), ); } if ( $duplicated && 'error' !== $duplicated ) { $notice = array( 'type' => 'info', /* translators: %s - Duplicated forms count. */ 'msg' => sprintf( _n( '%s form was successfully duplicated.', '%s forms were successfully duplicated.', $duplicated, 'wpforms-lite' ), $duplicated ), ); } if ( 'error' === $deleted || 'error' === $duplicated ) { $notice = array( 'type' => 'error', 'msg' => esc_html__( 'Security check failed. Please try again.', 'wpforms-lite' ), ); } if ( ! empty( $notice ) ) { WPForms_Admin_Notice::add( $notice['msg'], $notice['type'] ); } } /** * Process the bulk table actions. * * @since 1.5.7 */ public function process_bulk_actions() { $ids = isset( $_GET['form_id'] ) ? array_map( 'absint', (array) $_GET['form_id'] ) : array(); // phpcs:ignore WordPress.Security.NonceVerification $action = ! empty( $_REQUEST['action'] ) ? sanitize_key( $_REQUEST['action'] ) : false; // phpcs:ignore WordPress.Security.NonceVerification // Checking the sortable column link. $is_orderby_link = ! empty( $_REQUEST['orderby'] ) && ! empty( $_REQUEST['order'] ); if ( empty( $ids ) || empty( $action ) || $is_orderby_link ) { return; } // Check exact action values. if ( ! in_array( $action, [ 'delete', 'duplicate' ], true ) ) { return; } if ( empty( $_GET['_wpnonce'] ) ) { return; } // Check the nonce. if ( ! wp_verify_nonce( sanitize_key( $_GET['_wpnonce'] ), 'bulk-forms' ) && ! wp_verify_nonce( sanitize_key( $_GET['_wpnonce'] ), 'wpforms_' . $action . '_form_nonce' ) ) { return; } // Check that we have a method for this action. if ( ! method_exists( $this, 'bulk_action_' . $action . '_forms' ) ) { return; } $processed_forms = count( $this->{'bulk_action_' . $action . '_forms'}( $ids ) ); // Unset get vars and perform redirect to avoid action reuse. wp_safe_redirect( add_query_arg( $action . 'd', $processed_forms, remove_query_arg( array( 'action', 'action2', '_wpnonce', 'form_id', 'paged', '_wp_http_referer' ) ) ) ); exit; } /** * Delete forms. * * @since 1.5.7 * * @param array $ids Form ids to delete. * * @return array List of deleted forms. */ private function bulk_action_delete_forms( $ids ) { if ( ! is_array( $ids ) ) { return []; } $deleted = []; foreach ( $ids as $id ) { $deleted[ $id ] = wpforms()->form->delete( $id ); } return array_keys( array_filter( $deleted ) ); } /** * Duplicate forms. * * @since 1.5.7 * * @param array $ids Form ids to duplicate. * * @return array List of duplicated forms. */ private function bulk_action_duplicate_forms( $ids ) { if ( ! is_array( $ids ) ) { return []; } if ( ! wpforms_current_user_can( 'create_forms' ) ) { return []; } $duplicated = []; foreach ( $ids as $id ) { if ( wpforms_current_user_can( 'view_form_single', $id ) ) { $duplicated[ $id ] = wpforms()->form->duplicate( $id ); } } return array_keys( array_filter( $duplicated ) ); } /** * Remove certain arguments from a query string that WordPress should always hide for users. * * @since 1.5.7 * * @param array $removable_query_args An array of parameters to remove from the URL. * * @return array Extended/filtered array of parameters to remove from the URL. */ public function removable_query_args( $removable_query_args ) { if ( wpforms_is_admin_page( 'overview' ) ) { $removable_query_args[] = 'duplicated'; } return $removable_query_args; } } new WPForms_Overview(); admin/overview/class-overview-table.php 0000666 00000022333 15213301445 0014256 0 ustar 00 <?php /** * Generate the table on the plugin overview page. * * @since 1.0.0 */ class WPForms_Overview_Table extends WP_List_Table { /** * Number of forms to show per page. * * @since 1.0.0 * * @var int */ public $per_page; /** * Primary class constructor. * * @since 1.0.0 */ public function __construct() { // Utilize the parent constructor to build the main class properties. parent::__construct( array( 'singular' => 'form', 'plural' => 'forms', 'ajax' => false, ) ); // Default number of forms to show per page. $this->per_page = (int) apply_filters( 'wpforms_overview_per_page', 20 ); } /** * Retrieve the table columns. * * @since 1.0.0 * * @return array $columns Array of all the list table columns. */ public function get_columns() { $columns = array( 'cb' => '<input type="checkbox" />', 'form_name' => esc_html__( 'Name', 'wpforms-lite' ), 'shortcode' => esc_html__( 'Shortcode', 'wpforms-lite' ), 'created' => esc_html__( 'Created', 'wpforms-lite' ), ); return apply_filters( 'wpforms_overview_table_columns', $columns ); } /** * Render the checkbox column. * * @since 1.0.0 * * @param WP_Post $form * * @return string */ public function column_cb( $form ) { return '<input type="checkbox" name="form_id[]" value="' . absint( $form->ID ) . '" />'; } /** * Render the columns. * * @since 1.0.0 * * @param WP_Post $form * @param string $column_name * * @return string */ public function column_default( $form, $column_name ) { switch ( $column_name ) { case 'id': $value = $form->ID; break; case 'shortcode': $value = '[wpforms id="' . $form->ID . '"]'; break; case 'created': $value = get_the_date( get_option( 'date_format' ), $form ); break; case 'modified': $value = get_post_modified_time( get_option( 'date_format' ), false, $form ); break; case 'author': $author = get_userdata( $form->post_author ); $value = $author->display_name; break; case 'php': $value = '<code style="display:block;font-size:11px;">if( function_exists( \'wpforms_get\' ) ){ wpforms_get( ' . $form->ID . ' ); }</code>'; break; default: $value = ''; } return apply_filters( 'wpforms_overview_table_column_value', $value, $form, $column_name ); } /** * Render the form name column with action links. * * @since 1.0.0 * * @param WP_Post $form * * @return string */ public function column_form_name( $form ) { // Build the row action links and return the value. return $this->get_column_form_name_title( $form ) . $this->get_column_form_name_row_actions( $form ); } /** * Get the form name HTML for the form name column. * * @since 1.5.8 * * @param WP_Post $form Form object. * * @return string */ protected function get_column_form_name_title( $form ) { $title = ! empty( $form->post_title ) ? $form->post_title : $form->post_name; $name = sprintf( '<span><strong>%s</strong></span>', esc_html( $title ) ); if ( wpforms_current_user_can( 'view_form_single', $form->ID ) ) { $name = sprintf( '<a href="%s" title="%s" class="row-title" target="_blank" rel="noopener noreferrer"><strong>%s</strong></a>', esc_url( wpforms_get_form_preview_url( $form->ID ) ), esc_attr__( 'View preview', 'wpforms-lite' ), esc_html( $title ) ); } if ( wpforms_current_user_can( 'view_entries_form_single', $form->ID ) ) { $name = sprintf( '<a href="%s" title="%s"><strong>%s</strong></a>', esc_url( add_query_arg( array( 'view' => 'list', 'form_id' => $form->ID, ), admin_url( 'admin.php?page=wpforms-entries' ) ) ), esc_attr__( 'View entries', 'wpforms-lite' ), esc_html( $title ) ); } if ( wpforms_current_user_can( 'edit_form_single', $form->ID ) ) { $name = sprintf( '<a href="%s" title="%s"><strong>%s</strong></a>', esc_url( add_query_arg( array( 'view' => 'fields', 'form_id' => $form->ID, ), admin_url( 'admin.php?page=wpforms-builder' ) ) ), esc_attr__( 'Edit This Form', 'wpforms-lite' ), esc_html( $title ) ); } return $name; } /** * Get the row actions HTML for the form name column. * * @since 1.5.8 * * @param WP_Post $form Form object. * * @return string */ protected function get_column_form_name_row_actions( $form ) { // Build all of the row action links. $row_actions = array(); // Edit. if ( wpforms_current_user_can( 'edit_form_single', $form->ID ) ) { $row_actions['edit'] = sprintf( '<a href="%s" title="%s">%s</a>', esc_url( add_query_arg( array( 'view' => 'fields', 'form_id' => $form->ID, ), admin_url( 'admin.php?page=wpforms-builder' ) ) ), esc_attr__( 'Edit This Form', 'wpforms-lite' ), esc_html__( 'Edit', 'wpforms-lite' ) ); } // Entries. if ( wpforms_current_user_can( 'view_entries_form_single', $form->ID ) ) { $row_actions['entries'] = sprintf( '<a href="%s" title="%s">%s</a>', esc_url( add_query_arg( array( 'view' => 'list', 'form_id' => $form->ID, ), admin_url( 'admin.php?page=wpforms-entries' ) ) ), esc_attr__( 'View entries', 'wpforms-lite' ), esc_html__( 'Entries', 'wpforms-lite' ) ); } // Preview. if ( wpforms_current_user_can( 'view_form_single', $form->ID ) ) { $row_actions['preview_'] = sprintf( '<a href="%s" title="%s" target="_blank" rel="noopener noreferrer">%s</a>', esc_url( wpforms_get_form_preview_url( $form->ID ) ), esc_attr__( 'View preview', 'wpforms-lite' ), esc_html__( 'Preview', 'wpforms-lite' ) ); } // Duplicate. if ( wpforms_current_user_can( 'create_forms' ) && wpforms_current_user_can( 'view_form_single', $form->ID ) ) { $row_actions['duplicate'] = sprintf( '<a href="%s" title="%s">%s</a>', esc_url( wp_nonce_url( add_query_arg( array( 'action' => 'duplicate', 'form_id' => $form->ID, ), admin_url( 'admin.php?page=wpforms-overview' ) ), 'wpforms_duplicate_form_nonce' ) ), esc_attr__( 'Duplicate this form', 'wpforms-lite' ), esc_html__( 'Duplicate', 'wpforms-lite' ) ); } // Delete. if ( wpforms_current_user_can( 'delete_form_single', $form->ID ) ) { $row_actions['delete'] = sprintf( '<a href="%s" title="%s">%s</a>', esc_url( wp_nonce_url( add_query_arg( array( 'action' => 'delete', 'form_id' => $form->ID, ), admin_url( 'admin.php?page=wpforms-overview' ) ), 'wpforms_delete_form_nonce' ) ), esc_attr__( 'Delete this form', 'wpforms-lite' ), esc_html__( 'Delete', 'wpforms-lite' ) ); } return $this->row_actions( apply_filters( 'wpforms_overview_row_actions', $row_actions, $form ) ); } /** * Define bulk actions available for our table listing. * * @since 1.0.0 * * @return array */ public function get_bulk_actions() { $actions = array(); if ( wpforms_current_user_can( 'delete_entries' ) ) { $actions = array( 'delete' => esc_html__( 'Delete', 'wpforms-lite' ), ); } return $actions; } /** * Message to be displayed when there are no forms. * * @since 1.0.0 */ public function no_items() { printf( wp_kses( /* translators: %s - WPForms Builder page. */ __( 'Whoops, you haven\'t created a form yet. Want to <a href="%s">give it a go</a>?', 'wpforms-lite' ), array( 'a' => array( 'href' => array(), ), ) ), esc_url( admin_url( 'admin.php?page=wpforms-builder' ) ) ); } /** * Fetch and setup the final data for the table. * * @since 1.0.0 */ public function prepare_items() { // Setup the columns. $columns = $this->get_columns(); // Hidden columns (none). $hidden = array(); // Define which columns can be sorted - form name, date. $sortable = array( 'form_name' => array( 'title', false ), 'created' => array( 'date', false ), ); // Set column headers. $this->_column_headers = array( $columns, $hidden, $sortable ); // Get forms. $total = wp_count_posts( 'wpforms' )->publish; $page = $this->get_pagenum(); $order = isset( $_GET['order'] ) ? $_GET['order'] : 'DESC'; $orderby = isset( $_GET['orderby'] ) ? $_GET['orderby'] : 'ID'; $per_page = $this->get_items_per_page( 'wpforms_forms_per_page', $this->per_page ); $args = array( 'orderby' => $orderby, 'order' => $order, 'nopaging' => false, 'posts_per_page' => $per_page, 'paged' => $page, 'no_found_rows' => false, 'post_status' => 'publish', ); $data = wpforms()->form->get( '', $args ); // Giddy up. $this->items = $data; // Finalize pagination. $this->set_pagination_args( array( 'total_items' => $total, 'per_page' => $per_page, 'total_pages' => ceil( $total / $per_page ), ) ); } /** * Extending the `display_rows()` method in order to add hooks. * * @since 1.5.6 */ public function display_rows() { do_action( 'wpforms_admin_overview_before_rows', $this ); parent::display_rows(); do_action( 'wpforms_admin_overview_after_rows', $this ); } } admin/class-menu.php 0000666 00000015334 15213301445 0010424 0 ustar 00 <?php /** * Register menu elements and do other global tasks. * * @since 1.0.0 */ class WPForms_Admin_Menu { /** * Primary class constructor. * * @since 1.0.0 */ public function __construct() { // Let's make some menus. add_action( 'admin_menu', array( $this, 'register_menus' ), 9 ); add_action( 'admin_head', array( $this, 'hide_wpforms_submenu_items' ) ); // Plugins page settings link. add_filter( 'plugin_action_links_' . plugin_basename( WPFORMS_PLUGIN_DIR . 'wpforms.php' ), array( $this, 'settings_link' ), 10 ); } /** * Register our menus. * * @since 1.0.0 */ public function register_menus() { $manage_cap = wpforms_get_capability_manage_options(); $access = wpforms()->get( 'access' ); // Default Forms top level menu item. add_menu_page( esc_html__( 'WPForms', 'wpforms-lite' ), esc_html__( 'WPForms', 'wpforms-lite' ), $access->get_menu_cap( 'view_forms' ), 'wpforms-overview', array( $this, 'admin_page' ), 'data:image/svg+xml;base64,' . base64_encode( '<svg width="1792" height="1792" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg"><path fill="#9ea3a8" d="M643 911v128h-252v-128h252zm0-255v127h-252v-127h252zm758 511v128h-341v-128h341zm0-256v128h-672v-128h672zm0-255v127h-672v-127h672zm135 860v-1240q0-8-6-14t-14-6h-32l-378 256-210-171-210 171-378-256h-32q-8 0-14 6t-6 14v1240q0 8 6 14t14 6h1240q8 0 14-6t6-14zm-855-1110l185-150h-406zm430 0l221-150h-406zm553-130v1240q0 62-43 105t-105 43h-1240q-62 0-105-43t-43-105v-1240q0-62 43-105t105-43h1240q62 0 105 43t43 105z"/></svg>' ), apply_filters( 'wpforms_menu_position', '57.7' ) ); // All Forms sub menu item. add_submenu_page( 'wpforms-overview', esc_html__( 'WPForms', 'wpforms-lite' ), esc_html__( 'All Forms', 'wpforms-lite' ), $access->get_menu_cap( 'view_forms' ), 'wpforms-overview', array( $this, 'admin_page' ) ); // Add New sub menu item. add_submenu_page( 'wpforms-overview', esc_html__( 'WPForms Builder', 'wpforms-lite' ), esc_html__( 'Add New', 'wpforms-lite' ), $access->get_menu_cap( array( 'create_forms', 'edit_forms' ) ), 'wpforms-builder', array( $this, 'admin_page' ) ); // Entries sub menu item. add_submenu_page( 'wpforms-overview', esc_html__( 'Form Entries', 'wpforms-lite' ), esc_html__( 'Entries', 'wpforms-lite' ), $access->get_menu_cap( 'view_entries' ), 'wpforms-entries', array( $this, 'admin_page' ) ); do_action_deprecated( 'wpform_admin_menu', array( $this ), '1.5.5 of the WPForms plugin', 'wpforms_admin_menu' ); do_action( 'wpforms_admin_menu', $this ); // Settings sub menu item. add_submenu_page( 'wpforms-overview', esc_html__( 'WPForms Settings', 'wpforms-lite' ), esc_html__( 'Settings', 'wpforms-lite' ), $manage_cap, 'wpforms-settings', array( $this, 'admin_page' ) ); // Tools sub menu item. add_submenu_page( 'wpforms-overview', esc_html__( 'WPForms Tools', 'wpforms-lite' ), esc_html__( 'Tools', 'wpforms-lite' ), $access->get_menu_cap( array( 'create_forms', 'view_forms', 'view_entries' ) ), 'wpforms-tools', array( $this, 'admin_page' ) ); // Hidden placeholder paged used for misc content. add_submenu_page( 'wpforms-settings', esc_html__( 'WPForms', 'wpforms-lite' ), esc_html__( 'Info', 'wpforms-lite' ), $access->get_menu_cap( 'any' ), 'wpforms-page', array( $this, 'admin_page' ) ); // Addons submenu page. add_submenu_page( 'wpforms-overview', esc_html__( 'WPForms Addons', 'wpforms-lite' ), '<span style="color:#f18500">' . esc_html__( 'Addons', 'wpforms-lite' ) . '</span>', $manage_cap, 'wpforms-addons', array( $this, 'admin_page' ) ); // Analytics submenu page. add_submenu_page( 'wpforms-overview', esc_html__( 'Analytics', 'wpforms-lite' ), esc_html__( 'Analytics', 'wpforms-lite' ), $manage_cap, WPForms\Admin\Pages\Analytics::SLUG, array( $this, 'admin_page' ) ); // SMTP submenu page. add_submenu_page( 'wpforms-overview', esc_html__( 'SMTP', 'wpforms-lite' ), esc_html__( 'SMTP', 'wpforms-lite' ), $manage_cap, WPForms\Admin\Pages\SMTP::SLUG, array( $this, 'admin_page' ) ); // About submenu page. add_submenu_page( 'wpforms-overview', esc_html__( 'About WPForms', 'wpforms-lite' ), esc_html__( 'About Us', 'wpforms-lite' ), $access->get_menu_cap( 'any' ), WPForms_About::SLUG, array( $this, 'admin_page' ) ); // Community submenu page. add_submenu_page( 'wpforms-overview', esc_html__( 'Community', 'wpforms-lite' ), esc_html__( 'Community', 'wpforms-lite' ), $manage_cap, WPForms\Admin\Pages\Community::SLUG, array( $this, 'admin_page' ) ); } /** * Hide "Add New" admin menu item if a user can't create forms. * * @since 1.5.8 */ public function hide_wpforms_submenu_items() { if ( wpforms_current_user_can( 'create_forms' ) ) { return; } global $submenu; if ( ! isset( $submenu['wpforms-overview'] ) ) { return; } foreach ( $submenu['wpforms-overview'] as $key => $item ) { if ( isset( $item[2] ) && 'wpforms-builder' === $item[2] ) { unset( $submenu['wpforms-overview'][ $key ] ); break; } } $this->hide_wpforms_menu_item(); } /** * Hide "WPForms" admin menu if it has no submenu items. * * @since 1.5.8 */ public function hide_wpforms_menu_item() { global $submenu, $menu; if ( ! empty( $submenu['wpforms-overview'] ) ) { return; } unset( $submenu['wpforms-overview'] ); foreach ( $menu as $key => $item ) { if ( isset( $item[2] ) && 'wpforms-overview' === $item[2] ) { unset( $menu[ $key ] ); break; } } } /** * Wrapper for the hook to render our custom settings pages. * * @since 1.0.0 */ public function admin_page() { do_action( 'wpforms_admin_page' ); } /** * Add settings link to the Plugins page. * * @since 1.3.9 * * @param array $links Plugin row links. * * @return array $links */ public function settings_link( $links ) { $custom['settings'] = sprintf( '<a href="%s" aria-label="%s">%s</a>', esc_url( add_query_arg( array( 'page' => 'wpforms-settings', ), admin_url( 'admin.php' ) ) ), esc_attr__( 'Go to WPForms Settings page', 'wpforms-lite' ), esc_html__( 'Settings', 'wpforms-lite' ) ); $custom['support'] = sprintf( '<a href="%1$s" aria-label="%2$s" style="font-weight:bold;">%3$s</a>', esc_url( add_query_arg( array( 'page' => 'wpforms-about', 'view' => 'versus', ), admin_url( 'admin.php' ) ) ), esc_attr__( 'Go to WPForms Lite vs Pro comparison page', 'wpforms-lite' ), esc_html__( 'Premium Support', 'wpforms-lite' ) ); return array_merge( $custom, (array) $links ); } } new WPForms_Admin_Menu(); admin/class-welcome.php 0000666 00000032723 15213301445 0011114 0 ustar 00 <?php /** * Welcome page class. * * This page is shown when the plugin is activated. * * @since 1.0.0 */ class WPForms_Welcome { /** * Hidden welcome page slug. * * @since 1.5.6 */ const SLUG = 'wpforms-getting-started'; /** * Primary class constructor. * * @since 1.0.0 */ public function __construct() { add_action( 'plugins_loaded', array( $this, 'hooks' ) ); } /** * Register all WP hooks. * * @since 1.5.6 */ public function hooks() { // If user is in admin ajax or doing cron, return. if ( wp_doing_ajax() || wp_doing_cron() ) { return; } // If user cannot manage_options, return. if ( ! wpforms_current_user_can() ) { return; } add_action( 'admin_menu', array( $this, 'register' ) ); add_action( 'admin_head', array( $this, 'hide_menu' ) ); add_action( 'admin_init', array( $this, 'redirect' ), 9999 ); } /** * Register the pages to be used for the Welcome screen (and tabs). * * These pages will be removed from the Dashboard menu, so they will * not actually show. Sneaky, sneaky. * * @since 1.0.0 */ public function register() { // Getting started - shows after installation. add_dashboard_page( esc_html__( 'Welcome to WPForms', 'wpforms-lite' ), esc_html__( 'Welcome to WPForms', 'wpforms-lite' ), apply_filters( 'wpforms_welcome_cap', wpforms_get_capability_manage_options() ), self::SLUG, array( $this, 'output' ) ); } /** * Removed the dashboard pages from the admin menu. * * This means the pages are still available to us, but hidden. * * @since 1.0.0 */ public function hide_menu() { remove_submenu_page( 'index.php', self::SLUG ); } /** * Welcome screen redirect. * * This function checks if a new install or update has just occurred. If so, * then we redirect the user to the appropriate page. * * @since 1.0.0 */ public function redirect() { // Check if we should consider redirection. if ( ! get_transient( 'wpforms_activation_redirect' ) ) { return; } // If we are redirecting, clear the transient so it only happens once. delete_transient( 'wpforms_activation_redirect' ); // Check option to disable welcome redirect. if ( get_option( 'wpforms_activation_redirect', false ) ) { return; } // Only do this for single site installs. if ( isset( $_GET['activate-multi'] ) || is_network_admin() ) { // WPCS: CSRF ok. return; } // Check if this is an update or first install. $upgrade = get_option( 'wpforms_version_upgraded_from' ); if ( ! $upgrade ) { // Initial install. wp_safe_redirect( admin_url( 'index.php?page=' . self::SLUG ) ); exit; } } /** * Getting Started screen. Shows after first install. * * @since 1.0.0 */ public function output() { $class = wpforms()->pro ? 'pro' : 'lite'; ?> <div id="wpforms-welcome" class="<?php echo sanitize_html_class( $class ); ?>"> <div class="container"> <div class="intro"> <div class="sullie"> <img src="<?php echo WPFORMS_PLUGIN_URL; ?>assets/images/sullie.png" alt="<?php esc_attr_e( 'Sullie the WPForms mascot', 'wpforms-lite' ); ?>"> </div> <div class="block"> <h1><?php esc_html_e( 'Welcome to WPForms', 'wpforms-lite' ); ?></h1> <h6><?php esc_html_e( 'Thank you for choosing WPForms - the most powerful drag & drop WordPress form builder in the market.', 'wpforms-lite' ); ?></h6> </div> <a href="#" class="play-video" title="<?php esc_attr_e( 'Watch how to create your first form', 'wpforms-lite' ); ?>"> <img src="<?php echo WPFORMS_PLUGIN_URL; ?>assets/images/welcome-video.png" alt="<?php esc_attr_e( 'Watch how to create your first form', 'wpforms-lite' ); ?>" class="video-thumbnail"> </a> <div class="block"> <h6><?php esc_html_e( 'WPForms makes it easy to create forms in WordPress. You can watch the video tutorial or read our guide on how create your first form.', 'wpforms-lite' ); ?></h6> <div class="button-wrap wpforms-clear"> <div class="left"> <a href="<?php echo esc_url( admin_url( 'admin.php?page=wpforms-builder' ) ); ?>" class="wpforms-btn wpforms-btn-block wpforms-btn-lg wpforms-btn-orange"> <?php esc_html_e( 'Create Your First Form', 'wpforms-lite' ); ?> </a> </div> <div class="right"> <a href="https://wpforms.com/docs/creating-first-form/?utm_source=WordPress&utm_medium=link&utm_campaign=liteplugin" class="wpforms-btn wpforms-btn-block wpforms-btn-lg wpforms-btn-grey" target="_blank" rel="noopener noreferrer"> <?php esc_html_e( 'Read the Full Guide', 'wpforms-lite' ); ?> </a> </div> </div> </div> </div><!-- /.intro --> <?php do_action( 'wpforms_welcome_intro_after' ); ?> <div class="features"> <div class="block"> <h1><?php esc_html_e( 'WPForms Features & Addons', 'wpforms-lite' ); ?></h1> <h6><?php esc_html_e( 'WPForms is both easy to use and extremely powerful. We have tons of helpful features that allow us to give you everything you need from a form builder.', 'wpforms-lite' ); ?></h6> <div class="feature-list wpforms-clear"> <div class="feature-block first"> <img src="<?php echo WPFORMS_PLUGIN_URL; ?>assets/images/welcome-feature-icon-1.png"> <h5><?php esc_html_e( 'Drag & Drop Form Builder', 'wpforms-lite' ); ?></h5> <p><?php esc_html_e( 'Easily create an amazing form in just a few minutes without writing any code.', 'wpforms-lite' ); ?></p> </div> <div class="feature-block last"> <img src="<?php echo WPFORMS_PLUGIN_URL; ?>assets/images/welcome-feature-icon-2.png"> <h5><?php esc_html_e( 'Form Templates', 'wpforms-lite' ); ?></h5> <p><?php esc_html_e( 'Start with pre-built form templates to save even more time.', 'wpforms-lite' ); ?></p> </div> <div class="feature-block first"> <img src="<?php echo WPFORMS_PLUGIN_URL; ?>assets/images/welcome-feature-icon-3.png"> <h5><?php esc_html_e( 'Responsive Mobile Friendly', 'wpforms-lite' ); ?></h5> <p><?php esc_html_e( 'WPForms is 100% responsive meaning it works on mobile, tablets & desktop.', 'wpforms-lite' ); ?></p> </div> <div class="feature-block last"> <img src="<?php echo WPFORMS_PLUGIN_URL; ?>assets/images/welcome-feature-icon-4.png"> <h5><?php esc_html_e( 'Smart Conditional Logic', 'wpforms-lite' ); ?></h5> <p><?php esc_html_e( 'Easily create high performance forms with our smart conditional logic.', 'wpforms-lite' ); ?></p> </div> <div class="feature-block first"> <img src="<?php echo WPFORMS_PLUGIN_URL; ?>assets/images/welcome-feature-icon-5.png"> <h5><?php esc_html_e( 'Instant Notifications', 'wpforms-lite' ); ?></h5> <p><?php esc_html_e( 'Respond to leads quickly with our instant form notification feature for your team.', 'wpforms-lite' ); ?></p> </div> <div class="feature-block last"> <img src="<?php echo WPFORMS_PLUGIN_URL; ?>assets/images/welcome-feature-icon-6.png"> <h5><?php esc_html_e( 'Entry Management', 'wpforms-lite' ); ?></h5> <p><?php esc_html_e( 'View all your leads in one place to streamline your workflow.', 'wpforms-lite' ); ?></p> </div> <div class="feature-block first"> <img src="<?php echo WPFORMS_PLUGIN_URL; ?>assets/images/welcome-feature-icon-7.png"> <h5><?php esc_html_e( 'Payments Made Easy', 'wpforms-lite' ); ?></h5> <p><?php esc_html_e( 'Easily collect payments, donations, and online orders without hiring a developer.', 'wpforms-lite' ); ?></p> </div> <div class="feature-block last"> <img src="<?php echo WPFORMS_PLUGIN_URL; ?>assets/images/welcome-feature-icon-8.png"> <h5><?php esc_html_e( 'Marketing & Subscriptions', 'wpforms-lite' ); ?></h5> <p><?php esc_html_e( 'Create subscription forms and connect with your email marketing service.', 'wpforms-lite' ); ?></p> </div> <div class="feature-block first"> <img src="<?php echo WPFORMS_PLUGIN_URL; ?>assets/images/welcome-feature-icon-9.png"> <h5><?php esc_html_e( 'Easy to Embed', 'wpforms-lite' ); ?></h5> <p><?php esc_html_e( 'Easily embed your forms in blog posts, pages, sidebar widgets, footer, etc.', 'wpforms-lite' ); ?></p> </div> <div class="feature-block last"> <img src="<?php echo WPFORMS_PLUGIN_URL; ?>assets/images/welcome-feature-icon-10.png"> <h5><?php esc_html_e( 'Spam Protection', 'wpforms-lite' ); ?></h5> <p><?php esc_html_e( 'Our smart captcha and honeypot automatically prevent spam submissions.', 'wpforms-lite' ); ?></p> </div> </div> <div class="button-wrap"> <a href="https://wpforms.com/features/?utm_source=WordPress&utm_medium=link&utm_campaign=liteplugin&utm_content=welcome" class="wpforms-btn wpforms-btn-lg wpforms-btn-grey" rel="noopener noreferrer" target="_blank"> <?php esc_html_e( 'See All Features', 'wpforms-lite' ); ?> </a> </div> </div> </div><!-- /.features --> <div class="upgrade-cta upgrade"> <div class="block wpforms-clear"> <div class="left"> <h2><?php esc_html_e( 'Upgrade to PRO', 'wpforms-lite' ); ?></h2> <ul> <li><span class="dashicons dashicons-yes"></span> <?php esc_html_e( 'PayPal', 'wpforms-lite' ); ?></li> <li><span class="dashicons dashicons-yes"></span> <?php esc_html_e( 'Post Submissions', 'wpforms-lite' ); ?></li> <li><span class="dashicons dashicons-yes"></span> <?php esc_html_e( 'Stripe', 'wpforms-lite' ); ?></li> <li><span class="dashicons dashicons-yes"></span> <?php esc_html_e( 'Signatures', 'wpforms-lite' ); ?></li> <li><span class="dashicons dashicons-yes"></span> <?php esc_html_e( 'User Registration', 'wpforms-lite' ); ?></li> <li><span class="dashicons dashicons-yes"></span> <?php esc_html_e( 'Form Abandonment', 'wpforms-lite' ); ?></li> <li><span class="dashicons dashicons-yes"></span> <?php esc_html_e( 'Geolocation', 'wpforms-lite' ); ?></li> <li><span class="dashicons dashicons-yes"></span> <?php esc_html_e( 'Polls', 'wpforms-lite' ); ?></li> <li><span class="dashicons dashicons-yes"></span> <?php esc_html_e( 'Zapier', 'wpforms-lite' ); ?></li> <li><span class="dashicons dashicons-yes"></span> <?php esc_html_e( 'Unlimited Sites', 'wpforms-lite' ); ?></li> <li><span class="dashicons dashicons-yes"></span> <?php esc_html_e( 'Surveys', 'wpforms-lite' ); ?></li> <li><span class="dashicons dashicons-yes"></span> <?php esc_html_e( 'Priority Support', 'wpforms-lite' ); ?></li> </ul> </div> <div class="right"> <h2><span><?php esc_html_e( 'PRO', 'wpforms-lite' ); ?></span></h2> <div class="price"> <span class="amount">199</span><br> <span class="term"><?php esc_html_e( 'per year', 'wpforms-lite' ); ?></span> </div> <a href="<?php echo esc_url( wpforms_admin_upgrade_link( 'welcome' ) ); ?>" rel="noopener noreferrer" target="_blank" class="wpforms-btn wpforms-btn-block wpforms-btn-lg wpforms-btn-orange wpforms-upgrade-modal"> <?php esc_html_e( 'Upgrade Now', 'wpforms-lite' ); ?> </a> </div> </div> </div> <div class="testimonials upgrade"> <div class="block"> <h1><?php esc_html_e( 'Testimonials', 'wpforms-lite' ); ?></h1> <div class="testimonial-block wpforms-clear"> <img src="<?php echo WPFORMS_PLUGIN_URL; ?>assets/images/welcome-testimonial-bill.jpg"> <p><?php esc_html_e( 'WPForms is by far the easiest form plugin to use. My clients love it – it’s one of the few plugins they can use without any training. As a developer I appreciate how fast, modern, clean and extensible it is.', 'wpforms-lite' ); ?> <p> <p><strong>Bill Erickson</strong>, Erickson Web Consulting</p> </div> <div class="testimonial-block wpforms-clear"> <img src="<?php echo WPFORMS_PLUGIN_URL; ?>assets/images/welcome-testimonial-david.jpg"> <p><?php esc_html_e( 'As a business owner, time is my most valuable asset. WPForms allow me to create smart online forms with just a few clicks. With their pre-built form templates and the drag & drop builder, I can create a new form that works in less than 2 minutes without writing a single line of code. Well worth the investment.', 'wpforms-lite' ); ?> <p> <p><strong>David Henzel</strong>, MaxCDN</p> </div> </div> </div><!-- /.testimonials --> <div class="footer"> <div class="block wpforms-clear"> <div class="button-wrap wpforms-clear"> <div class="left"> <a href="<?php echo esc_url( admin_url( 'admin.php?page=wpforms-builder' ) ); ?>" class="wpforms-btn wpforms-btn-block wpforms-btn-lg wpforms-btn-orange"> <?php esc_html_e( 'Create Your First Form', 'wpforms-lite' ); ?> </a> </div> <div class="right"> <a href="<?php echo esc_url( wpforms_admin_upgrade_link( 'welcome' ) ); ?>" target="_blank" rel="noopener noreferrer" class="wpforms-btn wpforms-btn-block wpforms-btn-lg wpforms-btn-trans-green wpforms-upgrade-modal"> <span class="underline"> <?php esc_html_e( 'Upgrade to WPForms Pro', 'wpforms-lite' ); ?> <span class="dashicons dashicons-arrow-right"></span> </span> </a> </div> </div> </div> </div><!-- /.footer --> </div><!-- /.container --> </div><!-- /#wpforms-welcome --> <?php } } new WPForms_Welcome(); admin/settings-api.php 0000666 00000032475 15213301445 0010771 0 ustar 00 <?php /** * Settings API. * * @since 1.3.7 */ /** * Settings output wrapper. * * @since 1.3.9 * * @param array $args * * @return string */ function wpforms_settings_output_field( $args ) { // Define default callback for this field type. $callback = ! empty( $args['type'] ) && function_exists( 'wpforms_settings_' . $args['type'] . '_callback' ) ? 'wpforms_settings_' . $args['type'] . '_callback' : 'wpforms_settings_missing_callback'; // Allow custom callback to be provided via arg. if ( ! empty( $args['callback'] ) && function_exists( $args['callback'] ) ) { $callback = $args['callback']; } // Store returned markup from callback. $field = call_user_func( $callback, $args ); // Allow arg to bypass standard field wrap for custom display. if ( ! empty( $args['wrap'] ) ) { return $field; } // Custom row classes. $class = ! empty( $args['class'] ) ? wpforms_sanitize_classes( (array) $args['class'], true ) : ''; // Build standard field markup and return. $output = '<div class="wpforms-setting-row wpforms-setting-row-' . sanitize_html_class( $args['type'] ) . ' wpforms-clear ' . $class . '" id="wpforms-setting-row-' . wpforms_sanitize_key( $args['id'] ) . '">'; if ( ! empty( $args['name'] ) && empty( $args['no_label'] ) ) { $output .= '<span class="wpforms-setting-label">'; $output .= '<label for="wpforms-setting-' . wpforms_sanitize_key( $args['id'] ) . '">' . esc_html( $args['name'] ) . '</label>'; $output .= '</span>'; } $output .= '<span class="wpforms-setting-field">'; $output .= $field; if ( ! empty( $args['desc_after'] ) ) { $output .= '<div class="wpforms-clear">' . $args['desc_after'] . '</div>'; } $output .= '</span>'; $output .= '</div>'; return $output; } /** * Missing Callback. * * If a function is missing for settings callbacks alert the user. * * @since 1.3.9 * * @param array $args Arguments passed by the setting. * * @return string */ function wpforms_settings_missing_callback( $args ) { return sprintf( /* translators: %s - ID of a setting. */ esc_html__( 'The callback function used for the %s setting is missing.', 'wpforms-lite' ), '<strong>' . wpforms_sanitize_key( $args['id'] ) . '</strong>' ); } /** * Settings content field callback. * * @since 1.3.9 * * @param array $args * * @return string */ function wpforms_settings_content_callback( $args ) { return ! empty( $args['content'] ) ? $args['content'] : ''; } /** * Settings license field callback. * * @since 1.3.9 * * @param array $args * * @return string */ function wpforms_settings_license_callback( $args ) { // Lite users don't need to worry about license keys. if ( ! wpforms()->pro || ! class_exists( 'WPForms_License', false ) ) { $output = '<p>' . esc_html__( 'You\'re using WPForms Lite - no license needed. Enjoy!', 'wpforms-lite' ) . ' 🙂</p>'; $output .= '<p>' . sprintf( wp_kses( /* translators: %s - WPForms.com upgrade URL. */ __( 'To unlock more features consider <strong><a href="%s" target="_blank" rel="noopener noreferrer" class="wpforms-upgrade-modal">upgrading to PRO</a></strong>.', 'wpforms-lite' ), array( 'a' => array( 'href' => array(), 'class' => array(), 'target' => array(), 'rel' => array(), ), 'strong' => array(), ) ), esc_url( wpforms_admin_upgrade_link( 'settings-license' ) ) ) . '</p>'; $output .= '<p class="discount-note">' . wp_kses( __( 'As a valued WPForms Lite user you receive <strong>50% off</strong>, automatically applied at checkout!', 'wpforms-lite' ), array( 'strong' => array(), 'br' => array(), ) ) . '</p>'; $output .= '<hr><p>' . esc_html__( 'Already purchased? Simply enter your license key below to connect with WPForms PRO!', 'wpforms-lite' ) . '</p>'; $output .= '<p>'; $output .= '<input type="password" id="wpforms-settings-upgrade-license-key" placeholder="' . esc_attr__( 'Paste license key here', 'wpforms-lite' ) . '" value="" />'; $output .= '<button type="button" class="wpforms-btn wpforms-btn-md wpforms-btn-orange" id="wpforms-settings-connect-btn">' . esc_attr__( 'Connect', 'wpforms-lite' ) . '</button>'; $output .= '</p>'; return $output; } $key = wpforms_setting( 'key', '', 'wpforms_license' ); $type = wpforms_get_license_type(); $output = '<input type="password" id="wpforms-setting-license-key" value="' . esc_attr( $key ) . '" />'; $output .= '<button id="wpforms-setting-license-key-verify" class="wpforms-btn wpforms-btn-md wpforms-btn-orange">' . esc_html__( 'Verify Key', 'wpforms-lite' ) . '</button>'; // Offer option to deactivate the key. $class = empty( $key ) ? 'wpforms-hide' : ''; $output .= '<button id="wpforms-setting-license-key-deactivate" class="wpforms-btn wpforms-btn-md wpforms-btn-light-grey ' . $class . '">' . esc_html__( 'Deactivate Key', 'wpforms-lite' ) . '</button>'; // If we have previously looked up the license type, display it. $class = empty( $type ) ? 'wpforms-hide' : ''; $output .= '<p class="type ' . $class . '">' . sprintf( /* translators: $s - license type. */ esc_html__( 'Your license key type is %s.', 'wpforms-lite' ), '<strong>' . esc_html( $type ) . '</strong>' ) . '</p>'; $output .= '<p class="desc ' . $class . '">' . wp_kses( __( 'If your license has been upgraded or is incorrect, <a href="#" id="wpforms-setting-license-key-refresh">click here to force a refresh</a>.', 'wpforms-lite' ), array( 'a' => array( 'href' => array(), 'id' => array(), ), ) ) . '</p>'; return $output; } /** * Settings text input field callback. * * @since 1.3.9 * * @param array $args * * @return string */ function wpforms_settings_text_callback( $args ) { $default = isset( $args['default'] ) ? esc_html( $args['default'] ) : ''; $value = wpforms_setting( $args['id'], $default ); $id = wpforms_sanitize_key( $args['id'] ); $output = '<input type="text" id="wpforms-setting-' . $id . '" name="' . $id . '" value="' . esc_attr( $value ) . '">'; if ( ! empty( $args['desc'] ) ) { $output .= '<p class="desc">' . wp_kses_post( $args['desc'] ) . '</p>'; } return $output; } /** * Settings number input field callback. * * @since 1.5.3 * * @param array $args Setting field arguments. * * @return string */ function wpforms_settings_number_callback( $args ) { $default = isset( $args['default'] ) ? esc_html( $args['default'] ) : ''; $id = 'wpforms-setting-' . wpforms_sanitize_key( $args['id'] ); $attr = array( 'value' => wpforms_setting( $args['id'], $default ), 'name' => wpforms_sanitize_key( $args['id'] ), ); $data = ! empty( $args['data'] ) ? $args['data'] : array(); if ( ! empty( $args['attr'] ) ) { $attr = array_merge( $attr, $args['attr'] ); } $output = sprintf( '<input type="number" %s>', wpforms_html_attributes( $id, array(), $data, $attr ) ); if ( ! empty( $args['desc'] ) ) { $output .= '<p class="desc">' . wp_kses_post( $args['desc'] ) . '</p>'; } return $output; } /** * Settings select field callback. * * @since 1.3.9 * * @param array $args * * @return string */ function wpforms_settings_select_callback( $args ) { $default = isset( $args['default'] ) ? esc_html( $args['default'] ) : ''; $value = wpforms_setting( $args['id'], $default ); $id = wpforms_sanitize_key( $args['id'] ); $select_name = $id; $class = ! empty( $args['choicesjs'] ) ? 'choicesjs-select' : ''; $choices = ! empty( $args['choicesjs'] ) ? true : false; $data = isset( $args['data'] ) ? (array) $args['data'] : array(); $attr = isset( $args['attr'] ) ? (array) $args['attr'] : array(); if ( $choices && ! empty( $args['search'] ) ) { $data['search'] = 'true'; } if ( ! empty( $args['placeholder'] ) ) { $data['placeholder'] = $args['placeholder']; } if ( $choices && ! empty( $args['multiple'] ) ) { $attr[] = 'multiple'; $select_name = $id . '[]'; } foreach ( $data as $name => $val ) { $data[ $name ] = 'data-' . sanitize_html_class( $name ) . '="' . esc_attr( $val ) . '"'; } $data = implode( ' ', $data ); $attr = implode( ' ', array_map( 'sanitize_html_class', $attr ) ); $output = $choices ? '<span class="choicesjs-select-wrap">' : ''; $output .= '<select id="wpforms-setting-' . $id . '" name="' . $select_name . '" class="' . $class . '"' . $data . $attr . '>'; foreach ( $args['options'] as $option => $name ) { if ( empty( $args['selected'] ) ) { $selected = selected( $value, $option, false ); } else { $selected = is_array( $args['selected'] ) && in_array( $option, $args['selected'], true ) ? 'selected' : ''; } $output .= '<option value="' . esc_attr( $option ) . '" ' . $selected . '>' . esc_html( $name ) . '</option>'; } $output .= '</select>'; $output .= $choices ? '</span>' : ''; if ( ! empty( $args['desc'] ) ) { $output .= '<p class="desc">' . wp_kses_post( $args['desc'] ) . '</p>'; } return $output; } /** * Settings checkbox field callback. * * @since 1.3.9 * * @param array $args * * @return string */ function wpforms_settings_checkbox_callback( $args ) { $value = wpforms_setting( $args['id'] ); $id = wpforms_sanitize_key( $args['id'] ); $checked = ! empty( $value ) ? checked( 1, $value, false ) : ''; $output = '<input type="checkbox" id="wpforms-setting-' . $id . '" name="' . $id . '" ' . $checked . '>'; if ( ! empty( $args['desc'] ) ) { $output .= '<p class="desc">' . wp_kses_post( $args['desc'] ) . '</p>'; } return $output; } /** * Settings radio field callback. * * @since 1.3.9 * * @param array $args * * @return string */ function wpforms_settings_radio_callback( $args ) { $default = isset( $args['default'] ) ? esc_html( $args['default'] ) : ''; $value = wpforms_setting( $args['id'], $default ); $id = wpforms_sanitize_key( $args['id'] ); $output = ''; $x = 1; foreach ( $args['options'] as $option => $name ) { $checked = checked( $value, $option, false ); $output .= '<label for="wpforms-setting-' . $id . '[' . $x . ']" class="option-' . sanitize_html_class( $option ) . '">'; $output .= '<input type="radio" id="wpforms-setting-' . $id . '[' . $x . ']" name="' . $id . '" value="' . esc_attr( $option ) . '" ' . $checked . '>'; $output .= esc_html( $name ); $output .= '</label>'; $x ++; } if ( ! empty( $args['desc'] ) ) { $output .= '<p class="desc">' . wp_kses_post( $args['desc'] ) . '</p>'; } return $output; } /** * Settings image upload field callback. * * @since 1.3.9 * * @param array $args * * @return string */ function wpforms_settings_image_callback( $args ) { $default = isset( $args['default'] ) ? esc_html( $args['default'] ) : ''; $value = wpforms_setting( $args['id'], $default ); $id = wpforms_sanitize_key( $args['id'] ); $output = ''; if ( ! empty( $value ) ) { $output .= '<img src="' . esc_url_raw( $value ) . '">'; } $output .= '<input type="text" id="wpforms-setting-' . $id . '" name="' . $id . '" value="' . esc_url_raw( $value ) . '">'; $output .= '<button class="wpforms-btn wpforms-btn-md wpforms-btn-light-grey">' . esc_html__( 'Upload Image', 'wpforms-lite' ) . '</button>'; if ( ! empty( $args['desc'] ) ) { $output .= '<p class="desc">' . wp_kses_post( $args['desc'] ) . '</p>'; } return $output; } /** * Settings color picker field callback. * * @since 1.3.9 * * @param array $args * * @return string */ function wpforms_settings_color_callback( $args ) { $default = isset( $args['default'] ) ? esc_html( $args['default'] ) : ''; $value = wpforms_setting( $args['id'], $default ); $id = wpforms_sanitize_key( $args['id'] ); $output = '<input type="text" id="wpforms-setting-' . $id . '" class="wpforms-color-picker" name="' . $id . '" value="' . esc_attr( $value ) . '">'; if ( ! empty( $args['desc'] ) ) { $output .= '<p class="desc">' . wp_kses_post( $args['desc'] ) . '</p>'; } return $output; } /** * Settings providers field callback - this is for the Integrations tab. * * @since 1.3.9 * * @param array $args * * @return string */ function wpforms_settings_providers_callback( $args ) { $active = wpforms_get_providers_available(); $providers = wpforms_get_providers_options(); $output = '<div id="wpforms-settings-providers">'; ob_start(); do_action( 'wpforms_settings_providers', $active, $providers ); $output .= ob_get_clean(); $output .= '</div>'; return $output; } /** * Settings field columns callback. * * @since 1.5.8 * * @param array $args Arguments passed by the setting. * * @return string */ function wpforms_settings_columns_callback( $args ) { if ( empty( $args['columns'] ) || ! is_array( $args['columns'] ) ) { return ''; } $output = '<div class="wpforms-setting-columns">'; foreach ( $args['columns'] as $column ) { // Define default callback for this field type. $callback = ! empty( $column['type'] ) ? 'wpforms_settings_' . $column['type'] . '_callback' : ''; // Allow custom callback to be provided via arg. if ( ! empty( $column['callback'] ) ) { $callback = $column['callback']; } $output .= '<div class="wpforms-setting-column">'; if ( ! empty( $column['name'] ) ) { $output .= '<label><b>' . wp_kses_post( $column['name'] ) . '</b></label>'; } if ( function_exists( $callback ) ) { $output .= call_user_func( $callback, $column ); } $output .= '</div>'; } $output .= '</div>'; return $output; } admin/importers/interface.php 0000666 00000001543 15213301445 0012336 0 ustar 00 <?php /** * Interface WPForms_Importer_Interface to handle common methods for all importers. * * @since 1.4.2 */ interface WPForms_Importer_Interface { /** * Define required properties. * * @since 1.4.2 */ public function init(); /** * Get ALL THE FORMS. * * @since 1.4.2 */ public function get_forms(); /** * Get a single form. * * @since 1.4.2 * * @param int $id Form ID. */ public function get_form( $id ); /** * Import a single form using AJAX. * * @since 1.4.2 */ public function import_form(); /** * Replace 3rd-party form provider tags/shortcodes with our own Smart Tags. * * @since 1.4.2 * * @param string $string Text to look for Smart Tags in. * @param array $fields List of fields to process Smart Tags in. * * @return string */ public function get_smarttags( $string, $fields ); } admin/importers/class-contact-form-7.php 0000666 00000041667 15213301445 0014254 0 ustar 00 <?php /** * Contact Form 7 Importer class. * * @since 1.4.2 */ class WPForms_Contact_Form_7 extends WPForms_Importer { /** * @inheritdoc */ public function init() { $this->name = 'Contact Form 7'; $this->slug = 'contact-form-7'; $this->path = 'contact-form-7/wp-contact-form-7.php'; } /** * @inheritdoc */ public function get_forms() { $forms_final = array(); if ( ! $this->is_active() ) { return $forms_final; } $forms = WPCF7_ContactForm::find( array( 'posts_per_page' => - 1, ) ); if ( ! empty( $forms ) ) { foreach ( $forms as $form ) { if ( ! empty( $form ) && ( $form instanceof WPCF7_ContactForm ) ) { $forms_final[ $form->id() ] = $form->title(); } } } return $forms_final; } /** * Get a single form. * * @since 1.4.2 * * @param int $id Form ID. * * @return WPCF7_ContactForm|bool */ public function get_form( $id ) { $form = WPCF7_ContactForm::find( array( 'posts_per_page' => 1, 'p' => $id, ) ); if ( ! empty( $form[0] ) && ( $form[0] instanceof WPCF7_ContactForm ) ) { return $form[0]; } return false; } /** * @inheritdoc */ public function import_form() { // Run a security check. check_ajax_referer( 'wpforms-admin', 'nonce' ); // Check for permissions. if ( ! wpforms_current_user_can( 'create_forms' ) ) { wp_send_json_error(); } // Define some basic information. $analyze = isset( $_POST['analyze'] ); $cf7_id = ! empty( $_POST['form_id'] ) ? (int) $_POST['form_id'] : 0; $cf7_form = $this->get_form( $cf7_id ); if ( ! $cf7_form ) { wp_send_json_error( array( 'error' => true, 'name' => esc_html__( 'Unknown Form', 'wpforms-lite' ), 'msg' => esc_html__( 'The form you are trying to import does not exist.', 'wpforms-lite' ), ) ); } $cf7_form_name = $cf7_form->title(); $cf7_fields = $cf7_form->scan_form_tags(); $cf7_properties = $cf7_form->get_properties(); $cf7_recaptcha = false; $fields_pro_plain = array( 'url', 'tel', 'date' ); $fields_pro_omit = array( 'file' ); $fields_unsupported = array( 'quiz', 'hidden' ); $upgrade_plain = array(); $upgrade_omit = array(); $unsupported = array(); $form = array( 'id' => '', 'field_id' => '', 'fields' => array(), 'settings' => array( 'form_title' => $cf7_form_name, 'form_desc' => '', 'submit_text' => esc_html__( 'Submit', 'wpforms-lite' ), 'submit_text_processing' => esc_html__( 'Sending', 'wpforms-lite' ), 'honeypot' => '1', 'notification_enable' => '1', 'notifications' => array( 1 => array( 'notification_name' => esc_html__( 'Notification 1', 'wpforms-lite' ), 'email' => '{admin_email}', /* translators: %s - form name. */ 'subject' => sprintf( esc_html__( 'New Entry: %s', 'wpforms-lite' ), $cf7_form_name ), 'sender_name' => get_bloginfo( 'name' ), 'sender_address' => '{admin_email}', 'replyto' => '', 'message' => '{all_fields}', ), ), 'confirmations' => array( 1 => array( 'type' => 'message', 'message' => esc_html__( 'Thanks for contacting us! We will be in touch with you shortly.', 'wpforms-lite' ), 'message_scroll' => '1', ), ), 'import_form_id' => $cf7_id, ), ); // If form does not contain fields, bail. if ( empty( $cf7_fields ) ) { wp_send_json_success( array( 'error' => true, 'name' => sanitize_text_field( $cf7_form_name ), 'msg' => esc_html__( 'No form fields found.', 'wpforms-lite' ), ) ); } // Convert fields. foreach ( $cf7_fields as $cf7_field ) { if ( ! $cf7_field instanceof WPCF7_FormTag ) { continue; } // Try to determine field label to use. $label = $this->get_field_label( $cf7_properties['form'], $cf7_field->type, $cf7_field->name ); // Next, check if field is unsupported. If supported make note and // then continue to the next field. if ( in_array( $cf7_field->basetype, $fields_unsupported, true ) ) { $unsupported[] = $label; continue; } // Now check if this install is Lite. If it is Lite and it's a // field type not included, make a note then continue to the next // field. if ( ! wpforms()->pro && in_array( $cf7_field->basetype, $fields_pro_plain, true ) ) { $upgrade_plain[] = $label; } if ( ! wpforms()->pro && in_array( $cf7_field->basetype, $fields_pro_omit, true ) ) { $upgrade_omit[] = $label; continue; } // Determine next field ID to assign. if ( empty( $form['fields'] ) ) { $field_id = 1; } else { $field_id = (int) max( array_keys( $form['fields'] ) ) + 1; } switch ( $cf7_field->basetype ) { // Plain text, email, URL, number, and textarea fields. case 'text': case 'email': case 'url': case 'number': case 'textarea': $type = $cf7_field->basetype; if ( 'url' === $type && ! wpforms()->pro ) { $type = 'text'; } $form['fields'][ $field_id ] = array( 'id' => $field_id, 'type' => $type, 'label' => $label, 'size' => 'medium', 'required' => $cf7_field->is_required() ? '1' : '', 'placeholder' => $this->get_field_placeholder_default( $cf7_field ), 'default_value' => $this->get_field_placeholder_default( $cf7_field, 'default' ), 'cf7_name' => $cf7_field->name, ); break; // Phone number field. case 'tel': $form['fields'][ $field_id ] = array( 'id' => $field_id, 'type' => 'phone', 'label' => $label, 'format' => 'international', 'size' => 'medium', 'required' => $cf7_field->is_required() ? '1' : '', 'placeholder' => $this->get_field_placeholder_default( $cf7_field ), 'default_value' => $this->get_field_placeholder_default( $cf7_field, 'default' ), 'cf7_name' => $cf7_field->name, ); break; // Date field. case 'date': $type = wpforms()->pro ? 'date-time' : 'text'; $form['fields'][ $field_id ] = array( 'id' => $field_id, 'type' => $type, 'label' => $label, 'format' => 'date', 'size' => 'medium', 'required' => $cf7_field->is_required() ? '1' : '', 'date_placeholder' => '', 'date_format' => 'm/d/Y', 'date_type' => 'datepicker', 'time_format' => 'g:i A', 'time_interval' => 30, 'cf7_name' => $cf7_field->name, ); break; // Select, radio, and checkbox fields. case 'select': case 'radio': case 'checkbox': $choices = array(); $options = (array) $cf7_field->labels; foreach ( $options as $option ) { $choices[] = array( 'label' => $option, 'value' => '', ); } $form['fields'][ $field_id ] = array( 'id' => $field_id, 'type' => $cf7_field->basetype, 'label' => $label, 'choices' => $choices, 'size' => 'medium', 'required' => $cf7_field->is_required() ? '1' : '', 'cf7_name' => $cf7_field->name, ); if ( 'select' === $cf7_field->basetype && $cf7_field->has_option( 'include_blank' ) ) { $form['fields'][ $field_id ]['placeholder'] = '---'; } break; // File upload field. case 'file': $extensions = ''; $max_size = ''; $file_types = $cf7_field->get_option( 'filetypes' ); $limit = $cf7_field->get_option( 'limit' ); if ( ! empty( $file_types[0] ) ) { $extensions = implode( ',', explode( '|', strtolower( preg_replace( '/[^A-Za-z0-9|]/', '', strtolower( $file_types[0] ) ) ) ) ); } if ( ! empty( $limit[0] ) ) { $limit = $limit[0]; $mb = ( strpos( $limit, 'm' ) !== false ); $kb = ( strpos( $limit, 'kb' ) !== false ); $limit = (int) preg_replace( '/[^0-9]/', '', $limit ); if ( $mb ) { $max_size = $limit; } elseif ( $kb ) { $max_size = round( $limit / 1024, 1 ); } else { $max_size = round( $limit / 1048576, 1 ); } } $form['fields'][ $field_id ] = array( 'id' => $field_id, 'type' => 'file-upload', 'label' => $label, 'size' => 'medium', 'extensions' => $extensions, 'max_size' => $max_size, 'required' => $cf7_field->is_required() ? '1' : '', 'cf7_name' => $cf7_field->name, ); break; // Acceptance field. case 'acceptance': $form['fields'][ $field_id ] = array( 'id' => $field_id, 'type' => 'checkbox', 'label' => esc_html__( 'Acceptance Field', 'wpforms-lite' ), 'choices' => array( 1 => array( 'label' => $label, 'value' => '', ), ), 'size' => 'medium', 'required' => '1', 'label_hide' => '1', 'cf7_name' => $cf7_field->name, ); break; // ReCAPTCHA field. case 'recaptcha': $cf7_recaptcha = true; } } // If we are only analyzing the form, we can stop here and return the // details about this form. if ( $analyze ) { wp_send_json_success( array( 'name' => $cf7_form_name, 'upgrade_plain' => $upgrade_plain, 'upgrade_omit' => $upgrade_omit, ) ); } // Settings. // Confirmation message. if ( ! empty( $cf7_properties['messages']['mail_sent_ok'] ) ) { $form['settings']['confirmation_message'] = $cf7_properties['messages']['mail_sent_ok']; } // ReCAPTCHA. if ( $cf7_recaptcha ) { // If the user has already defined v2 reCAPTCHA keys in the WPForms // settings, use those. $site_key = wpforms_setting( 'recaptcha-site-key', '' ); $secret_key = wpforms_setting( 'recaptcha-secret-key', '' ); $type = wpforms_setting( 'recaptcha-type', 'v2' ); // Try to abstract keys from CF7. if ( empty( $site_key ) || empty( $secret_key ) ) { $cf7_settings = get_option( 'wpcf7' ); if ( ! empty( $cf7_settings['recaptcha'] ) && is_array( $cf7_settings['recaptcha'] ) ) { foreach ( $cf7_settings['recaptcha'] as $key => $val ) { if ( ! empty( $key ) && ! empty( $val ) ) { $site_key = $key; $secret_key = $val; } } $wpforms_settings = get_option( 'wpforms_settings', array() ); $wpforms_settings['recaptcha-site-key'] = $site_key; $wpforms_settings['recaptcha-secret-key'] = $secret_key; update_option( 'wpforms_settings', $wpforms_settings ); } } // Don't enable reCAPTCHA if user had configured invisible reCAPTCHA. if ( 'v2' === $type && ! empty( $site_key ) && ! empty( $secret_key ) ) { $form['settings']['recaptcha'] = '1'; } } // Setup email notifications. if ( ! empty( $cf7_properties['mail']['subject'] ) ) { $form['settings']['notifications'][1]['subject'] = $this->get_smarttags( $cf7_properties['mail']['subject'], $form['fields'] ); } if ( ! empty( $cf7_properties['mail']['recipient'] ) ) { $form['settings']['notifications'][1]['email'] = $this->get_smarttags( $cf7_properties['mail']['recipient'], $form['fields'] ); } if ( ! empty( $cf7_properties['mail']['body'] ) ) { $form['settings']['notifications'][1]['message'] = $this->get_smarttags( $cf7_properties['mail']['body'], $form['fields'] ); } if ( ! empty( $cf7_properties['mail']['additional_headers'] ) ) { $form['settings']['notifications'][1]['replyto'] = $this->get_replyto( $cf7_properties['mail']['additional_headers'], $form['fields'] ); } if ( ! empty( $cf7_properties['mail']['sender'] ) ) { $sender = $this->get_sender_details( $cf7_properties['mail']['sender'], $form['fields'] ); if ( $sender ) { $form['settings']['notifications'][1]['sender_name'] = $sender['name']; $form['settings']['notifications'][1]['sender_address'] = $sender['address']; } } if ( ! empty( $cf7_properties['mail_2'] ) && '1' == $cf7_properties['mail_2']['active'] ) { // Check if a secondary notification is enabled, if so set defaults // and set it up. $form['settings']['notifications'][2] = array( 'notification_name' => esc_html__( 'Notification 2', 'wpforms-lite' ), 'email' => '{admin_email}', /* translators: %s - form name. */ 'subject' => sprintf( esc_html__( 'New Entry: %s', 'wpforms-lite' ), $cf7_form_name ), 'sender_name' => get_bloginfo( 'name' ), 'sender_address' => '{admin_email}', 'replyto' => '', 'message' => '{all_fields}', ); if ( ! empty( $cf7_properties['mail_2']['subject'] ) ) { $form['settings']['notifications'][2]['subject'] = $this->get_smarttags( $cf7_properties['mail_2']['subject'], $form['fields'] ); } if ( ! empty( $cf7_properties['mail_2']['recipient'] ) ) { $form['settings']['notifications'][2]['email'] = $this->get_smarttags( $cf7_properties['mail_2']['recipient'], $form['fields'] ); } if ( ! empty( $cf7_properties['mail_2']['body'] ) ) { $form['settings']['notifications'][2]['message'] = $this->get_smarttags( $cf7_properties['mail_2']['body'], $form['fields'] ); } if ( ! empty( $cf7_properties['mail_2']['additional_headers'] ) ) { $form['settings']['notifications'][2]['replyto'] = $this->get_replyto( $cf7_properties['mail_2']['additional_headers'], $form['fields'] ); } if ( ! empty( $cf7_properties['mail_2']['sender'] ) ) { $sender = $this->get_sender_details( $cf7_properties['mail_2']['sender'], $form['fields'] ); if ( $sender ) { $form['settings']['notifications'][2]['sender_name'] = $sender['name']; $form['settings']['notifications'][2]['sender_address'] = $sender['address']; } } } $this->add_form( $form, $unsupported, $upgrade_plain, $upgrade_omit ); } /** * Lookup and return the placeholder or default value. * * @since 1.4.2 * * @param object $field Field object. * @param string $type Type of the field. * * @return string */ public function get_field_placeholder_default( $field, $type = 'placeholder' ) { $placeholder = ''; $default_value = (string) reset( $field->values ); if ( $field->has_option( 'placeholder' ) || $field->has_option( 'watermark' ) ) { $placeholder = $default_value; $default_value = ''; } if ( 'placeholder' === $type ) { return $placeholder; } return $default_value; } /** * Get the field label. * * @since 1.4.2 * * @param string $form Form data and settings. * @param string $type Field type. * @param string $name Field name. * * @return string */ public function get_field_label( $form, $type, $name = '' ) { preg_match_all( '/<label>([ \w\S\r\n\t]+?)<\/label>/', $form, $matches ); foreach ( $matches[1] as $match ) { $match = trim( str_replace( "\n", '', $match ) ); preg_match( '/\[(?:' . preg_quote( $type ) . ') ' . $name . '(?:[ ](.*?))?(?:[\r\n\t ](\/))?\]/', $match, $input_match ); if ( ! empty( $input_match[0] ) ) { return strip_shortcodes( sanitize_text_field( str_replace( $input_match[0], '', $match ) ) ); } } $label = sprintf( /* translators: %1$s - field type; %2$s - field name if available. */ esc_html__( '%1$s Field %2$s', 'wpforms-lite' ), ucfirst( $type ), ! empty( $name ) ? "($name)" : '' ); return trim( $label ); } /** * @inheritdoc */ public function get_smarttags( $string, $fields ) { preg_match_all( '/\[(.+?)\]/', $string, $tags ); if ( empty( $tags[1] ) ) { return $string; } foreach ( $tags[1] as $tag ) { foreach ( $fields as $field ) { if ( ! empty( $field['cf7_name'] ) && $field['cf7_name'] === $tag ) { $string = str_replace( '[' . $tag . ']', '{field_id="' . $field['id'] . '"}', $string ); } } } return $string; } /** * Find Reply-To in headers if provided. * * @since 1.4.2 * * @param string $headers CF7 email headers. * @param array $fields List of fields. * * @return string */ public function get_replyto( $headers, $fields ) { if ( strpos( $headers, 'Reply-To:' ) !== false ) { preg_match( '/Reply-To: \[(.+?)\]/', $headers, $tag ); if ( ! empty( $tag[1] ) ) { foreach ( $fields as $field ) { if ( ! empty( $field['cf7_name'] ) && $field['cf7_name'] === $tag[1] ) { return '{field_id="' . $field['id'] . '"}'; } } } } return ''; } /** * Sender information. * * @since 1.4.2 * * @param string $sender Sender strings in "Name <email@example.com>" format. * @param array $fields List of fields. * * @return bool|array */ public function get_sender_details( $sender, $fields ) { preg_match( '/(.+?)\<(.+?)\>/', $sender, $tag ); if ( ! empty( $tag[1] ) && ! empty( $tag[2] ) ) { return array( 'name' => $this->get_smarttags( $tag[1], $fields ), 'address' => $this->get_smarttags( $tag[2], $fields ), ); } return false; } } new WPForms_Contact_Form_7(); admin/importers/class-ninja-forms.php 0000666 00000036143 15213301445 0013730 0 ustar 00 <?php /** * Ninja Forms Importer class. * * @since 1.4.2 */ class WPForms_Ninja_Forms extends WPForms_Importer { /** * @inheritdoc */ public function init() { $this->name = 'Ninja Forms'; $this->slug = 'ninja-forms'; $this->path = 'ninja-forms/ninja-forms.php'; } /** * Get ALL THE FORMS. * * @since 1.4.2 * * @return NF_Database_Models_Form[] */ public function get_forms() { $forms_final = array(); if ( ! $this->is_active() ) { return $forms_final; } $forms = Ninja_Forms()->form()->get_forms(); if ( ! empty( $forms ) ) { foreach ( $forms as $form ) { if ( ! $form instanceof NF_Database_Models_Form ) { continue; } $forms_final[ $form->get_id() ] = $form->get_setting( 'title' ); } } return $forms_final; } /** * @inheritdoc */ public function get_form( $id ) { $form = array(); $form['settings'] = Ninja_Forms()->form( $id )->get()->get_settings(); $fields = Ninja_Forms()->form( $id )->get_fields(); $actions = Ninja_Forms()->form( $id )->get_actions(); foreach ( $fields as $field ) { if ( ! $field instanceof NF_Database_Models_Field ) { continue; } $form['fields'][] = array_merge( array( 'id' => $field->get_id(), ), $field->get_settings() ); } foreach ( $actions as $action ) { if ( ! $action instanceof NF_Database_Models_Action ) { continue; } $form['actions'][] = $action->get_settings(); } return $form; } /** * @inheritdoc */ public function import_form() { // Run a security check. check_ajax_referer( 'wpforms-admin', 'nonce' ); // Check for permissions. if ( ! wpforms_current_user_can( 'create_forms' ) ) { wp_send_json_error(); } // Define some basic information. $analyze = isset( $_POST['analyze'] ); $nf_id = ! empty( $_POST['form_id'] ) ? (int) $_POST['form_id'] : 0; $nf_form = $this->get_form( $nf_id ); $nf_form_name = $nf_form['settings']['title']; $nf_recaptcha = false; $nf_recaptcha_type = 'v2'; $fields_pro_plain = array( 'phone', 'date' ); $fields_pro_omit = array( 'html', 'divider' ); $fields_unsupported = array( 'spam', 'starrating', 'listmultiselect', 'hidden', 'total', 'shipping', 'quantity', 'product' ); $upgrade_plain = array(); $upgrade_omit = array(); $unsupported = array(); $form = array( 'id' => '', 'field_id' => '', 'fields' => array(), 'settings' => array( 'form_title' => $nf_form_name, 'form_desc' => '', 'submit_text' => esc_html__( 'Submit', 'wpforms-lite' ), 'submit_text_processing' => esc_html__( 'Sending', 'wpforms-lite' ), 'honeypot' => '1', 'notification_enable' => '1', 'notifications' => array( 1 => array( 'notification_name' => esc_html__( 'Notification 1', 'wpforms-lite' ), 'email' => '{admin_email}', /* translators: %s - form name. */ 'subject' => sprintf( esc_html__( 'New Entry: %s', 'wpforms-lite' ), $nf_form_name ), 'sender_name' => get_bloginfo( 'name' ), 'sender_address' => '{admin_email}', 'replyto' => '', 'message' => '{all_fields}', ), ), 'confirmations' => array( 1 => array( 'type' => 'message', 'message' => esc_html__( 'Thanks for contacting us! We will be in touch with you shortly.', 'wpforms-lite' ), 'message_scroll' => '1', ), ), 'import_form_id' => $nf_id, ), ); // If form does not contain fields, bail. if ( empty( $nf_form['fields'] ) ) { wp_send_json_success( array( 'error' => true, 'name' => sanitize_text_field( $nf_form_name ), 'msg' => esc_html__( 'No form fields found.', 'wpforms-lite' ), ) ); } // Convert fields. foreach ( $nf_form['fields'] as $nf_field ) { // Try to determine field label to use. $label = $this->get_field_label( $nf_field ); // Next, check if field is unsupported. If unsupported make note and // then continue to the next field. if ( in_array( $nf_field['type'], $fields_unsupported, true ) ) { $unsupported[] = $label; continue; } // Now check if this install is Lite. If it is Lite and it's a // field type not included, make a note then continue to the next // field. if ( ! wpforms()->pro && in_array( $nf_field['type'], $fields_pro_plain, true ) ) { $upgrade_plain[] = $label; } if ( ! wpforms()->pro && in_array( $nf_field['type'], $fields_pro_omit, true ) ) { $upgrade_omit[] = $label; continue; } // Determine next field ID to assign. if ( empty( $form['fields'] ) ) { $field_id = 1; } else { $field_id = (int) max( array_keys( $form['fields'] ) ) + 1; } switch ( $nf_field['type'] ) { // Single line text, address, city, first name, last name, // zipcode, email, number, textarea fields. case 'textbox': case 'address': case 'city': case 'firstname': case 'lastname': case 'zip': case 'email': case 'number': case 'textarea': $type = 'text'; if ( 'email' === $nf_field['type'] ) { $type = 'email'; } elseif ( 'number' === $nf_field['type'] ) { $type = 'number'; } elseif ( 'textarea' === $nf_field['type'] ) { $type = 'textarea'; } $form['fields'][ $field_id ] = array( 'id' => $field_id, 'type' => $type, 'label' => $label, 'description' => ! empty( $nf_field['desc_text'] ) ? $nf_field['desc_text'] : '', 'size' => 'medium', 'required' => ! empty( $nf_field['required'] ) ? '1' : '', 'placeholder' => ! empty( $nf_field['placeholder'] ) ? $nf_field['placeholder'] : '', 'default_value' => ! empty( $nf_field['default'] ) ? $nf_field['default'] : '', 'nf_key' => $nf_field['key'], ); break; // Single checkbox field. case 'checkbox': $form['fields'][ $field_id ] = array( 'id' => $field_id, 'type' => 'checkbox', 'label' => esc_html__( 'Single Checkbox Field', 'wpforms-lite' ), 'choices' => array( 1 => array( 'label' => $label, 'value' => '', ), ), 'description' => ! empty( $nf_field['desc_text'] ) ? $nf_field['desc_text'] : '', 'size' => 'medium', 'required' => ! empty( $nf_field['required'] ) ? '1' : '', 'label_hide' => '1', 'nf_key' => $nf_field['key'], ); break; // Multi-check field, radio, select, state, and country fields. case 'listcheckbox': case 'listradio': case 'listselect': case 'liststate': case 'listcountry': $type = 'select'; if ( 'listcheckbox' === $nf_field['type'] ) { $type = 'checkbox'; } elseif ( 'listradio' === $nf_field['type'] ) { $type = 'radio'; } $choices = array(); if ( 'listcountry' === $nf_field['type'] ) { $countries = wpforms_countries(); foreach ( $countries as $key => $country ) { $choices[] = array( 'label' => $country, 'value' => $key, 'default' => isset( $nf_field['default'] ) && $nf_field['default'] === $key ? '1' : '', ); } } else { foreach ( $nf_field['options'] as $option ) { $choices[] = array( 'label' => $option['label'], 'value' => $option['value'], ); } } $form['fields'][ $field_id ] = array( 'id' => $field_id, 'type' => $type, 'label' => $label, 'choices' => $choices, 'description' => ! empty( $nf_field['desc_text'] ) ? $nf_field['desc_text'] : '', 'size' => 'medium', 'required' => ! empty( $nf_field['required'] ) ? '1' : '', 'nf_key' => $nf_field['key'], ); break; // HTML field. case 'html': $form['fields'][ $field_id ] = array( 'id' => $field_id, 'type' => 'html', 'code' => ! empty( $nf_field['default'] ) ? $nf_field['default'] : '', 'label_disable' => '1', 'nf_key' => $nf_field['key'], ); break; // Divider field. case 'hr': $form['fields'][ $field_id ] = array( 'id' => $field_id, 'type' => 'divider', 'label' => '', 'description' => '', 'label_disable' => '1', 'nf_key' => $nf_field['key'], ); break; // Phone number field. case 'phone': $type = wpforms()->pro ? 'phone' : 'text'; $form['fields'][ $field_id ] = array( 'id' => $field_id, 'type' => $type, 'label' => $label, 'format' => ! empty( $nf_field['mask'] ) && '(999) 999-9999' === $nf_field['mask'] ? 'us' : 'international', 'description' => ! empty( $nf_field['desc_text'] ) ? $nf_field['desc_text'] : '', 'size' => 'medium', 'required' => ! empty( $nf_field['required'] ) ? '1' : '', 'placeholder' => ! empty( $nf_field['placeholder'] ) ? $nf_field['placeholder'] : '', 'default_value' => ! empty( $nf_field['default'] ) ? $nf_field['default'] : '', 'nf_key' => $nf_field['key'], ); break; // Date field. case 'date': $type = wpforms()->pro ? 'date-time' : 'text'; $form['fields'][ $field_id ] = array( 'id' => $field_id, 'type' => $type, 'label' => $label, 'description' => ! empty( $nf_field['desc_text'] ) ? $nf_field['desc_text'] : '', 'format' => 'date', 'size' => 'medium', 'required' => ! empty( $nf_field['required'] ) ? '1' : '', 'date_placeholder' => '', 'date_format' => 'm/d/Y', 'date_type' => 'datepicker', 'time_format' => 'g:i A', 'time_interval' => 30, 'nf_key' => $nf_field['key'], ); break; // ReCAPTCHA field. case 'recaptcha': $nf_recaptcha = true; if ( 'invisible' === $nf_field['size'] ) { $nf_recaptcha_type = 'invisible'; } } } // If we are only analyzing the form, we can stop here and return the // details about this form. if ( $analyze ) { wp_send_json_success( array( 'name' => $nf_form_name, 'upgrade_plain' => $upgrade_plain, 'upgrade_omit' => $upgrade_omit, ) ); } // Settings. // Confirmation message. foreach ( $nf_form['actions'] as $action ) { if ( 'successmessage' === $action['type'] ) { $form['settings']['confirmations'][1]['message'] = $this->get_smarttags( $action['message'], $form['fields'] ); } } // ReCAPTCHA. if ( $nf_recaptcha ) { // If the user has already defined v2 reCAPTCHA keys in the WPForms // settings, use those. $site_key = wpforms_setting( 'recaptcha-site-key', '' ); $secret_key = wpforms_setting( 'recaptcha-secret-key', '' ); // Try to abstract keys from NF. if ( empty( $site_key ) || empty( $secret_key ) ) { $nf_settings = get_option( 'ninja_forms_settings' ); if ( ! empty( $nf_settings['recaptcha_site_key'] ) && ! empty( $nf_settings['recaptcha_secret_key'] ) ) { $wpforms_settings = get_option( 'wpforms_settings', array() ); $wpforms_settings['recaptcha-site-key'] = $nf_settings['recaptcha_site_key']; $wpforms_settings['recaptcha-secret-key'] = $nf_settings['recaptcha_secret_key']; $wpforms_settings['recaptcha-type'] = $nf_recaptcha_type; update_option( 'wpforms_settings', $wpforms_settings ); } } if ( ! empty( $site_key ) && ! empty( $secret_key ) ) { $form['settings']['recaptcha'] = '1'; } } // Setup email notifications. $action_count = 1; $action_defaults = array( 'notification_name' => esc_html__( 'Notification', 'wpforms-lite' ) . " $action_count", 'email' => '{admin_email}', /* translators: %s - form name. */ 'subject' => sprintf( esc_html__( 'New Entry: %s', 'wpforms-lite' ), $nf_form_name ), 'sender_name' => get_bloginfo( 'name' ), 'sender_address' => '{admin_email}', 'replyto' => '', 'message' => '{all_fields}', ); foreach ( $nf_form['actions'] as $action ) { if ( 'email' !== $action['type'] ) { continue; } $action_defaults['notification_name'] = esc_html__( 'Notification', 'wpforms-lite' ) . " $action_count"; $form['settings']['notifications'][ $action_count ] = $action_defaults; if ( ! empty( $action['label'] ) ) { $form['settings']['notifications'][ $action_count ]['notification_name'] = $action['label']; } if ( ! empty( $action['to'] ) ) { $form['settings']['notifications'][ $action_count ]['email'] = $this->get_smarttags( $action['to'], $form['fields'] ); } if ( ! empty( $action['reply_to'] ) ) { $form['settings']['notifications'][ $action_count ]['replyto'] = $this->get_smarttags( $action['reply_to'], $form['fields'] ); } if ( ! empty( $action['email_subject'] ) ) { $form['settings']['notifications'][ $action_count ]['subject'] = $this->get_smarttags( $action['email_subject'], $form['fields'] ); } if ( ! empty( $action['email_message'] ) ) { $form['settings']['notifications'][ $action_count ]['message'] = $this->get_smarttags( $action['email_message'], $form['fields'] ); } if ( ! empty( $action['from_name'] ) ) { $form['settings']['notifications'][ $action_count ]['sender_name'] = $this->get_smarttags( $action['from_name'], $form['fields'] ); } if ( ! empty( $action['from_address'] ) ) { $form['settings']['notifications'][ $action_count ]['sender_address'] = $this->get_smarttags( $action['from_address'], $form['fields'] ); } $action_count ++; } $this->add_form( $form, $unsupported, $upgrade_plain, $upgrade_omit ); } /** * Get the field label. * * @since 1.4.2 * * @param array $field * * @return string */ public function get_field_label( $field ) { if ( ! empty( $field['label'] ) ) { $label = sanitize_text_field( $field['label'] ); } else { $label = sprintf( /* translators: %1$s - field type; %2$s - field name if available. */ esc_html__( '%1$s Field', 'wpforms-lite' ), ucfirst( $field['type'] ) ); } return trim( $label ); } /** * @inheritdoc */ public function get_smarttags( $string, $fields ) { preg_match_all( '/\{(.+?)\}/', $string, $tags ); if ( empty( $tags[1] ) ) { return $string; } foreach ( $tags[1] as $tag ) { $tag_formatted = str_replace( 'field:', '', $tag ); foreach ( $fields as $field ) { if ( ! empty( $field['nf_key'] ) && $field['nf_key'] === $tag_formatted ) { $string = str_replace( '{' . $tag . '}', '{field_id="' . $field['id'] . '"}', $string ); } } if ( 'wp:admin_email' === $tag ) { $string = str_replace( '{wp:admin_email}', '{admin_email}', $string ); } if ( 'all_fields_table' === $tag || 'fields_table' === $tag ) { $string = str_replace( '{' . $tag . '}', '{all_fields}', $string ); } } return $string; } } new WPForms_Ninja_Forms(); admin/importers/class-base.php 0000666 00000007263 15213301445 0012420 0 ustar 00 <?php /** * Base Importer class. * * @since 1.4.2 */ abstract class WPForms_Importer implements WPForms_Importer_Interface { /** * Importer name. * * @since 1.4.2 * * @var string */ public $name; /** * Importer name in slug format. * * @since 1.4.2 * * @var string */ public $slug; /** * Importer plugin path. * * @since 1.4.2 * * @var string */ public $path; /** * Primary class constructor. * * @since 1.4.2 */ public function __construct() { $this->init(); // Add to list of available importers. add_filter( 'wpforms_importers', array( $this, 'register' ), 10, 1 ); // Return array of all available forms. add_filter( "wpforms_importer_forms_{$this->slug}", array( $this, 'get_forms' ), 10, 1 ); // Import a specific form with AJAX. add_action( "wp_ajax_wpforms_import_form_{$this->slug}", array( $this, 'import_form' ) ); } /** * Add to list of registered importers. * * @since 1.4.2 * * @param array $importers List of supported importers. * * @return array */ public function register( $importers = array() ) { $importers[ $this->slug ] = array( 'name' => $this->name, 'slug' => $this->slug, 'path' => $this->path, 'installed' => file_exists( trailingslashit( WP_PLUGIN_DIR ) . $this->path ), 'active' => $this->is_active(), ); return $importers; } /** * If the importer source is available. * * @since 1.4.2 * * @return bool */ protected function is_active() { return is_plugin_active( $this->path ); } /** * Add the new form to the database and return AJAX data. * * @since 1.4.2 * * @param array $form Form to import. * @param array $unsupported List of unsupported fields. * @param array $upgrade_plain List of fields, that are supported inside the paid WPForms, but not in Lite. * @param array $upgrade_omit No field alternative in WPForms. */ public function add_form( $form, $unsupported = array(), $upgrade_plain = array(), $upgrade_omit = array() ) { // Create empty form so we have an ID to work with. $form_id = wp_insert_post( array( 'post_status' => 'publish', 'post_type' => 'wpforms', ) ); if ( empty( $form_id ) || is_wp_error( $form_id ) ) { wp_send_json_success( array( 'error' => true, 'name' => sanitize_text_field( $form['settings']['form_title'] ), 'msg' => esc_html__( 'There was an error while creating a new form.', 'wpforms-lite' ), ) ); } $form['id'] = $form_id; $form['field_id'] = count( $form['fields'] ) + 1; // Update the form with all our compiled data. wpforms()->form->update( $form_id, $form ); // Make note that this form has been imported. $this->track_import( $form['settings']['import_form_id'], $form_id ); // Build and send final AJAX response! wp_send_json_success( array( 'name' => $form['settings']['form_title'], 'edit' => esc_url_raw( admin_url( 'admin.php?page=wpforms-builder&view=fields&form_id=' . $form_id ) ), 'preview' => wpforms_get_form_preview_url( $form_id ), 'unsupported' => $unsupported, 'upgrade_plain' => $upgrade_plain, 'upgrade_omit' => $upgrade_omit, ) ); } /** * After a form has been successfully imported we track it, so that in the * future we can alert users if they try to import a form that has already * been imported. * * @since 1.4.2 * * @param int $source_id Imported plugin form ID. * @param int $wpforms_id WPForms form ID. */ public function track_import( $source_id, $wpforms_id ) { $imported = get_option( 'wpforms_imported', array() ); $imported[ $this->slug ][ $wpforms_id ] = $source_id; update_option( 'wpforms_imported', $imported, false ); } } admin/importers/class-pirate-forms.php 0000666 00000043760 15213301445 0014120 0 ustar 00 <?php /** * Pirate Forms Importer class. * * @since 1.4.9 */ class WPForms_Pirate_Forms extends WPForms_Importer { /** * Direct URL to download the latest version of WP Mail SMTP plugin from WP.org repo. * * @since 1.4.9 * * @var string */ const URL_SMTP_ZIP = 'https://downloads.wordpress.org/plugin/wp-mail-smtp.zip'; /** * WP Mail SMTP plugin basename. * * @since 1.4.9 * * @var string */ const SLUG_SMTP_PLUGIN = 'wp-mail-smtp/wp_mail_smtp.php'; /** * Default PirateForms smart tags. * * @var array */ public static $tags = array( '[email]', ); /** * Define required properties. * * @since 1.4.9 */ public function init() { $this->name = 'Pirate Forms'; $this->slug = 'pirate-forms'; $this->path = 'pirate-forms/pirate-forms.php'; } /** * Get ALL THE FORMS. * We need only ID's and names here. * * @since 1.4.9 * * @return array */ public function get_forms() { // Union those arrays, as array_merge() does keys reindexing. $forms = $this->get_default_forms() + $this->get_pro_forms(); // Sort by IDs ASC. ksort( $forms ); return $forms; } /** * Pirate Forms has a default form, which doesn't have an ID. * * @since 1.4.9 * * @return array */ protected function get_default_forms() { $form = PirateForms_Util::get_form_options(); // Just make sure that it's there and not broken. if ( empty( $form ) ) { return array(); } return array( 0 => esc_html__( 'Default Form', 'wpforms-lite' ) ); } /** * Copy-paste from Pro plugin code, it doesn't have API to get this data easily. * * @since 1.4.9 * * @return array */ protected function get_pro_forms() { $forms = array(); $query = new WP_Query( array( 'post_type' => 'pf_form', 'post_status' => 'publish', 'posts_per_page' => - 1, 'update_post_meta_cache' => false, 'update_post_term_cache' => false, ) ); if ( $query->have_posts() ) { while ( $query->have_posts() ) { $query->the_post(); $forms[ get_the_ID() ] = get_the_title(); } } return $forms; } /** * Get a single form options. * * @since 1.4.9 * * @param int $id Form ID. * * @return array */ public function get_form( $id ) { return PirateForms_Util::get_form_options( (int) $id ); } /** * Import a single form using AJAX. * * @since 1.4.9 */ public function import_form() { // Run a security check. check_ajax_referer( 'wpforms-admin', 'nonce' ); // Check for permissions. if ( ! wpforms_current_user_can( 'create_forms' ) ) { wp_send_json_error(); } $analyze = isset( $_POST['analyze'] ); $pf_form_id = isset( $_POST['form_id'] ) ? (int) $_POST['form_id'] : 0; $pf_form = $this->get_form( $pf_form_id ); $pf_fields_custom = PirateForms_Util::get_post_meta( $pf_form_id, 'custom' ); $pf_fields_default = array( 'name', 'email', 'subject', 'message', 'attachment', 'checkbox', 'recaptcha', ); $fields_pro_plain = array( 'tel' ); // Convert them in Lite to the closest Standard alternatives. $fields_pro_omit = array( 'label', 'file', 'attachment' ); // Strict PRO fields with no Lite alternatives. $upgrade_plain = array(); $upgrade_omit = array(); $unsupported = array(); $fields = array(); if ( ! empty( $pf_fields_custom[0] ) ) { $pf_fields_custom = $pf_fields_custom[0]; } else { $pf_fields_custom = array(); } if ( empty( $pf_form_id ) ) { $pf_form_name = esc_html__( 'Default Form', 'wpforms-lite' ); } else { $pf_form_name = get_post_field( 'post_title', $pf_form_id ); } $pf_form_name = wpforms_decode_string( apply_filters( 'the_title', $pf_form_name, $pf_form_id ) ); // Prepare all DEFAULT fields. foreach ( $pf_fields_default as $field ) { // Ignore fields that are not displayed or not added at all. if ( empty( $pf_form[ 'pirateformsopt_' . $field . '_field' ] ) ) { continue; } // Ignore certain fields as they are dealt with later. if ( 'recaptcha' === $field ) { continue; } $required = 'req' === $pf_form[ 'pirateformsopt_' . $field . '_field' ] ? '1' : ''; $label = ! empty( $pf_form[ 'pirateformsopt_label_' . $field ] ) ? $pf_form[ 'pirateformsopt_label_' . $field ] : ucwords( $field ); // If it is Lite and it's a field type not included, make a note then continue to the next field. if ( ! wpforms()->pro && in_array( $field, $fields_pro_plain, true ) ) { $upgrade_plain[] = $label; } if ( ! wpforms()->pro && in_array( $field, $fields_pro_omit, true ) ) { $upgrade_omit[] = $label; continue; } // Determine next field ID to assign. if ( empty( $fields ) ) { $field_id = 1; } else { $field_id = (int) max( array_keys( $fields ) ) + 1; } // Separately process certain fields. switch ( $field ) { case 'name': case 'email': case 'subject': case 'message': $type = $field; if ( 'subject' === $field ) { $type = 'text'; } elseif ( 'message' === $field ) { $type = 'textarea'; } $fields[ $field_id ] = array( 'id' => $field_id, 'type' => $type, 'label' => $label, 'required' => $required, 'size' => 'medium', ); if ( 'name' === $field ) { $fields[ $field_id ]['format'] = 'simple'; } break; case 'checkbox': $fields[ $field_id ] = array( 'id' => $field_id, 'type' => 'checkbox', 'label' => esc_html__( 'Single Checkbox Field', 'wpforms-lite' ), 'choices' => array( 1 => array( 'label' => $label, 'value' => '', ), ), 'size' => 'medium', 'required' => $required, 'label_hide' => true, ); break; case 'attachment': case 'file': $fields[ $field_id ] = array( 'id' => $field_id, 'type' => 'file-upload', 'label' => $label, 'required' => $required, 'label_hide' => true, ); // If PF attachments were saved into FS, we need to save them in WP Media. // That will allow admins to easily delete if needed. if ( ! empty( $pf_form['pirateformsopt_save_attachment'] ) && 'yes' === $pf_form['pirateformsopt_save_attachment'] ) { $fields[ $field_id ]['media_library'] = true; } break; } } // Prepare all CUSTOM fields. foreach ( $pf_fields_custom as $id => $field ) { // Ignore fields that are not displayed. if ( empty( $field['display'] ) ) { continue; } $required = 'req' === $field['display'] ? '1' : ''; // Possible values in PF: 'yes', 'req'. $label = sanitize_text_field( $field['label'] ); // If it is Lite and it's a field type not included, make a note then continue to the next field. if ( ! wpforms()->pro && in_array( $field['type'], $fields_pro_plain, true ) ) { $upgrade_plain[] = $label; } if ( ! wpforms()->pro && in_array( $field['type'], $fields_pro_omit, true ) ) { $upgrade_omit[] = $label; continue; } // Determine next field ID to assign. if ( empty( $fields ) ) { $field_id = 1; } else { $field_id = (int) max( array_keys( $fields ) ) + 1; } switch ( $field['type'] ) { case 'text': case 'textarea': case 'number': case 'tel': $type = $field['type']; if ( 'textarea' === $field['type'] ) { $type = 'textarea'; } if ( 'tel' === $field['type'] ) { $type = 'phone'; } $fields[ $field_id ] = array( 'id' => $field_id, 'type' => $type, 'label' => $label, 'required' => $required, 'size' => 'medium', ); if ( 'tel' === $field['type'] ) { $fields[ $field_id ]['format'] = 'international'; } break; case 'checkbox': $fields[ $field_id ] = array( 'id' => $field_id, 'type' => 'checkbox', 'label' => esc_html__( 'Single Checkbox Field', 'wpforms-lite' ), 'choices' => array( 1 => array( 'label' => $label, 'value' => '', ), ), 'size' => 'medium', 'required' => $required, 'label_hide' => true, ); break; case 'select': case 'multiselect': $options = array(); $i = 1; $type = 'select'; if ( 'multiselect' === $field['type'] ) { $type = 'checkbox'; } foreach ( explode( PHP_EOL, $field['options'] ) as $option ) { $options[ $i ] = array( 'label' => $option, 'value' => '', 'image' => '', ); $i ++; } $fields[ $field_id ] = array( 'id' => $field_id, 'type' => $type, 'label' => $label, 'required' => $required, 'size' => 'medium', 'choices' => $options, ); break; case 'label': $fields[ $field_id ] = array( 'id' => $field_id, 'type' => 'html', 'code' => $field['label'], 'label_disable' => true, ); break; case 'file': $fields[ $field_id ] = array( 'id' => $field_id, 'type' => 'file-upload', 'label' => $label, 'required' => $required, 'label_hide' => true, ); // If PF attachments were saved into FS, we need to save them in WP Media. // That will allow admins to easily delete if needed. if ( ! empty( $pf_form['pirateformsopt_save_attachment'] ) && 'yes' === $pf_form['pirateformsopt_save_attachment'] ) { $fields[ $field_id ]['media_library'] = true; } break; } } // If we are analyzing the form (in Lite only), // we can stop here and return the details about this form. if ( $analyze ) { wp_send_json_success( array( 'name' => $pf_form_name, 'upgrade_plain' => $upgrade_plain, 'upgrade_omit' => $upgrade_omit, ) ); } // Make sure we have imported some fields. if ( empty( $fields ) ) { wp_send_json_success( array( 'error' => true, 'name' => $pf_form_name, 'msg' => esc_html__( 'No form fields found.', 'wpforms-lite' ), ) ); } // Create a form array, that holds all the data. $form = array( 'id' => '', 'field_id' => '', 'fields' => $fields, 'settings' => array( 'form_title' => $pf_form_name, 'form_desc' => '', 'submit_text' => stripslashes( $pf_form['pirateformsopt_label_submit_btn'] ), 'submit_text_processing' => esc_html__( 'Sending', 'wpforms-lite' ), 'honeypot' => empty( $pf_form['pirateformsopt_recaptcha_field'] ) ? '0' : '1', 'notification_enable' => '1', 'notifications' => array( 1 => array( 'notification_name' => esc_html__( 'Default Notification', 'wpforms-lite' ), 'email' => $pf_form['pirateformsopt_email_recipients'], /* translators: %s - form name. */ 'subject' => sprintf( esc_html__( 'New Entry: %s', 'wpforms-lite' ), $pf_form_name ), 'sender_name' => get_bloginfo( 'name' ), 'sender_address' => $this->get_smarttags( $pf_form['pirateformsopt_email'], $fields ), 'replyto' => '', 'message' => '{all_fields}', ), ), 'confirmations' => array( 1 => array( 'type' => empty( $pf_form['pirateformsopt_thank_you_url'] ) ? 'message' : 'page', 'page' => (int) $pf_form['pirateformsopt_thank_you_url'], 'message' => ! empty( $pf_form['pirateformsopt_label_submit'] ) ? $pf_form['pirateformsopt_label_submit'] : esc_html__( 'Thanks for contacting us! We will be in touch with you shortly.', 'wpforms-lite' ), 'message_scroll' => '1', ), ), 'disable_entries' => 'yes' === $pf_form['pirateformsopt_store'] ? '0' : '1', 'import_form_id' => $pf_form_id, ), ); // Do not save user IP address and UA. if ( empty( $pf_form['pirateformsopt_store_ip'] ) || 'yes' !== $pf_form['pirateformsopt_store_ip'] ) { $wpforms_settings = get_option( 'wpforms_settings', array() ); $wpforms_settings['gdpr'] = true; update_option( 'wpforms_settings', $wpforms_settings ); $form['settings']['disable_ip'] = true; } // Save recaptcha keys. if ( ! empty( $pf_form['pirateformsopt_recaptcha_field'] ) && 'yes' === $pf_form['pirateformsopt_recaptcha_field'] ) { // If the user has already defined v2 reCAPTCHA keys, use those. $site_key = wpforms_setting( 'recaptcha-site-key', '' ); $secret_key = wpforms_setting( 'recaptcha-secret-key', '' ); // Try to abstract keys from PF. if ( empty( $site_key ) || empty( $secret_key ) ) { if ( ! empty( $pf_form['pirateformsopt_recaptcha_sitekey'] ) && ! empty( $pf_form['pirateformsopt_recaptcha_secretkey'] ) ) { $wpforms_settings = get_option( 'wpforms_settings', array() ); $wpforms_settings['recaptcha-site-key'] = $pf_form['pirateformsopt_recaptcha_sitekey']; $wpforms_settings['recaptcha-secret-key'] = $pf_form['pirateformsopt_recaptcha_secretkey']; $wpforms_settings['recaptcha-type'] = 'v2'; update_option( 'wpforms_settings', $wpforms_settings ); } } if ( ( ! empty( $site_key ) && ! empty( $secret_key ) ) || ( ! empty( $wpforms_settings['recaptcha-site-key'] ) && ! empty( $wpforms_settings['recaptcha-secret-key'] ) ) ) { $form['settings']['recaptcha'] = '1'; } } $this->import_smtp( $pf_form_id, $form ); $this->add_form( $form, $unsupported, $upgrade_plain, $upgrade_omit ); } /** * Replace 3rd-party form provider tags/shortcodes with our own Smart Tags. * See: PirateForms_Util::get_magic_tags() for all PF tags. * * @since 1.4.9 * * @param string $string String to process the smart tag in. * @param array $fields List of fields for the form. * * @return string */ public function get_smarttags( $string, $fields ) { foreach ( self::$tags as $tag ) { $wpf_tag = ''; if ( '[email]' === $tag ) { foreach ( $fields as $field ) { if ( 'email' === $field['type'] ) { $wpf_tag = '{field_id="' . $field['id'] . '"}'; break; } } } $string = str_replace( $tag, $wpf_tag, $string ); } return $string; } /** * Import SMTP settings from Default form only. * * @since 1.4.9 * * @param int $pf_form_id PirateForms form ID. * @param array $form WPForms form array. */ protected function import_smtp( $pf_form_id, $form ) { // At this point we import only default form SMTP settings. if ( 0 !== $pf_form_id ) { return; } $pf_form = $this->get_form( 0 ); // Use only if enabled. if ( empty( $pf_form['pirateformsopt_use_smtp'] ) || 'yes' !== $pf_form['pirateformsopt_use_smtp'] ) { return; } // If user has WP Mail SMTP already activated - do nothing as it's most likely already configured. if ( is_plugin_active( self::SLUG_SMTP_PLUGIN ) ) { return; } // Check that we successfully installed and activated the plugin. if ( ! $this->install_activate_smtp() ) { return; } /* * Finally, start the settings importing. */ // WP Mail SMTP 1.x and PHP 5.3+ are allowed. Older WPMS versions are ignored. if ( ! function_exists( 'wp_mail_smtp' ) ) { return; } // TODO: change to \WPMailSMTP\Options in future. $options = get_option( 'wp_mail_smtp', array() ); $options['mail']['from_email'] = $this->get_smarttags( $pf_form['pirateformsopt_email'], $form['fields'] ); $options['mail']['mailer'] = 'smtp'; $options['smtp']['host'] = $pf_form['pirateformsopt_smtp_host']; $options['smtp']['port'] = $pf_form['pirateformsopt_smtp_port']; $options['smtp']['encryption'] = empty( $pf_form['pirateformsopt_use_secure'] ) ? 'none' : $pf_form['pirateformsopt_use_secure']; $options['smtp']['auth'] = ! empty( $pf_form['pirateformsopt_use_smtp_authentication'] ) && 'yes' === $pf_form['pirateformsopt_use_smtp_authentication']; $options['smtp']['user'] = $pf_form['pirateformsopt_smtp_username']; $options['smtp']['pass'] = $pf_form['pirateformsopt_smtp_password']; update_option( 'wp_mail_smtp', $options ); } /** * Do all the voodoo to install and activate the WP Mail SMTP plugin behind the scene. * No user interaction is needed. * * @since 1.4.9 * * @return bool */ protected function install_activate_smtp() { /* * Check installation. * If installed but not activated - bail. * We don't want to break current site email deliverability. */ if ( ! function_exists( 'get_plugins' ) ) { require_once ABSPATH . 'wp-admin/includes/plugin.php'; } // FALSE will bail the import. if ( array_key_exists( self::SLUG_SMTP_PLUGIN, get_plugins() ) ) { return false; } /* * Let's try to install. */ $url = add_query_arg( array( 'provider' => $this->slug, 'page' => 'wpforms-tools', 'view' => 'importer', ), admin_url( 'admin.php' ) ); $creds = request_filesystem_credentials( esc_url_raw( $url ), '', false, false, null ); // Check for file system permissions. if ( false === $creds ) { return false; } if ( ! WP_Filesystem( $creds ) ) { return false; } // Do not allow WordPress to search/download translations, as this will break JS output. remove_action( 'upgrader_process_complete', array( 'Language_Pack_Upgrader', 'async_upgrade' ), 20 ); // Create the plugin upgrader with our custom skin. $installer = new \WPForms\Helpers\PluginSilentUpgrader( new \WPForms\Helpers\PluginSilentUpgraderSkin() ); // Error check. if ( ! method_exists( $installer, 'install' ) ) { return false; } $installer->install( self::URL_SMTP_ZIP ); // Flush the cache and return the newly installed plugin basename. wp_cache_flush(); if ( $installer->plugin_info() ) { $plugin_basename = $installer->plugin_info(); // Activate, do not redirect, run the plugin activation routine. $activated = activate_plugin( $plugin_basename ); if ( ! is_wp_error( $activated ) ) { return true; } } return false; } } new WPForms_Pirate_Forms(); templates/class-contact.php 0000666 00000004275 15213301445 0012023 0 ustar 00 <?php /** * Contact form template. * * @since 1.0.0 */ class WPForms_Template_Contact extends WPForms_Template { /** * Primary class constructor. * * @since 1.0.0 */ public function init() { $this->name = esc_html__( 'Simple Contact Form', 'wpforms-lite' ); $this->slug = 'contact'; $this->description = esc_html__( 'Allow your users to contact you with this simple contact form. You can add and remove fields as needed.', 'wpforms-lite' ); $this->includes = ''; $this->icon = ''; $this->modal = ''; $this->core = true; $this->data = array( 'field_id' => '3', 'fields' => array( '0' => array( 'id' => '0', 'type' => 'name', 'format' => 'first-last', 'label' => esc_html__( 'Name', 'wpforms-lite' ), 'required' => '1', 'size' => 'medium', ), '1' => array( 'id' => '1', 'type' => 'email', 'label' => esc_html__( 'Email', 'wpforms-lite' ), 'required' => '1', 'size' => 'medium', ), '2' => array( 'id' => '2', 'type' => 'textarea', 'label' => esc_html__( 'Comment or Message', 'wpforms-lite' ), 'description' => '', 'required' => '1', 'size' => 'medium', 'placeholder' => '', 'css' => '', ), ), 'settings' => array( 'notification_enable' => '1', 'notifications' => array( '1' => array( 'email' => '{admin_email}', 'sender_address' => '{admin_email}', 'replyto' => '{field_id="1"}', 'message' => '{all_fields}', ), ), 'confirmations' => array( '1' => array( 'type' => 'message', 'message' => esc_html__( 'Thanks for contacting us! We will be in touch with you shortly.', 'wpforms-lite' ), 'message_scroll' => '1', ), ), 'honeypot' => '1', 'submit_text' => esc_html__( 'Submit', 'wpforms-lite' ), 'submit_text_processing' => esc_html__( 'Sending...', 'wpforms-lite' ), ), 'meta' => array( 'template' => $this->slug, ), ); } } new WPForms_Template_Contact; templates/class-subscribe.php 0000666 00000004126 15213301445 0012344 0 ustar 00 <?php /** * Scribe to Email list form template. * * @since 1.0.0 */ class WPForms_Template_Subscribe extends WPForms_Template { /** * Primary class constructor. * * @since 1.0.0 */ public function init() { $this->name = esc_html__( 'Newsletter Signup Form', 'wpforms-lite' ); $this->slug = 'subscribe'; $this->description = esc_html__( 'Add subscribers and grow your email list with this newsletter signup form. You can add and remove fields as needed.', 'wpforms-lite' ); $this->includes = ''; $this->icon = ''; $this->core = true; $this->modal = array( 'title' => esc_html__( 'Don't Forget', 'wpforms-lite' ), 'message' => esc_html__( 'Click the marketing tab to configure your newsletter service provider', 'wpforms-lite' ), ); $this->data = array( 'field_id' => '2', 'fields' => array( '0' => array( 'id' => '0', 'type' => 'name', 'label' => esc_html__( 'Name', 'wpforms-lite' ), 'required' => '1', 'size' => 'medium', ), '1' => array( 'id' => '1', 'type' => 'email', 'label' => esc_html__( 'Email', 'wpforms-lite' ), 'required' => '1', 'size' => 'medium', ), ), 'settings' => array( 'honeypot' => '1', 'confirmation_message_scroll' => '1', 'submit_text_processing' => esc_html__( 'Sending...', 'wpforms-lite' ), ), 'meta' => array( 'template' => $this->slug, ), ); } /** * Conditional to determine if the template informational modal screens * should display. * * @since 1.0.0 * * @param array $form_data Form data and settings. * * @return bool */ public function template_modal_conditional( $form_data ) { // If we do not have provider data, then we can assume a provider // method has not yet been configured, so we display the modal to // remind the user they need to set it up for the form to work // correctly. if ( empty( $form_data['providers'] ) ) { return true; } return false; } } new WPForms_Template_Subscribe(); templates/class-blank.php 0000666 00000001636 15213301445 0011455 0 ustar 00 <?php /** * Blank form template. * * @since 1.0.0 */ class WPForms_Template_Blank extends WPForms_Template { /** * Primary class constructor. * * @since 1.0.0 */ public function init() { $this->name = esc_html__( 'Blank Form', 'wpforms-lite' ); $this->slug = 'blank'; $this->description = esc_html__( 'The blank form allows you to create any type of form using our drag & drop builder.', 'wpforms-lite' ); $this->includes = ''; $this->icon = ''; $this->modal = ''; $this->core = true; $this->data = array( 'field_id' => '1', 'fields' => array(), 'settings' => array( 'honeypot' => '1', 'confirmation_message_scroll' => '1', 'submit_text_processing' => esc_html__( 'Sending...', 'wpforms-lite' ), ), 'meta' => array( 'template' => $this->slug, ), ); } } new WPForms_Template_Blank; templates/class-base.php 0000666 00000010352 15213301445 0011273 0 ustar 00 <?php /** * Base form template. * * @since 1.0.0 */ abstract class WPForms_Template { /** * Full name of the template, eg "Contact Form". * * @since 1.0.0 * @var string */ public $name; /** * Slug of the template, eg "contact-form" - no spaces. * * @since 1.0.0 * @var string */ public $slug; /** * Short description the template. * * @since 1.0.0 * @var string */ public $description = ''; /** * Short description of the fields included with the template. * * @since 1.0.0 * @var string */ public $includes = ''; /** * URL of the icon to display in the admin area. * * @since 1.0.0 * @var string */ public $icon = ''; /** * Array of data that is assigned to the post_content on form creation. * * @since 1.0.0 * @var array */ public $data; /** * Priority to show in the list of available templates. * * @since 1.0.0 * @var int */ public $priority = 20; /** * Core or additional template. * * @since 1.4.0 * @var bool */ public $core = false; /** * Modal message to display when the template is applied. * * @since 1.0.0 * @var array */ public $modal = ''; /** * Primary class constructor. * * @since 1.0.0 */ public function __construct() { // Bootstrap. $this->init(); $type = $this->core ? '_core' : ''; add_filter( "wpforms_form_templates{$type}", array( $this, 'template_details' ), $this->priority ); add_filter( 'wpforms_create_form_args', array( $this, 'template_data' ), 10, 2 ); add_filter( 'wpforms_save_form_args', array( $this, 'template_replace' ), 10, 3 ); add_filter( 'wpforms_builder_template_active', array( $this, 'template_active' ), 10, 2 ); } /** * Let's get started. * * @since 1.0.0 */ public function init() { } /** * Add basic template details to the Add New Form admin screen. * * @since 1.0.0 * * @param array $templates * * @return array */ public function template_details( $templates ) { $templates[] = array( 'name' => $this->name, 'slug' => $this->slug, 'description' => $this->description, 'includes' => $this->includes, 'icon' => $this->icon, ); return $templates; } /** * Add template data when form is created. * * @since 1.0.0 * * @param array $args * @param array $data * * @return array */ public function template_data( $args, $data ) { if ( ! empty( $data ) && ! empty( $data['template'] ) ) { if ( $data['template'] === $this->slug ) { $args['post_content'] = wpforms_encode( $this->data ); } } return $args; } /** * Replace template on post update if triggered. * * @since 1.0.0 * * @param array $form * @param array $data * @param array $args * * @return array */ public function template_replace( $form, $data, $args ) { if ( ! empty( $args['template'] ) ) { if ( $args['template'] === $this->slug ) { $new = $this->data; $new['settings'] = ! empty( $form['post_content']['settings'] ) ? $form['post_content']['settings'] : array(); $form['post_content'] = wpforms_encode( $new ); } } return $form; } /** * Pass information about the active template back to the builder. * * @since 1.0.0 * * @param array $details * @param object $form * * @return array */ public function template_active( $details, $form ) { if ( empty( $form ) ) { return; } $form_data = wpforms_decode( $form->post_content ); if ( empty( $this->modal ) || empty( $form_data['meta']['template'] ) || $this->slug !== $form_data['meta']['template'] ) { return $details; } else { $display = $this->template_modal_conditional( $form_data ); } $template = array( 'name' => $this->name, 'slug' => $this->slug, 'description' => $this->description, 'includes' => $this->includes, 'icon' => $this->icon, 'modal' => $this->modal, 'modal_display' => $display, ); return $template; } /** * Conditional to determine if the template informational modal screens * should display. * * @since 1.0.0 * * @param array $form_data Form data and settings. * * @return bool */ public function template_modal_conditional( $form_data ) { return false; } } templates/class-suggestion.php 0000666 00000005156 15213301445 0012556 0 ustar 00 <?php /** * Suggestion form template. * * @since 1.1.3.2 */ class WPForms_Template_Suggestion extends WPForms_Template { /** * Primary class constructor. * * @since 1.0.0 */ public function init() { $this->name = esc_html__( 'Suggestion Form', 'wpforms-lite' ); $this->slug = 'suggestion'; $this->description = esc_html__( 'Ask your users for suggestions with this simple form template. You can add and remove fields as needed.', 'wpforms-lite' ); $this->includes = ''; $this->icon = ''; $this->modal = ''; $this->core = true; $this->data = array( 'field_id' => '5', 'fields' => array( '0' => array( 'id' => '0', 'type' => 'name', 'label' => esc_html__( 'Name', 'wpforms-lite' ), 'required' => '1', 'size' => 'medium', ), '1' => array( 'id' => '1', 'type' => 'email', 'label' => esc_html__( 'Email', 'wpforms-lite' ), 'description' => esc_html__( 'Please enter your email, so we can follow up with you.', 'wpforms-lite' ), 'required' => '1', 'size' => 'medium', ), '2' => array( 'id' => '2', 'type' => 'radio', 'label' => esc_html__( 'Which department do you have a suggestion for?', 'wpforms-lite' ), 'choices' => array( '1' => array( 'label' => esc_html__( 'Sales', 'wpforms-lite' ), ), '2' => array( 'label' => esc_html__( 'Customer Support', 'wpforms-lite' ), ), '3' => array( 'label' => esc_html__( 'Product Development', 'wpforms-lite' ), ), '4' => array( 'label' => esc_html__( 'Other', 'wpforms-lite' ), ), ), 'required' => '1', ), '3' => array( 'id' => '3', 'type' => 'text', 'label' => esc_html__( 'Subject', 'wpforms-lite' ), 'required' => '1', 'size' => 'medium', ), '4' => array( 'id' => '4', 'type' => 'textarea', 'label' => esc_html__( 'Message', 'wpforms-lite' ), 'required' => '1', 'size' => 'medium', ), ), 'settings' => array( 'notifications' => array( '1' => array( 'replyto' => '{field_id="1"}', 'sender_name' => '{field_id="0"}', 'sender_address' => '{admin_email}', ), ), 'honeypot' => '1', 'confirmation_message_scroll' => '1', 'submit_text_processing' => esc_html__( 'Sending...', 'wpforms-lite' ), ), 'meta' => array( 'template' => $this->slug, ), ); } } new WPForms_Template_Suggestion; fields/class-checkbox.php 0000666 00000051205 15213301445 0011421 0 ustar 00 <?php /** * Checkbox field. * * @since 1.0.0 */ class WPForms_Field_Checkbox extends WPForms_Field { /** * Primary class constructor. * * @since 1.0.0 */ public function init() { // Define field type information. $this->name = esc_html__( 'Checkboxes', 'wpforms-lite' ); $this->type = 'checkbox'; $this->icon = 'fa-check-square-o'; $this->order = 110; $this->defaults = array( 1 => array( 'label' => esc_html__( 'First Choice', 'wpforms-lite' ), 'value' => '', 'image' => '', 'default' => '', ), 2 => array( 'label' => esc_html__( 'Second Choice', 'wpforms-lite' ), 'value' => '', 'image' => '', 'default' => '', ), 3 => array( 'label' => esc_html__( 'Third Choice', 'wpforms-lite' ), 'value' => '', 'image' => '', 'default' => '', ), ); // Customize HTML field values. add_filter( 'wpforms_html_field_value', array( $this, 'field_html_value' ), 10, 4 ); // Define additional field properties. add_filter( 'wpforms_field_properties_checkbox', array( $this, 'field_properties' ), 5, 3 ); } /** * Return images, if any, for HTML supported values. * * @since 1.4.5 * * @param string $value Field value. * @param array $field Field settings. * @param array $form_data Form data and settings. * @param string $context Value display context. * * @return string */ public function field_html_value( $value, $field, $form_data = array(), $context = '' ) { // Only use HTML formatting for checkbox fields, with image choices // enabled, and exclude the entry table display. Lastly, provides a // filter to disable fancy display. if ( ! empty( $field['value'] ) && $this->type === $field['type'] && ! empty( $field['images'] ) && 'entry-table' !== $context && apply_filters( 'wpforms_checkbox_field_html_value_images', true, $context ) ) { $items = array(); $values = explode( "\n", $field['value'] ); foreach ( $values as $key => $val ) { if ( ! empty( $field['images'][ $key ] ) ) { $items[] = sprintf( '<span style="max-width:200px;display:block;margin:0 0 5px 0;"><img src="%s" style="max-width:100%%;display:block;margin:0;"></span>%s', esc_url( $field['images'][ $key ] ), $val ); } else { $items[] = $val; } } return implode( '<br><br>', $items ); } return $value; } /** * Define additional field properties. * * @since 1.4.5 * * @param array $properties Field properties. * @param array $field Field settings. * @param array $form_data Form data and settings. * * @return array */ public function field_properties( $properties, $field, $form_data ) { // Define data. $form_id = absint( $form_data['id'] ); $field_id = absint( $field['id'] ); $choices = $field['choices']; $dynamic = wpforms_get_field_dynamic_choices( $field, $form_id, $form_data ); if ( $dynamic ) { $choices = $dynamic; $field['show_values'] = true; } // Remove primary input. unset( $properties['inputs']['primary'] ); // Set input container (ul) properties. $properties['input_container'] = array( 'class' => array( ! empty( $field['random'] ) ? 'wpforms-randomize' : '' ), 'data' => array(), 'attr' => array(), 'id' => "wpforms-{$form_id}-field_{$field_id}", ); $field['choice_limit'] = empty( $field['choice_limit'] ) ? 0 : (int) $field['choice_limit']; if ( $field['choice_limit'] > 0 ) { $properties['input_container']['data']['choice-limit'] = $field['choice_limit']; } // Set input properties. foreach ( $choices as $key => $choice ) { // Used for dynamic choices. $depth = isset( $choice['depth'] ) ? absint( $choice['depth'] ) : 1; // Choice labels should not be left blank, but if they are we // provide a basic value. $value = isset( $field['show_values'] ) ? $choice['value'] : $choice['label']; if ( '' === $value ) { if ( 1 === count( $choices ) ) { $value = esc_html__( 'Checked', 'wpforms-lite' ); } else { /* translators: %s - choice number. */ $value = sprintf( esc_html__( 'Choice %s', 'wpforms-lite' ), $key ); } } $properties['inputs'][ $key ] = array( 'container' => array( 'attr' => array(), 'class' => array( "choice-{$key}", "depth-{$depth}" ), 'data' => array(), 'id' => '', ), 'label' => array( 'attr' => array( 'for' => "wpforms-{$form_id}-field_{$field_id}_{$key}", ), 'class' => array( 'wpforms-field-label-inline' ), 'data' => array(), 'id' => '', 'text' => $choice['label'], ), 'attr' => array( 'name' => "wpforms[fields][{$field_id}][]", 'value' => $value, ), 'class' => array(), 'data' => array(), 'id' => "wpforms-{$form_id}-field_{$field_id}_{$key}", 'image' => isset( $choice['image'] ) ? $choice['image'] : '', 'required' => ! empty( $field['required'] ) ? 'required' : '', 'default' => isset( $choice['default'] ), ); // Rule for validator only if needed. if ( $field['choice_limit'] > 0 ) { $properties['inputs'][ $key ]['data']['rule-check-limit'] = 'true'; } } // Required class for pagebreak validation. if ( ! empty( $field['required'] ) ) { $properties['input_container']['class'][] = 'wpforms-field-required'; } // Custom properties if image choices is enabled. if ( ! $dynamic && ! empty( $field['choices_images'] ) ) { $properties['input_container']['class'][] = 'wpforms-image-choices'; $properties['input_container']['class'][] = 'wpforms-image-choices-' . sanitize_html_class( $field['choices_images_style'] ); foreach ( $properties['inputs'] as $key => $inputs ) { $properties['inputs'][ $key ]['container']['class'][] = 'wpforms-image-choices-item'; if ( in_array( $field['choices_images_style'], array( 'modern', 'classic' ), true ) ) { $properties['inputs'][ $key ]['class'][] = 'wpforms-screen-reader-element'; } } } // Custom properties for disclaimer format display. if ( ! empty( $field['disclaimer_format'] ) ) { $properties['description']['class'][] = 'wpforms-disclaimer-description'; $properties['description']['value'] = nl2br( $properties['description']['value'] ); } // Add selected class for choices with defaults. foreach ( $properties['inputs'] as $key => $inputs ) { if ( ! empty( $inputs['default'] ) ) { $properties['inputs'][ $key ]['container']['class'][] = 'wpforms-selected'; } } return $properties; } /** * Field options panel inside the builder. * * @since 1.0.0 * * @param array $field Field settings. */ public function field_options( $field ) { /* * Basic field options. */ // Options open markup. $this->field_option( 'basic-options', $field, array( 'markup' => 'open', ) ); // Label. $this->field_option( 'label', $field ); // Choices. $this->field_option( 'choices', $field ); // Choices Images. $this->field_option( 'choices_images', $field ); // Description. $this->field_option( 'description', $field ); // Required toggle. $this->field_option( 'required', $field ); // Options close markup. $this->field_option( 'basic-options', $field, array( 'markup' => 'close', ) ); /* * Advanced field options */ // Options open markup. $this->field_option( 'advanced-options', $field, array( 'markup' => 'open', ) ); // Randomize order of choices. $this->field_element( 'row', $field, array( 'slug' => 'random', 'content' => $this->field_element( 'checkbox', $field, array( 'slug' => 'random', 'value' => isset( $field['random'] ) ? '1' : '0', 'desc' => esc_html__( 'Randomize Choices', 'wpforms-lite' ), 'tooltip' => esc_html__( 'Check this option to randomize the order of the choices.', 'wpforms-lite' ), ), false ), ) ); // Show Values toggle option. This option will only show if already used // or if manually enabled by a filter. if ( ! empty( $field['show_values'] ) || wpforms_show_fields_options_setting() ) { $this->field_element( 'row', $field, array( 'slug' => 'show_values', 'content' => $this->field_element( 'checkbox', $field, array( 'slug' => 'show_values', 'value' => isset( $field['show_values'] ) ? $field['show_values'] : '0', 'desc' => esc_html__( 'Show Values', 'wpforms-lite' ), 'tooltip' => esc_html__( 'Check this to manually set form field values.', 'wpforms-lite' ), ), false ), ) ); } // Choices Images Style (theme). $this->field_option( 'choices_images_style', $field ); // Display format. $this->field_option( 'input_columns', $field ); // Choice Limit. $field['choice_limit'] = empty( $field['choice_limit'] ) ? 0 : (int) $field['choice_limit']; $this->field_element( 'row', $field, array( 'slug' => 'choice_limit', 'content' => $this->field_element( 'label', $field, array( 'slug' => 'choice_limit', 'value' => esc_html__( 'Choice Limit', 'wpforms-lite' ), 'tooltip' => esc_html__( 'Limit the number of checkboxes a user can select. Leave empty for unlimited.', 'wpforms-lite' ), ), false ) . $this->field_element( 'text', $field, array( 'slug' => 'choice_limit', 'value' => $field['choice_limit'] > 0 ? $field['choice_limit'] : '', 'type' => 'number', ), false ), ) ); // Hide label. $this->field_option( 'label_hide', $field ); // Custom CSS classes. $this->field_option( 'css', $field ); // Dynamic choice auto-populating toggle. $this->field_option( 'dynamic_choices', $field ); // Dynamic choice source. $this->field_option( 'dynamic_choices_source', $field ); // Enable Disclaimer formatting. $this->field_element( 'row', $field, array( 'slug' => 'disclaimer_format', 'content' => $this->field_element( 'checkbox', $field, array( 'slug' => 'disclaimer_format', 'value' => isset( $field['disclaimer_format'] ) ? '1' : '0', 'desc' => esc_html__( 'Enable Disclaimer / Terms of Service Display', 'wpforms-lite' ), 'tooltip' => esc_html__( 'Check this option to adjust the field styling to support Disclaimers and Terms of Service type agreements.', 'wpforms-lite' ), ), false ), ) ); // Options close markup. $this->field_option( 'advanced-options', $field, array( 'markup' => 'close', ) ); } /** * Field preview inside the builder. * * @since 1.0.0 * * @param array $field Field settings. */ public function field_preview( $field ) { // Label. $this->field_preview_option( 'label', $field ); // Choices. $this->field_preview_option( 'choices', $field ); // Description. $this->field_preview_option( 'description', $field, array( 'class' => ! empty( $field['disclaimer_format'] ) ? 'disclaimer nl2br' : false, ) ); } /** * Field display on the form front-end. * * @since 1.0.0 * * @param array $field Field settings. * @param array $deprecated Deprecated array. * @param array $form_data Form data and settings. */ public function field_display( $field, $deprecated, $form_data ) { $using_image_choices = empty( $field['dynamic_choices'] ) && ! empty( $field['choices_images'] ); // Define data. $container = $field['properties']['input_container']; $choices = $field['properties']['inputs']; $amp_state_id = ''; if ( wpforms_is_amp() && $using_image_choices ) { $amp_state_id = str_replace( '-', '_', sanitize_key( $container['id'] ) ) . '_state'; $state = array(); foreach ( $choices as $key => $choice ) { $state[ $choice['id'] ] = ! empty( $choice['default'] ); } printf( '<amp-state id="%s"><script type="application/json">%s</script></amp-state>', esc_attr( $amp_state_id ), wp_json_encode( $state ) ); } printf( '<ul %s>', wpforms_html_attributes( $container['id'], $container['class'], $container['data'], $container['attr'] ) ); foreach ( $choices as $key => $choice ) { if ( wpforms_is_amp() && $using_image_choices ) { $choice['container']['attr']['[class]'] = sprintf( '%s + ( %s[%s] ? " wpforms-selected" : "")', wp_json_encode( implode( ' ', $choice['container']['class'] ) ), $amp_state_id, wp_json_encode( $choice['id'] ) ); } // If the field is required, has the label hidden, and has // disclaimer mode enabled, so the required status in choice // label. $required = ''; if ( ! empty( $field['disclaimer_format'] ) && ! empty( $choice['required'] ) && ! empty( $field['label_hide'] ) ) { $required = wpforms_get_field_required_label(); } printf( '<li %s>', wpforms_html_attributes( $choice['container']['id'], $choice['container']['class'], $choice['container']['data'], $choice['container']['attr'] ) ); // The required constraint in HTML5 form validation does not work with checkbox groups, so omit in AMP. $required_attr = wpforms_is_amp() && count( $choices ) > 1 ? '' : $choice['required']; if ( $using_image_choices ) { // Make sure the image choices are keyboard-accessible. $choice['label']['attr']['tabindex'] = 0; if ( wpforms_is_amp() ) { $choice['label']['attr']['on'] = sprintf( 'tap:AMP.setState({ %s: { %s: ! %s[%s] } })', wp_json_encode( $amp_state_id ), wp_json_encode( $choice['id'] ), $amp_state_id, wp_json_encode( $choice['id'] ) ); $choice['label']['attr']['role'] = 'button'; } // Image choices. printf( '<label %s>', wpforms_html_attributes( $choice['label']['id'], $choice['label']['class'], $choice['label']['data'], $choice['label']['attr'] ) ); if ( ! empty( $choice['image'] ) ) { printf( '<span class="wpforms-image-choices-image"><img src="%s" alt="%s"%s></span>', esc_url( $choice['image'] ), esc_attr( $choice['label']['text'] ), ! empty( $choice['label']['text'] ) ? ' title="' . esc_attr( $choice['label']['text'] ) . '"' : '' ); } if ( 'none' === $field['choices_images_style'] ) { echo '<br>'; } $choice['attr']['tabindex'] = '-1'; if ( wpforms_is_amp() ) { $choice['attr']['[checked]'] = sprintf( '%s[%s]', $amp_state_id, wp_json_encode( $choice['id'] ) ); } printf( '<input type="checkbox" %s %s %s>', wpforms_html_attributes( $choice['id'], $choice['class'], $choice['data'], $choice['attr'] ), esc_attr( $required_attr ), checked( '1', $choice['default'], false ) ); echo '<span class="wpforms-image-choices-label">' . wp_kses_post( $choice['label']['text'] ) . '</span>'; echo '</label>'; } else { // Normal display. printf( '<input type="checkbox" %s %s %s>', wpforms_html_attributes( $choice['id'], $choice['class'], $choice['data'], $choice['attr'] ), esc_attr( $required_attr ), checked( '1', $choice['default'], false ) ); printf( '<label %s>%s%s</label>', wpforms_html_attributes( $choice['label']['id'], $choice['label']['class'], $choice['label']['data'], $choice['label']['attr'] ), wp_kses_post( $choice['label']['text'] ), $required ); // phpcs:ignore } echo '</li>'; } echo '</ul>'; } /** * Validate field on form submit. * * @since 1.5.2 * * @param int $field_id field ID. * @param array $field_submit submitted data. * @param array $form_data form data. */ public function validate( $field_id, $field_submit, $form_data ) { $field_submit = (array) $field_submit; $choice_limit = empty( $form_data['fields'][ $field_id ]['choice_limit'] ) ? 0 : (int) $form_data['fields'][ $field_id ]['choice_limit']; $count_choices = count( $field_submit ); if ( $choice_limit > 0 && $count_choices > $choice_limit ) { // Generating the error. $error = wpforms_setting( 'validation-check-limit', esc_html__( 'You have exceeded the number of allowed selections: {#}.', 'wpforms-lite' ) ); $error = str_replace( '{#}', $choice_limit, $error ); } // Basic required check - If field is marked as required, check for entry data. if ( ! empty( $form_data['fields'][ $field_id ]['required'] ) && ( empty( $field_submit ) || ( count( $field_submit ) === 1 && ( ! isset( $field_submit[0] ) || (string) $field_submit[0] === '' ) ) ) ) { $error = wpforms_get_required_label(); } if ( ! empty( $error ) ) { wpforms()->process->errors[ $form_data['id'] ][ $field_id ] = $error; } } /** * Format and sanitize field. * * @since 1.0.2 * * @param int $field_id Field ID. * @param array $field_submit Submitted form data. * @param array $form_data Form data and settings. */ public function format( $field_id, $field_submit, $form_data ) { $field_submit = (array) $field_submit; $field = $form_data['fields'][ $field_id ]; $dynamic = ! empty( $field['dynamic_choices'] ) ? $field['dynamic_choices'] : false; $name = sanitize_text_field( $field['label'] ); $value_raw = wpforms_sanitize_array_combine( $field_submit ); $data = array( 'name' => $name, 'value' => '', 'value_raw' => $value_raw, 'id' => absint( $field_id ), 'type' => $this->type, ); if ( 'post_type' === $dynamic && ! empty( $field['dynamic_post_type'] ) ) { // Dynamic population is enabled using post type. $value_raw = implode( ',', array_map( 'absint', $field_submit ) ); $data['value_raw'] = $value_raw; $data['dynamic'] = 'post_type'; $data['dynamic_items'] = $value_raw; $data['dynamic_post_type'] = $field['dynamic_post_type']; $posts = array(); foreach ( $field_submit as $id ) { $post = get_post( $id ); if ( ! is_wp_error( $post ) && ! empty( $post ) && $data['dynamic_post_type'] === $post->post_type ) { $posts[] = esc_html( $post->post_title ); } } $data['value'] = ! empty( $posts ) ? wpforms_sanitize_array_combine( $posts ) : ''; } elseif ( 'taxonomy' === $dynamic && ! empty( $field['dynamic_taxonomy'] ) ) { // Dynamic population is enabled using taxonomy. $value_raw = implode( ',', array_map( 'absint', $field_submit ) ); $data['value_raw'] = $value_raw; $data['dynamic'] = 'taxonomy'; $data['dynamic_items'] = $value_raw; $data['dynamic_taxonomy'] = $field['dynamic_taxonomy']; $terms = array(); foreach ( $field_submit as $id ) { $term = get_term( $id, $field['dynamic_taxonomy'] ); if ( ! is_wp_error( $term ) && ! empty( $term ) ) { $terms[] = esc_html( $term->name ); } } $data['value'] = ! empty( $terms ) ? wpforms_sanitize_array_combine( $terms ) : ''; } else { // Normal processing, dynamic population is off. $choice_keys = array(); // If show_values is true, that means values posted are the raw values // and not the labels. So we need to set label values. Also store // the choice keys. if ( ! empty( $field['show_values'] ) && '1' == $field['show_values'] ) { foreach ( $field_submit as $item ) { foreach ( $field['choices'] as $key => $choice ) { if ( $item === $choice['value'] || ( empty( $choice['value'] ) && (int) str_replace( 'Choice ', '', $item ) === $key ) ) { $value[] = $choice['label']; $choice_keys[] = $key; break; } } } $data['value'] = ! empty( $value ) ? wpforms_sanitize_array_combine( $value ) : ''; } else { $data['value'] = $value_raw; // Determine choices keys, this is needed for image choices. foreach ( $field_submit as $item ) { foreach ( $field['choices'] as $key => $choice ) { /* translators: %s - choice number. */ if ( $item === $choice['label'] || $item === sprintf( esc_html__( 'Choice %s', 'wpforms-lite' ), $key ) ) { $choice_keys[] = $key; break; } } } } // Images choices are enabled, lookup and store image URLs. if ( ! empty( $choice_keys ) && ! empty( $field['choices_images'] ) ) { $data['images'] = array(); foreach ( $choice_keys as $key ) { $data['images'][] = ! empty( $field['choices'][ $key ]['image'] ) ? esc_url_raw( $field['choices'][ $key ]['image'] ) : ''; } } } // Push field details to be saved. wpforms()->process->fields[ $field_id ] = $data; } } new WPForms_Field_Checkbox(); fields/class-select.php 0000666 00000023331 15213301445 0011111 0 ustar 00 <?php /** * Dropdown field. * * @since 1.0.0 */ class WPForms_Field_Select extends WPForms_Field { /** * Primary class constructor. * * @since 1.0.0 */ public function init() { // Define field type information. $this->name = esc_html__( 'Dropdown', 'wpforms-lite' ); $this->type = 'select'; $this->icon = 'fa-caret-square-o-down'; $this->order = 70; $this->defaults = array( 1 => array( 'label' => esc_html__( 'First Choice', 'wpforms-lite' ), 'value' => '', 'default' => '', ), 2 => array( 'label' => esc_html__( 'Second Choice', 'wpforms-lite' ), 'value' => '', 'default' => '', ), 3 => array( 'label' => esc_html__( 'Third Choice', 'wpforms-lite' ), 'value' => '', 'default' => '', ), ); // Define additional field properties. add_filter( 'wpforms_field_properties_' . $this->type, array( $this, 'field_properties' ), 5, 3 ); } /** * Define additional field properties. * * @since 1.5.0 * * @param array $properties Field properties. * @param array $field Field settings. * @param array $form_data Form data and settings. * * @return array */ public function field_properties( $properties, $field, $form_data ) { // Remove primary input. unset( $properties['inputs']['primary'] ); // Define data. $form_id = absint( $form_data['id'] ); $field_id = absint( $field['id'] ); $choices = $field['choices']; $dynamic = wpforms_get_field_dynamic_choices( $field, $form_id, $form_data ); if ( $dynamic ) { $choices = $dynamic; $field['show_values'] = true; } // Set options container (<select>) properties. $properties['input_container'] = array( 'class' => array(), 'data' => array(), 'id' => "wpforms-{$form_id}-field_{$field_id}", 'attr' => array( 'name' => "wpforms[fields][{$field_id}]", ), ); // Set properties. foreach ( $choices as $key => $choice ) { // Used for dynamic choices. $depth = isset( $choice['depth'] ) ? absint( $choice['depth'] ) : 1; $properties['inputs'][ $key ] = array( 'container' => array( 'attr' => array(), 'class' => array( "choice-{$key}", "depth-{$depth}" ), 'data' => array(), 'id' => '', ), 'label' => array( 'attr' => array( 'for' => "wpforms-{$form_id}-field_{$field_id}_{$key}", ), 'class' => array( 'wpforms-field-label-inline' ), 'data' => array(), 'id' => '', 'text' => $choice['label'], ), 'attr' => array( 'name' => "wpforms[fields][{$field_id}]", 'value' => isset( $field['show_values'] ) ? $choice['value'] : $choice['label'], ), 'class' => array(), 'data' => array(), 'id' => "wpforms-{$form_id}-field_{$field_id}_{$key}", 'required' => ! empty( $field['required'] ) ? 'required' : '', 'default' => isset( $choice['default'] ), ); } // Add class that changes the field size. if ( ! empty( $field['size'] ) ) { $properties['input_container']['class'][] = 'wpforms-field-' . esc_attr( $field['size'] ); } // Required class for pagebreak validation. if ( ! empty( $field['required'] ) ) { $properties['input_container']['class'][] = 'wpforms-field-required'; } return $properties; } /** * Field options panel inside the builder. * * @since 1.0.0 * * @param array $field Field settings. */ public function field_options( $field ) { /* * Basic field options. */ // Options open markup. $this->field_option( 'basic-options', $field, array( 'markup' => 'open', ) ); // Label. $this->field_option( 'label', $field ); // Choices. $this->field_option( 'choices', $field ); // Description. $this->field_option( 'description', $field ); // Required toggle. $this->field_option( 'required', $field ); // Options close markup. $this->field_option( 'basic-options', $field, array( 'markup' => 'close', ) ); /* * Advanced field options. */ // Options open markup. $this->field_option( 'advanced-options', $field, array( 'markup' => 'open', ) ); // Show Values toggle option. This option will only show if already used // or if manually enabled by a filter. if ( ! empty( $field['show_values'] ) || wpforms_show_fields_options_setting() ) { $show_values = $this->field_element( 'checkbox', $field, array( 'slug' => 'show_values', 'value' => isset( $field['show_values'] ) ? $field['show_values'] : '0', 'desc' => esc_html__( 'Show Values', 'wpforms-lite' ), 'tooltip' => esc_html__( 'Check this to manually set form field values.', 'wpforms-lite' ), ), false ); $this->field_element( 'row', $field, array( 'slug' => 'show_values', 'content' => $show_values, ) ); } // Size. $this->field_option( 'size', $field ); // Placeholder. $this->field_option( 'placeholder', $field ); // Hide label. $this->field_option( 'label_hide', $field ); // Custom CSS classes. $this->field_option( 'css', $field ); // Dynamic choice auto-populating toggle. $this->field_option( 'dynamic_choices', $field ); // Dynamic choice source. $this->field_option( 'dynamic_choices_source', $field ); // Options close markup. $this->field_option( 'advanced-options', $field, array( 'markup' => 'close', ) ); } /** * Field preview inside the builder. * * @since 1.0.0 * * @param array $field Field settings. */ public function field_preview( $field ) { // Label. $this->field_preview_option( 'label', $field ); // Choices. $this->field_preview_option( 'choices', $field ); // Description. $this->field_preview_option( 'description', $field ); } /** * Field display on the form front-end. * * @since 1.0.0 * @since 1.5.0 Converted to a new format, where all the data are taken not from $deprecated, but field properties. * * @param array $field Field data and settings. * @param array $deprecated Deprecated array of field attributes. * @param array $form_data Form data and settings. */ public function field_display( $field, $deprecated, $form_data ) { $container = $field['properties']['input_container']; $field_placeholder = ! empty( $field['placeholder'] ) ? $field['placeholder'] : ''; if ( ! empty( $field['required'] ) ) { $container['attr']['required'] = 'required'; } $choices = $field['properties']['inputs']; $has_default = false; // Check to see if any of the options were selected by default. foreach ( $choices as $choice ) { if ( ! empty( $choice['default'] ) ) { $has_default = true; break; } } // Preselect default if no other choices were marked as default. printf( '<select %s>', wpforms_html_attributes( $container['id'], $container['class'], $container['data'], $container['attr'] ) ); // Optional placeholder. if ( ! empty( $field_placeholder ) ) { printf( '<option value="" class="placeholder" disabled %s>%s</option>', selected( false, $has_default, false ), esc_html( $field_placeholder ) ); } // Build the select options. foreach ( $choices as $key => $choice ) { printf( '<option value="%s" %s>%s</option>', esc_attr( $choice['attr']['value'] ), selected( true, ! empty( $choice['default'] ), false ), esc_html( $choice['label']['text'] ) ); } echo '</select>'; } /** * Format and sanitize field. * * @since 1.0.2 * * @param int $field_id Field ID. * @param string $field_submit Submitted field value (selected option). * @param array $form_data Form data and settings. */ public function format( $field_id, $field_submit, $form_data ) { $field = $form_data['fields'][ $field_id ]; $dynamic = ! empty( $field['dynamic_choices'] ) ? $field['dynamic_choices'] : false; $name = sanitize_text_field( $field['label'] ); $value_raw = sanitize_text_field( $field_submit ); $value = ''; $data = array( 'name' => $name, 'value' => '', 'value_raw' => $value_raw, 'id' => absint( $field_id ), 'type' => $this->type, ); if ( 'post_type' === $dynamic && ! empty( $field['dynamic_post_type'] ) ) { // Dynamic population is enabled using post type. $data['dynamic'] = 'post_type'; $data['dynamic_items'] = absint( $value_raw ); $data['dynamic_post_type'] = $field['dynamic_post_type']; $post = get_post( $value_raw ); if ( ! is_wp_error( $post ) && ! empty( $post ) && $data['dynamic_post_type'] === $post->post_type ) { $data['value'] = esc_html( $post->post_title ); } } elseif ( 'taxonomy' === $dynamic && ! empty( $field['dynamic_taxonomy'] ) ) { // Dynamic population is enabled using taxonomy. $data['dynamic'] = 'taxonomy'; $data['dynamic_items'] = absint( $value_raw ); $data['dynamic_taxonomy'] = $field['dynamic_taxonomy']; $term = get_term( $value_raw, $data['dynamic_taxonomy'] ); if ( ! is_wp_error( $term ) && ! empty( $term ) ) { $data['value'] = esc_html( $term->name ); } } else { // Normal processing, dynamic population is off. // If show_values is true, that means values posted are the raw values // and not the labels. So we need to get the label values. if ( ! empty( $field['show_values'] ) && '1' == $field['show_values'] ) { foreach ( $field['choices'] as $choice ) { if ( $choice['value'] === $field_submit ) { $value = $choice['label']; break; } } $data['value'] = sanitize_text_field( $value ); } else { $data['value'] = $value_raw; } } // Push field details to be saved. wpforms()->process->fields[ $field_id ] = $data; } } new WPForms_Field_Select(); fields/class-number.php 0000666 00000011602 15213301445 0011120 0 ustar 00 <?php /** * Number text field. * * @since 1.0.0 */ class WPForms_Field_Number extends WPForms_Field { /** * Primary class constructor. * * @since 1.0.0 */ public function init() { // Define field type information. $this->name = esc_html__( 'Numbers', 'wpforms-lite' ); $this->type = 'number'; $this->icon = 'fa-hashtag'; $this->order = 130; } /** * Field options panel inside the builder. * * @since 1.0.0 * * @param array $field Field data. */ public function field_options( $field ) { /* * Basic field options. */ // Options open markup. $args = array( 'markup' => 'open', ); $this->field_option( 'basic-options', $field, $args ); // Label. $this->field_option( 'label', $field ); // Description. $this->field_option( 'description', $field ); // Required toggle. $this->field_option( 'required', $field ); // Options close markup. $args = array( 'markup' => 'close', ); $this->field_option( 'basic-options', $field, $args ); /* * Advanced field options. */ // Options open markup. $args = array( 'markup' => 'open', ); $this->field_option( 'advanced-options', $field, $args ); // Size. $this->field_option( 'size', $field ); // Placeholder. $this->field_option( 'placeholder', $field ); // Hide label. $this->field_option( 'label_hide', $field ); // Default value. $this->field_option( 'default_value', $field ); // Custom CSS classes. $this->field_option( 'css', $field ); // Options close markup. $args = array( 'markup' => 'close', ); $this->field_option( 'advanced-options', $field, $args ); } /** * Field preview inside the builder. * * @since 1.0.0 * * @param array $field Field data. */ public function field_preview( $field ) { // Define data. $placeholder = ! empty( $field['placeholder'] ) ? $field['placeholder'] : ''; // Label. $this->field_preview_option( 'label', $field ); // Primary input. echo '<input type="text" placeholder="' . esc_attr( $placeholder ) . '" class="primary-input" disabled>'; // Description. $this->field_preview_option( 'description', $field ); } /** * Field display on the form front-end. * * @since 1.0.0 * * @param array $field Field data. * @param array $deprecated Deprecated, not used. * @param array $form_data Form data. */ public function field_display( $field, $deprecated, $form_data ) { // Define data. $primary = $field['properties']['inputs']['primary']; // Primary field. printf( '<input type="number" pattern="\d*" %s %s>', wpforms_html_attributes( $primary['id'], $primary['class'], $primary['data'], $primary['attr'] ), esc_attr( $primary['required'] ) ); } /** * Validate field on form submit. * * @since 1.0.0 * * @param int $field_id Field id. * @param string $field_submit Submitted value. * @param array $form_data Form data. */ public function validate( $field_id, $field_submit, $form_data ) { $form_id = $form_data['id']; $value = $this->sanitize_value( $field_submit ); // If field is marked as required, check for entry data. if ( ! empty( $form_data['fields'][ $field_id ]['required'] ) && empty( $value ) && ! is_numeric( $value ) ) { wpforms()->process->errors[ $form_id ][ $field_id ] = wpforms_get_required_label(); } // Check if value is numeric. if ( ! empty( $value ) && ! is_numeric( $value ) ) { wpforms()->process->errors[ $form_id ][ $field_id ] = apply_filters( 'wpforms_valid_number_label', esc_html__( 'Please enter a valid number.', 'wpforms-lite' ) ); } } /** * Format and sanitize field. * * @since 1.3.5 * * @param int $field_id Field id. * @param string $field_submit Submitted value. * @param array $form_data Form data. */ public function format( $field_id, $field_submit, $form_data ) { // Define data. $name = ! empty( $form_data['fields'][ $field_id ]['label'] ) ? $form_data['fields'][ $field_id ]['label'] : ''; // Set final field details. wpforms()->process->fields[ $field_id ] = array( 'name' => sanitize_text_field( $name ), 'value' => $this->sanitize_value( $field_submit ), 'id' => absint( $field_id ), 'type' => $this->type, ); } /** * Sanitize the value. * * @since 1.5.7 * * @param string $value The number field submitted value. * * @return float|int|string */ private function sanitize_value( $value ) { if ( empty( $value ) && ! is_numeric( $value ) ) { return ''; } // Some browsers allow other non-digit/decimal characters to be submitted // with the num input, which then trips the is_numeric validation below. // To get around this we remove all chars that are not expected. $signed_value = preg_replace( '/[^-0-9.]/', '', $value ); $abs_value = str_replace( '-', '', $signed_value ); return $signed_value < 0 ? '-' . $abs_value : $abs_value; } } new WPForms_Field_Number(); fields/class-name.php 0000666 00000050044 15213301445 0010553 0 ustar 00 <?php /** * Name text field. * * @since 1.0.0 */ class WPForms_Field_Name extends WPForms_Field { /** * Primary class constructor. * * @since 1.0.0 */ public function init() { // Define field type information. $this->name = esc_html__( 'Name', 'wpforms-lite' ); $this->type = 'name'; $this->icon = 'fa-user'; $this->order = 150; // Define additional field properties. add_filter( 'wpforms_field_properties_name', array( $this, 'field_properties' ), 5, 3 ); // Set field to default to required. add_filter( 'wpforms_field_new_required', array( $this, 'default_required' ), 10, 2 ); } /** * Define additional field properties. * * @since 1.3.7 * * @param array $properties Field properties. * @param array $field Field data and settings. * @param array $form_data Form data and settings. * * @return array */ public function field_properties( $properties, $field, $form_data ) { $format = ! empty( $field['format'] ) ? esc_attr( $field['format'] ) : 'first-last'; // Simple format. if ( 'simple' === $format ) { $properties['inputs']['primary']['attr']['placeholder'] = ! empty( $field['simple_placeholder'] ) ? $field['simple_placeholder'] : ''; $properties['inputs']['primary']['attr']['value'] = ! empty( $field['simple_default'] ) ? apply_filters( 'wpforms_process_smart_tags', $field['simple_default'], $form_data ) : ''; return $properties; } // Expanded formats. // Remove primary for expanded formats since we have first, middle, last. unset( $properties['inputs']['primary'] ); $form_id = absint( $form_data['id'] ); $field_id = absint( $field['id'] ); $props = array( 'inputs' => array( 'first' => array( 'attr' => array( 'name' => "wpforms[fields][{$field_id}][first]", 'value' => ! empty( $field['first_default'] ) ? apply_filters( 'wpforms_process_smart_tags', $field['first_default'], $form_data ) : '', 'placeholder' => ! empty( $field['first_placeholder'] ) ? $field['first_placeholder'] : '', ), 'block' => array( 'wpforms-field-row-block', 'wpforms-first', ), 'class' => array( 'wpforms-field-name-first', ), 'data' => array(), 'id' => "wpforms-{$form_id}-field_{$field_id}", 'required' => ! empty( $field['required'] ) ? 'required' : '', 'sublabel' => array( 'hidden' => ! empty( $field['sublabel_hide'] ), 'value' => esc_html__( 'First', 'wpforms-lite' ), ), ), 'middle' => array( 'attr' => array( 'name' => "wpforms[fields][{$field_id}][middle]", 'value' => ! empty( $field['middle_default'] ) ? apply_filters( 'wpforms_process_smart_tags', $field['middle_default'], $form_data ) : '', 'placeholder' => ! empty( $field['middle_placeholder'] ) ? $field['middle_placeholder'] : '', ), 'block' => array( 'wpforms-field-row-block', 'wpforms-one-fifth', ), 'class' => array( 'wpforms-field-name-middle', ), 'data' => array(), 'id' => "wpforms-{$form_id}-field_{$field_id}-middle", 'required' => '', 'sublabel' => array( 'hidden' => ! empty( $field['sublabel_hide'] ), 'value' => esc_html__( 'Middle', 'wpforms-lite' ), ), ), 'last' => array( 'attr' => array( 'name' => "wpforms[fields][{$field_id}][last]", 'value' => ! empty( $field['last_default'] ) ? apply_filters( 'wpforms_process_smart_tags', $field['last_default'], $form_data ) : '', 'placeholder' => ! empty( $field['last_placeholder'] ) ? $field['last_placeholder'] : '', ), 'block' => array( 'wpforms-field-row-block', ), 'class' => array( 'wpforms-field-name-last', ), 'data' => array(), 'id' => "wpforms-{$form_id}-field_{$field_id}-last", 'required' => ! empty( $field['required'] ) ? 'required' : '', 'sublabel' => array( 'hidden' => ! empty( $field['sublabel_hide'] ), 'value' => esc_html__( 'Last', 'wpforms-lite' ), ), ), ), ); $properties = array_merge_recursive( $properties, $props ); // Input First: add error class if needed. if ( ! empty( $properties['error']['value']['first'] ) ) { $properties['inputs']['first']['class'][] = 'wpforms-error'; } // Input First: add required class if needed. if ( ! empty( $field['required'] ) ) { $properties['inputs']['first']['class'][] = 'wpforms-field-required'; } // Input First: add column class. $properties['inputs']['first']['block'][] = 'first-last' === $format ? 'wpforms-one-half' : 'wpforms-two-fifths'; // Input Last: add error class if needed. if ( ! empty( $properties['error']['value']['last'] ) ) { $properties['inputs']['last']['class'][] = 'wpforms-error'; } // Input Last: add required class if needed. if ( ! empty( $field['required'] ) ) { $properties['inputs']['last']['class'][] = 'wpforms-field-required'; } // Input Last: add column class. $properties['inputs']['last']['block'][] = 'first-last' === $format ? 'wpforms-one-half' : 'wpforms-two-fifths'; return $properties; } /** * Name fields should default to being required. * * @since 1.0.8 * * @param bool $required * @param array $field * * @return bool */ public function default_required( $required, $field ) { if ( 'name' === $field['type'] ) { return true; } return $required; } /** * Field options panel inside the builder. * * @since 1.0.0 * * @param array $field */ public function field_options( $field ) { // Define data. $format = ! empty( $field['format'] ) ? esc_attr( $field['format'] ) : 'first-last'; /* * Basic field options. */ // Options open markup. $args = array( 'markup' => 'open', ); $this->field_option( 'basic-options', $field, $args ); // Label. $this->field_option( 'label', $field ); // Format. $lbl = $this->field_element( 'label', $field, array( 'slug' => 'format', 'value' => esc_html__( 'Format', 'wpforms-lite' ), 'tooltip' => esc_html__( 'Select format to use for the name form field', 'wpforms-lite' ), ), false ); $fld = $this->field_element( 'select', $field, array( 'slug' => 'format', 'value' => $format, 'options' => array( 'simple' => esc_html__( 'Simple', 'wpforms-lite' ), 'first-last' => esc_html__( 'First Last', 'wpforms-lite' ), 'first-middle-last' => esc_html__( 'First Middle Last', 'wpforms-lite' ), ), ), false ); $args = array( 'slug' => 'format', 'content' => $lbl . $fld, ); $this->field_element( 'row', $field, $args ); // Description. $this->field_option( 'description', $field ); // Required toggle. $this->field_option( 'required', $field ); // Options close markup. $args = array( 'markup' => 'close', ); $this->field_option( 'basic-options', $field, $args ); /* * Advanced field options. */ // Options open markup. $args = array( 'markup' => 'open', ); $this->field_option( 'advanced-options', $field, $args ); // Size. $this->field_option( 'size', $field ); echo '<div class="format-selected-' . $format . ' format-selected">'; // Simple. $simple_placeholder = ! empty( $field['simple_placeholder'] ) ? esc_attr( $field['simple_placeholder'] ) : ''; $simple_default = ! empty( $field['simple_default'] ) ? esc_attr( $field['simple_default'] ) : ''; printf( '<div class="wpforms-clear wpforms-field-option-row wpforms-field-option-row-simple" id="wpforms-field-option-row-%d-simple" data-subfield="simple" data-field-id="%d">', $field['id'], $field['id'] ); $this->field_element( 'label', $field, array( 'slug' => 'simple_placeholder', 'value' => esc_html__( 'Name', 'wpforms-lite' ), 'tooltip' => esc_html__( 'Name field advanced options.', 'wpforms-lite' ) ) ); echo '<div class="placeholder">'; printf( '<input type="text" class="placeholder" id="wpforms-field-option-%d-simple_placeholder" name="fields[%d][simple_placeholder]" value="%s">', $field['id'], $field['id'], $simple_placeholder ); printf( '<label for="wpforms-field-option-%d-simple_placeholder" class="sub-label">%s</label>', $field['id'], esc_html__( 'Placeholder', 'wpforms-lite' ) ); echo '</div>'; echo '<div class="default">'; printf( '<input type="text" class="default" id="wpforms-field-option-%d-simple_default" name="fields[%d][simple_default]" value="%s">', $field['id'], $field['id'], $simple_default ); printf( '<label for="wpforms-field-option-%d-simple_default" class="sub-label">%s</label>', $field['id'], esc_html__( 'Default Value', 'wpforms-lite' ) ); echo '</div>'; echo '</div>'; // First. $first_placeholder = ! empty( $field['first_placeholder'] ) ? esc_attr( $field['first_placeholder'] ) : ''; $first_default = ! empty( $field['first_default'] ) ? esc_attr( $field['first_default'] ) : ''; printf( '<div class="wpforms-clear wpforms-field-option-row wpforms-field-option-row-first" id="wpforms-field-option-row-%d-first" data-subfield="first-name" data-field-id="%d">', $field['id'], $field['id'] ); $this->field_element( 'label', $field, array( 'slug' => 'first_placeholder', 'value' => esc_html__( 'First Name', 'wpforms-lite' ), 'tooltip' => esc_html__( 'First name field advanced options.', 'wpforms-lite' ) ) ); echo '<div class="placeholder">'; printf( '<input type="text" class="placeholder" id="wpforms-field-option-%d-first_placeholder" name="fields[%d][first_placeholder]" value="%s">', $field['id'], $field['id'], $first_placeholder ); printf( '<label for="wpforms-field-option-%d-first_placeholder" class="sub-label">%s</label>', $field['id'], esc_html__( 'Placeholder', 'wpforms-lite' ) ); echo '</div>'; echo '<div class="default">'; printf( '<input type="text" class="default" id="wpforms-field-option-%d-first_default" name="fields[%d][first_default]" value="%s">', $field['id'], $field['id'], $first_default ); printf( '<label for="wpforms-field-option-%d-first_default" class="sub-label">%s</label>', $field['id'], esc_html__( 'Default Value', 'wpforms-lite' ) ); echo '</div>'; echo '</div>'; // Middle. $middle_placeholder = ! empty( $field['middle_placeholder'] ) ? esc_attr( $field['middle_placeholder'] ) : ''; $middle_default = ! empty( $field['middle_default'] ) ? esc_attr( $field['middle_default'] ) : ''; printf( '<div class="wpforms-clear wpforms-field-option-row wpforms-field-option-row-middle" id="wpforms-field-option-row-%d-middle" data-subfield="middle-name" data-field-id="%d">', $field['id'], $field['id'] ); $this->field_element( 'label', $field, array( 'slug' => 'middle_placeholder', 'value' => esc_html__( 'Middle Name', 'wpforms-lite' ), 'tooltip' => esc_html__( 'Middle name field advanced options.', 'wpforms-lite' ) ) ); echo '<div class="placeholder">'; printf( '<input type="text" class="placeholder" id="wpforms-field-option-%d-middle_placeholder" name="fields[%d][middle_placeholder]" value="%s">', $field['id'], $field['id'], $middle_placeholder ); printf( '<label for="wpforms-field-option-%d-middle_placeholder" class="sub-label">%s</label>', $field['id'], esc_html__( 'Placeholder', 'wpforms-lite' ) ); echo '</div>'; echo '<div class="default">'; printf( '<input type="text" class="default" id="wpforms-field-option-%d-middle_default" name="fields[%d][middle_default]" value="%s">', $field['id'], $field['id'], $middle_default ); printf( '<label for="wpforms-field-option-%d-middle_default" class="sub-label">%s</label>', $field['id'], esc_html__( 'Default Value', 'wpforms-lite' ) ); echo '</div>'; echo '</div>'; // Last. $last_placeholder = ! empty( $field['last_placeholder'] ) ? esc_attr( $field['last_placeholder'] ) : ''; $last_default = ! empty( $field['last_default'] ) ? esc_attr( $field['last_default'] ) : ''; printf( '<div class="wpforms-clear wpforms-field-option-row wpforms-field-option-row-last" id="wpforms-field-option-row-%d-last" data-subfield="last-name" data-field-id="%d">', $field['id'], $field['id'] ); $this->field_element( 'label', $field, array( 'slug' => 'last_placeholder', 'value' => esc_html__( 'Last Name', 'wpforms-lite' ), 'tooltip' => esc_html__( 'Last name field advanced options.', 'wpforms-lite' ) ) ); echo '<div class="placeholder">'; printf( '<input type="text" class="placeholder" id="wpforms-field-option-%d-last_placeholder" name="fields[%d][last_placeholder]" value="%s">', $field['id'], $field['id'], $last_placeholder ); printf( '<label for="wpforms-field-option-%d-last_placeholder" class="sub-label">%s</label>', $field['id'], esc_html__( 'Placeholder', 'wpforms-lite' ) ); echo '</div>'; echo '<div class="default">'; printf( '<input type="text" class="default" id="wpforms-field-option-%d-last_default" name="fields[%d][last_default]" value="%s">', $field['id'], $field['id'], $last_default ); printf( '<label for="wpforms-field-option-%d-last_default" class="sub-label">%s</label>', $field['id'], esc_html__( 'Default Value', 'wpforms-lite' ) ); echo '</div>'; echo '</div>'; echo '</div>'; // Hide Label. $this->field_option( 'label_hide', $field ); // Hide sub-labels. $this->field_option( 'sublabel_hide', $field ); // Custom CSS classes. $this->field_option( 'css', $field ); // Options close markup. $args = array( 'markup' => 'close', ); $this->field_option( 'advanced-options', $field, $args ); } /** * Field preview inside the builder. * * @since 1.0.0 * * @param array $field Field information. */ public function field_preview( $field ) { // Define data. $simple_placeholder = ! empty( $field['simple_placeholder'] ) ? esc_attr( $field['simple_placeholder'] ) : ''; $first_placeholder = ! empty( $field['first_placeholder'] ) ? esc_attr( $field['first_placeholder'] ) : ''; $middle_placeholder = ! empty( $field['middle_placeholder'] ) ? esc_attr( $field['middle_placeholder'] ) : ''; $last_placeholder = ! empty( $field['last_placeholder'] ) ? esc_attr( $field['last_placeholder'] ) : ''; $format = ! empty( $field['format'] ) ? esc_attr( $field['format'] ) : 'first-last'; // Label. $this->field_preview_option( 'label', $field ); ?> <div class="format-selected-<?php echo $format; ?> format-selected"> <div class="wpforms-simple"> <input type="text" placeholder="<?php echo $simple_placeholder; ?>" class="primary-input" disabled> </div> <div class="wpforms-first-name"> <input type="text" placeholder="<?php echo $first_placeholder; ?>" class="primary-input" disabled> <label class="wpforms-sub-label"><?php esc_html_e( 'First', 'wpforms-lite' ); ?></label> </div> <div class="wpforms-middle-name"> <input type="text" placeholder="<?php echo $middle_placeholder; ?>" class="primary-input" disabled> <label class="wpforms-sub-label"><?php esc_html_e( 'Middle', 'wpforms-lite' ); ?></label> </div> <div class="wpforms-last-name"> <input type="text" placeholder="<?php echo $last_placeholder; ?>" class="primary-input" disabled> <label class="wpforms-sub-label"><?php esc_html_e( 'Last', 'wpforms-lite' ); ?></label> </div> </div> <?php // Description. $this->field_preview_option( 'description', $field ); } /** * Field display on the form front-end. * * @since 1.0.0 * * @param array $field Field information. * @param array $deprecated Deprecated parameter, not used anymore. * @param array $form_data Form data and settings. */ public function field_display( $field, $deprecated, $form_data ) { // Define data. $format = ! empty( $field['format'] ) ? esc_attr( $field['format'] ) : 'first-last'; $primary = ! empty( $field['properties']['inputs']['primary'] ) ? $field['properties']['inputs']['primary'] : ''; $first = ! empty( $field['properties']['inputs']['first'] ) ? $field['properties']['inputs']['first'] : ''; $middle = ! empty( $field['properties']['inputs']['middle'] ) ? $field['properties']['inputs']['middle'] : ''; $last = ! empty( $field['properties']['inputs']['last'] ) ? $field['properties']['inputs']['last'] : ''; // Simple format. if ( 'simple' === $format ) { // Primary field (Simple). printf( '<input type="text" %s %s>', wpforms_html_attributes( $primary['id'], $primary['class'], $primary['data'], $primary['attr'] ), $primary['required'] ); // Expanded formats. } else { // Row wrapper. echo '<div class="wpforms-field-row wpforms-field-' . sanitize_html_class( $field['size'] ) . '">'; // First name. echo '<div ' . wpforms_html_attributes( false, $first['block'] ) . '>'; $this->field_display_sublabel( 'first', 'before', $field ); printf( '<input type="text" %s %s>', wpforms_html_attributes( $first['id'], $first['class'], $first['data'], $first['attr'] ), $first['required'] ); $this->field_display_sublabel( 'first', 'after', $field ); $this->field_display_error( 'first', $field ); echo '</div>'; // Middle name. if ( 'first-middle-last' === $format ) { echo '<div ' . wpforms_html_attributes( false, $middle['block'] ) . '>'; $this->field_display_sublabel( 'middle', 'before', $field ); printf( '<input type="text" %s %s>', wpforms_html_attributes( $middle['id'], $middle['class'], $middle['data'], $middle['attr'] ), $middle['required'] ); $this->field_display_sublabel( 'middle', 'after', $field ); $this->field_display_error( 'middle', $field ); echo '</div>'; } // Last name. echo '<div ' . wpforms_html_attributes( false, $last['block'] ) . '>'; $this->field_display_sublabel( 'last', 'before', $field ); printf( '<input type="text" %s %s>', wpforms_html_attributes( $last['id'], $last['class'], $last['data'], $last['attr'] ), $last['required'] ); $this->field_display_sublabel( 'last', 'after', $field ); $this->field_display_error( 'last', $field ); echo '</div>'; echo '</div>'; } } /** * Validate field on form submit. * * @since 1.0.0 * * @param int $field_id * @param array $field_submit * @param array $form_data */ public function validate( $field_id, $field_submit, $form_data ) { // Extended validation needed for the different name fields. if ( ! empty( $form_data['fields'][ $field_id ]['required'] ) ) { $form_id = $form_data['id']; $format = $form_data['fields'][ $field_id ]['format']; $required = wpforms_get_required_label(); if ( 'simple' === $format && empty( $field_submit ) ) { wpforms()->process->errors[ $form_id ][ $field_id ] = $required; } if ( ( 'first-last' === $format || 'first-middle-last' === $format ) && empty( $field_submit['first'] ) ) { wpforms()->process->errors[ $form_id ][ $field_id ]['first'] = $required; } if ( ( 'first-last' === $format || 'first-middle-last' === $format ) && empty( $field_submit['last'] ) ) { wpforms()->process->errors[ $form_id ][ $field_id ]['last'] = $required; } } } /** * Format and sanitize field. * * @since 1.0.0 * * @param int $field_id * @param array $field_submit * @param array $form_data */ public function format( $field_id, $field_submit, $form_data ) { // Define data. $name = ! empty( $form_data['fields'][ $field_id ]['label'] ) ? $form_data['fields'][ $field_id ]['label'] : ''; $first = ! empty( $field_submit['first'] ) ? $field_submit['first'] : ''; $middle = ! empty( $field_submit['middle'] ) ? $field_submit['middle'] : ''; $last = ! empty( $field_submit['last'] ) ? $field_submit['last'] : ''; if ( is_array( $field_submit ) ) { $value = implode( ' ', array_filter( array( $first, $middle, $last ) ) ); } else { $value = $field_submit; } // Set final field details. wpforms()->process->fields[ $field_id ] = array( 'name' => sanitize_text_field( $name ), 'value' => sanitize_text_field( $value ), 'id' => absint( $field_id ), 'type' => $this->type, 'first' => sanitize_text_field( $first ), 'middle' => sanitize_text_field( $middle ), 'last' => sanitize_text_field( $last ), ); } } new WPForms_Field_Name(); fields/class-textarea.php 0000666 00000017350 15213301445 0011453 0 ustar 00 <?php /** * Paragraph text field. * * @since 1.0.0 */ class WPForms_Field_Textarea extends WPForms_Field { /** * Primary class constructor. * * @since 1.0.0 */ public function init() { // Define field type information. $this->name = esc_html__( 'Paragraph Text', 'wpforms-lite' ); $this->type = 'textarea'; $this->icon = 'fa-paragraph'; $this->order = 50; add_action( 'wpforms_frontend_js', array( $this, 'frontend_js' ) ); } /** * Field options panel inside the builder. * * @since 1.0.0 * * @param array $field Field data and settings. */ public function field_options( $field ) { /* * Basic field options. */ // Options open markup. $this->field_option( 'basic-options', $field, array( 'markup' => 'open', ) ); // Label. $this->field_option( 'label', $field ); // Description. $this->field_option( 'description', $field ); // Required toggle. $this->field_option( 'required', $field ); // Options close markup. $this->field_option( 'basic-options', $field, array( 'markup' => 'close', ) ); /* * Advanced field options. */ // Options open markup. $args = array( 'markup' => 'open', ); $this->field_option( 'advanced-options', $field, $args ); // Size. $this->field_option( 'size', $field ); // Placeholder. $this->field_option( 'placeholder', $field ); // Hide label. $this->field_option( 'label_hide', $field ); // Limit length. $args = array( 'slug' => 'limit_enabled', 'content' => $this->field_element( 'checkbox', $field, array( 'slug' => 'limit_enabled', 'value' => isset( $field['limit_enabled'] ) ? '1' : '0', 'desc' => esc_html__( 'Limit Length', 'wpforms-lite' ), 'tooltip' => esc_html__( 'Check this option to limit text length by characters or words count.', 'wpforms-lite' ), ), false ), ); $this->field_element( 'row', $field, $args ); $count = $this->field_element( 'text', $field, array( 'type' => 'number', 'slug' => 'limit_count', 'attrs' => array( 'min' => 1, 'step' => 1, 'pattern' => '[0-9]', ), 'value' => ! empty( $field['limit_count'] ) ? $field['limit_count'] : 1, ), false ); $mode = $this->field_element( 'select', $field, array( 'slug' => 'limit_mode', 'value' => ! empty( $field['limit_mode'] ) ? esc_attr( $field['limit_mode'] ) : 'characters', 'options' => array( 'characters' => esc_html__( 'Characters', 'wpforms-lite' ), 'words' => esc_html__( 'Words', 'wpforms-lite' ), ), ), false ); $args = array( 'slug' => 'limit_controls', 'class' => ! isset( $field['limit_enabled'] ) ? 'wpforms-hide' : '', 'content' => $count . $mode, ); $this->field_element( 'row', $field, $args ); // Default value. $this->field_option( 'default_value', $field ); // Custom CSS classes. $this->field_option( 'css', $field ); // Options close markup. $this->field_option( 'advanced-options', $field, array( 'markup' => 'close', ) ); } /** * Field preview inside the builder. * * @since 1.0.0 * * @param array $field Field data and settings. */ public function field_preview( $field ) { // Label. $this->field_preview_option( 'label', $field ); // Primary input. $placeholder = ! empty( $field['placeholder'] ) ? $field['placeholder'] : ''; echo '<textarea placeholder="' . esc_attr( $placeholder ) . '" class="primary-input" disabled></textarea>'; // Description. $this->field_preview_option( 'description', $field ); } /** * Field display on the form front-end. * * @since 1.0.0 * * @param array $field Field data and settings. * @param array $deprecated Deprecated. * @param array $form_data Form data and settings. */ public function field_display( $field, $deprecated, $form_data ) { // Define data. $primary = $field['properties']['inputs']['primary']; $value = ''; if ( ! empty( $primary['attr']['value'] ) ) { $value = wpforms_sanitize_textarea_field( $primary['attr']['value'] ); unset( $primary['attr']['value'] ); } if ( isset( $field['limit_enabled'] ) ) { $limit_count = isset( $field['limit_count'] ) ? absint( $field['limit_count'] ) : 0; $limit_mode = isset( $field['limit_mode'] ) ? sanitize_key( $field['limit_mode'] ) : 'characters'; $primary['data']['form-id'] = $form_data['id']; $primary['data']['field-id'] = $field['id']; if ( 'characters' === $limit_mode ) { $primary['class'][] = 'wpforms-limit-characters-enabled'; $primary['attr']['maxlength'] = $limit_count; $primary['data']['text-limit'] = $limit_count; } else { $primary['class'][] = 'wpforms-limit-words-enabled'; $primary['data']['text-limit'] = $limit_count; } } // Primary field. printf( '<textarea %s %s>%s</textarea>', wpforms_html_attributes( $primary['id'], $primary['class'], $primary['data'], $primary['attr'] ), $primary['required'], // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped $value // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ); } /** * Enqueue frontend limit option js. * * @since 1.5.6 * * @param array $forms Forms on the current page. */ public function frontend_js( $forms ) { // Get fields. $fields = array_map( function( $form ) { return empty( $form['fields'] ) ? array() : $form['fields']; }, (array) $forms ); // Make fields flat. $fields = array_reduce( $fields, function( $accumulator, $current ) { return array_merge( $accumulator, $current ); }, array() ); // Leave only fields with limit. $fields = array_filter( $fields, function( $field ) { return $field['type'] === $this->type && isset( $field['limit_enabled'] ); } ); if ( count( $fields ) ) { $min = \wpforms_get_min_suffix(); wp_enqueue_script( 'wpforms-text-limit', WPFORMS_PLUGIN_URL . "assets/js/text-limit{$min}.js", array(), WPFORMS_VERSION, true ); } } /** * Format and sanitize field. * * @since 1.5.6 * * @param int $field_id Field ID. * @param mixed $field_submit Field value that was submitted. * @param array $form_data Form data and settings. */ public function format( $field_id, $field_submit, $form_data ) { $field = $form_data['fields'][ $field_id ]; if ( is_array( $field_submit ) ) { $field_submit = array_filter( $field_submit ); $field_submit = implode( "\r\n", $field_submit ); } $name = ! empty( $field['label'] ) ? sanitize_text_field( $field['label'] ) : ''; // Sanitize but keep line breaks. $value = wpforms_sanitize_textarea_field( $field_submit ); if ( isset( $field['limit_enabled'] ) ) { $limit = absint( $field['limit_count'] ); $mode = sanitize_key( $field['limit_mode'] ); if ( 'characters' === $mode ) { if ( mb_strlen( str_replace( "\r\n", "\n", $value ) ) > $limit ) { /* translators: %s - limit characters number. */ wpforms()->process->errors[ $form_data['id'] ][ $field_id ] = sprintf( _n( 'Text can\'t exceed %d character.', 'Text can\'t exceed %d characters.', $limit, 'wpforms-lite' ), $limit ); return; } } else { $words = preg_split( '/[\s,]+/', $value ); $words = is_array( $words ) ? count( $words ) : 0; if ( $words > $limit ) { /* translators: %s - limit words number. */ wpforms()->process->errors[ $form_data['id'] ][ $field_id ] = sprintf( _n( 'Text can\'t exceed %d word.', 'Text can\'t exceed %d words.', $limit, 'wpforms-lite' ), $limit ); return; } } } wpforms()->process->fields[ $field_id ] = array( 'name' => $name, 'value' => $value, 'id' => absint( $field_id ), 'type' => $this->type, ); } } new WPForms_Field_Textarea(); fields/class-number-slider.php 0000666 00000030755 15213301445 0012412 0 ustar 00 <?php /** * Number Slider field. * * @since 1.5.7 */ class WPForms_Field_Number_Slider extends WPForms_Field { /** * Default minimum value of the field. * * @since 1.5.7 */ const SLIDER_MIN = 0; /** * Default maximum value of the field. * * @since 1.5.7 */ const SLIDER_MAX = 10; /** * Default step value of the field. * * @since 1.5.7 */ const SLIDER_STEP = 1; /** * Primary class constructor. * * @since 1.5.7 */ public function init() { // Define field type information. $this->name = esc_html__( 'Number Slider', 'wpforms-lite' ); $this->type = 'number-slider'; $this->icon = 'fa-sliders'; $this->order = 180; // Customize value format for HTML emails. add_filter( 'wpforms_html_field_value', array( $this, 'html_email_value' ), 10, 4 ); } /** * Customize format for HTML email notifications. * * @since 1.5.7 * * @param string $val Field value. * @param array $field Field settings. * @param array $form_data Form data and settings. * @param string $context Value display context. * * @return string */ public function html_email_value( $val, $field, $form_data = array(), $context = '' ) { if ( empty( $field['value_raw'] ) || $field['type'] !== $this->type ) { return $val; } $value = isset( $field['value_raw']['value'] ) ? (float) $field['value_raw']['value'] : 0; $min = isset( $field['value_raw']['min'] ) ? (float) $field['value_raw']['min'] : self::SLIDER_MIN; $max = isset( $field['value_raw']['max'] ) ? (float) $field['value_raw']['max'] : self::SLIDER_MAX; $html_value = $value; if ( strpos( $field['value_raw']['value_display'], '{value}' ) !== false ) { $html_value = str_replace( '{value}', /* translators: %1$s - Number slider selected value, %2$s - its minimum value, %3$s - its maximum value. */ sprintf( esc_html__( '%1$s (%2$s min / %3$s max)', 'wpforms-lite' ), $value, $min, $max ), $field['value_raw']['value_display'] ); } return $html_value; } /** * Field options panel inside the builder. * * @since 1.5.7 * * @param array $field Field settings. */ public function field_options( $field ) { /* * Basic field options. */ // Options open markup. $args = array( 'markup' => 'open', ); $this->field_option( 'basic-options', $field, $args ); // Label. $this->field_option( 'label', $field ); // Description. $this->field_option( 'description', $field ); // Required toggle disabled. $this->field_element( 'text', $field, array( 'slug' => 'required', 'value' => '', 'type' => 'hidden', ) ); // Value: min/max. $lbl = $this->field_element( 'label', $field, array( 'slug' => 'value', 'value' => esc_html__( 'Value', 'wpforms-lite' ), 'tooltip' => esc_html__( 'Define the minimum and the maximum values for the slider.', 'wpforms-lite' ), ), false ); $min = $this->field_element( 'text', $field, array( 'type' => 'number', 'slug' => 'min', 'class' => 'wpforms-number-slider-min', 'value' => ! empty( $field['min'] ) ? (float) $field['min'] : self::SLIDER_MIN, ), false ); $max = $this->field_element( 'text', $field, array( 'type' => 'number', 'slug' => 'max', 'class' => 'wpforms-number-slider-max', 'value' => ! empty( $field['max'] ) ? (float) $field['max'] : self::SLIDER_MAX, ), false ); $this->field_element( 'row', $field, array( 'slug' => 'min_max', 'content' => $lbl . wpforms_render( 'fields/number-slider/builder-option-min-max', array( 'label' => $lbl, 'input_min' => $min, 'input_max' => $max, 'field_id' => $field['id'], ), true ), ) ); // Options close markup. $args = array( 'markup' => 'close', ); $this->field_option( 'basic-options', $field, $args ); /* * Advanced field options. */ // Options open markup. $args = array( 'markup' => 'open', ); $this->field_option( 'advanced-options', $field, $args ); // Size. $this->field_option( 'size', $field ); // Hide label. $this->field_option( 'label_hide', $field ); // Default value. $lbl = $this->field_element( 'label', $field, array( 'slug' => 'default_value', 'value' => esc_html__( 'Default Value', 'wpforms-lite' ), 'tooltip' => esc_html__( 'Enter a default value for this field.', 'wpforms-lite' ), ), false ); $fld = $this->field_element( 'text', $field, array( 'type' => 'number', 'slug' => 'default_value', 'class' => 'wpforms-number-slider-default-value', 'value' => ! empty( $field['default_value'] ) ? (float) $field['default_value'] : 0, 'attrs' => array( 'min' => isset( $field['min'] ) && is_numeric( $field['min'] ) ? (float) $field['min'] : self::SLIDER_MIN, 'max' => isset( $field['max'] ) && is_numeric( $field['max'] ) ? (float) $field['max'] : self::SLIDER_MAX, 'step' => isset( $field['step'] ) && is_numeric( $field['step'] ) ? (float) $field['step'] : self::SLIDER_STEP, ), ), false ); $this->field_element( 'row', $field, array( 'slug' => 'default_value', 'content' => $lbl . $fld, ) ); // Value display. $lbl = $this->field_element( 'label', $field, array( 'slug' => 'value_display', 'value' => esc_html__( 'Value Display', 'wpforms-lite' ), 'tooltip' => esc_html__( 'Displays the currently selected value below the slider.', 'wpforms-lite' ), ), false ); $fld = $this->field_element( 'text', $field, array( 'slug' => 'value_display', 'class' => 'wpforms-number-slider-value-display', 'value' => isset( $field['value_display'] ) ? $field['value_display'] : esc_html__( 'Selected Value: {value}', 'wpforms-lite' ), ), false ); $this->field_element( 'row', $field, array( 'slug' => 'value_display', 'content' => $lbl . $fld, ) ); // Steps. $lbl = $this->field_element( 'label', $field, array( 'slug' => 'step', 'value' => esc_html__( 'Increment', 'wpforms-lite' ), 'tooltip' => esc_html__( 'Determines the increment between selectable values on the slider.', 'wpforms-lite' ), ), false ); $fld = $this->field_element( 'text', $field, array( 'type' => 'number', 'slug' => 'step', 'class' => 'wpforms-number-slider-step', 'value' => ! empty( $field['step'] ) ? abs( $field['step'] ) : self::SLIDER_STEP, 'attrs' => array( 'min' => 0, 'max' => isset( $field['max'] ) && is_numeric( $field['max'] ) ? (float) $field['max'] : self::SLIDER_MAX, ), ), false ); $this->field_element( 'row', $field, array( 'slug' => 'step', 'content' => $lbl . $fld, ) ); // Custom CSS classes. $this->field_option( 'css', $field ); // Options close markup. $args = array( 'markup' => 'close', ); $this->field_option( 'advanced-options', $field, $args ); } /** * Field preview inside the builder. * * @since 1.5.7 * * @param array $field Field data. */ public function field_preview( $field ) { // Label. $this->field_preview_option( 'label', $field ); $value_display = isset( $field['value_display'] ) ? esc_attr( $field['value_display'] ) : esc_html__( 'Selected Value: {value}', 'wpforms-lite' ); $default_value = ! empty( $field['default_value'] ) ? (float) $field['default_value'] : 0; echo wpforms_render( // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped 'fields/number-slider/builder-preview', array( 'min' => isset( $field['min'] ) && is_numeric( $field['min'] ) ? (float) $field['min'] : self::SLIDER_MIN, 'max' => isset( $field['max'] ) && is_numeric( $field['max'] ) ? (float) $field['max'] : self::SLIDER_MAX, 'step' => isset( $field['step'] ) && is_numeric( $field['step'] ) ? (float) $field['step'] : self::SLIDER_STEP, 'value_display' => $value_display, 'default_value' => $default_value, 'value_hint' => str_replace( '{value}', '<b>' . $default_value . '</b>', wp_kses( $value_display, wpforms_builder_preview_get_allowed_tags() ) ), 'field_id' => $field['id'], ), true ); // Description. $this->field_preview_option( 'description', $field ); } /** * Field display on the form front-end. * * @since 1.5.7 * * @param array $field Field data and settings. * @param array $deprecated Deprecated field attributes. Use $field['properties'] instead. * @param array $form_data Form data and settings. */ public function field_display( $field, $deprecated, $form_data ) { // Define data. $primary = $field['properties']['inputs']['primary']; $value_display = isset( $field['value_display'] ) ? esc_attr( $field['value_display'] ) : esc_html__( 'Selected Value: {value}', 'wpforms-lite' ); $default_value = ! empty( $field['default_value'] ) ? (float) $field['default_value'] : 0; $hint_value = ! empty( $primary['attr']['value'] ) ? (float) $primary['attr']['value'] : $default_value; $hint = str_replace( '{value}', '<b>' . $hint_value . '</b>', $value_display ); // phpcs:ignore echo wpforms_render( 'fields/number-slider/frontend', array( 'min' => isset( $field['min'] ) && is_numeric( $field['min'] ) ? (float) $field['min'] : self::SLIDER_MIN, 'max' => isset( $field['max'] ) && is_numeric( $field['max'] ) ? (float) $field['max'] : self::SLIDER_MAX, 'step' => isset( $field['step'] ) && is_numeric( $field['step'] ) ? (float) $field['step'] : self::SLIDER_STEP, 'value_display' => $value_display, 'default_value' => $default_value, 'value_hint' => $hint, 'field_id' => $field['id'], 'required' => $primary['required'], 'html_atts' => wpforms_html_attributes( $primary['id'], $primary['class'], $primary['data'], $primary['attr'] ), ), true ); } /** * Validate field on form submit. * * @since 1.5.7 * * @param int $field_id Field ID. * @param int|float|string $field_submit Submitted field value. * @param array $form_data Form data and settings. */ public function validate( $field_id, $field_submit, $form_data ) { $form_id = $form_data['id']; $field_submit = (float) $this->sanitize_value( $field_submit ); // Basic required check - if field is marked as required, check for entry data. if ( ! empty( $form_data['fields'][ $field_id ]['required'] ) && empty( $field_submit ) && 0 != $field_submit ) { wpforms()->process->errors[ $form_id ][ $field_id ] = wpforms_get_required_label(); } // Check if value is numeric. if ( ! empty( $field_submit ) && ! is_numeric( $field_submit ) ) { wpforms()->process->errors[ $form_id ][ $field_id ] = apply_filters( 'wpforms_valid_number_label', esc_html__( 'Please provide a valid value.', 'wpforms-lite' ) ); } } /** * Format and sanitize field. * * @since 1.5.7 * * @param int $field_id Field ID. * @param int|string|float $field_submit Submitted field value. * @param array $form_data Form data and settings. */ public function format( $field_id, $field_submit, $form_data ) { // Define data. $name = ! empty( $form_data['fields'][ $field_id ]['label'] ) ? $form_data['fields'][ $field_id ]['label'] : ''; $value = (float) $this->sanitize_value( $field_submit ); $value_raw = array( 'value' => $value, 'min' => (float) $form_data['fields'][ $field_id ]['min'], 'max' => (float) $form_data['fields'][ $field_id ]['max'], 'value_display' => wp_kses_post( $form_data['fields'][ $field_id ]['value_display'] ), ); // Set final field details. wpforms()->process->fields[ $field_id ] = array( 'name' => sanitize_text_field( $name ), 'value' => $value, 'value_raw' => $value_raw, 'id' => absint( $field_id ), 'type' => $this->type, ); } /** * Sanitize the value. * * @since 1.5.7 * * @param string $value The number field submitted value. * * @return float|int|string */ private function sanitize_value( $value ) { // Some browsers allow other non-digit/decimal characters to be submitted // with the num input, which then trips the is_numeric validation below. // To get around this we remove all chars that are not expected. $signed_value = preg_replace( '/[^-0-9.]/', '', $value ); $abs_value = abs( $signed_value ); $value = strpos( $signed_value, '-' ) === 0 ? '-' . $abs_value : $abs_value; return $value; } } new WPForms_Field_Number_Slider(); fields/class-radio.php 0000666 00000036673 15213301445 0010745 0 ustar 00 <?php /** * Multiple Choice field. * * @since 1.0.0 */ class WPForms_Field_Radio extends WPForms_Field { /** * Primary class constructor. * * @since 1.0.0 */ public function init() { // Define field type information. $this->name = esc_html__( 'Multiple Choice', 'wpforms-lite' ); $this->type = 'radio'; $this->icon = 'fa-list-ul'; $this->order = 110; $this->defaults = array( 1 => array( 'label' => esc_html__( 'First Choice', 'wpforms-lite' ), 'value' => '', 'image' => '', 'default' => '', ), 2 => array( 'label' => esc_html__( 'Second Choice', 'wpforms-lite' ), 'value' => '', 'image' => '', 'default' => '', ), 3 => array( 'label' => esc_html__( 'Third Choice', 'wpforms-lite' ), 'value' => '', 'image' => '', 'default' => '', ), ); // Customize HTML field values. add_filter( 'wpforms_html_field_value', array( $this, 'field_html_value' ), 10, 4 ); // Define additional field properties. add_filter( 'wpforms_field_properties_radio', array( $this, 'field_properties' ), 5, 3 ); } /** * Return images, if any, for HTML supported values. * * @since 1.4.5 * * @param string $value Field value. * @param array $field Field settings. * @param array $form_data Form data and settings. * @param string $context Value display context. * * @return string */ public function field_html_value( $value, $field, $form_data = array(), $context = '' ) { // Only use HTML formatting for radio fields, with image choices // enabled, and exclude the entry table display. Lastly, provides a // filter to disable fancy display. if ( ! empty( $field['value'] ) && 'radio' === $field['type'] && ! empty( $field['image'] ) && 'entry-table' !== $context && apply_filters( 'wpforms_radio_field_html_value_images', true, $context ) ) { if ( ! empty( $field['image'] ) ) { return sprintf( '<span style="max-width:200px;display:block;margin:0 0 5px 0;"><img src="%s" style="max-width:100%%;display:block;margin:0;"></span>%s', esc_url( $field['image'] ), $value ); } } return $value; } /** * Define additional field properties. * * @since 1.4.5 * * @param array $properties Field properties. * @param array $field Field settings. * @param array $form_data Form data and settings. * * @return array */ public function field_properties( $properties, $field, $form_data ) { // Remove primary input. unset( $properties['inputs']['primary'] ); // Define data. $form_id = absint( $form_data['id'] ); $field_id = absint( $field['id'] ); $choices = $field['choices']; $dynamic = wpforms_get_field_dynamic_choices( $field, $form_id, $form_data ); if ( $dynamic ) { $choices = $dynamic; $field['show_values'] = true; } // Set input container (ul) properties. $properties['input_container'] = array( 'class' => array( ! empty( $field['random'] ) ? 'wpforms-randomize' : '' ), 'data' => array(), 'attr' => array(), 'id' => "wpforms-{$form_id}-field_{$field_id}", ); // Set input properties. foreach ( $choices as $key => $choice ) { // Used for dynamic choices. $depth = isset( $choice['depth'] ) ? absint( $choice['depth'] ) : 1; $value = isset( $field['show_values'] ) ? $choice['value'] : $choice['label']; /* translators: %s - choice number. */ $value = ( '' === $value ) ? sprintf( esc_html__( 'Choice %s', 'wpforms-lite' ), $key ) : $value; $properties['inputs'][ $key ] = array( 'container' => array( 'attr' => array(), 'class' => array( "choice-{$key}", "depth-{$depth}" ), 'data' => array(), 'id' => '', ), 'label' => array( 'attr' => array( 'for' => "wpforms-{$form_id}-field_{$field_id}_{$key}", ), 'class' => array( 'wpforms-field-label-inline' ), 'data' => array(), 'id' => '', 'text' => $choice['label'], ), 'attr' => array( 'name' => "wpforms[fields][{$field_id}]", 'value' => $value, ), 'class' => array(), 'data' => array(), 'id' => "wpforms-{$form_id}-field_{$field_id}_{$key}", 'image' => isset( $choice['image'] ) ? $choice['image'] : '', 'required' => ! empty( $field['required'] ) ? 'required' : '', 'default' => isset( $choice['default'] ), ); } // Required class for pagebreak validation. if ( ! empty( $field['required'] ) ) { $properties['input_container']['class'][] = 'wpforms-field-required'; } // Custom properties if image choices is enabled. if ( ! $dynamic && ! empty( $field['choices_images'] ) ) { $properties['input_container']['class'][] = 'wpforms-image-choices'; $properties['input_container']['class'][] = 'wpforms-image-choices-' . sanitize_html_class( $field['choices_images_style'] ); foreach ( $properties['inputs'] as $key => $inputs ) { $properties['inputs'][ $key ]['container']['class'][] = 'wpforms-image-choices-item'; if ( in_array( $field['choices_images_style'], array( 'modern', 'classic' ), true ) ) { $properties['inputs'][ $key ]['class'][] = 'wpforms-screen-reader-element'; } } } // Add selected class for choices with defaults. foreach ( $properties['inputs'] as $key => $inputs ) { if ( ! empty( $inputs['default'] ) ) { $properties['inputs'][ $key ]['container']['class'][] = 'wpforms-selected'; } } return $properties; } /** * Field options panel inside the builder. * * @since 1.0.0 * * @param array $field Field settings. */ public function field_options( $field ) { /* * Basic field options. */ // Options open markup. $this->field_option( 'basic-options', $field, array( 'markup' => 'open', ) ); // Label. $this->field_option( 'label', $field ); // Choices. $this->field_option( 'choices', $field ); // Choices Images. $this->field_option( 'choices_images', $field ); // Description. $this->field_option( 'description', $field ); // Required toggle. $this->field_option( 'required', $field ); // Options close markup. $this->field_option( 'basic-options', $field, array( 'markup' => 'close', ) ); /* * Advanced field options. */ // Options open markup. $this->field_option( 'advanced-options', $field, array( 'markup' => 'open', ) ); // Randomize order of choices. $this->field_element( 'row', $field, array( 'slug' => 'random', 'content' => $this->field_element( 'checkbox', $field, array( 'slug' => 'random', 'value' => isset( $field['random'] ) ? '1' : '0', 'desc' => esc_html__( 'Randomize Choices', 'wpforms-lite' ), 'tooltip' => esc_html__( 'Check this option to randomize the order of the choices.', 'wpforms-lite' ), ), false ), ) ); // Show Values toggle option. This option will only show if already used // or if manually enabled by a filter. if ( ! empty( $field['show_values'] ) || wpforms_show_fields_options_setting() ) { $this->field_element( 'row', $field, array( 'slug' => 'show_values', 'content' => $this->field_element( 'checkbox', $field, array( 'slug' => 'show_values', 'value' => isset( $field['show_values'] ) ? $field['show_values'] : '0', 'desc' => esc_html__( 'Show Values', 'wpforms-lite' ), 'tooltip' => esc_html__( 'Check this to manually set form field values.', 'wpforms-lite' ), ), false ), ) ); } // Choices Images Style (theme). $this->field_option( 'choices_images_style', $field ); // Display format. $this->field_option( 'input_columns', $field ); // Hide label. $this->field_option( 'label_hide', $field ); // Custom CSS classes. $this->field_option( 'css', $field ); // Dynamic choice auto-populating toggle. $this->field_option( 'dynamic_choices', $field ); // Dynamic choice source. $this->field_option( 'dynamic_choices_source', $field ); // Options close markup. $this->field_option( 'advanced-options', $field, array( 'markup' => 'close', ) ); } /** * Field preview inside the builder. * * @since 1.0.0 * * @param array $field Field settings. */ public function field_preview( $field ) { // Label. $this->field_preview_option( 'label', $field ); // Choices. $this->field_preview_option( 'choices', $field ); // Description. $this->field_preview_option( 'description', $field ); } /** * Field display on the form front-end. * * @since 1.0.0 * * @param array $field Field settings. * @param array $deprecated Deprecated array. * @param array $form_data Form data and settings. */ public function field_display( $field, $deprecated, $form_data ) { $using_image_choices = empty( $field['dynamic_choices'] ) && ! empty( $field['choices_images'] ); // Define data. $container = $field['properties']['input_container']; $choices = $field['properties']['inputs']; $amp_state_id = ''; if ( wpforms_is_amp() && $using_image_choices ) { $amp_state_id = str_replace( '-', '_', sanitize_key( $container['id'] ) ) . '_state'; $state = array( 'selected' => null, ); foreach ( $choices as $key => $choice ) { if ( $choice['default'] ) { $state['selected'] = $choice['attr']['value']; break; } } printf( '<amp-state id="%s"><script type="application/json">%s</script></amp-state>', esc_attr( $amp_state_id ), wp_json_encode( $state ) ); } printf( '<ul %s>', wpforms_html_attributes( $container['id'], $container['class'], $container['data'], $container['attr'] ) ); // WPCS: XSS ok. foreach ( $choices as $key => $choice ) { if ( wpforms_is_amp() && $using_image_choices ) { $choice['container']['attr']['[class]'] = sprintf( '%s + ( %s == %s ? " wpforms-selected" : "")', wp_json_encode( implode( ' ', $choice['container']['class'] ) ), $amp_state_id, wp_json_encode( $choice['attr']['value'] ) ); } printf( '<li %s>', wpforms_html_attributes( $choice['container']['id'], $choice['container']['class'], $choice['container']['data'], $choice['container']['attr'] ) ); // WPCS: XSS ok. if ( $using_image_choices ) { // Make sure the image choices are keyboard-accessible. $choice['label']['attr']['tabindex'] = 0; if ( wpforms_is_amp() ) { $choice['label']['attr']['on'] = sprintf( 'tap:AMP.setState(%s)', wp_json_encode( array( $amp_state_id => $choice['attr']['value'] ) ) ); $choice['label']['attr']['role'] = 'button'; } // Image choices. printf( '<label %s>', wpforms_html_attributes( $choice['label']['id'], $choice['label']['class'], $choice['label']['data'], $choice['label']['attr'] ) ); // WPCS: XSS ok. if ( ! empty( $choice['image'] ) ) { printf( '<span class="wpforms-image-choices-image"><img src="%s" alt="%s"%s></span>', esc_url( $choice['image'] ), esc_attr( $choice['label']['text'] ), ! empty( $choice['label']['text'] ) ? ' title="' . esc_attr( $choice['label']['text'] ) . '"' : '' ); } if ( 'none' === $field['choices_images_style'] ) { echo '<br>'; } $choice['attr']['tabindex'] = '-1'; if ( wpforms_is_amp() ) { $choice['attr']['[checked]'] = sprintf( '%s == %s', $amp_state_id, wp_json_encode( $choice['attr']['value'] ) ); } printf( '<input type="radio" %s %s %s>', wpforms_html_attributes( $choice['id'], $choice['class'], $choice['data'], $choice['attr'] ), esc_attr( $choice['required'] ), checked( '1', $choice['default'], false ) ); // WPCS: XSS ok. echo '<span class="wpforms-image-choices-label">' . wp_kses_post( $choice['label']['text'] ) . '</span>'; echo '</label>'; } else { // Normal display. printf( '<input type="radio" %s %s %s>', wpforms_html_attributes( $choice['id'], $choice['class'], $choice['data'], $choice['attr'] ), esc_attr( $choice['required'] ), checked( '1', $choice['default'], false ) ); // WPCS: XSS ok. printf( '<label %s>%s</label>', wpforms_html_attributes( $choice['label']['id'], $choice['label']['class'], $choice['label']['data'], $choice['label']['attr'] ), wp_kses_post( $choice['label']['text'] ) ); // WPCS: XSS ok. } echo '</li>'; } echo '</ul>'; } /** * Format and sanitize field. * * @since 1.0.2 * * @param int $field_id Field ID. * @param string $field_submit Submitted form data. * @param array $form_data Form data and settings. */ public function format( $field_id, $field_submit, $form_data ) { $field = $form_data['fields'][ $field_id ]; $dynamic = ! empty( $field['dynamic_choices'] ) ? $field['dynamic_choices'] : false; $name = sanitize_text_field( $field['label'] ); $value_raw = sanitize_text_field( $field_submit ); $data = array( 'name' => $name, 'value' => '', 'value_raw' => $value_raw, 'id' => absint( $field_id ), 'type' => $this->type, ); if ( 'post_type' === $dynamic && ! empty( $field['dynamic_post_type'] ) ) { // Dynamic population is enabled using post type. $data['dynamic'] = 'post_type'; $data['dynamic_items'] = absint( $value_raw ); $data['dynamic_post_type'] = $field['dynamic_post_type']; $post = get_post( $value_raw ); if ( ! empty( $post ) && ! is_wp_error( $post ) && $data['dynamic_post_type'] === $post->post_type ) { $data['value'] = esc_html( $post->post_title ); } } elseif ( 'taxonomy' === $dynamic && ! empty( $field['dynamic_taxonomy'] ) ) { // Dynamic population is enabled using taxonomy. $data['dynamic'] = 'taxonomy'; $data['dynamic_items'] = absint( $value_raw ); $data['dynamic_taxonomy'] = $field['dynamic_taxonomy']; $term = get_term( $value_raw, $data['dynamic_taxonomy'] ); if ( ! empty( $term ) && ! is_wp_error( $term ) ) { $data['value'] = esc_html( $term->name ); } } else { // Normal processing, dynamic population is off. $choice_key = ''; // If show_values is true, that means value posted is the raw value // and not the label. So we need to set label value. Also store // the choice key. if ( ! empty( $field['show_values'] ) ) { foreach ( $field['choices'] as $key => $choice ) { if ( $choice['value'] === $field_submit ) { $data['value'] = sanitize_text_field( $choice['label'] ); $choice_key = $key; break; } } } else { $data['value'] = $value_raw; // Determine choice key, this is needed for image choices. foreach ( $field['choices'] as $key => $choice ) { /* translators: %s - choice number. */ if ( $value_raw === $choice['label'] || $value_raw === sprintf( esc_html__( 'Choice %s', 'wpforms-lite' ), $key ) ) { $choice_key = $key; break; } } } // Images choices are enabled, lookup and store image URL. if ( ! empty( $choice_key ) && ! empty( $field['choices_images'] ) ) { $data['image'] = ! empty( $field['choices'][ $choice_key ]['image'] ) ? esc_url_raw( $field['choices'][ $choice_key ]['image'] ) : ''; } } // Push field details to be saved. wpforms()->process->fields[ $field_id ] = $data; } } new WPForms_Field_Radio(); fields/class-text.php 0000666 00000033135 15213301445 0010621 0 ustar 00 <?php /** * Single line text field. * * @since 1.0.0 */ class WPForms_Field_Text extends WPForms_Field { /** * Primary class constructor. * * @since 1.0.0 */ public function init() { // Define field type information. $this->name = esc_html__( 'Single Line Text', 'wpforms-lite' ); $this->type = 'text'; $this->icon = 'fa-text-width'; $this->order = 30; // Define additional field properties. add_filter( 'wpforms_field_properties_text', array( $this, 'field_properties' ), 5, 3 ); add_action( 'wpforms_frontend_js', array( $this, 'frontend_js' ) ); } /** * Convert mask formatted for jquery.inputmask into the format used by amp-inputmask. * * Note that amp-inputmask does not yet support all of the options that jquery.inputmask provides. * In particular, amp-inputmask doesn't provides: * - Upper-alphabetical mask. * - Upper-alphanumeric mask. * - Advanced Input Masks with arbitrary repeating groups. * * @link https://amp.dev/documentation/components/amp-inputmask * @link https://wpforms.com/docs/how-to-use-custom-input-masks/ * * @param string $mask Mask formatted for jquery.inputmask. * @return array { * Mask and placeholder. * * @type string $mask Mask for amp-inputmask. * @type string $placeholder Placeholder derived from mask if one is not supplied. * } */ protected function convert_mask_to_amp_inputmask( $mask ) { $placeholder = ''; // Convert jquery.inputmask format into amp-inputmask format. $amp_mask = ''; $req_mask_mapping = array( '9' => '0', // Numeric. 'a' => 'L', // Alphabetical (a-z or A-Z). 'A' => 'L', // Upper-alphabetical (A-Z). Note: AMP does not have an uppercase-alphabetical mask type, so same as previous. '*' => 'A', // Alphanumeric (0-9, a-z, A-Z). '&' => 'A', // Upper-alphanumeric (A-Z, 0-9). Note: AMP does not have an uppercase-alphanumeric mask type, so same as previous. ' ' => '_', // Automatically insert spaces. ); $opt_mask_mapping = array( '9' => '9', // The user may optionally add a numeric character. 'a' => 'l', // The user may optionally add an alphabetical character. 'A' => 'l', // The user may optionally add an alphabetical character. '*' => 'a', // The user may optionally add an alphanumeric character. '&' => 'a', // The user may optionally add an alphanumeric character. ); $placeholder_mapping = array( '9' => '0', 'a' => 'a', 'A' => 'a', '*' => '_', '&' => '_', ); $is_inside_optional = false; $last_mask_token = null; for ( $i = 0, $len = strlen( $mask ); $i < $len; $i++ ) { if ( '[' === $mask[ $i ] ) { $is_inside_optional = true; $placeholder .= $mask[ $i ]; continue; } elseif ( ']' === $mask[ $i ] ) { $is_inside_optional = false; $placeholder .= $mask[ $i ]; continue; } elseif ( isset( $last_mask_token ) && preg_match( '/^\{(?P<n>\d+)(?:,(?P<m>\d+))?\}/', substr( $mask, $i ), $matches ) ) { $amp_mask .= str_repeat( $req_mask_mapping[ $last_mask_token ], $matches['n'] ); $placeholder .= str_repeat( $placeholder_mapping[ $last_mask_token ], $matches['n'] ); if ( isset( $matches['m'] ) ) { $amp_mask .= str_repeat( $opt_mask_mapping[ $last_mask_token ], $matches['m'] ); $placeholder .= str_repeat( $placeholder_mapping[ $last_mask_token ], $matches['m'] ); } $i += strlen( $matches[0] ) - 1; $last_mask_token = null; // Reset. continue; } if ( '\\' === $mask[ $i ] ) { $amp_mask .= '\\'; $i++; if ( ! isset( $mask[ $i ] ) ) { continue; } $amp_mask .= $mask[ $i ]; } else { // Remember this token in case it is a mask. if ( isset( $opt_mask_mapping[ $mask[ $i ] ] ) ) { $last_mask_token = $mask[ $i ]; } if ( $is_inside_optional && isset( $opt_mask_mapping[ $mask[ $i ] ] ) ) { $amp_mask .= $opt_mask_mapping[ $mask[ $i ] ]; } elseif ( isset( $req_mask_mapping[ $mask[ $i ] ] ) ) { $amp_mask .= $req_mask_mapping[ $mask[ $i ] ]; } else { $amp_mask .= '\\' . $mask[ $i ]; } } if ( isset( $placeholder_mapping[ $mask[ $i ] ] ) ) { $placeholder .= $placeholder_mapping[ $mask[ $i ] ]; } else { $placeholder .= $mask[ $i ]; } } return array( $amp_mask, $placeholder ); } /** * Define additional field properties. * * @since 1.4.5 * * @param array $properties Field properties. * @param array $field Field settings. * @param array $form_data Form data and settings. * * @return array */ public function field_properties( $properties, $field, $form_data ) { // Input primary: Detect custom input mask. if ( ! empty( $field['input_mask'] ) ) { // Add class that will trigger custom mask. $properties['inputs']['primary']['class'][] = 'wpforms-masked-input'; if ( wpforms_is_amp() ) { list( $amp_mask, $placeholder ) = $this->convert_mask_to_amp_inputmask( $field['input_mask'] ); $properties['inputs']['primary']['attr']['mask'] = $amp_mask; if ( empty( $properties['inputs']['primary']['attr']['placeholder'] ) ) { $properties['inputs']['primary']['attr']['placeholder'] = $placeholder; } } elseif ( false !== strpos( $field['input_mask'], 'alias:' ) ) { $mask = str_replace( 'alias:', '', $field['input_mask'] ); $properties['inputs']['primary']['data']['inputmask-alias'] = $mask; } elseif ( false !== strpos( $field['input_mask'], 'regex:' ) ) { $mask = str_replace( 'regex:', '', $field['input_mask'] ); $properties['inputs']['primary']['data']['inputmask-regex'] = $mask; } elseif ( false !== strpos( $field['input_mask'], 'date:' ) ) { $mask = str_replace( 'date:', '', $field['input_mask'] ); $properties['inputs']['primary']['data']['inputmask-alias'] = 'datetime'; $properties['inputs']['primary']['data']['inputmask-inputformat'] = $mask; } else { $properties['inputs']['primary']['data']['inputmask-mask'] = $field['input_mask']; } } return $properties; } /** * Field options panel inside the builder. * * @since 1.0.0 * * @param array $field Field settings. */ public function field_options( $field ) { /* * Basic field options. */ // Options open markup. $this->field_option( 'basic-options', $field, array( 'markup' => 'open', ) ); // Label. $this->field_option( 'label', $field ); // Description. $this->field_option( 'description', $field ); // Required toggle. $this->field_option( 'required', $field ); // Options close markup. $this->field_option( 'basic-options', $field, array( 'markup' => 'close', ) ); /* * Advanced field options. */ // Options open markup. $this->field_option( 'advanced-options', $field, array( 'markup' => 'open', ) ); // Size. $this->field_option( 'size', $field ); // Placeholder. $this->field_option( 'placeholder', $field ); // Hide label. $this->field_option( 'label_hide', $field ); // Limit length. $args = array( 'slug' => 'limit_enabled', 'content' => $this->field_element( 'checkbox', $field, array( 'slug' => 'limit_enabled', 'value' => isset( $field['limit_enabled'] ), 'desc' => esc_html__( 'Limit Length', 'wpforms-lite' ), 'tooltip' => esc_html__( 'Check this option to limit text length by characters or words count.', 'wpforms-lite' ), ), false ), ); $this->field_element( 'row', $field, $args ); $count = $this->field_element( 'text', $field, array( 'type' => 'number', 'slug' => 'limit_count', 'attrs' => array( 'min' => 1, 'step' => 1, 'pattern' => '[0-9]', ), 'value' => ! empty( $field['limit_count'] ) ? absint( $field['limit_count'] ) : 1, ), false ); $mode = $this->field_element( 'select', $field, array( 'slug' => 'limit_mode', 'value' => ! empty( $field['limit_mode'] ) ? esc_attr( $field['limit_mode'] ) : 'characters', 'options' => array( 'characters' => esc_html__( 'Characters', 'wpforms-lite' ), 'words' => esc_html__( 'Words', 'wpforms-lite' ), ), ), false ); $args = array( 'slug' => 'limit_controls', 'class' => ! isset( $field['limit_enabled'] ) ? 'wpforms-hide' : '', 'content' => $count . $mode, ); $this->field_element( 'row', $field, $args ); // Default value. $this->field_option( 'default_value', $field ); // Custom CSS classes. $this->field_option( 'css', $field ); // Input Mask. $lbl = $this->field_element( 'label', $field, array( 'slug' => 'input_mask', 'value' => esc_html__( 'Input Mask', 'wpforms-lite' ), 'tooltip' => esc_html__( 'Enter your custom input mask.', 'wpforms-lite' ), 'after_tooltip' => '<a href="https://wpforms.com/how-to-use-custom-input-masks/" class="after-label-description" target="_blank" rel="noopener noreferrer">' . esc_html__( 'See Examples & Docs', 'wpforms-lite' ) . '</a>', ), false ); $fld = $this->field_element( 'text', $field, array( 'slug' => 'input_mask', 'value' => ! empty( $field['input_mask'] ) ? esc_attr( $field['input_mask'] ) : '', ), false ); $this->field_element( 'row', $field, array( 'slug' => 'input_mask', 'content' => $lbl . $fld, ) ); // Options close markup. $this->field_option( 'advanced-options', $field, array( 'markup' => 'close', ) ); } /** * Field preview inside the builder. * * @since 1.0.0 * * @param array $field Field settings. */ public function field_preview( $field ) { // Define data. $placeholder = ! empty( $field['placeholder'] ) ? esc_attr( $field['placeholder'] ) : ''; // Label. $this->field_preview_option( 'label', $field ); // Primary input. echo '<input type="text" placeholder="' . esc_attr( $placeholder ) . '" class="primary-input" disabled>'; // Description. $this->field_preview_option( 'description', $field ); } /** * Field display on the form front-end. * * @since 1.0.0 * * @param array $field Field settings. * @param array $deprecated Deprecated. * @param array $form_data Form data and settings. */ public function field_display( $field, $deprecated, $form_data ) { // Define data. $primary = $field['properties']['inputs']['primary']; if ( isset( $field['limit_enabled'] ) ) { $limit_count = isset( $field['limit_count'] ) ? absint( $field['limit_count'] ) : 0; $limit_mode = isset( $field['limit_mode'] ) ? sanitize_key( $field['limit_mode'] ) : 'characters'; $primary['data']['form-id'] = $form_data['id']; $primary['data']['field-id'] = $field['id']; if ( 'characters' === $limit_mode ) { $primary['class'][] = 'wpforms-limit-characters-enabled'; $primary['attr']['maxlength'] = $limit_count; $primary['data']['text-limit'] = $limit_count; } else { $primary['class'][] = 'wpforms-limit-words-enabled'; $primary['data']['text-limit'] = $limit_count; } } // Primary field. printf( '<input type="text" %s %s>', wpforms_html_attributes( $primary['id'], $primary['class'], $primary['data'], $primary['attr'] ), $primary['required'] // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ); } /** * Enqueue frontend limit option js. * * @since 1.5.6 * * @param array $forms Forms on the current page. */ public function frontend_js( $forms ) { // Get fields. $fields = array_map( function( $form ) { return empty( $form['fields'] ) ? array() : $form['fields']; }, (array) $forms ); // Make fields flat. $fields = array_reduce( $fields, function( $accumulator, $current ) { return array_merge( $accumulator, $current ); }, array() ); // Leave only fields with limit. $fields = array_filter( $fields, function( $field ) { return $field['type'] === $this->type && isset( $field['limit_enabled'] ) && ! empty( $field['limit_count'] ); } ); if ( count( $fields ) ) { $min = \wpforms_get_min_suffix(); wp_enqueue_script( 'wpforms-text-limit', WPFORMS_PLUGIN_URL . "assets/js/text-limit{$min}.js", array(), WPFORMS_VERSION, true ); } } /** * Format and sanitize field. * * @since 1.5.6 * * @param int $field_id Field ID. * @param mixed $field_submit Field value that was submitted. * @param array $form_data Form data and settings. */ public function format( $field_id, $field_submit, $form_data ) { $field = $form_data['fields'][ $field_id ]; $name = ! empty( $field['label'] ) ? sanitize_text_field( $field['label'] ) : ''; // Sanitize. $value = sanitize_text_field( $field_submit ); if ( isset( $field['limit_enabled'] ) ) { $limit = absint( $field['limit_count'] ); $mode = sanitize_key( $field['limit_mode'] ); if ( 'characters' === $mode ) { if ( mb_strlen( $value ) > $limit ) { /* translators: %s - limit characters number. */ wpforms()->process->errors[ $form_data['id'] ][ $field_id ] = sprintf( _n( 'Text can\'t exceed %d character.', 'Text can\'t exceed %d characters.', $limit, 'wpforms-lite' ), $limit ); return; } } else { $words = preg_split( '/[\s,]+/', $value ); $words = is_array( $words ) ? count( $words ) : 0; if ( $words > $limit ) { /* translators: %s - limit words number. */ wpforms()->process->errors[ $form_data['id'] ][ $field_id ] = sprintf( _n( 'Text can\'t exceed %d word.', 'Text can\'t exceed %d words.', $limit, 'wpforms-lite' ), $limit ); return; } } } wpforms()->process->fields[ $field_id ] = array( 'name' => $name, 'value' => $value, 'id' => absint( $field_id ), 'type' => $this->type, ); } } new WPForms_Field_Text(); fields/class-gdpr-checkbox.php 0000666 00000016374 15213301445 0012363 0 ustar 00 <?php /** * GDPR Checkbox field. * * @since 1.4.6 */ class WPForms_Field_GDPR_Checkbox extends WPForms_Field { /** * Primary class constructor. * * @since 1.4.6 */ public function init() { // Define field type information. $this->name = esc_html__( 'GDPR Agreement', 'wpforms-lite' ); $this->type = 'gdpr-checkbox'; $this->icon = 'fa-check-square-o'; $this->order = 500; $this->defaults = array( 1 => array( 'label' => esc_html__( 'I consent to having this website store my submitted information so they can respond to my inquiry.', 'wpforms-lite' ), 'value' => '', 'image' => '', 'default' => '', ), ); // Set field to default to required. add_filter( 'wpforms_field_new_required', array( $this, 'field_default_required' ), 10, 2 ); // Define additional field properties. add_filter( 'wpforms_field_properties_gdpr-checkbox', array( $this, 'field_properties' ), 5, 3 ); } /** * Field should default to being required. * * @since 1.4.6 * * @param bool $required Required status, true is required. * @param array $field Field settings. * * @return bool */ public function field_default_required( $required, $field ) { if ( $this->type === $field['type'] ) { return true; } return $required; } /** * Define additional field properties. * * @since 1.4.6 * * @param array $properties Field properties. * @param array $field Field settings. * @param array $form_data Form data and settings. * * @return array */ public function field_properties( $properties, $field, $form_data ) { // Define data. $form_id = absint( $form_data['id'] ); $field_id = absint( $field['id'] ); $choices = ! empty( $field['choices'] ) ? $field['choices'] : []; // Remove primary input. unset( $properties['inputs']['primary'] ); // Set input container (ul) properties. $properties['input_container'] = array( 'class' => array(), 'data' => array(), 'attr' => array(), 'id' => "wpforms-{$form_id}-field_{$field_id}", ); // Set input properties. foreach ( $choices as $key => $choice ) { $properties['inputs'][ $key ] = array( 'container' => array( 'attr' => array(), 'class' => array( "choice-{$key}" ), 'data' => array(), 'id' => '', ), 'label' => array( 'attr' => array( 'for' => "wpforms-{$form_id}-field_{$field_id}_{$key}", ), 'class' => array( 'wpforms-field-label-inline' ), 'data' => array(), 'id' => '', 'text' => $choice['label'], ), 'attr' => array( 'name' => "wpforms[fields][{$field_id}][]", 'value' => $choice['label'], ), 'class' => array(), 'data' => array(), 'id' => "wpforms-{$form_id}-field_{$field_id}_{$key}", 'image' => '', 'required' => ! empty( $field['required'] ) ? 'required' : '', 'default' => '', ); } // Required class for pagebreak validation. if ( ! empty( $field['required'] ) ) { $properties['input_container']['class'][] = 'wpforms-field-required'; } return $properties; } /** * @inheritdoc */ public function is_dynamic_population_allowed( $properties, $field ) { return false; } /** * Field options panel inside the builder. * * @since 1.4.6 * * @param array $field Field settings. */ public function field_options( $field ) { // Field is always required. $this->field_element( 'text', $field, array( 'type' => 'hidden', 'slug' => 'required', 'value' => '1', ) ); // -------------------------------------------------------------------// // Basic field options // -------------------------------------------------------------------// // Options open markup. $this->field_option( 'basic-options', $field, array( 'markup' => 'open', ) ); // Label. $this->field_option( 'label', $field ); // Choices. $this->field_option( 'choices', $field, array( 'label' => esc_html__( 'Agreement', 'wpforms-lite' ), ) ); // Description. $this->field_option( 'description', $field ); // Options close markup. $this->field_option( 'basic-options', $field, array( 'markup' => 'close', ) ); // -------------------------------------------------------------------// // Advanced field options // -------------------------------------------------------------------// // Options open markup. $this->field_option( 'advanced-options', $field, array( 'markup' => 'open', ) ); // Hide label. $this->field_option( 'label_hide', $field ); // Custom CSS classes. $this->field_option( 'css', $field ); // Options close markup. $this->field_option( 'advanced-options', $field, array( 'markup' => 'close', ) ); } /** * Field preview inside the builder. * * @since 1.4.6 * * @param array $field Field settings. */ public function field_preview( $field ) { // Label. $this->field_preview_option( 'label', $field ); // Choices. $this->field_preview_option( 'choices', $field ); // Description. $this->field_preview_option( 'description', $field ); } /** * Field display on the form front-end. * * @since 1.4.6 * * @param array $field Field settings. * @param array $deprecated Deprecated array. * @param array $form_data Form data and settings. */ public function field_display( $field, $deprecated, $form_data ) { // Define data. $container = $field['properties']['input_container']; $choices = $field['properties']['inputs']; printf( '<ul %s>', wpforms_html_attributes( $container['id'], $container['class'], $container['data'], $container['attr'] ) ); foreach ( $choices as $key => $choice ) { $required = ''; if ( ! empty( $choice['required'] ) && ! empty( $field['label_hide'] ) ) { $required = wpforms_get_field_required_label(); } printf( '<li %s>', wpforms_html_attributes( $choice['container']['id'], $choice['container']['class'], $choice['container']['data'], $choice['container']['attr'] ) ); // Normal display. printf( '<input type="checkbox" %s %s %s>', wpforms_html_attributes( $choice['id'], $choice['class'], $choice['data'], $choice['attr'] ), esc_attr( $choice['required'] ), checked( '1', $choice['default'], false ) ); printf( '<label %s>%s%s</label>', wpforms_html_attributes( $choice['label']['id'], $choice['label']['class'], $choice['label']['data'], $choice['label']['attr'] ), wp_kses_post( $choice['label']['text'] ), $required ); // WPCS: XSS ok. echo '</li>'; } echo '</ul>'; } /** * Format and sanitize field. * * @since 1.4.6 * * @param int $field_id Field ID. * @param array $field_submit Submitted form data. * @param array $form_data Form data and settings. */ public function format( $field_id, $field_submit, $form_data ) { wpforms()->process->fields[ $field_id ] = array( 'name' => ! empty( $form_data['fields'][ $field_id ]['label'] ) ? sanitize_text_field( $form_data['fields'][ $field_id ]['label'] ) : '', 'value' => $form_data['fields'][ $field_id ]['choices'][1]['label'], 'id' => absint( $field_id ), 'type' => $this->type, ); } } new WPForms_Field_GDPR_Checkbox(); fields/class-email.php 0000666 00000027450 15213301445 0010727 0 ustar 00 <?php /** * Email text field. * * @since 1.0.0 */ class WPForms_Field_Email extends WPForms_Field { /** * Primary class constructor. * * @since 1.0.0 */ public function init() { // Define field type information. $this->name = esc_html__( 'Email', 'wpforms-lite' ); $this->type = 'email'; $this->icon = 'fa-envelope-o'; $this->order = 170; // Define additional field properties. add_filter( 'wpforms_field_properties_email', array( $this, 'field_properties' ), 5, 3 ); // Set field to default to required. add_filter( 'wpforms_field_new_required', array( $this, 'default_required' ), 10, 2 ); // Set confirmation status to option wrapper class. add_filter( 'wpforms_builder_field_option_class', array( $this, 'field_option_class' ), 10, 2 ); } /** * Define additional field properties. * * @since 1.3.7 * @param array $properties * @param array $field * @param array $form_data * @return array */ public function field_properties( $properties, $field, $form_data ) { if ( empty( $field['confirmation'] ) ) { return $properties; } $form_id = absint( $form_data['id'] ); $field_id = absint( $field['id'] ); // Email confirmation setting enabled. $props = array( 'inputs' => array( 'primary' => array( 'block' => array( 'wpforms-field-row-block', 'wpforms-one-half', 'wpforms-first', ), 'class' => array( 'wpforms-field-email-primary', ), 'sublabel' => array( 'hidden' => ! empty( $field['sublabel_hide'] ), 'value' => esc_html__( 'Email', 'wpforms-lite' ), ), ), 'secondary' => array( 'attr' => array( 'name' => "wpforms[fields][{$field_id}][secondary]", 'value' => '', 'placeholder' => ! empty( $field['confirmation_placeholder'] ) ? $field['confirmation_placeholder'] : '', ), 'block' => array( 'wpforms-field-row-block', 'wpforms-one-half', ), 'class' => array( 'wpforms-field-email-secondary', ), 'data' => array( 'rule-confirm' => '#' . $properties['inputs']['primary']['id'], ), 'id' => "wpforms-{$form_id}-field_{$field_id}-secondary", 'required' => ! empty( $field['required'] ) ? 'required' : '', 'sublabel' => array( 'hidden' => ! empty( $field['sublabel_hide'] ), 'value' => esc_html__( 'Confirm Email', 'wpforms-lite' ), ), 'value' => '', ), ), ); $properties = array_merge_recursive( $properties, $props ); // Input Primary: adjust name. $properties['inputs']['primary']['attr']['name'] = "wpforms[fields][{$field_id}][primary]"; // Input Primary: remove size and error classes. $properties['inputs']['primary']['class'] = array_diff( $properties['inputs']['primary']['class'], array( 'wpforms-field-' . sanitize_html_class( $field['size'] ), 'wpforms-error', ) ); // Input Primary: add error class if needed. if ( ! empty( $properties['error']['value']['primary'] ) ) { $properties['inputs']['primary']['class'][] = 'wpforms-error'; } // Input Secondary: add error class if needed. if ( ! empty( $properties['error']['value']['secondary'] ) ) { $properties['inputs']['secondary']['class'][] = 'wpforms-error'; } // Input Secondary: add required class if needed. if ( ! empty( $field['required'] ) ) { $properties['inputs']['secondary']['class'][] = 'wpforms-field-required'; } return $properties; } /** * Field should default to being required. * * @since 1.0.9 * @param bool $required * @param array $field * @return bool */ public function default_required( $required, $field ) { if ( 'email' === $field['type'] ) { return true; } return $required; } /** * Add class to field options wrapper to indicate if field confirmation is * enabled. * * @since 1.3.0 * * @param string $class * @param array $field * * @return string */ public function field_option_class( $class, $field ) { if ( 'email' === $field['type'] ) { if ( isset( $field['confirmation'] ) ) { $class = 'wpforms-confirm-enabled'; } else { $class = 'wpforms-confirm-disabled'; } } return $class; } /** * Field options panel inside the builder. * * @since 1.0.0 * * @param array $field */ public function field_options( $field ) { /* * Basic field options. */ // Options open markup. $args = array( 'markup' => 'open', ); $this->field_option( 'basic-options', $field, $args ); // Label. $this->field_option( 'label', $field ); // Description. $this->field_option( 'description', $field ); // Required toggle. $this->field_option( 'required', $field ); // Confirmation toggle. $fld = $this->field_element( 'checkbox', $field, array( 'slug' => 'confirmation', 'value' => isset( $field['confirmation'] ) ? '1' : '0', 'desc' => esc_html__( 'Enable Email Confirmation', 'wpforms-lite' ), 'tooltip' => esc_html__( 'Check this option to ask users to provide an email address twice.', 'wpforms-lite' ), ), false ); $args = array( 'slug' => 'confirmation', 'content' => $fld, ); $this->field_element( 'row', $field, $args ); // Options close markup. $args = array( 'markup' => 'close', ); $this->field_option( 'basic-options', $field, $args ); /* * Advanced field options. */ // Options open markup. $args = array( 'markup' => 'open', ); $this->field_option( 'advanced-options', $field, $args ); // Size. $this->field_option( 'size', $field ); // Placeholder. $this->field_option( 'placeholder', $field ); // Confirmation Placeholder. $lbl = $this->field_element( 'label', $field, array( 'slug' => 'confirmation_placeholder', 'value' => esc_html__( 'Confirmation Placeholder Text', 'wpforms-lite' ), 'tooltip' => esc_html__( 'Enter text for the confirmation field placeholder.', 'wpforms-lite' ), ), false ); $fld = $this->field_element( 'text', $field, array( 'slug' => 'confirmation_placeholder', 'value' => ! empty( $field['confirmation_placeholder'] ) ? esc_attr( $field['confirmation_placeholder'] ) : '', ), false ); $args = array( 'slug' => 'confirmation_placeholder', 'content' => $lbl . $fld, ); $this->field_element( 'row', $field, $args ); // Hide Label. $this->field_option( 'label_hide', $field ); // Hide sub-labels. $this->field_option( 'sublabel_hide', $field ); // Default value. $this->field_option( 'default_value', $field ); // Custom CSS classes. $this->field_option( 'css', $field ); // Options close markup. $args = array( 'markup' => 'close', ); $this->field_option( 'advanced-options', $field, $args ); } /** * Field preview inside the builder. * * @since 1.0.0 * @param array $field */ public function field_preview( $field ) { // Define data. $placeholder = ! empty( $field['placeholder'] ) ? esc_attr( $field['placeholder'] ) : ''; $confirm_placeholder = ! empty( $field['confirmation_placeholder'] ) ? esc_attr( $field['confirmation_placeholder'] ) : ''; $confirm = ! empty( $field['confirmation'] ) ? 'enabled' : 'disabled'; // Label. $this->field_preview_option( 'label', $field ); ?> <div class="wpforms-confirm wpforms-confirm-<?php echo $confirm; ?>"> <div class="wpforms-confirm-primary"> <input type="email" placeholder="<?php echo $placeholder; ?>" class="primary-input" disabled> <label class="wpforms-sub-label"><?php esc_html_e( 'Email', 'wpforms-lite' ); ?></label> </div> <div class="wpforms-confirm-confirmation"> <input type="email" placeholder="<?php echo $confirm_placeholder; ?>" class="secondary-input" disabled> <label class="wpforms-sub-label"><?php esc_html_e( 'Confirm Email', 'wpforms-lite' ); ?></label> </div> </div> <?php // Description. $this->field_preview_option( 'description', $field ); } /** * Field display on the form front-end. * * @since 1.0.0 * @param array $field * @param array $deprecated * @param array $form_data */ public function field_display( $field, $deprecated, $form_data ) { // Define data. $form_id = absint( $form_data['id'] ); $confirmation = ! empty( $field['confirmation'] ); $primary = $field['properties']['inputs']['primary']; $secondary = ! empty( $field['properties']['inputs']['secondary'] ) ? $field['properties']['inputs']['secondary'] : ''; // Standard email field. if ( ! $confirmation ) { // Primary field. printf( '<input type="email" %s %s>', wpforms_html_attributes( $primary['id'], $primary['class'], $primary['data'], $primary['attr'] ), esc_attr( $primary['required'] ) ); $this->field_display_error( 'primary', $field ); // Confirmation email field configuration. } else { // Row wrapper. echo '<div class="wpforms-field-row wpforms-field-' . sanitize_html_class( $field['size'] ) . '">'; // Primary field. echo '<div ' . wpforms_html_attributes( false, $primary['block'] ) . '>'; $this->field_display_sublabel( 'primary', 'before', $field ); printf( '<input type="email" %s %s>', wpforms_html_attributes( $primary['id'], $primary['class'], $primary['data'], $primary['attr'] ), $primary['required'] ); $this->field_display_sublabel( 'primary', 'after', $field ); $this->field_display_error( 'primary', $field ); echo '</div>'; // Secondary field. echo '<div ' . wpforms_html_attributes( false, $secondary['block'] ) . '>'; $this->field_display_sublabel( 'secondary', 'before', $field ); printf( '<input type="email" %s %s>', wpforms_html_attributes( $secondary['id'], $secondary['class'], $secondary['data'], $secondary['attr'] ), $secondary['required'] ); $this->field_display_sublabel( 'secondary', 'after', $field ); $this->field_display_error( 'secondary', $field ); echo '</div>'; echo '</div>'; } // End if(). } /** * Format and sanitize field. * * @since 1.3.0 * @param int $field_id Field ID. * @param mixed $field_submit Field value that was submitted. * @param array $form_data Form data and settings. */ public function format( $field_id, $field_submit, $form_data ) { // Define data. if ( is_array( $field_submit ) ) { $value = ! empty( $field_submit['primary'] ) ? $field_submit['primary'] : ''; } else { $value = ! empty( $field_submit ) ? $field_submit : ''; } $name = ! empty( $form_data['fields'][ $field_id ] ['label'] ) ? $form_data['fields'][ $field_id ]['label'] : ''; // Set final field details. wpforms()->process->fields[ $field_id ] = array( 'name' => sanitize_text_field( $name ), 'value' => sanitize_text_field( $value ), 'id' => absint( $field_id ), 'type' => $this->type, ); } /** * Validate field on form submit. * * @since 1.0.0 * * @param int $field_id Field ID. * @param mixed $field_submit Field value that was submitted. * @param array $form_data Form data and settings. */ public function validate( $field_id, $field_submit, $form_data ) { $form_id = (int) $form_data['id']; parent::validate( $field_id, $field_submit, $form_data ); if ( ! is_array( $field_submit ) && ! empty( $field_submit ) ) { $field_submit = array( 'primary' => $field_submit, ); } if ( ! empty( $field_submit['primary'] ) && ! is_email( $field_submit['primary'] ) ) { wpforms()->process->errors[ $form_id ][ $field_id ]['primary'] = esc_html__( 'The provided email is not valid.', 'wpforms-lite' ); } elseif ( isset( $field_submit['primary'] ) && isset( $field_submit['secondary'] ) && $field_submit['secondary'] !== $field_submit['primary'] ) { wpforms()->process->errors[ $form_id ][ $field_id ]['secondary'] = esc_html__( 'The provided emails do not match.', 'wpforms-lite' ); } } } new WPForms_Field_Email(); fields/class-base.php 0000666 00000167507 15213301445 0010562 0 ustar 00 <?php /** * Base field template. * * @since 1.0.0 */ abstract class WPForms_Field { /** * Full name of the field type, eg "Paragraph Text". * * @since 1.0.0 * * @var string */ public $name; /** * Type of the field, eg "textarea". * * @since 1.0.0 * * @var string */ public $type; /** * Font Awesome Icon used for the editor button, eg "fa-list". * * @since 1.0.0 * * @var mixed */ public $icon = false; /** * Priority order the field button should show inside the "Add Fields" tab. * * @since 1.0.0 * * @var int */ public $order = 1; /** * Field group the field belongs to. * * @since 1.0.0 * * @var string */ public $group = 'standard'; /** * Placeholder to hold default value(s) for some field types. * * @since 1.0.0 * * @var mixed */ public $defaults; /** * Current form ID in the admin builder. * * @since 1.1.1 * * @var int|bool */ public $form_id; /** * Current field ID. * * @since 1.5.6 * * @var int */ public $field_id; /** * Current form data. * * @since 1.1.1 * * @var array */ public $form_data; /** * Current field data. * * @since 1.5.6 * * @var array */ public $field_data; /** * Primary class constructor. * * @since 1.0.0 * * @param bool $init Pass false to allow to shortcut the whole initialization, if needed. */ public function __construct( $init = true ) { if ( ! $init ) { return; } // The form ID is to be accessed in the builder. $this->form_id = isset( $_GET['form_id'] ) ? (int) $_GET['form_id'] : false; // phpcs:ignore WordPress.Security.NonceVerification // Bootstrap. $this->init(); // Temporary solution to get an object of the field class. add_filter( "wpforms_fields_get_field_object_{$this->type}", function () { return $this; } ); // Add fields tab. add_filter( 'wpforms_builder_fields_buttons', array( $this, 'field_button' ), 15 ); // Field options tab. add_action( "wpforms_builder_fields_options_{$this->type}", array( $this, 'field_options' ), 10 ); // Preview fields. add_action( "wpforms_builder_fields_previews_{$this->type}", array( $this, 'field_preview' ), 10 ); // AJAX Add new field. add_action( "wp_ajax_wpforms_new_field_{$this->type}", array( $this, 'field_new' ) ); // Display field input elements on front-end. add_action( "wpforms_display_field_{$this->type}", array( $this, 'field_display' ), 10, 3 ); // Validation on submit. add_action( "wpforms_process_validate_{$this->type}", array( $this, 'validate' ), 10, 3 ); // Format. add_action( "wpforms_process_format_{$this->type}", array( $this, 'format' ), 10, 3 ); // Prefill. add_filter( 'wpforms_field_properties', array( $this, 'field_prefill_value_property' ), 10, 3 ); } /** * All systems go. Used by subclasses. Required. * * @since 1.0.0 * @since 1.5.0 Converted to abstract method, as it's required for all fields. */ abstract public function init(); /** * Prefill field value with either fallback or dynamic data. * This needs to be public (although internal) to be used in WordPress hooks. * * @since 1.5.0 * * @param array $properties Field properties. * @param array $field Current field specific data. * @param array $form_data Prepared form data/settings. * * @return array Modified field properties. */ public function field_prefill_value_property( $properties, $field, $form_data ) { // Process only for current field. if ( $this->type !== $field['type'] ) { return $properties; } // Set the form data, so we can reuse it later, even on front-end. $this->form_data = $form_data; // Dynamic data. if ( ! empty( $this->form_data['settings']['dynamic_population'] ) ) { $properties = $this->field_prefill_value_property_dynamic( $properties, $field ); } // Fallback data, rewrites dynamic because user-submitted data is more important. $properties = $this->field_prefill_value_property_fallback( $properties, $field ); return $properties; } /** * As we are processing user submitted data - ignore all admin-defined defaults. * Preprocess choices-related fields only. * * @since 1.5.0 * * @param array $field Field data and settings. * @param array $properties Properties we are modifying. */ public function field_prefill_remove_choices_defaults( $field, &$properties ) { if ( ! empty( $field['dynamic_choices'] ) || ! empty( $field['choices'] ) ) { array_walk_recursive( $properties['inputs'], function ( &$value, $key ) { if ( 'default' === $key ) { $value = false; } if ( 'wpforms-selected' === $value ) { $value = ''; } } ); } } /** * Whether current field can be populated dynamically. * * @since 1.5.0 * * @param array $properties Field properties. * @param array $field Current field specific data. * * @return bool */ public function is_dynamic_population_allowed( $properties, $field ) { $allowed = true; // Allow population on front-end only. if ( is_admin() ) { $allowed = false; } // For dynamic population we require $_GET. if ( empty( $_GET ) ) { // phpcs:ignore $allowed = false; } return apply_filters( 'wpforms_field_is_dynamic_population_allowed', $allowed, $properties, $field ); } /** * Prefill the field value with a dynamic value, that we get from $_GET. * The pattern is: wpf4_12_primary, where: * 4 - form_id, * 12 - field_id, * first - input key. * As 'primary' is our default input key, "wpf4_12_primary" and "wpf4_12" are the same. * * @since 1.5.0 * * @param array $properties Field properties. * @param array $field Current field specific data. * * @return array Modified field properties. */ protected function field_prefill_value_property_dynamic( $properties, $field ) { if ( ! $this->is_dynamic_population_allowed( $properties, $field ) ) { return $properties; } // Iterate over each GET key, parse, and scrap data from there. foreach ( $_GET as $key => $raw_value ) { // phpcs:ignore preg_match( '/wpf(\d+)_(\d+)(.*)/i', $key, $matches ); if ( empty( $matches ) || ! is_array( $matches ) ) { continue; } // Required. $form_id = absint( $matches[1] ); $field_id = absint( $matches[2] ); $input = 'primary'; // Optional. if ( ! empty( $matches[3] ) ) { $input = sanitize_key( trim( $matches[3], '_' ) ); } // Both form and field IDs should be the same as current form/field. if ( (int) $this->form_data['id'] !== $form_id || (int) $field['id'] !== $field_id ) { // Go to the next GET param. continue; } if ( ! empty( $raw_value ) ) { $this->field_prefill_remove_choices_defaults( $field, $properties ); } /* * Some fields (like checkboxes) support multiple selection. * We do not support nested values, so omit them. * Example: ?wpf771_19_wpforms[fields][19][address1]=test * In this case: * $input = wpforms * $raw_value = [fields=>[]] * $single_value = [19=>[]] * There is no reliable way to clean those things out. * So we will ignore the value altogether if it's an array. * We support only single value numeric arrays, like these: * ?wpf771_19[]=test1&wpf771_19[]=test2 * ?wpf771_19_value[]=test1&wpf771_19_value[]=test2 * ?wpf771_41_r3_c2[]=1&wpf771_41_r1_c4[]=1 */ if ( is_array( $raw_value ) ) { foreach ( $raw_value as $single_value ) { $properties = $this->get_field_populated_single_property_value( $single_value, $input, $properties, $field ); } } else { $properties = $this->get_field_populated_single_property_value( $raw_value, $input, $properties, $field ); } } return $properties; } /** * Public version of get_field_populated_single_property_value() to use by external classes. * * @since 1.6.0.1 * * @param string $raw_value Value from a GET param, always a string. * @param string $input Represent a subfield inside the field. May be empty. * @param array $properties Field properties. * @param array $field Current field specific data. * * @return array Modified field properties. */ public function get_field_populated_single_property_value_public( $raw_value, $input, $properties, $field ) { return $this->get_field_populated_single_property_value( $raw_value, $input, $properties, $field ); } /** * Get the value, that is used to prefill via dynamic or fallback population. * Based on field data and current properties. * * @since 1.5.0 * * @param string $raw_value Value from a GET param, always a string. * @param string $input Represent a subfield inside the field. May be empty. * @param array $properties Field properties. * @param array $field Current field specific data. * * @return array Modified field properties. */ protected function get_field_populated_single_property_value( $raw_value, $input, $properties, $field ) { if ( ! is_string( $raw_value ) ) { return $properties; } $get_value = stripslashes( sanitize_text_field( $raw_value ) ); // For fields that have dynamic choices we need to add extra logic. if ( ! empty( $field['dynamic_choices'] ) ) { $properties = $this->get_field_populated_single_property_value_dynamic_choices( $get_value, $properties ); } elseif ( ! empty( $field['choices'] ) && is_array( $field['choices'] ) ) { $properties = $this->get_field_populated_single_property_value_normal_choices( $get_value, $properties, $field ); } else { /* * For other types of fields we need to check that * the key is registered for the defined field in inputs array. */ if ( ! empty( $input ) && isset( $properties['inputs'][ $input ] ) ) { $properties['inputs'][ $input ]['attr']['value'] = $get_value; } } return $properties; } /** * Get the value, that is used to prefill via dynamic or fallback population. * Based on field data and current properties. * Dynamic choices section. * * @since 1.6.0 * * @param string $get_value Value from a GET param, always a string, sanitized, stripped slashes. * @param array $properties Field properties. * * @return array Modified field properties. */ protected function get_field_populated_single_property_value_dynamic_choices( $get_value, $properties ) { $default_key = null; foreach ( $properties['inputs'] as $input_key => $input_arr ) { // Dynamic choices support only integers in its values. if ( absint( $get_value ) === $input_arr['attr']['value'] ) { $default_key = $input_key; // Stop iterating over choices. break; } } // Redefine default choice only if dynamic value has changed anything. if ( null !== $default_key ) { foreach ( $properties['inputs'] as $input_key => $choice_arr ) { if ( $input_key === $default_key ) { $properties['inputs'][ $input_key ]['default'] = true; $properties['inputs'][ $input_key ]['container']['class'][] = 'wpforms-selected'; // Stop iterating over choices. break; } } } return $properties; } /** * Get the value, that is used to prefill via dynamic or fallback population. * Based on field data and current properties. * Normal choices section. * * @since 1.6.0 * * @param string $get_value Value from a GET param, always a string, sanitized. * @param array $properties Field properties. * @param array $field Current field specific data. * * @return array Modified field properties. */ protected function get_field_populated_single_property_value_normal_choices( $get_value, $properties, $field ) { $default_key = null; // For fields that have normal choices we need to add extra logic. foreach ( $field['choices'] as $choice_key => $choice_arr ) { $choice_value_key = isset( $field['show_values'] ) ? 'value' : 'label'; if ( isset( $choice_arr[ $choice_value_key ] ) && strtoupper( sanitize_text_field( $choice_arr[ $choice_value_key ] ) ) === strtoupper( $get_value ) ) { $default_key = $choice_key; // Stop iterating over choices. break; } } // Redefine default choice only if population value has changed anything. if ( null !== $default_key ) { foreach ( $field['choices'] as $choice_key => $choice_arr ) { if ( $choice_key === $default_key ) { $properties['inputs'][ $choice_key ]['default'] = true; $properties['inputs'][ $choice_key ]['container']['class'][] = 'wpforms-selected'; break; } } } return $properties; } /** * Whether current field can be populated dynamically. * * @since 1.5.0 * * @param array $properties Field properties. * @param array $field Current field specific data. * * @return bool */ public function is_fallback_population_allowed( $properties, $field ) { $allowed = true; // Allow population on front-end only. if ( is_admin() ) { $allowed = false; } /* * Commented out to allow partial fail for complex multi-inputs fields. * Example: name field with first/last format and being required, filled out only first. * On submit we will preserve those sub-inputs that are not empty and display an error for an empty. */ // Do not populate if there are errors for that field. /* $errors = wpforms()->process->errors; if ( ! empty( $errors[ $this->form_data['id'] ][ $field['id'] ] ) ) { $allowed = false; } */ // Require form id being the same for submitted and currently rendered form. if ( ! empty( $_POST['wpforms']['id'] ) && // phpcs:ignore (int) $_POST['wpforms']['id'] !== (int) $this->form_data['id'] // phpcs:ignore ) { $allowed = false; } // Require $_POST of submitted field. if ( empty( $_POST['wpforms']['fields'] ) ) { // phpcs:ignore $allowed = false; } // Require field (processed and rendered) being the same. if ( ! isset( $_POST['wpforms']['fields'][ $field['id'] ] ) ) { // phpcs:ignore $allowed = false; } return apply_filters( 'wpforms_field_is_fallback_population_allowed', $allowed, $properties, $field ); } /** * Prefill the field value with a fallback value from form submission (in case of JS validation failed), that we get from $_POST. * * @since 1.5.0 * * @param array $properties Field properties. * @param array $field Current field specific data. * * @return array Modified field properties. */ protected function field_prefill_value_property_fallback( $properties, $field ) { if ( ! $this->is_fallback_population_allowed( $properties, $field ) ) { return $properties; } if ( empty( $_POST['wpforms']['fields'] ) || ! is_array( $_POST['wpforms']['fields'] ) ) { // phpcs:ignore return $properties; } // We got user submitted raw data (not processed, will be done later). $raw_value = $_POST['wpforms']['fields'][ $field['id'] ]; // phpcs:ignore $input = 'primary'; if ( ! empty( $raw_value ) ) { $this->field_prefill_remove_choices_defaults( $field, $properties ); } /* * For this particular field this value may be either array or a string. * In array - this is a complex field, like address. * The key in array will be a sub-input (address1, state), and its appropriate value. */ if ( is_array( $raw_value ) ) { foreach ( $raw_value as $input => $single_value ) { $properties = $this->get_field_populated_single_property_value( $single_value, sanitize_key( $input ), $properties, $field ); } } else { $properties = $this->get_field_populated_single_property_value( $raw_value, sanitize_key( $input ), $properties, $field ); } return $properties; } /** * Create the button for the 'Add Fields' tab, inside the form editor. * * @since 1.0.0 * * @param array $fields List of form fields with their data. * * @return array */ public function field_button( $fields ) { // Add field information to fields array. $fields[ $this->group ]['fields'][] = array( 'order' => $this->order, 'name' => $this->name, 'type' => $this->type, 'icon' => $this->icon, ); // Wipe hands clean. return $fields; } /** * Create the field options panel. Used by subclasses. * * @since 1.0.0 * @since 1.5.0 Converted to abstract method, as it's required for all fields. * * @param array $field Field data and settings. */ abstract public function field_options( $field ); /** * Create the field preview. Used by subclasses. * * @since 1.0.0 * @since 1.5.0 Converted to abstract method, as it's required for all fields. * * @param array $field Field data and settings. */ abstract public function field_preview( $field ); /** * Helper function to create field option elements. * * Field option elements are pieces that help create a field option. * They are used to quickly build field options. * * @since 1.0.0 * * @param string $option Field option to render. * @param array $field Field data and settings. * @param array $args Field preview arguments. * @param bool $echo Print or return the value. Print by default. * * @return mixed echo or return string */ public function field_element( $option, $field, $args = array(), $echo = true ) { $id = (int) $field['id']; $class = ! empty( $args['class'] ) ? sanitize_html_class( $args['class'] ) : ''; $slug = ! empty( $args['slug'] ) ? sanitize_title( $args['slug'] ) : ''; $attrs = ''; $output = ''; if ( ! empty( $args['data'] ) ) { foreach ( $args['data'] as $arg_key => $val ) { if ( is_array( $val ) ) { $val = wp_json_encode( $val ); } $attrs .= ' data-' . $arg_key . '=\'' . $val . '\''; } } if ( ! empty( $args['attrs'] ) ) { foreach ( $args['attrs'] as $arg_key => $val ) { if ( is_array( $val ) ) { $val = wp_json_encode( $val ); } $attrs .= $arg_key . '=\'' . $val . '\''; } } switch ( $option ) { // Row. case 'row': $output = sprintf( '<div class="wpforms-field-option-row wpforms-field-option-row-%s %s" id="wpforms-field-option-row-%d-%s" data-field-id="%d">%s</div>', $slug, $class, $id, $slug, $id, $args['content'] ); break; // Label. case 'label': $output = sprintf( '<label for="wpforms-field-option-%d-%s">%s', $id, $slug, esc_html( $args['value'] ) ); if ( isset( $args['tooltip'] ) && ! empty( $args['tooltip'] ) ) { $output .= ' ' . sprintf( '<i class="fa fa-question-circle wpforms-help-tooltip" title="%s"></i>', esc_attr( $args['tooltip'] ) ); } if ( isset( $args['after_tooltip'] ) && ! empty( $args['after_tooltip'] ) ) { $output .= $args['after_tooltip']; } $output .= '</label>'; break; // Text input. case 'text': $type = ! empty( $args['type'] ) ? esc_attr( $args['type'] ) : 'text'; $placeholder = ! empty( $args['placeholder'] ) ? esc_attr( $args['placeholder'] ) : ''; $before = ! empty( $args['before'] ) ? '<span class="before-input">' . esc_html( $args['before'] ) . '</span>' : ''; if ( ! empty( $before ) ) { $class .= ' has-before'; } $output = sprintf( '%s<input type="%s" class="%s" id="wpforms-field-option-%d-%s" name="fields[%d][%s]" value="%s" placeholder="%s" %s>', $before, $type, $class, $id, $slug, $id, $slug, esc_attr( $args['value'] ), $placeholder, $attrs ); break; // Textarea. case 'textarea': $rows = ! empty( $args['rows'] ) ? (int) $args['rows'] : '3'; $output = sprintf( '<textarea class="%s" id="wpforms-field-option-%d-%s" name="fields[%d][%s]" rows="%d" %s>%s</textarea>', $class, $id, $slug, $id, $slug, $rows, $attrs, $args['value'] ); break; // Checkbox. case 'checkbox': $checked = checked( '1', $args['value'], false ); $output = sprintf( '<input type="checkbox" class="%s" id="wpforms-field-option-%d-%s" name="fields[%d][%s]" value="1" %s %s>', $class, $id, $slug, $id, $slug, $checked, $attrs ); $output .= sprintf( '<label for="wpforms-field-option-%d-%s" class="inline">%s', $id, $slug, $args['desc'] ); if ( isset( $args['tooltip'] ) && ! empty( $args['tooltip'] ) ) { $output .= ' ' . sprintf( '<i class="fa fa-question-circle wpforms-help-tooltip" title="%s"></i>', esc_attr( $args['tooltip'] ) ); } $output .= '</label>'; break; // Toggle. case 'toggle': $checked = checked( '1', $args['value'], false ); $icon = $args['value'] ? 'fa-toggle-on' : 'fa-toggle-off'; $cls = $args['value'] ? 'wpforms-on' : 'wpforms-off'; $status = $args['value'] ? esc_html__( 'On', 'wpforms-lite' ) : esc_html__( 'Off', 'wpforms-lite' ); $output = sprintf( '<span class="wpforms-toggle-icon %s"><i class="fa %s" aria-hidden="true"></i> <span class="wpforms-toggle-icon-label">%s</span>', $cls, $icon, $status ); $output .= sprintf( '<input type="checkbox" class="%s" id="wpforms-field-option-%d-%s" name="fields[%d][%s]" value="1" %s %s></span>', $class, $id, $slug, $id, $slug, $checked, $attrs ); break; // Select. case 'select': $options = $args['options']; $value = isset( $args['value'] ) ? $args['value'] : ''; $output = sprintf( '<select class="%s" id="wpforms-field-option-%d-%s" name="fields[%d][%s]" %s>', $class, $id, $slug, $id, $slug, $attrs ); foreach ( $options as $arg_key => $arg_option ) { $output .= sprintf( '<option value="%s" %s>%s</option>', esc_attr( $arg_key ), selected( $arg_key, $value, false ), $arg_option ); } $output .= '</select>'; break; } if ( ! $echo ) { return $output; } echo $output; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped } /** * Helper function to create common field options that are used frequently. * * @since 1.0.0 * * @param string $option Field option to render. * @param array $field Field data and settings. * @param array $args Field preview arguments. * @param bool $echo Print or return the value. Print by default. * * @return mixed echo or return string */ public function field_option( $option, $field, $args = array(), $echo = true ) { switch ( $option ) { /** * Basic Fields. */ /* * Basic Options markup. */ case 'basic-options': $markup = ! empty( $args['markup'] ) ? $args['markup'] : 'open'; $class = ! empty( $args['class'] ) ? esc_html( $args['class'] ) : ''; if ( 'open' === $markup ) { $output = sprintf( '<div class="wpforms-field-option-group wpforms-field-option-group-basic" id="wpforms-field-option-basic-%d">', $field['id'] ); $output .= sprintf( '<a href="#" class="wpforms-field-option-group-toggle">%s <span>(ID #%d)</span> <i class="fa fa-angle-down"></i></a>', $this->name, $field['id'] ); $output .= sprintf( '<div class="wpforms-field-option-group-inner %s">', $class ); } else { $output = '</div></div>'; } break; /* * Field Label. */ case 'label': $value = ! empty( $field['label'] ) ? esc_attr( $field['label'] ) : ''; $tooltip = esc_html__( 'Enter text for the form field label. Field labels are recommended and can be hidden in the Advanced Settings.', 'wpforms-lite' ); $output = $this->field_element( 'label', $field, array( 'slug' => 'label', 'value' => esc_html__( 'Label', 'wpforms-lite' ), 'tooltip' => $tooltip ), false ); $output .= $this->field_element( 'text', $field, array( 'slug' => 'label', 'value' => $value ), false ); $output = $this->field_element( 'row', $field, array( 'slug' => 'label', 'content' => $output ), false ); break; /* * Field Description. */ case 'description': $value = ! empty( $field['description'] ) ? esc_attr( $field['description'] ) : ''; $tooltip = esc_html__( 'Enter text for the form field description.', 'wpforms-lite' ); $output = $this->field_element( 'label', $field, array( 'slug' => 'description', 'value' => esc_html__( 'Description', 'wpforms-lite' ), 'tooltip' => $tooltip ), false ); $output .= $this->field_element( 'textarea', $field, array( 'slug' => 'description', 'value' => $value ), false ); $output = $this->field_element( 'row', $field, array( 'slug' => 'description', 'content' => $output ), false ); break; /* * Field Required toggle. */ case 'required': $default = ! empty( $args['default'] ) ? $args['default'] : '0'; $value = isset( $field['required'] ) ? $field['required'] : $default; $tooltip = esc_html__( 'Check this option to mark the field required. A form will not submit unless all required fields are provided.', 'wpforms-lite' ); $output = $this->field_element( 'checkbox', $field, array( 'slug' => 'required', 'value' => $value, 'desc' => esc_html__( 'Required', 'wpforms-lite' ), 'tooltip' => $tooltip ), false ); $output = $this->field_element( 'row', $field, array( 'slug' => 'required', 'content' => $output ), false ); break; /* * Field Meta (field type and ID). */ case 'meta': $output = sprintf( '<label>%s</label>', 'Type' ); $output .= sprintf( '<p class="meta">%s <span class="id">(ID #%d)</span></p>', $this->name, $field['id'] ); $output = $this->field_element( 'row', $field, array( 'slug' => 'meta', 'content' => $output ), false ); break; /* * Code Block. */ case 'code': $value = ! empty( $field['code'] ) ? esc_textarea( $field['code'] ) : ''; $tooltip = esc_html__( 'Enter code for the form field.', 'wpforms-lite' ); $output = $this->field_element( 'label', $field, array( 'slug' => 'code', 'value' => esc_html__( 'Code', 'wpforms-lite' ), 'tooltip' => $tooltip ), false ); $output .= $this->field_element( 'textarea', $field, array( 'slug' => 'code', 'value' => $value ), false ); $output = $this->field_element( 'row', $field, array( 'slug' => 'code', 'content' => $output ), false ); break; /* * Choices. */ case 'choices': $values = ! empty( $field['choices'] ) ? $field['choices'] : $this->defaults; $label = ! empty( $args['label'] ) ? esc_html( $args['label'] ) : esc_html__( 'Choices', 'wpforms-lite' ); $class = array(); if ( ! empty( $field['show_values'] ) ) { $class[] = 'show-values'; } if ( ! empty( $field['dynamic_choices'] ) ) { $class[] = 'wpforms-hidden'; } if ( ! empty( $field['choices_images'] ) ) { $class[] = 'show-images'; } // Field label. $lbl = $this->field_element( 'label', $field, array( 'slug' => 'choices', 'value' => $label, 'tooltip' => esc_html__( 'Add choices for the form field.', 'wpforms-lite' ), 'after_tooltip' => '<a href="#" class="toggle-bulk-add-display"><i class="fa fa-download"></i> <span>' . esc_html__( 'Bulk Add', 'wpforms-lite' ) . '</span></a>', ), false ); // Field contents. $fld = sprintf( '<ul data-next-id="%s" class="choices-list %s" data-field-id="%d" data-field-type="%s">', max( array_keys( $values ) ) + 1, wpforms_sanitize_classes( $class, true ), $field['id'], $this->type ); foreach ( $values as $key => $value ) { $default = ! empty( $value['default'] ) ? $value['default'] : ''; $base = sprintf( 'fields[%s][choices][%s]', $field['id'], $key ); $image = ! empty( $value['image'] ) ? $value['image'] : ''; $image_btn = ''; $fld .= '<li data-key="' . absint( $key ) . '">'; $fld .= sprintf( '<input type="%s" name="%s[default]" class="default" value="1" %s>', 'checkbox' === $this->type ? 'checkbox' : 'radio', $base, checked( '1', $default, false ) ); $fld .= '<span class="move"><i class="fa fa-bars"></i></span>'; $fld .= sprintf( '<input type="text" name="%s[label]" value="%s" class="label">', $base, esc_attr( $value['label'] ) ); $fld .= '<a class="add" href="#"><i class="fa fa-plus-circle"></i></a><a class="remove" href="#"><i class="fa fa-minus-circle"></i></a>'; $fld .= sprintf( '<input type="text" name="%s[value]" value="%s" class="value">', $base, esc_attr( ! isset( $value['value'] ) ? '' : $value['value'] ) ); $fld .= '<div class="wpforms-image-upload">'; $fld .= '<div class="preview">'; if ( ! empty( $image ) ) { $fld .= sprintf( '<a href="#" title="%s" class="wpforms-image-upload-remove"><img src="%s"></a>', esc_attr__( 'Remove Image', 'wpforms-lite' ), esc_url_raw( $image ) ); $image_btn = ' style="display:none;"'; } $fld .= '</div>'; $fld .= sprintf( '<button class="wpforms-btn wpforms-btn-md wpforms-btn-light-grey wpforms-btn-block wpforms-image-upload-add" data-after-upload="hide"%s>%s</button>', $image_btn, esc_html__( 'Upload Image', 'wpforms-lite' ) ); $fld .= sprintf( '<input type="hidden" name="%s[image]" value="%s" class="source">', $base, esc_url_raw( $image ) ); $fld .= '</div>'; $fld .= '</li>'; } $fld .= '</ul>'; // Field note: dynamic status. $source = ''; $type = ''; $dynamic = ! empty( $field['dynamic_choices'] ) ? esc_html( $field['dynamic_choices'] ) : ''; if ( 'post_type' === $dynamic && ! empty( $field[ 'dynamic_' . $dynamic ] ) ) { $type = esc_html__( 'post type', 'wpforms-lite' ); $pt = get_post_type_object( $field[ 'dynamic_' . $dynamic ] ); $source = ''; if ( null !== $pt ) { $source = $pt->labels->name; } } elseif ( 'taxonomy' === $dynamic && ! empty( $field[ 'dynamic_' . $dynamic ] ) ) { $type = esc_html__( 'taxonomy', 'wpforms-lite' ); $tax = get_taxonomy( $field[ 'dynamic_' . $dynamic ] ); $source = ''; if ( false !== $tax ) { $source = $tax->labels->name; } } $note = sprintf( '<div class="wpforms-alert-warning wpforms-alert-small wpforms-alert %s">', ! empty( $dynamic ) && ! empty( $field[ 'dynamic_' . $dynamic ] ) ? '' : 'wpforms-hidden' ); $note .= sprintf( /* translators: %1$s - source name; %2$s - type name. */ esc_html__( 'Choices are dynamically populated from the %1$s %2$s.', 'wpforms' ), '<span class="dynamic-name">' . $source . '</span>', '<span class="dynamic-type">' . $type . '</span>' ); $note .= '</div>'; // Final field output. $output = $this->field_element( 'row', $field, array( 'slug' => 'choices', 'content' => $lbl . $fld . $note, ), false ); break; /* * Choices for payments. */ case 'choices_payments': $values = ! empty( $field['choices'] ) ? $field['choices'] : $this->defaults; $class = array(); $input_type = in_array( $field['type'], array( 'payment-multiple', 'payment-select' ), true ) ? 'radio' : 'checkbox'; if ( ! empty( $field['choices_images'] ) ) { $class[] = 'show-images'; } // Field label. $lbl = $this->field_element( 'label', $field, array( 'slug' => 'choices', 'value' => esc_html__( 'Items', 'wpforms-lite' ), 'tooltip' => esc_html__( 'Add choices for the form field.', 'wpforms-lite' ), ), false ); // Field contents. $fld = sprintf( '<ul data-next-id="%s" class="choices-list %s" data-field-id="%d" data-field-type="%s">', max( array_keys( $values ) ) + 1, wpforms_sanitize_classes( $class, true ), $field['id'], $this->type ); foreach ( $values as $key => $value ) { $default = ! empty( $value['default'] ) ? $value['default'] : ''; $base = sprintf( 'fields[%s][choices][%s]', $field['id'], $key ); $image = ! empty( $value['image'] ) ? $value['image'] : ''; $image_btn = ''; $fld .= '<li data-key="' . absint( $key ) . '">'; $fld .= sprintf( '<input type="%s" name="%s[default]" class="default" value="1" %s>', $input_type, $base, checked( '1', $default, false ) ); $fld .= '<span class="move"><i class="fa fa-bars"></i></span>'; $fld .= sprintf( '<input type="text" name="%s[label]" value="%s" class="label">', $base, esc_attr( $value['label'] ) ); $fld .= sprintf( '<input type="text" name="%s[value]" value="%s" class="value wpforms-money-input" placeholder="%s">', $base, esc_attr( $value['value'] ), wpforms_format_amount( 0 ) ); $fld .= '<a class="add" href="#"><i class="fa fa-plus-circle"></i></a><a class="remove" href="#"><i class="fa fa-minus-circle"></i></a>'; $fld .= '<div class="wpforms-image-upload">'; $fld .= '<div class="preview">'; if ( ! empty( $image ) ) { $fld .= sprintf( '<a href="#" title="%s" class="wpforms-image-upload-remove"><img src="%s"></a>', esc_attr__( 'Remove Image', 'wpforms-lite' ), esc_url_raw( $image ) ); $image_btn = ' style="display:none;"'; } $fld .= '</div>'; $fld .= sprintf( '<button class="wpforms-btn wpforms-btn-md wpforms-btn-light-grey wpforms-btn-block wpforms-image-upload-add" data-after-upload="hide"%s>%s</button>', $image_btn, esc_html__( 'Upload Image', 'wpforms-lite' ) ); $fld .= sprintf( '<input type="hidden" name="%s[image]" value="%s" class="source">', $base, esc_url_raw( $image ) ); $fld .= '</div>'; $fld .= '</li>'; } $fld .= '</ul>'; // Final field output. $output = $this->field_element( 'row', $field, array( 'slug' => 'choices', 'content' => $lbl . $fld, ), false ); break; /* * Choices Images. */ case 'choices_images': // Field note: Image tips. $note = sprintf( '<div class="wpforms-alert-warning wpforms-alert-small wpforms-alert %s">', ! empty( $field['choices_images'] ) ? '' : 'wpforms-hidden' ); $note .= esc_html__( 'Images are not cropped or resized. For best results, they should be the same size and 250x250 pixels or smaller.', 'wpforms-lite' ); $note .= '</div>'; // Field contents. $fld = $this->field_element( 'checkbox', $field, array( 'slug' => 'choices_images', 'value' => isset( $field['choices_images'] ) ? '1' : '0', 'desc' => esc_html__( 'Use image choices', 'wpforms-lite' ), 'tooltip' => esc_html__( 'Check this option to enable using images with the choices.', 'wpforms-lite' ), ), false ); // Final field output. $output = $this->field_element( 'row', $field, array( 'slug' => 'choices_images', 'class' => ! empty( $field['dynamic_choices'] ) ? 'wpforms-hidden' : '', 'content' => $note . $fld, ), false ); break; /* * Choices Images Style. */ case 'choices_images_style': // Field label. $lbl = $this->field_element( 'label', $field, array( 'slug' => 'choices_images_style', 'value' => esc_html__( 'Image Choice Style', 'wpforms-lite' ), 'tooltip' => esc_html__( 'Select the style for the image choices.', 'wpforms-lite' ), ), false ); // Field contents. $fld = $this->field_element( 'select', $field, array( 'slug' => 'choices_images_style', 'value' => ! empty( $field['choices_images_style'] ) ? esc_attr( $field['choices_images_style'] ) : 'modern', 'options' => array( 'modern' => esc_html__( 'Modern', 'wpforms-lite' ), 'classic' => esc_html__( 'Classic', 'wpforms-lite' ), 'none' => esc_html__( 'None', 'wpforms-lite' ), ), ), false ); // Final field output. $output = $this->field_element( 'row', $field, array( 'slug' => 'choices_images_style', 'content' => $lbl . $fld, 'class' => ! empty( $field['choices_images'] ) ? '' : 'wpforms-hidden', ), false ); break; /** * Advanced Fields. */ /* * Default value. */ case 'default_value': $value = ! empty( $field['default_value'] ) || ( isset( $field['default_value'] ) && '0' === (string) $field['default_value'] ) ? esc_attr( $field['default_value'] ) : ''; $tooltip = esc_html__( 'Enter text for the default form field value.', 'wpforms-lite' ); $toggle = '<a href="#" class="toggle-smart-tag-display" data-type="other"><i class="fa fa-tags"></i> <span>' . esc_html__( 'Show Smart Tags', 'wpforms-lite' ) . '</span></a>'; $output = $this->field_element( 'label', $field, array( 'slug' => 'default_value', 'value' => esc_html__( 'Default Value', 'wpforms-lite' ), 'tooltip' => $tooltip, 'after_tooltip' => $toggle ), false ); $output .= $this->field_element( 'text', $field, array( 'slug' => 'default_value', 'value' => $value ), false ); $output = $this->field_element( 'row', $field, array( 'slug' => 'default_value', 'content' => $output ), false ); break; /* * Size. */ case 'size': $value = ! empty( $field['size'] ) ? esc_attr( $field['size'] ) : 'medium'; $class = ! empty( $args['class'] ) ? esc_html( $args['class'] ) : ''; $tooltip = esc_html__( 'Select the default form field size.', 'wpforms-lite' ); $options = array( 'small' => esc_html__( 'Small', 'wpforms-lite' ), 'medium' => esc_html__( 'Medium', 'wpforms-lite' ), 'large' => esc_html__( 'Large', 'wpforms-lite' ), ); $output = $this->field_element( 'label', $field, array( 'slug' => 'size', 'value' => esc_html__( 'Field Size', 'wpforms-lite' ), 'tooltip' => $tooltip ), false ); $output .= $this->field_element( 'select', $field, array( 'slug' => 'size', 'value' => $value, 'options' => $options ), false ); $output = $this->field_element( 'row', $field, array( 'slug' => 'size', 'content' => $output, 'class' => $class ), false ); break; /* * Advanced Options markup. */ case 'advanced-options': $markup = ! empty( $args['markup'] ) ? $args['markup'] : 'open'; if ( 'open' === $markup ) { $override = apply_filters( 'wpforms_advanced_options_override', false ); $override = ! empty( $override ) ? 'style="display:' . $override . ';"' : ''; $output = sprintf( '<div class="wpforms-field-option-group wpforms-field-option-group-advanced wpforms-hide" id="wpforms-field-option-advanced-%d" %s>', $field['id'], $override ); $output .= sprintf( '<a href="#" class="wpforms-field-option-group-toggle">%s <i class="fa fa-angle-right"></i></a>', esc_html__( 'Advanced Options', 'wpforms-lite' ) ); $output .= '<div class="wpforms-field-option-group-inner">'; } else { $output = '</div></div>'; } break; /* * Placeholder. */ case 'placeholder': $value = ! empty( $field['placeholder'] ) ? esc_attr( $field['placeholder'] ) : ''; $tooltip = esc_html__( 'Enter text for the form field placeholder.', 'wpforms-lite' ); $output = $this->field_element( 'label', $field, array( 'slug' => 'placeholder', 'value' => esc_html__( 'Placeholder Text', 'wpforms-lite' ), 'tooltip' => $tooltip ), false ); $output .= $this->field_element( 'text', $field, array( 'slug' => 'placeholder', 'value' => $value ), false ); $output = $this->field_element( 'row', $field, array( 'slug' => 'placeholder', 'content' => $output ), false ); break; /* * CSS classes. */ case 'css': $toggle = ''; $value = ! empty( $field['css'] ) ? esc_attr( $field['css'] ) : ''; $tooltip = esc_html__( 'Enter CSS class names for the form field container. Class names should be separated with spaces.', 'wpforms-lite' ); if ( 'pagebreak' !== $field['type'] ) { $toggle = '<a href="#" class="toggle-layout-selector-display"><i class="fa fa-th-large"></i> <span>' . esc_html__( 'Show Layouts', 'wpforms-lite' ) . '</span></a>'; } // Build output. $output = $this->field_element( 'label', $field, array( 'slug' => 'css', 'value' => esc_html__( 'CSS Classes', 'wpforms-lite' ), 'tooltip' => $tooltip, 'after_tooltip' => $toggle ), false ); $output .= $this->field_element( 'text', $field, array( 'slug' => 'css', 'value' => $value ), false ); $output = $this->field_element( 'row', $field, array( 'slug' => 'css', 'content' => $output ), false ); break; /* * Hide Label. */ case 'label_hide': $value = isset( $field['label_hide'] ) ? $field['label_hide'] : '0'; $tooltip = esc_html__( 'Check this option to hide the form field label.', 'wpforms-lite' ); // Build output. $output = $this->field_element( 'checkbox', $field, array( 'slug' => 'label_hide', 'value' => $value, 'desc' => esc_html__( 'Hide Label', 'wpforms-lite' ), 'tooltip' => $tooltip ), false ); $output = $this->field_element( 'row', $field, array( 'slug' => 'label_hide', 'content' => $output ), false ); break; /* * Hide Sub-Labels. */ case 'sublabel_hide': $value = isset( $field['sublabel_hide'] ) ? $field['sublabel_hide'] : '0'; $tooltip = esc_html__( 'Check this option to hide the form field sub-label.', 'wpforms-lite' ); // Build output. $output = $this->field_element( 'checkbox', $field, array( 'slug' => 'sublabel_hide', 'value' => $value, 'desc' => esc_html__( 'Hide Sub-Labels', 'wpforms-lite' ), 'tooltip' => $tooltip ), false ); $output = $this->field_element( 'row', $field, array( 'slug' => 'sublabel_hide', 'content' => $output ), false ); break; /* * Input Columns. */ case 'input_columns': $value = ! empty( $field['input_columns'] ) ? esc_attr( $field['input_columns'] ) : ''; $tooltip = esc_html__( 'Select the layout for displaying field choices.', 'wpforms-lite' ); $options = array( '' => esc_html__( 'One Column', 'wpforms-lite' ), '2' => esc_html__( 'Two Columns', 'wpforms-lite' ), '3' => esc_html__( 'Three Columns', 'wpforms-lite' ), 'inline' => esc_html__( 'Inline', 'wpforms-lite' ), ); $output = $this->field_element( 'label', $field, array( 'slug' => 'input_columns', 'value' => esc_html__( 'Choice Layout', 'wpforms-lite' ), 'tooltip' => $tooltip ), false ); $output .= $this->field_element( 'select', $field, array( 'slug' => 'input_columns', 'value' => $value, 'options' => $options ), false ); $output = $this->field_element( 'row', $field, array( 'slug' => 'input_columns', 'content' => $output ), false ); break; /* * Dynamic Choices. */ case 'dynamic_choices': $value = ! empty( $field['dynamic_choices'] ) ? esc_attr( $field['dynamic_choices'] ) : ''; $tooltip = esc_html__( 'Select auto-populate method to use.', 'wpforms-lite' ); $options = array( '' => esc_html__( 'Off', 'wpforms-lite' ), 'post_type' => esc_html__( 'Post Type', 'wpforms-lite' ), 'taxonomy' => esc_html__( 'Taxonomy', 'wpforms-lite' ), ); $output = $this->field_element( 'label', $field, array( 'slug' => 'dynamic_choices', 'value' => esc_html__( 'Dynamic Choices', 'wpforms-lite' ), 'tooltip' => $tooltip ), false ); $output .= $this->field_element( 'select', $field, array( 'slug' => 'dynamic_choices', 'value' => $value, 'options' => $options ), false ); $output = $this->field_element( 'row', $field, array( 'slug' => 'dynamic_choices', 'content' => $output ), false ); break; /* * Dynamic Choices Source. */ case 'dynamic_choices_source': $output = ''; $type = ! empty( $field['dynamic_choices'] ) ? esc_attr( $field['dynamic_choices'] ) : ''; if ( ! empty( $type ) ) { $type_name = ''; $items = array(); if ( 'post_type' === $type ) { $type_name = esc_html__( 'Post Type', 'wpforms-lite' ); $items = get_post_types( array( 'public' => true, ), 'objects' ); unset( $items['attachment'] ); } elseif ( 'taxonomy' === $type ) { $type_name = esc_html__( 'Taxonomy', 'wpforms-lite' ); $items = get_taxonomies( array( 'public' => true, ), 'objects' ); unset( $items['post_format'] ); } /* translators: %s - dynamic source type name. */ $tooltip = sprintf( esc_html__( 'Select %s to use for auto-populating field choices.', 'wpforms-lite' ), $type_name ); /* translators: %s - dynamic source type name. */ $label = sprintf( esc_html__( 'Dynamic %s Source', 'wpforms-lite' ), $type_name ); $options = array(); $source = ! empty( $field[ 'dynamic_' . $type ] ) ? esc_attr( $field[ 'dynamic_' . $type ] ) : ''; foreach ( $items as $key => $item ) { $options[ $key ] = $item->labels->name; } // Field option label. $option_label = $this->field_element( 'label', $field, array( 'slug' => 'dynamic_' . $type, 'value' => $label, 'tooltip' => $tooltip, ), false ); // Field option select input. $option_input = $this->field_element( 'select', $field, array( 'slug' => 'dynamic_' . $type, 'options' => $options, 'value' => $source, ), false ); // Field option row (markup) including label and input. $output = $this->field_element( 'row', $field, array( 'slug' => 'dynamic_' . $type, 'content' => $option_label . $option_input, ), false ); } // End if(). break; } if ( ! $echo ) { return $output; } if ( in_array( $option, array( 'basic-options', 'advanced-options' ), true ) ) { if ( 'open' === $markup ) { do_action( "wpforms_field_options_before_{$option}", $field, $this ); } if ( 'close' === $markup ) { do_action( "wpforms_field_options_bottom_{$option}", $field, $this ); } echo $output; // WPCS: XSS ok. if ( 'open' === $markup ) { do_action( "wpforms_field_options_top_{$option}", $field, $this ); } if ( 'close' === $markup ) { do_action( "wpforms_field_options_after_{$option}", $field, $this ); } } else { echo $output; // WPCS: XSS ok. } } /** * Helper function to create common field options that are used frequently * in the field preview. * * @since 1.0.0 * @since 1.5.0 Added support for <select> HTML tag for choices. * * @param string $option Field option to render. * @param array $field Field data and settings. * @param array $args Field preview arguments. * @param bool $echo Print or return the value. Print by default. * * @return mixed Print or return a string. */ public function field_preview_option( $option, $field, $args = array(), $echo = true ) { $output = ''; $class = ! empty( $args['class'] ) ? wpforms_sanitize_classes( $args['class'] ) : ''; $allowed_tags = wpforms_builder_preview_get_allowed_tags(); switch ( $option ) { case 'label': $label = isset( $field['label'] ) && ! empty( $field['label'] ) ? esc_html( $field['label'] ) : ''; $output = sprintf( '<label class="label-title %s"><span class="text">%s</span><span class="required">*</span></label>', $class, $label ); break; case 'description': $description = isset( $field['description'] ) && ! empty( $field['description'] ) ? wp_kses( $field['description'], $allowed_tags ) : ''; $description = strpos( $class, 'nl2br' ) !== false ? nl2br( $description ) : $description; $output = sprintf( '<div class="description %s">%s</div>', $class, $description ); break; case 'choices': $fields_w_choices = array( 'checkbox', 'gdpr-checkbox', 'select', 'payment-select', 'radio', 'payment-multiple', 'payment-checkbox' ); $values = ! empty( $field['choices'] ) ? $field['choices'] : $this->defaults; $dynamic = ! empty( $field['dynamic_choices'] ) ? $field['dynamic_choices'] : false; $total = 0; /* * Check to see if this field is configured for Dynamic Choices, * either auto populating from a post type or a taxonomy. */ if ( ! empty( $field['dynamic_post_type'] ) || ! empty( $field['dynamic_taxonomy'] ) ) { switch ( $dynamic ) { case 'post_type': // Post type dynamic populating. $total_obj = wp_count_posts( $field['dynamic_post_type'] ); $total = isset( $total_obj->publish ) ? (int) $total_obj->publish : 0; $values = array(); $posts = wpforms_get_hierarchical_object( apply_filters( 'wpforms_dynamic_choice_post_type_args', array( 'post_type' => $field['dynamic_post_type'], 'posts_per_page' => -1, 'orderby' => 'title', 'order' => 'ASC', ), $field, $this->form_id ), true ); foreach ( $posts as $post ) { $values[] = array( 'label' => $post->post_title, ); } break; case 'taxonomy': // Taxonomy dynamic populating. $total = (int) wp_count_terms( $field['dynamic_taxonomy'] ); $values = array(); $terms = wpforms_get_hierarchical_object( apply_filters( 'wpforms_dynamic_choice_taxonomy_args', array( 'taxonomy' => $field['dynamic_taxonomy'], 'hide_empty' => false, ), $field, $this->form_id ), true ); foreach ( $terms as $term ) { $values[] = array( 'label' => $term->name, ); } break; } } // Notify if dynamic choices source is currently empty. if ( empty( $values ) ) { $values = array( array( 'label' => esc_html__( '(empty)', 'wpforms-lite' ), ), ); } // Build output. if ( ! in_array( $field['type'], $fields_w_choices, true ) ) { break; } switch ( $field['type'] ) { case 'checkbox': case 'gdpr-checkbox': case 'payment-checkbox': $type = 'checkbox'; break; case 'select': case 'payment-select': $type = 'select'; break; default: $type = 'radio'; break; } $list_class = array( 'primary-input' ); $with_images = empty( $field['dynamic_choices'] ) && ! empty( $field['choices_images'] ); if ( $with_images ) { $list_class[] = 'wpforms-image-choices'; $list_class[] = 'wpforms-image-choices-' . sanitize_html_class( $field['choices_images_style'] ); } // Special rules for <select>-based fields. if ( 'select' === $type ) { $placeholder = ! empty( $field['placeholder'] ) ? $field['placeholder'] : ''; $output = sprintf( '<select class="%s" disabled>', wpforms_sanitize_classes( $list_class, true ) ); // Optional placeholder. if ( ! empty( $placeholder ) ) { $output .= sprintf( '<option value="" class="placeholder">%s</option>', esc_html( $placeholder ) ); } // Build the select options (even though user can only see 1st option). foreach ( $values as $key => $value ) { $default = isset( $value['default'] ) ? (bool) $value['default'] : false; $selected = ! empty( $placeholder ) ? '' : selected( true, $default, false ); $output .= sprintf( '<option %s>%s</option>', $selected, esc_html( $value['label'] ) ); } $output .= '</select>'; } else { // Normal checkbox/radio-based fields. $output = sprintf( '<ul class="%s">', wpforms_sanitize_classes( $list_class, true ) ); foreach ( $values as $key => $value ) { $default = isset( $value['default'] ) ? $value['default'] : ''; $selected = checked( '1', $default, false ); $input_class = array(); $item_class = array(); if ( ! empty( $value['default'] ) ) { $item_class[] = 'wpforms-selected'; } if ( $with_images ) { $item_class[] = 'wpforms-image-choices-item'; } $output .= sprintf( '<li class="%s">', wpforms_sanitize_classes( $item_class, true ) ); if ( $with_images ) { if ( in_array( $field['choices_images_style'], array( 'modern', 'classic' ), true ) ) { $input_class[] = 'wpforms-screen-reader-element'; } $output .= '<label>'; $output .= sprintf( '<span class="wpforms-image-choices-image"><img src="%s" alt="%s"%s></span>', ! empty( $value['image'] ) ? esc_url( $value['image'] ) : WPFORMS_PLUGIN_URL . 'assets/images/placeholder-200x125.png', esc_attr( $value['label'] ), ! empty( $value['label'] ) ? ' title="' . esc_attr( $value['label'] ) . '"' : '' ); if ( 'none' === $field['choices_images_style'] ) { $output .= '<br>'; } $output .= sprintf( '<input type="%s" class="%s" %s disabled>', $type, wpforms_sanitize_classes( $input_class, true ), $selected ); $output .= '<span class="wpforms-image-choices-label">' . wp_kses_post( $value['label'] ) . '</span>'; $output .= '</label>'; } else { $output .= sprintf( '<input type="%s" %s disabled>%s', $type, $selected, wp_kses( $value['label'], $allowed_tags ) ); } $output .= '</li>'; } $output .= '</ul>'; } /* * Dynamic population is enabled and contains more than 20 items, * include a note about results displayed. */ if ( $total > 20 ) { $output .= '<div class="wpforms-alert-dynamic wpforms-alert wpforms-alert-warning">'; $output .= sprintf( wp_kses( /* translators: %d - total amount of choices. */ __( 'Showing the first 20 choices.<br> All %d choices will be displayed when viewing the form.', 'wpforms-lite' ), array( 'br' => array(), ) ), $total ); $output .= '</div>'; } break; } if ( ! $echo ) { return $output; } echo $output; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped } /** * Create a new field in the admin AJAX editor. * * @since 1.0.0 */ public function field_new() { // Run a security check. check_ajax_referer( 'wpforms-builder', 'nonce' ); // Check for permissions. if ( ! wpforms_current_user_can( 'edit_forms' ) ) { die( esc_html__( 'You do not have permission.', 'wpforms-lite' ) ); } // Check for form ID. if ( ! isset( $_POST['id'] ) || empty( $_POST['id'] ) ) { die( esc_html__( 'No form ID found', 'wpforms-lite' ) ); } // Check for field type to add. if ( ! isset( $_POST['type'] ) || empty( $_POST['type'] ) ) { die( esc_html__( 'No field type found', 'wpforms-lite' ) ); } // Grab field data. $field_args = ! empty( $_POST['defaults'] ) ? (array) $_POST['defaults'] : array(); $field_type = esc_attr( $_POST['type'] ); $field_id = wpforms()->form->next_field_id( $_POST['id'] ); $field = array( 'id' => $field_id, 'type' => $field_type, 'label' => $this->name, 'description' => '', ); $field = wp_parse_args( $field_args, $field ); $field = apply_filters( 'wpforms_field_new_default', $field ); $field_required = apply_filters( 'wpforms_field_new_required', '', $field ); $field_class = apply_filters( 'wpforms_field_new_class', '', $field ); // Field types that default to required. if ( ! empty( $field_required ) ) { $field_required = 'required'; $field['required'] = '1'; } // Build Preview. ob_start(); $this->field_preview( $field ); $prev = ob_get_clean(); $preview = sprintf( '<div class="wpforms-field wpforms-field-%s %s %s" id="wpforms-field-%d" data-field-id="%d" data-field-type="%s">', $field_type, $field_required, $field_class, $field['id'], $field['id'], $field_type ); if ( apply_filters( 'wpforms_field_new_display_duplicate_button', true, $field ) ) { $preview .= sprintf( '<a href="#" class="wpforms-field-duplicate" title="%s"><i class="fa fa-files-o" aria-hidden="true"></i></a>', esc_attr__( 'Duplicate Field', 'wpforms-lite' ) ); } $preview .= sprintf( '<a href="#" class="wpforms-field-delete" title="%s"><i class="fa fa-trash"></i></a>', esc_attr__( 'Delete Field', 'wpforms-lite' ) ); $preview .= sprintf( '<span class="wpforms-field-helper">%s</span>', esc_html__( 'Click to edit. Drag to reorder.', 'wpforms-lite' ) ); $preview .= $prev; $preview .= '</div>'; // Build Options. $class = apply_filters( 'wpforms_builder_field_option_class', '', $field ); $options = sprintf( '<div class="wpforms-field-option wpforms-field-option-%s %s" id="wpforms-field-option-%d" data-field-id="%d">', sanitize_html_class( $field['type'] ), sanitize_html_class( $class ), (int) $field['id'], (int) $field['id'] ); $options .= sprintf( '<input type="hidden" name="fields[%d][id]" value="%d" class="wpforms-field-option-hidden-id">', $field['id'], $field['id'] ); $options .= sprintf( '<input type="hidden" name="fields[%d][type]" value="%s" class="wpforms-field-option-hidden-type">', $field['id'], esc_attr( $field['type'] ) ); ob_start(); $this->field_options( $field ); $options .= ob_get_clean(); $options .= '</div>'; // Prepare to return compiled results. wp_send_json_success( array( 'form_id' => (int) $_POST['id'], 'field' => $field, 'preview' => $preview, 'options' => $options, ) ); } /** * Display the field input elements on the frontend. * * @since 1.0.0 * @since 1.5.0 Converted to abstract method, as it's required for all fields. * * @param array $field Field data and settings. * @param array $field_atts Field attributes. * @param array $form_data Form data and settings. */ abstract public function field_display( $field, $field_atts, $form_data ); /** * Display field input errors if present. * * @since 1.3.7 * * @param string $key Input key. * @param array $field Field data and settings. */ public function field_display_error( $key, $field ) { // Need an error. if ( empty( $field['properties']['error']['value'][ $key ] ) ) { return; } printf( '<label class="wpforms-error" for="%s">%s</label>', esc_attr( $field['properties']['inputs'][ $key ]['id'] ), esc_html( $field['properties']['error']['value'][ $key ] ) ); } /** * Display field input sublabel if present. * * @since 1.3.7 * * @param string $key Input key. * @param string $position Sublabel position. * @param array $field Field data and settings. */ public function field_display_sublabel( $key, $position, $field ) { // Need a sublabel value. if ( empty( $field['properties']['inputs'][ $key ]['sublabel']['value'] ) ) { return; } $pos = ! empty( $field['properties']['inputs'][ $key ]['sublabel']['position'] ) ? $field['properties']['inputs'][ $key ]['sublabel']['position'] : 'after'; $hidden = ! empty( $field['properties']['inputs'][ $key ]['sublabel']['hidden'] ) ? 'wpforms-sublabel-hide' : ''; if ( $pos !== $position ) { return; } printf( '<label for="%s" class="wpforms-field-sublabel %s %s">%s</label>', esc_attr( $field['properties']['inputs'][ $key ]['id'] ), sanitize_html_class( $pos ), $hidden, $field['properties']['inputs'][ $key ]['sublabel']['value'] ); } /** * Validate field on form submit. * * @since 1.0.0 * * @param int $field_id Field ID. * @param mixed $field_submit Field value that was submitted. * @param array $form_data Form data and settings. */ public function validate( $field_id, $field_submit, $form_data ) { // Basic required check - If field is marked as required, check for entry data. if ( ! empty( $form_data['fields'][ $field_id ]['required'] ) && empty( $field_submit ) && '0' !== (string) $field_submit ) { wpforms()->process->errors[ $form_data['id'] ][ $field_id ] = wpforms_get_required_label(); } } /** * Format and sanitize field. * * @since 1.0.0 * * @param int $field_id Field ID. * @param mixed $field_submit Field value that was submitted. * @param array $form_data Form data and settings. */ public function format( $field_id, $field_submit, $form_data ) { if ( is_array( $field_submit ) ) { $field_submit = array_filter( $field_submit ); $field_submit = implode( "\r\n", $field_submit ); } $name = ! empty( $form_data['fields'][ $field_id ]['label'] ) ? sanitize_text_field( $form_data['fields'][ $field_id ]['label'] ) : ''; // Sanitize but keep line breaks. $value = wpforms_sanitize_textarea_field( $field_submit ); wpforms()->process->fields[ $field_id ] = array( 'name' => $name, 'value' => $value, 'id' => absint( $field_id ), 'type' => $this->type, ); } } class-db.php 0000666 00000021673 15213301445 0006760 0 ustar 00 <?php /** * DB class. * * This handy class originated from Pippin's Easy Digital Downloads. * https://github.com/easydigitaldownloads/easy-digital-downloads/blob/master/includes/class-edd-db.php * * Sub-classes should define $table_name, $version, and $primary_key in __construct() method. * * @since 1.1.6 */ abstract class WPForms_DB { /** * Database table name. * * @since 1.1.6 * * @var string */ public $table_name; /** * Database version. * * @since 1.1.6 * * @var string */ public $version; /** * Primary key (unique field) for the database table. * * @since 1.1.6 * * @var string */ public $primary_key; /** * Database type identifier. * * @since 1.5.1 * * @var string */ public $type; /** * Retrieve the list of columns for the database table. * Sub-classes should define an array of columns here. * * @since 1.1.6 * * @return array List of columns. */ public function get_columns() { return array(); } /** * Retrieve column defaults. * Sub-classes can define default for any/all of columns defined in the get_columns() method. * * @since 1.1.6 * * @return array All defined column defaults. */ public function get_column_defaults() { return array(); } /** * Retrieve a row from the database based on a given row ID. * * @since 1.1.6 * * @param int $row_id Row ID. * * @return null|object */ public function get( $row_id ) { global $wpdb; // phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching return $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$this->table_name} WHERE {$this->primary_key} = %s LIMIT 1;", $row_id ) ); } /** * Retrieve a row based on column and row ID. * * @since 1.1.6 * * @param string $column Column name. * @param int|string $row_id Row ID. * * @return object|null|bool Database query result, object or null on failure. */ public function get_by( $column, $row_id ) { global $wpdb; if ( empty( $row_id ) || ! array_key_exists( $column, $this->get_columns() ) ) { return false; } // phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching return $wpdb->get_row( $wpdb->prepare( "SELECT * FROM $this->table_name WHERE $column = '%s' LIMIT 1;", $row_id ) ); } /** * Retrieve a value based on column name and row ID. * * @since 1.1.6 * * @param string $column Column name. * @param int|string $row_id Row ID. * * @return string|null Database query result (as string), or null on failure. */ public function get_column( $column, $row_id ) { global $wpdb; if ( empty( $row_id ) || ! array_key_exists( $column, $this->get_columns() ) ) { return false; } // phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching return $wpdb->get_var( $wpdb->prepare( "SELECT $column FROM $this->table_name WHERE $this->primary_key = '%s' LIMIT 1;", $row_id ) ); } /** * Retrieve one column value based on another given column and matching value. * * @since 1.1.6 * * @param string $column Column name. * @param string $column_where Column to match against in the WHERE clause. * @param string $column_value Value to match to the column in the WHERE clause. * * @return string|null Database query result (as string), or null on failure. */ public function get_column_by( $column, $column_where, $column_value ) { global $wpdb; if ( empty( $column ) || empty( $column_where ) || empty( $column_value ) || ! array_key_exists( $column, $this->get_columns() ) ) { return false; } // phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching return $wpdb->get_var( $wpdb->prepare( "SELECT $column FROM $this->table_name WHERE $column_where = %s LIMIT 1;", $column_value ) ); } /** * Insert a new record into the database. * * @since 1.1.6 * * @param array $data Column data. * @param string $type Optional. Data type context. * * @return int ID for the newly inserted record. 0 otherwise. */ public function add( $data, $type = '' ) { global $wpdb; // Set default values. $data = wp_parse_args( $data, $this->get_column_defaults() ); do_action( 'wpforms_pre_insert_' . $type, $data ); // Initialise column format array. $column_formats = $this->get_columns(); // Force fields to lower case. $data = array_change_key_case( $data ); // White list columns. $data = array_intersect_key( $data, $column_formats ); // Reorder $column_formats to match the order of columns given in $data. $data_keys = array_keys( $data ); $column_formats = array_merge( array_flip( $data_keys ), $column_formats ); $wpdb->insert( $this->table_name, $data, $column_formats ); do_action( 'wpforms_post_insert_' . $type, $wpdb->insert_id, $data ); return $wpdb->insert_id; } /** * Insert a new record into the database. This runs the add method. * * @since 1.1.6 * * @param array $data Column data. * * @return int ID for the newly inserted record. */ public function insert( $data ) { return $this->add( $data ); } /** * Update an existing record in the database. * * @since 1.1.6 * * @param int|string $row_id Row ID for the record being updated. * @param array $data Optional. Array of columns and associated data to update. Default empty array. * @param string $where Optional. Column to match against in the WHERE clause. If empty, $primary_key * will be used. Default empty. * @param string $type Optional. Data type context, e.g. 'affiliate', 'creative', etc. Default empty. * * @return bool False if the record could not be updated, true otherwise. */ public function update( $row_id, $data = array(), $where = '', $type = '' ) { global $wpdb; // Row ID must be a positive integer. $row_id = absint( $row_id ); if ( empty( $row_id ) ) { return false; } if ( empty( $where ) ) { $where = $this->primary_key; } do_action( 'wpforms_pre_update_' . $type, $data ); // Initialise column format array. $column_formats = $this->get_columns(); // Force fields to lower case. $data = array_change_key_case( $data ); // White list columns. $data = array_intersect_key( $data, $column_formats ); // Reorder $column_formats to match the order of columns given in $data. $data_keys = array_keys( $data ); $column_formats = array_merge( array_flip( $data_keys ), $column_formats ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching if ( false === $wpdb->update( $this->table_name, $data, array( $where => $row_id ), $column_formats ) ) { return false; } do_action( 'wpforms_post_update_' . $type, $data ); return true; } /** * Delete a record from the database. * * @since 1.1.6 * * @param int|string $row_id Row ID. * * @return bool False if the record could not be deleted, true otherwise. */ public function delete( $row_id = 0 ) { global $wpdb; // Row ID must be positive integer. $row_id = absint( $row_id ); if ( empty( $row_id ) ) { return false; } do_action( 'wpforms_pre_delete', $row_id ); do_action( 'wpforms_pre_delete_' . $this->type, $row_id ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching if ( false === $wpdb->query( $wpdb->prepare( "DELETE FROM {$this->table_name} WHERE {$this->primary_key} = %d", $row_id ) ) ) { return false; } do_action( 'wpforms_post_delete', $row_id ); do_action( 'wpforms_post_delete_' . $this->type, $row_id ); return true; } /** * Delete a record from the database by column. * * @since 1.1.6 * * @param string $column Column name. * @param int|string $column_value Column value. * * @return bool False if the record could not be deleted, true otherwise. */ public function delete_by( $column, $column_value ) { global $wpdb; if ( empty( $column ) || empty( $column_value ) || ! array_key_exists( $column, $this->get_columns() ) ) { return false; } do_action( 'wpforms_pre_delete', $column_value ); do_action( 'wpforms_pre_delete_' . $this->type, $column_value ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching if ( false === $wpdb->query( $wpdb->prepare( "DELETE FROM {$this->table_name} WHERE $column = %s", $column_value ) ) ) { return false; } do_action( 'wpforms_post_delete', $column_value ); do_action( 'wpforms_post_delete_' . $this->type, $column_value ); return true; } /** * Check if the given table exists. * * @since 1.1.6 * @since 1.5.9 Default value is now the current child class table name. * * @param string $table The table name. Defaults to the child class table name. * * @return string|null If the table name exists. */ public function table_exists( $table = '' ) { global $wpdb; if ( ! empty( $table ) ) { $table = sanitize_text_field( $table ); } else { $table = $this->table_name; } // phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching return $wpdb->get_var( $wpdb->prepare( 'SHOW TABLES LIKE %s', $table ) ) === $table; } } functions-list.php 0000666 00000012234 15213301445 0010242 0 ustar 00 <?php /** * Helper functions to work with multidimensional arrays easier. * * @since 1.5.6 */ /** * Determine whether the given value is array accessible. * * @since 1.5.6 * * @param mixed $value Checkin to accessible. * * @return bool */ function wpforms_list_accessible( $value ) { return is_array( $value ) || $value instanceof ArrayAccess; } /** * Set an array item to a given value using "dot" notation. * * If no key is given to the method, the entire array will be replaced. * * @since 1.5.6 * * @param array $array Existing array. * @param string $key Path to set. * @param mixed $value Value to set. * @param string $separator Separator. * * @return array New array. */ function wpforms_list_set( $array, $key, $value, $separator = '.' ) { if ( ! wpforms_list_accessible( $array ) ) { return $value; } if ( is_null( $key ) ) { $array = $value; return $array; } $keys = explode( $separator, $key ); $count_keys = count( $keys ); $values = array_values( $keys ); $last_key = $values[ $count_keys - 1 ]; $tmp_array = &$array; for ( $i = 0; $i < $count_keys - 1; $i ++ ) { $k = $keys[ $i ]; $tmp_array = &$tmp_array[ $k ]; } $tmp_array[ $last_key ] = $value; return $array; } /** * Determine if the given key exists in the provided array. * * @since 1.5.6 * * @param \ArrayAccess|array $array Existing array. * @param string|int $key To check. * * @return bool */ function wpforms_list_exists( $array, $key ) { if ( ! wpforms_list_accessible( $array ) ) { return false; } if ( $array instanceof ArrayAccess ) { return $array->offsetExists( $key ); } return array_key_exists( $key, $array ); } /** * Get an item from an array using "dot" notation. * * @since 1.5.6 * * @param \ArrayAccess|array $array Where we want to get. * @param string $key Key with dot's. * @param mixed $default Value. * * @return mixed */ function wpforms_list_get( $array, $key, $default = null ) { if ( ! wpforms_list_accessible( $array ) ) { return $default; } if ( is_null( $key ) ) { return $array; } if ( ! is_string( $key ) ) { return $default; } if ( wpforms_list_exists( $array, $key ) ) { return $array[ $key ]; } foreach ( explode( '.', $key ) as $segment ) { if ( wpforms_list_accessible( $array ) && wpforms_list_exists( $array, $segment ) ) { $array = $array[ $segment ]; } else { return $default; } } return $array; } /** * Check if an item exists in an array using "dot" notation. * * @since 1.5.6 * * @param \ArrayAccess|array $array To check. * @param string $key Keys with dot's. * * @return bool */ function wpforms_list_has( $array, $key ) { if ( ! $array ) { return false; } if ( is_null( $key ) || ! is_string( $key ) ) { return false; } if ( wpforms_list_exists( $array, $key ) ) { return true; } foreach ( explode( '.', $key ) as $segment ) { if ( wpforms_list_accessible( $array ) && wpforms_list_exists( $array, $segment ) ) { $array = $array[ $segment ]; } else { return false; } } return true; } /** * Determine if an array is associative. * * An array is "associative" if it doesn't have sequential numerical keys beginning with zero. * * @since 1.5.6 * * @param array $array To check. * * @return bool */ function wpforms_list_is_assoc( $array ) { $keys = array_keys( $array ); return array_keys( $keys ) !== $keys; } /** * Get a subset of the items from the given array. * * @since 1.5.6 * * @param array $array To get. * @param array|string $keys To filter. * * @return array */ function wpforms_list_only( $array, $keys ) { return array_intersect_key( $array, array_flip( (array) $keys ) ); } /** * Remove one or many array items from a given array using "dot" notation. * * @since 1.5.6 * * @param array $array To forget. * @param array|string $keys To exclude. * * @return array */ function wpforms_list_forget( $array, $keys ) { $tmp_array = &$array; $keys = (array) $keys; if ( count( $keys ) === 0 ) { return $array; } foreach ( $keys as $key ) { // if the exact key exists in the top-level, remove it. if ( wpforms_list_exists( $array, $key ) ) { unset( $array[ $key ] ); continue; } $parts = explode( '.', $key ); $count_keys = count( $parts ); $values = array_values( $parts ); $last_key = $values[ $count_keys - 1 ]; for ( $i = 0; $i < $count_keys - 1; $i ++ ) { $k = $parts[ $i ]; $tmp_array = &$tmp_array[ $k ]; } unset( $tmp_array[ $last_key ] ); } return $array; } /** * Insert a value or key/value pair after a specific key in an array. * If key doesn't exist, value is appended to the end of the array. * * @since 1.5.8 * * @param array $array Array where to insert. * @param string $key Insert after key. * @param array $new Array to insert. * * @return array */ function wpforms_list_insert_after( $array, $key, $new ) { $keys = array_keys( $array ); $index = array_search( $key, $keys, true ); $pos = false === $index ? count( $array ) : $index + 1; return array_merge( array_slice( $array, 0, $pos ), $new, array_slice( $array, $pos ) ); } class-templates.php 0000666 00000002440 15213301445 0010360 0 ustar 00 <?php /** * Pre-configured packaged templates. * * @since 1.0.0 */ class WPForms_Templates { /** * Primary class constructor. * * @since 1.0.0 */ public function __construct() { $this->init(); } /** * Load and init the base form template class. * * @since 1.2.8 */ public function init() { // Parent class template require_once WPFORMS_PLUGIN_DIR . 'includes/templates/class-base.php'; // Load default templates on WP init add_action( 'init', array( $this, 'load' ) ); } /** * Load default form templates. * * @since 1.0.0 */ public function load() { $templates = apply_filters( 'wpforms_load_templates', array( 'blank', 'contact', 'request-quote', 'donation', 'order', 'subscribe', 'suggestion', ) ); foreach ( $templates as $template ) { $template = sanitize_file_name( $template ); if ( file_exists( WPFORMS_PLUGIN_DIR . 'includes/templates/class-' . $template . '.php' ) ) { require_once WPFORMS_PLUGIN_DIR . 'includes/templates/class-' . $template . '.php'; } elseif ( file_exists( WPFORMS_PLUGIN_DIR . 'pro/includes/templates/class-' . $template . '.php' ) && wpforms()->pro ) { require_once WPFORMS_PLUGIN_DIR . 'pro/includes/templates/class-' . $template . '.php'; } } } } new WPForms_Templates;
dvadf
dvadf
| ver. 1.4 |
Github
|
.
| PHP 7.0.33 | Generation time: 0.03 |
proxy
|
phpinfo
|
Settings