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
?>
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;}'
);
?>
>
title ); ?> ยท
render( $form ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>