Admin::SLUG_FORMS, 'action' => 'edit', 'form' => $form_id, ], admin_url( 'admin.php' ) ) ); exit; } /** * Show the list of existing forms. */ private static function render_list() { $forms = Form::all(); $new_url = add_query_arg( [ 'page' => Admin::SLUG_FORMS, 'action' => 'new', ], admin_url( 'admin.php' ) ); ?>

ID ); $edit_url = add_query_arg( [ 'page' => Admin::SLUG_FORMS, 'action' => 'edit', 'form' => $post->ID, ], admin_url( 'admin.php' ) ); $del_url = wp_nonce_url( add_query_arg( [ 'page' => Admin::SLUG_FORMS, 'action' => 'delete', 'form' => $post->ID, ], admin_url( 'admin.php' ) ), 'phemightforms_delete_' . $post->ID ); $star_url = wp_nonce_url( add_query_arg( [ 'page' => Admin::SLUG_FORMS, 'action' => 'star', 'form' => $post->ID, ], admin_url( 'admin.php' ) ), 'phemightforms_star_' . $post->ID ); $dup_url = wp_nonce_url( add_query_arg( [ 'page' => Admin::SLUG_FORMS, 'action' => 'duplicate', 'form' => $post->ID, ], admin_url( 'admin.php' ) ), 'phemightforms_duplicate_' . $post->ID ); $prev_url = add_query_arg( [ 'page' => Admin::SLUG_FORMS, 'action' => 'preview', 'form' => $post->ID, ], admin_url( 'admin.php' ) ); $exp_url = wp_nonce_url( add_query_arg( [ 'page' => Admin::SLUG_FORMS, 'action' => 'export', 'form' => $post->ID, ], admin_url( 'admin.php' ) ), 'phemightforms_export_' . $post->ID ); $starred = ( new Form( $post->ID ) )->is_starred(); ?>
post_title ); ?> [phemightform id="ID ); ?>"] get_fields() ) ); ?>
config ); $title = $form->exists() ? $form->title : __( 'New Form', 'phemightforms' ); $registry = \PhemightForms\phemightforms()->fields; $groups = $registry->groups(); $types = $registry->all(); $list_url = add_query_arg( [ 'page' => Admin::SLUG_FORMS ], admin_url( 'admin.php' ) ); $preview_url = $form_id ? add_query_arg( [ 'page' => Admin::SLUG_FORMS, 'action' => 'preview', 'form' => $form_id, ], admin_url( 'admin.php' ) ) : ''; $saved_flag = isset( $_GET['updated'] ) || isset( $_GET['created'] ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended ?>
PhemightForms

[phemightform id=""]

Admin::SLUG_FORMS, 'action' => 'edit', 'form' => $saved, $form_id ? 'updated' : 'created' => 1, ], admin_url( 'admin.php' ) ); wp_safe_redirect( $redirect ); exit; } /** * Delete a form after verifying the nonce. */ private static function handle_delete() { $form_id = isset( $_GET['form'] ) ? absint( wp_unslash( $_GET['form'] ) ) : 0; check_admin_referer( 'phemightforms_delete_' . $form_id ); if ( ! current_user_can( Admin::CAPABILITY ) ) { wp_die( esc_html__( 'Permission denied.', 'phemightforms' ) ); } Form::delete( $form_id ); wp_safe_redirect( add_query_arg( [ 'page' => Admin::SLUG_FORMS ], admin_url( 'admin.php' ) ) ); exit; } /** * Clean an untrusted config array before saving. * * @param mixed $config Decoded JSON. * @return array */ private static function sanitize_config( $config ) { $clean = Form::default_config(); if ( ! is_array( $config ) ) { return $clean; } $fields = ( isset( $config['fields'] ) && is_array( $config['fields'] ) ) ? $config['fields'] : []; $registry = \PhemightForms\phemightforms()->fields; $clean_fld = []; $max_id = 0; foreach ( $fields as $field ) { $type = isset( $field['type'] ) ? sanitize_key( $field['type'] ) : 'text'; if ( ! $registry->exists( $type ) ) { continue; } $id = isset( $field['id'] ) ? absint( $field['id'] ) : 0; $max_id = max( $max_id, $id ); $entry = [ 'id' => $id, 'type' => $type, 'label' => isset( $field['label'] ) ? sanitize_text_field( $field['label'] ) : '', 'placeholder' => isset( $field['placeholder'] ) ? sanitize_text_field( $field['placeholder'] ) : '', 'description' => isset( $field['description'] ) ? sanitize_text_field( $field['description'] ) : '', 'required' => ! empty( $field['required'] ) ? 1 : 0, ]; if ( $registry->has_choices( $type ) && isset( $field['choices'] ) && is_array( $field['choices'] ) ) { $entry['choices'] = array_values( array_filter( array_map( 'sanitize_text_field', $field['choices'] ) ) ); if ( isset( $field['correct'] ) && '' !== $field['correct'] ) { $entry['correct'] = sanitize_text_field( $field['correct'] ); } } if ( 'repeater' === $type && isset( $field['sub_label'] ) ) { $entry['sub_label'] = sanitize_text_field( $field['sub_label'] ); } if ( 'consent' === $type ) { $entry['consent_text'] = isset( $field['consent_text'] ) ? sanitize_text_field( $field['consent_text'] ) : ''; } if ( 'hidden' === $type ) { $entry['default_value'] = isset( $field['default_value'] ) ? sanitize_text_field( $field['default_value'] ) : ''; } if ( 'html' === $type && isset( $field['html_content'] ) ) { $entry['html_content'] = wp_kses_post( $field['html_content'] ); } if ( isset( $field['size'] ) && in_array( $field['size'], [ 'full', 'half' ], true ) ) { $entry['size'] = $field['size']; } if ( isset( $field['label_position'] ) && in_array( $field['label_position'], [ 'top', 'left', 'hidden' ], true ) ) { $entry['label_position'] = $field['label_position']; } if ( 'rating' === $type && isset( $field['rating_max'] ) ) { $entry['rating_max'] = max( 3, min( 10, absint( $field['rating_max'] ) ) ); } if ( 'payment_single' === $type ) { $entry['price'] = \PhemightForms\Payments::to_amount( isset( $field['price'] ) ? $field['price'] : 0 ); $entry['user_price'] = ! empty( $field['user_price'] ) ? 1 : 0; } if ( $registry->supports_logic( $type ) && ! empty( $field['conditional'] ) && is_array( $field['conditional'] ) ) { $entry['conditional'] = self::sanitize_conditional( $field['conditional'] ); } $clean_fld[] = $entry; } // Assign IDs to any field that arrived without one. foreach ( $clean_fld as &$fld ) { if ( empty( $fld['id'] ) ) { $fld['id'] = ++$max_id; } } unset( $fld ); $clean['fields'] = $clean_fld; $clean['_next_id'] = $max_id + 1; $settings = ( isset( $config['settings'] ) && is_array( $config['settings'] ) ) ? $config['settings'] : []; $conf_type = isset( $settings['confirmation_type'] ) ? sanitize_key( $settings['confirmation_type'] ) : 'message'; if ( ! in_array( $conf_type, [ 'message', 'redirect', 'page' ], true ) ) { $conf_type = 'message'; } $webhook_format = isset( $settings['webhook_format'] ) ? sanitize_key( $settings['webhook_format'] ) : 'generic'; if ( ! in_array( $webhook_format, [ 'generic', 'slack', 'discord', 'telegram' ], true ) ) { $webhook_format = 'generic'; } $embed_mode = isset( $settings['embed_mode'] ) ? sanitize_key( $settings['embed_mode'] ) : 'inline'; if ( ! in_array( $embed_mode, [ 'inline', 'popup', 'slide' ], true ) ) { $embed_mode = 'inline'; } $defaults = Form::default_config()['settings']; $clean['settings'] = wp_parse_args( [ 'submit_text' => isset( $settings['submit_text'] ) ? sanitize_text_field( $settings['submit_text'] ) : $defaults['submit_text'], 'confirmation' => isset( $settings['confirmation'] ) ? sanitize_textarea_field( $settings['confirmation'] ) : $defaults['confirmation'], 'confirmation_type' => $conf_type, 'confirmation_redirect' => isset( $settings['confirmation_redirect'] ) ? esc_url_raw( $settings['confirmation_redirect'] ) : '', 'confirmation_page' => isset( $settings['confirmation_page'] ) ? absint( $settings['confirmation_page'] ) : 0, 'notify_enabled' => ! empty( $settings['notify_enabled'] ) ? 1 : 0, 'notify_to' => isset( $settings['notify_to'] ) ? sanitize_email( $settings['notify_to'] ) : get_option( 'admin_email' ), 'notify_subject' => isset( $settings['notify_subject'] ) ? sanitize_text_field( $settings['notify_subject'] ) : $defaults['notify_subject'], 'notify_routes' => self::sanitize_routes( isset( $settings['notify_routes'] ) ? $settings['notify_routes'] : [] ), 'confirm_rules' => self::sanitize_confirm_rules( isset( $settings['confirm_rules'] ) ? $settings['confirm_rules'] : [] ), 'is_quiz' => ! empty( $settings['is_quiz'] ) ? 1 : 0, 'webhook_enabled' => ! empty( $settings['webhook_enabled'] ) ? 1 : 0, 'webhook_url' => isset( $settings['webhook_url'] ) ? esc_url_raw( $settings['webhook_url'] ) : '', 'webhook_format' => $webhook_format, 'save_resume' => ! empty( $settings['save_resume'] ) ? 1 : 0, 'mailchimp_enabled' => ! empty( $settings['mailchimp_enabled'] ) ? 1 : 0, 'mailchimp_list' => isset( $settings['mailchimp_list'] ) ? sanitize_text_field( $settings['mailchimp_list'] ) : '', 'sheets_url' => isset( $settings['sheets_url'] ) ? esc_url_raw( $settings['sheets_url'] ) : '', 'landing_page' => ! empty( $settings['landing_page'] ) ? 1 : 0, 'payments_enabled' => ! empty( $settings['payments_enabled'] ) ? 1 : 0, 'payment_method' => isset( $settings['payment_method'] ) && isset( \PhemightForms\Payments::providers()[ $settings['payment_method'] ] ) ? $settings['payment_method'] : 'offline', 'accent_color' => isset( $settings['accent_color'] ) ? sanitize_hex_color( $settings['accent_color'] ) : '#b56d18', 'button_text_color' => isset( $settings['button_text_color'] ) ? sanitize_hex_color( $settings['button_text_color'] ) : '#ffffff', 'form_bg_color' => isset( $settings['form_bg_color'] ) ? sanitize_hex_color( $settings['form_bg_color'] ) : '#ffffff', 'text_color' => isset( $settings['text_color'] ) ? sanitize_hex_color( $settings['text_color'] ) : '#0f172a', 'border_color' => isset( $settings['border_color'] ) ? sanitize_hex_color( $settings['border_color'] ) : '#e2e8f0', 'border_width' => isset( $settings['border_width'] ) ? min( 8, absint( $settings['border_width'] ) ) : 1, 'button_style' => isset( $settings['button_style'] ) ? sanitize_key( $settings['button_style'] ) : 'solid', 'border_radius' => isset( $settings['border_radius'] ) ? min( 32, absint( $settings['border_radius'] ) ) : 12, 'font_size' => isset( $settings['font_size'] ) ? absint( $settings['font_size'] ) : 16, 'label_position' => isset( $settings['label_position'] ) ? sanitize_key( $settings['label_position'] ) : 'top', 'embed_mode' => $embed_mode, 'embed_button_text' => isset( $settings['embed_button_text'] ) ? sanitize_text_field( $settings['embed_button_text'] ) : $defaults['embed_button_text'], ], $defaults ); return $clean; } /** * Sanitize notification routing rules. * * @param mixed $routes Raw routes. * @return array */ private static function sanitize_routes( $routes ) { if ( ! is_array( $routes ) ) { return []; } $clean = []; foreach ( $routes as $route ) { if ( empty( $route['field'] ) || empty( $route['email'] ) ) { continue; } $clean[] = [ 'field' => absint( $route['field'] ), 'value' => isset( $route['value'] ) ? sanitize_text_field( $route['value'] ) : '', 'email' => sanitize_email( $route['email'] ), ]; } return $clean; } /** * Sanitize conditional confirmation rules. * * @param mixed $rules Raw rules. * @return array */ private static function sanitize_confirm_rules( $rules ) { if ( ! is_array( $rules ) ) { return []; } $clean = []; foreach ( $rules as $rule ) { if ( empty( $rule['field'] ) || empty( $rule['message'] ) ) { continue; } $clean[] = [ 'field' => absint( $rule['field'] ), 'value' => isset( $rule['value'] ) ? sanitize_text_field( $rule['value'] ) : '', 'message' => sanitize_textarea_field( $rule['message'] ), ]; } return $clean; } /** * Sanitize a field's conditional-logic configuration. * * @param array $conditional Raw conditional config. * @return array */ private static function sanitize_conditional( array $conditional ) { $action = isset( $conditional['action'] ) && 'hide' === $conditional['action'] ? 'hide' : 'show'; $logic = isset( $conditional['logic'] ) && 'or' === $conditional['logic'] ? 'or' : 'and'; $rules = []; if ( ! empty( $conditional['rules'] ) && is_array( $conditional['rules'] ) ) { foreach ( $conditional['rules'] as $rule ) { if ( ! isset( $rule['field'] ) || '' === $rule['field'] ) { continue; } $operator = isset( $rule['operator'] ) ? sanitize_key( $rule['operator'] ) : 'is'; if ( ! in_array( $operator, [ 'is', 'is_not', 'empty', 'not_empty', 'contains' ], true ) ) { $operator = 'is'; } $rules[] = [ 'field' => (int) $rule['field'], 'operator' => $operator, 'value' => isset( $rule['value'] ) ? sanitize_text_field( $rule['value'] ) : '', ]; } } return [ 'enabled' => ! empty( $conditional['enabled'] ) ? 1 : 0, 'action' => $action, 'logic' => $logic, 'rules' => $rules, ]; } /** * Duplicate a form. */ private static function handle_duplicate() { $form_id = isset( $_GET['form'] ) ? absint( wp_unslash( $_GET['form'] ) ) : 0; check_admin_referer( 'phemightforms_duplicate_' . $form_id ); $form = new Form( $form_id ); $new = $form->duplicate(); wp_safe_redirect( add_query_arg( [ 'page' => Admin::SLUG_FORMS, 'action' => 'edit', 'form' => $new, 'created' => 1, ], admin_url( 'admin.php' ) ) ); exit; } /** * Toggle starred state. */ private static function handle_star() { $form_id = isset( $_GET['form'] ) ? absint( wp_unslash( $_GET['form'] ) ) : 0; check_admin_referer( 'phemightforms_star_' . $form_id ); $form = new Form( $form_id ); if ( $form->exists() ) { $form->set_starred( ! $form->is_starred() ); } wp_safe_redirect( add_query_arg( [ 'page' => Admin::SLUG_FORMS ], admin_url( 'admin.php' ) ) ); exit; } /** * Download form JSON export. */ private static function handle_export() { $form_id = isset( $_GET['form'] ) ? absint( wp_unslash( $_GET['form'] ) ) : 0; check_admin_referer( 'phemightforms_export_' . $form_id ); $form = new Form( $form_id ); if ( ! $form->exists() ) { wp_die( esc_html__( 'Form not found.', 'phemightforms' ) ); } nocache_headers(); header( 'Content-Type: application/json; charset=utf-8' ); header( 'Content-Disposition: attachment; filename="phemightform-' . $form_id . '.json"' ); echo $form->export_json(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped exit; } /** * Import a form from uploaded JSON. */ private static function handle_import() { check_admin_referer( 'phemightforms_import' ); if ( empty( $_FILES['phf_import_file']['tmp_name'] ) ) { wp_die( esc_html__( 'No file uploaded.', 'phemightforms' ) ); } $raw = file_get_contents( $_FILES['phf_import_file']['tmp_name'] ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_get_contents_file_get_contents $data = json_decode( $raw, true ); if ( ! is_array( $data ) || empty( $data['config'] ) ) { wp_die( esc_html__( 'Invalid form JSON file.', 'phemightforms' ) ); } $title = isset( $data['title'] ) ? sanitize_text_field( $data['title'] ) : __( 'Imported Form', 'phemightforms' ); $config = self::sanitize_config( $data['config'] ); $id = Form::save( $title, $config, 0 ); wp_safe_redirect( add_query_arg( [ 'page' => Admin::SLUG_FORMS, 'action' => 'edit', 'form' => $id, 'created' => 1, ], admin_url( 'admin.php' ) ) ); exit; } /** * Render a front-end preview in a minimal admin frame. */ private static function render_preview() { $form_id = isset( $_GET['form'] ) ? absint( wp_unslash( $_GET['form'] ) ) : 0; $form = new Form( $form_id ); if ( ! $form->exists() ) { wp_die( esc_html__( 'Form not found.', 'phemightforms' ) ); } $frontend = new \PhemightForms\Frontend(); wp_enqueue_style( 'phemightforms' ); wp_enqueue_script( 'phemightforms' ); \PhemightForms\Captcha::enqueue(); wp_add_inline_style( 'phemightforms', 'body{margin:0;padding:2rem;background:#faf6ee;} .phf-preview-bar{background:#2e1f0b;color:#ffd66b;padding:.75rem 1.25rem;font-family:sans-serif;font-size:.875rem;margin:-2rem -2rem 2rem;}' ); ?> > <?php echo esc_html( $form->title ); ?> ยท <?php esc_html_e( 'Preview', 'phemightforms' ); ?>
render( $form ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>