' . esc_html( $post->post_title ) . '
' . esc_html__( 'Embed & duplicate', 'killerconversions' ) . '
[killerconversions id="' . esc_html( $post->ID ) . '"]Conversions', 'kconv_view_entries', 'killerconversions', array( __CLASS__, 'screen' ), 'dashicons-feedback', 30 ); add_submenu_page( 'killerconversions', __( 'Forms', 'killerconversions' ), __( 'Forms', 'killerconversions' ), 'manage_options', 'killerconversions', array( __CLASS__, 'screen' ) ); add_submenu_page( 'killerconversions', __( 'Inbox', 'killerconversions' ), __( 'Inbox', 'killerconversions' ), 'kconv_view_entries', 'kconv-entries', array( __CLASS__, 'entries' ) ); do_action( 'kconv_admin_menu' ); } public static function assets( $hook ) { if ( ! KCONV_Admin_Scope::plugin() ) { return; } wp_enqueue_style( 'kconv-admin', KCONV_URL . 'assets/admin.css', array(), KCONV_VERSION ); wp_enqueue_style( 'kconv-workspace', KCONV_URL . 'assets/workspace.css', array( 'kconv-admin' ), KCONV_VERSION ); wp_enqueue_script( 'kconv-admin', KCONV_URL . 'assets/admin.js', array('wp-i18n'), KCONV_VERSION, true ); wp_set_script_translations( 'kconv-admin', 'killerconversions', KCONV_DIR . 'languages' ); wp_enqueue_script( 'kconv-workspace', KCONV_URL . 'assets/workspace.js', array( 'kconv-admin' , 'wp-i18n' ), KCONV_VERSION, true ); wp_set_script_translations( 'kconv-workspace', 'killerconversions', KCONV_DIR . 'languages' ); wp_enqueue_style( 'kconv-mobile-editor', KCONV_URL . 'assets/mobile-editor.css', array( 'kconv-workspace' ), KCONV_VERSION ); wp_enqueue_style( 'kconv-readability', KCONV_URL . 'assets/readability.css', array( 'kconv-workspace' ), KCONV_VERSION ); wp_enqueue_style( 'kconv-published-preview', KCONV_URL . 'assets/published-preview.css', array( 'kconv-workspace' ), KCONV_VERSION ); wp_enqueue_style( 'kconv-publish-next', KCONV_URL . 'assets/publish-next.css', array( 'kconv-workspace', 'kconv-readability' ), KCONV_VERSION ); wp_enqueue_script( 'kconv-publish-next', KCONV_URL . 'assets/publish-next.js', array( 'kconv-workspace' ), KCONV_VERSION, true ); wp_enqueue_script( 'kconv-published-preview', KCONV_URL . 'assets/published-preview.js', array( 'kconv-workspace' , 'wp-i18n' ), KCONV_VERSION, true ); wp_set_script_translations( 'kconv-published-preview', 'killerconversions', KCONV_DIR . 'languages' ); wp_enqueue_script( 'kconv-mobile-editor', KCONV_URL . 'assets/mobile-editor.js', array( 'kconv-workspace' , 'wp-i18n' ), KCONV_VERSION, true ); wp_set_script_translations( 'kconv-mobile-editor', 'killerconversions', KCONV_DIR . 'languages' ); wp_localize_script( 'kconv-published-preview', 'KCONV_Preview', array( 'endpoint' => rest_url( 'killerconversions/v1/admin/preview' ), 'nonce' => wp_create_nonce( 'wp_rest' ) ) ); } public static function navigation( $current = 'forms', $compact = false ) { KCONV_Workspace_Navigation::render( $current, $compact ); } public static function screen() { if ( ! current_user_can( 'manage_options' ) ) { self::entries(); return; } // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only screen() navigation/filter input; values are normalized or allowlisted and escaped at output. No state change occurs from this read; mutations use separate capability/nonce guards. $edit = isset( $_GET['edit'] ) && is_scalar( $_GET['edit'] ) ? sanitize_text_field( wp_unslash( $_GET['edit'] ) ) : ''; echo '
' . esc_html( 'unpublish' === $_GET['saved_as'] ? __( 'Form unpublished. Visitors can no longer submit it.', 'killerconversions' ) : __( 'Draft saved. Any published version is unchanged.', 'killerconversions' ) ) . '
' . esc_html__( 'These are the saved settings used by your published form. Edits below and saved drafts take effect only when you publish updates.', 'killerconversions' ) . '
' . esc_html__( 'Needs attention', 'killerconversions' ) . '
' . esc_html( $mail->get_error_message() ) . '
'; } elseif ( $mail_off ) { echo '' . esc_html__( 'Off — enquiries still appear in Inbox.', 'killerconversions' ) . '
'; } else { echo '' . esc_html( $delivery_paused ? __( 'Paused — review this site’s delivery settings.', 'killerconversions' ) : __( 'Configured — delivery is not verified.', 'killerconversions' ) ) . '
'; if ( ! empty( $mail['recipient'] ) ) { /* translators: %s: Saved default staff email recipient. */ echo '' . esc_html( sprintf( __( 'Default recipient: %s', 'killerconversions' ), $mail['recipient'] ) ) . '
'; } if ( ! empty( $mail['routes'] ) ) { echo '' . esc_html( empty( $mail['recipient'] ) ? __( 'Routing rules choose the recipient from submitted answers. With no default recipient, unmatched notifications are not sent.', 'killerconversions' ) : __( 'Routing rules can choose another recipient from submitted answers.', 'killerconversions' ) ) . '
'; } } if ( $delivery_paused && ! $mail_off ) { echo ''; } echo '' . esc_html__( 'Staff notifications are already off. Check Inbox regularly for new enquiries; no extra setting is needed.', 'killerconversions' ) . '
' . esc_html__( 'Open this form’s Inbox', 'killerconversions' ) . ' ' . esc_html__( '(new tab)', 'killerconversions' ) . '' . esc_html__( 'Visitor confirmations and other connections have separate settings.', 'killerconversions' ) . '
' . esc_html__( 'Honeypot and rate limits active.', 'killerconversions' ) . '
'; if ( 'invalid' === $spam_state ) { echo '' . esc_html__( 'Turnstile needs attention. Submissions are blocked until its settings are corrected or protection is saved as disabled.', 'killerconversions' ) . '
'; } elseif ( 'configured' === $spam_state ) { echo '' . esc_html__( 'Turnstile configured. Check the published page to verify it works for visitors.', 'killerconversions' ) . '
'; } else { echo '' . esc_html__( 'Optional Cloudflare Turnstile is off. Enabling it requires a Cloudflare site key and secret key. Included in Free.', 'killerconversions' ) . '
'; } echo '' . esc_html__( 'Review protection', 'killerconversions' ) . '' . esc_html( sprintf( _n( 'New entries scheduled for removal after %s day.', 'New entries scheduled for removal after %s days.', $days, 'killerconversions' ), number_format_i18n( $days ) ) ) . '
' . esc_html__( 'Cleanup depends on WordPress cron. Changing this period affects new entries; email copies and connected services are separate.', 'killerconversions' ) . '
' . esc_html__( 'Change retention', 'killerconversions' ) . '' . esc_html__( 'Build forms, collect responses and follow up.', 'killerconversions' ) . '
[killerconversions id="' . esc_html( $post->ID ) . '"]' . esc_html__( 'Create a form or try a different search.', 'killerconversions' ) . '
' . esc_html__( 'Choose a starting point. You can change every question before publishing.', 'killerconversions' ) . '
' . esc_html( $task[1] ) . '
'; if ( ! $pro || ( KCONV_Presentation::unlocked() && class_exists( 'KCONV_Guided_Setup' ) ) ) { echo '' . esc_html__( 'Start here', 'killerconversions' ) . ''; } elseif ( 'locked' === KCONV_Presentation::state() ) { echo '' . esc_html__( 'Activate your license', 'killerconversions' ) . ''; } else { KCONV_Pro_Discovery::link( 'crm', __( 'See a Pro CRM example', 'killerconversions' ) ); } echo '' . esc_html__( 'Browse the Free templates', 'killerconversions' ) . '
' . esc_html__( 'Form not found.', 'killerconversions' ) . '
'; return; } $templates = KCONV_Templates::all(); if ( ! $form ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only editor() navigation/filter input; values are normalized or allowlisted and escaped at output. No state change occurs from this read; mutations use separate capability/nonce guards. $key = isset( $_GET['template'] ) && is_string( $_GET['template'] ) ? sanitize_key( wp_unslash( $_GET['template'] ) ) : 'contact'; $template = isset( $templates[ $key ] ) ? $templates[ $key ] : $templates['contact']; $form = array_merge( array( 'id' => 0, 'title' => $template['name'], 'status' => 'draft', 'settings' => array_merge( KCONV_Core::defaults(), array_intersect_key( $template, array_flip( array( 'submit_label', 'success_message' ) ) ) ), 'fields' => $template['fields'] ), array_intersect_key( $template, array_flip( array( 'estimate', 'steps' ) ) ) ); } $types = array( 'repeater' => array( __( 'Repeatable group', 'killerconversions' ), '+', __( 'Add another person or item', 'killerconversions' ) ), 'text' => array( __( 'Short text', 'killerconversions' ), 'Aa', __( 'A name or a short answer', 'killerconversions' ) ), 'email' => array( __( 'Email', 'killerconversions' ), '@', __( 'Make it easy to follow up', 'killerconversions' ) ), 'textarea' => array( __( 'Long text', 'killerconversions' ), '¶', __( 'A message or detailed answer', 'killerconversions' ) ), 'select' => array( __( 'Dropdown', 'killerconversions' ), '⌄', __( 'Keep a list of choices compact', 'killerconversions' ) ), 'radio' => array( __( 'Single choice', 'killerconversions' ), '◉', __( 'Choose exactly one answer', 'killerconversions' ) ), 'checkbox' => array( __( 'Checkbox', 'killerconversions' ), '✓', __( 'An option or consent choice', 'killerconversions' ) ), 'number' => array( __( 'Number', 'killerconversions' ), '#', __( 'A quantity or a budget', 'killerconversions' ) ), 'tel' => array( __( 'Phone', 'killerconversions' ), 'Tel', __( 'A contact number', 'killerconversions' ) ), 'url' => array( __( 'Website', 'killerconversions' ), 'URL', __( 'A link to a website', 'killerconversions' ) ), 'checkbox_group' => array( __( 'Multiple choice', 'killerconversions' ), '☑', __( 'Choose more than one answer', 'killerconversions' ) ), 'date' => array( __( 'Date', 'killerconversions' ), '▦', __( 'Pick a calendar date', 'killerconversions' ) ), 'time' => array( __( 'Time', 'killerconversions' ), '◷', __( 'Pick a time of day', 'killerconversions' ) ), 'hidden' => array( __( 'Hidden value', 'killerconversions' ), '{ }', __( 'A fixed value saved with entries', 'killerconversions' ) ) ); if ( class_exists( 'KCONV_Calculations' ) ) { $types['calculated'] = array( __( 'Calculated estimate', 'killerconversions' ), '=', __( 'A formula or quote total', 'killerconversions' ) ); } if ( class_exists( 'KCONV_Uploads' ) ) { $types['file'] = array( __( 'File upload', 'killerconversions' ), '↑', __( 'Private attachments · Pro', 'killerconversions' ) ); } // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only editor() navigation/filter input; values are normalized or allowlisted and escaped at output. No state change occurs from this read; mutations use separate capability/nonce guards. echo ''; } public static function save() { if ( ! current_user_can( 'manage_options' ) ) { wp_die( esc_html__( 'You cannot manage forms.', 'killerconversions' ), '', array( 'response' => 403 ) ); } if ( ! isset( $_POST['_wpnonce'] ) || ! is_string( $_POST['_wpnonce'] ) ) { wp_die( esc_html__( 'You cannot manage forms.', 'killerconversions' ), '', array( 'response' => 403 ) ); } $nonce = sanitize_text_field( wp_unslash( $_POST['_wpnonce'] ) ); if ( ! wp_verify_nonce( $nonce, 'kconv_save' ) ) { wp_die( esc_html__( 'You cannot manage forms.', 'killerconversions' ), '', array( 'response' => 403 ) ); } $result = KCONV_Authoring::save( wp_unslash( $_POST ) ); if ( is_wp_error( $result ) ) { wp_die( esc_html( implode( ' ', $result->get_error_messages() ) ), '', array( 'response' => 400, 'back_link' => true ) ); } wp_safe_redirect( $result['url'] ); exit; } public static function entries() { KCONV_Entries::screen(); } public static function delete_entry() { $id = isset( $_POST['entry_id'] ) && is_scalar( $_POST['entry_id'] ) ? absint( $_POST['entry_id'] ) : 0; if ( ! KCONV_Core::can( 'kconv_delete_entries' ) ) { wp_die( esc_html__( 'You do not have permission for this action.', 'killerconversions' ), '', array( 'response' => 403 ) ); } if ( ! isset( $_POST['_wpnonce'] ) || ! is_string( $_POST['_wpnonce'] ) ) { wp_die( esc_html__( 'You do not have permission for this action.', 'killerconversions' ), '', array( 'response' => 403 ) ); } $nonce = sanitize_text_field( wp_unslash( $_POST['_wpnonce'] ) ); if ( ! wp_verify_nonce( $nonce, 'kconv_delete_entry_' . $id ) ) { wp_die( esc_html__( 'You do not have permission for this action.', 'killerconversions' ), '', array( 'response' => 403 ) ); } if ( ! KCONV_Entry_Access::assert_ids( array( $id ), 'delete' ) ) { wp_die( esc_html__( 'You do not have access to this entry.', 'killerconversions' ), '', array( 'response' => 403 ) ); } if ( ! KCONV_Core::delete_entries( array( $id ), true ) ) { wp_die( esc_html__( 'Entry deletion failed and was rolled back. Please retry after storage is repaired.', 'killerconversions' ), '', array( 'response' => 503 ) ); } wp_safe_redirect( admin_url( 'admin.php?page=kconv-entries' ) ); exit; } public static function csv_value( $value ) { $value = KCONV_Core::value_text( $value ); return preg_match( '/^[\s]*[=+@\-]/u', $value ) ? "'" . $value : $value; } public static function export() { if ( ! KCONV_Core::can( 'kconv_export_entries' ) ) { wp_die( esc_html__( 'You do not have permission for this action.', 'killerconversions' ), '', array( 'response' => 403 ) ); } if ( ! isset( $_POST['_wpnonce'] ) || ! is_string( $_POST['_wpnonce'] ) ) { wp_die( esc_html__( 'You do not have permission for this action.', 'killerconversions' ), '', array( 'response' => 403 ) ); } $nonce = sanitize_text_field( wp_unslash( $_POST['_wpnonce'] ) ); if ( ! wp_verify_nonce( $nonce, 'kconv_export' ) ) { wp_die( esc_html__( 'You do not have permission for this action.', 'killerconversions' ), '', array( 'response' => 403 ) ); } KCONV_Entries::export( wp_unslash( $_POST ) ); } }