forms = $forms; } public function init() { add_action( 'admin_post_bylt_form_file', array( $this, 'download_file' ) ); add_action( 'admin_menu', array( $this, 'menu' ), 22 ); add_action( 'admin_post_' . self::ACTION, array( $this, 'handle' ) ); add_filter( 'bylt_module_settings_urls', array( $this, 'settings_url' ) ); add_action( 'admin_enqueue_scripts', array( $this, 'assets' ) ); } /** Staff-only link to an entry's uploaded file. */ public static function file_url( $entry_id, $key ) { return wp_nonce_url( add_query_arg( array( 'action' => 'bylt_form_file', 'entry' => (int) $entry_id, 'key' => $key ), admin_url( 'admin-post.php' ) ), 'bylt_form_file_' . (int) $entry_id ); } public function download_file() { $id = isset( $_GET['entry'] ) ? absint( $_GET['entry'] ) : 0; // phpcs:ignore WordPress.Security.NonceVerification -- checked next. $key = isset( $_GET['key'] ) ? sanitize_key( wp_unslash( $_GET['key'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification check_admin_referer( 'bylt_form_file_' . $id ); if ( ! current_user_can( Bylt_Admin::cap() ) ) { wp_die( esc_html__( 'You are not allowed to open this file.', 'byltcommerce-toolkit' ), '', array( 'response' => 403 ) ); } $e = Bylt_Forms_Store::entry( $id ); $files = $e ? Bylt_Forms_Store::entry_files( $e ) : array(); if ( ! isset( $files[ $key ] ) ) { wp_die( esc_html__( 'File not found.', 'byltcommerce-toolkit' ), '', array( 'response' => 404 ) ); } Bylt_Forms_Files::serve( $files[ $key ], isset( $e['data'][ $key ] ) ? (string) $e['data'][ $key ] : 'file' ); } public static function url( $args = array() ) { return add_query_arg( array_merge( array( 'page' => self::PAGE ), $args ), admin_url( 'admin.php' ) ); } public function settings_url( $urls ) { $urls['forms'] = self::url(); return $urls; } public function menu() { $new = Bylt_Forms_Store::entries( array( 'status' => 'new', 'per_page' => 1 ) )['total']; $base = 'admin.php?page=' . self::PAGE; Bylt_Admin::app_menu( self::PAGE, __( 'Forms', 'byltcommerce-toolkit' ), array( $this, 'render' ), 'dashicons-feedback', 58.8, array( self::PAGE => __( 'All forms', 'byltcommerce-toolkit' ), $base . '&tab=entries' => __( 'Entries', 'byltcommerce-toolkit' ), $base . '&form=new' => __( 'Add form', 'byltcommerce-toolkit' ), $base . '&tab=io' => __( 'Import / Export', 'byltcommerce-toolkit' ), $base . '&tab=settings' => __( 'Settings', 'byltcommerce-toolkit' ), ), '', $new ); } public function assets( $hook ) { if ( false === strpos( (string) $hook, self::PAGE ) ) { return; } wp_enqueue_script( 'bylt-forms-admin', $this->forms->url( 'assets/forms-admin.js' ), array(), BYLT_VERSION, true ); wp_localize_script( 'bylt-forms-admin', 'byltFormsAdmin', array( 'previewUrl' => home_url( '/' ), 'nonce' => wp_create_nonce( 'bylt_form_preview' ), 'i18n' => array( 'title' => __( 'Preview', 'byltcommerce-toolkit' ), 'desktop' => __( 'Desktop', 'byltcommerce-toolkit' ), 'tablet' => __( 'Tablet', 'byltcommerce-toolkit' ), 'phone' => __( 'Phone', 'byltcommerce-toolkit' ), 'guest' => __( 'Visitor', 'byltcommerce-toolkit' ), 'user' => __( 'Logged in', 'byltcommerce-toolkit' ), 'viewAs' => __( 'View as', 'byltcommerce-toolkit' ), 'close' => __( 'Close', 'byltcommerce-toolkit' ), 'note' => __( 'Unsaved changes are included. Submitting checks the fields but sends nothing.', 'byltcommerce-toolkit' ), 'pickField' => __( '— Field —', 'byltcommerce-toolkit' ), ), ) ); } /* --------------------------------------------------------------------- * Page * ------------------------------------------------------------------- */ private function tabs( $current ) { $new = Bylt_Forms_Store::entries( array( 'status' => 'new', 'per_page' => 1 ) )['total']; $tabs = array( 'forms' => __( 'Forms', 'byltcommerce-toolkit' ), 'entries' => __( 'Entries', 'byltcommerce-toolkit' ) . ( $new ? ' (' . (int) $new . ')' : '' ), 'io' => __( 'Import / Export', 'byltcommerce-toolkit' ), 'settings' => __( 'Settings', 'byltcommerce-toolkit' ), ); echo ''; } private function form_start( $do, $id = '', $attrs = '' ) { echo '
'; // phpcs:ignore WordPress.Security.EscapeOutput -- fixed strings. echo ''; wp_nonce_field( self::ACTION . '_' . $do . '_' . $id ); } public function render() { if ( ! current_user_can( Bylt_Admin::cap() ) ) { wp_die( esc_html__( 'You are not allowed to view forms.', 'byltcommerce-toolkit' ) ); } // phpcs:disable WordPress.Security.NonceVerification -- display only. $tab = isset( $_GET['tab'] ) ? sanitize_key( wp_unslash( $_GET['tab'] ) ) : 'forms'; $form = isset( $_GET['form'] ) ? sanitize_key( wp_unslash( $_GET['form'] ) ) : ''; $entry = isset( $_GET['entry'] ) ? absint( $_GET['entry'] ) : 0; $msg = isset( $_GET['msg'] ) ? sanitize_text_field( wp_unslash( $_GET['msg'] ) ) : ''; $err = ! empty( $_GET['err'] ); // phpcs:enable echo '

' . esc_html__( 'Forms', 'byltcommerce-toolkit' ) . '

'; if ( $msg ) { echo '

' . esc_html( $msg ) . '

'; } if ( $entry ) { $this->render_entry( $entry ); } elseif ( $form ) { $this->render_editor( $form ); } else { $this->tabs( $tab ); switch ( $tab ) { case 'entries': $this->render_entries(); break; case 'io': $this->render_io(); break; case 'settings': $this->render_settings(); break; default: $this->render_forms(); } } echo '
'; } private function render_forms() { $forms = Bylt_Forms_Store::all(); $counts = Bylt_Forms_Store::counts(); echo '

'; foreach ( Bylt_Forms::templates() as $key => $t ) { /* translators: %s: template name */ echo '' . esc_html( 'blank' === $key ? __( 'Blank form', 'byltcommerce-toolkit' ) : sprintf( __( 'New %s', 'byltcommerce-toolkit' ), strtolower( $t['name'] ) ) ) . ' '; } echo '

'; echo ''; if ( ! $forms ) { echo ''; } foreach ( $forms as $f ) { $c = isset( $counts[ $f['id'] ] ) ? $counts[ $f['id'] ] : array(); $all = array_sum( $c ); $new = isset( $c['new'] ) ? $c['new'] : 0; $pg = $f['settings']['page_id']; echo ''; $kinds = Bylt_Forms::kinds(); echo ''; echo ''; echo ''; echo ''; } echo '
' . esc_html__( 'Form', 'byltcommerce-toolkit' ) . '' . esc_html__( 'Type', 'byltcommerce-toolkit' ) . '' . esc_html__( 'Shortcode', 'byltcommerce-toolkit' ) . '' . esc_html__( 'On page', 'byltcommerce-toolkit' ) . '' . esc_html__( 'Entries', 'byltcommerce-toolkit' ) . '
' . esc_html__( 'No forms yet. Start with a contact or quote form above.', 'byltcommerce-toolkit' ) . '
' . esc_html( $f['name'] ) . '
' . esc_html( sprintf( /* translators: %d: count */ _n( '%d field', '%d fields', count( $f['fields'] ), 'byltcommerce-toolkit' ), count( $f['fields'] ) ) ) . '
' . esc_html( isset( $kinds[ $f['settings']['kind'] ] ) ? $kinds[ $f['settings']['kind'] ] : $f['settings']['kind'] ) . '[bylt_form id="' . (int) $f['id'] . '"]' . ( $pg && get_post( $pg ) ? '' . esc_html( get_the_title( $pg ) ) . '' : '—' ) . '' . (int) $all . '' . ( $new ? ' ' . esc_html( sprintf( /* translators: %d: count */ __( '%d new', 'byltcommerce-toolkit' ), $new ) ) . '' : '' ) . '
'; echo '

' . esc_html__( 'Add a form to any page with the "BYLTCommerce Form" block or its shortcode.', 'byltcommerce-toolkit' ) . '

'; } /* --------------------------------------------------------------------- * Editor * ------------------------------------------------------------------- */ private static function type_labels() { return array( 'text' => __( 'Text', 'byltcommerce-toolkit' ), 'email' => __( 'Email', 'byltcommerce-toolkit' ), 'tel' => __( 'Phone', 'byltcommerce-toolkit' ), 'textarea' => __( 'Paragraph', 'byltcommerce-toolkit' ), 'number' => __( 'Number', 'byltcommerce-toolkit' ), 'date' => __( 'Date', 'byltcommerce-toolkit' ), 'url' => __( 'Website', 'byltcommerce-toolkit' ), 'select' => __( 'Dropdown', 'byltcommerce-toolkit' ), 'radio' => __( 'Choose one', 'byltcommerce-toolkit' ), 'checkboxes' => __( 'Choose several', 'byltcommerce-toolkit' ), 'consent' => __( 'Consent checkbox', 'byltcommerce-toolkit' ), 'hidden' => __( 'Hidden', 'byltcommerce-toolkit' ), 'html' => __( 'Heading / text', 'byltcommerce-toolkit' ), 'password' => __( 'Password', 'byltcommerce-toolkit' ), 'file' => __( 'File upload', 'byltcommerce-toolkit' ), ); } /** Comparisons offered in the conditions editor. */ private static function op_labels() { return array( 'is' => __( 'is', 'byltcommerce-toolkit' ), 'is_not' => __( 'is not', 'byltcommerce-toolkit' ), 'contains' => __( 'contains', 'byltcommerce-toolkit' ), 'not_contains' => __( 'doesn\'t contain', 'byltcommerce-toolkit' ), 'empty' => __( 'is empty', 'byltcommerce-toolkit' ), 'not_empty' => __( 'is filled in', 'byltcommerce-toolkit' ), 'gt' => __( 'is more than', 'byltcommerce-toolkit' ), 'lt' => __( 'is less than', 'byltcommerce-toolkit' ), ); } /** One condition row; the field list is filled in by forms-admin.js from the rows on screen. */ private static function rule_row( $n, $j, array $r, array $labels ) { $r = array_merge( array( 'field' => '', 'op' => 'is', 'value' => '' ), $r ); $rn = $n . '[cond][rules][' . $j . ']'; $out = '
'; $out .= ''; $out .= '
'; return $out; } /** @var array key => label of the form being edited, for condition rows. */ private $labels = array(); private function field_row( $i, array $f ) { $f = array_merge( Bylt_Forms_Store::blank_field(), $f ); $n = 'fields[' . $i . ']'; $opts = implode( "\n", (array) $f['options'] ); $locked = ! empty( $f['locked'] ); $on = $locked || ! empty( $f['enabled'] ); $row = 'bylt-fe-row' . ( $on ? '' : ' is-off' ) . ( $locked ? ' is-locked' : '' ) . ( ! empty( $f['cond']['action'] ) ? ' has-cond' : '' ); echo '
'; echo '
'; if ( $locked ) { // Locked by the form type: the type can't change, so it's sent as a hidden value. echo ''; echo ' ' . esc_html( isset( self::type_labels()[ $f['type'] ] ) ? self::type_labels()[ $f['type'] ] : $f['type'] ) . ''; } else { echo ''; } echo ''; if ( $locked ) { echo '' . esc_html( $f['required'] ? __( 'Required', 'byltcommerce-toolkit' ) : __( 'Optional', 'byltcommerce-toolkit' ) ) . ''; } else { echo ''; } echo ''; echo '' . esc_html__( 'Conditional', 'byltcommerce-toolkit' ) . ''; echo ' '; if ( ! $locked ) { echo ' '; } echo '
'; echo '
'; } private function render_editor( $which ) { if ( 'new' === $which ) { // phpcs:ignore WordPress.Security.NonceVerification -- display only. $tpl = isset( $_GET['template'] ) ? sanitize_key( wp_unslash( $_GET['template'] ) ) : 'contact'; $tpls = Bylt_Forms::templates(); $t = isset( $tpls[ $tpl ] ) ? $tpls[ $tpl ] : $tpls['contact']; $form = array( 'id' => 0, 'name' => $t['name'], 'fields' => $t['fields'], 'settings' => array_merge( Bylt_Forms_Store::default_settings(), $t['settings'] ) ); } else { $form = Bylt_Forms_Store::get( (int) $which ); if ( ! $form ) { echo '

' . esc_html__( 'Form not found.', 'byltcommerce-toolkit' ) . '

'; return; } } $s = $form['settings']; echo '

← ' . esc_html__( 'All forms', 'byltcommerce-toolkit' ) . '

'; $this->form_start( 'save', $form['id'], 'id="bylt-form-editor"' ); echo '
'; echo '
'; do_action( 'bylt_form_editor_notice', $form ); echo '

' . esc_html__( 'Fields', 'byltcommerce-toolkit' ) . '

'; foreach ( $form['fields'] as $f ) { if ( ! empty( $f['key'] ) ) { $this->labels[ $f['key'] ] = '' !== (string) $f['label'] ? (string) $f['label'] : (string) $f['key']; } } foreach ( array_values( $form['fields'] ) as $i => $f ) { $this->field_row( $i, $f ); } echo '

'; $pages = get_pages( array( 'post_status' => 'publish' ) ); $cats = taxonomy_exists( 'product_cat' ) ? get_terms( array( 'taxonomy' => 'product_cat', 'hide_empty' => false ) ) : array(); ?>

'; if ( $form['id'] ) { echo '
'; if ( ! $s['page_id'] ) { $this->form_start( 'make_page', $form['id'], 'style="display:inline-block;margin-right:8px"' ); echo ''; } echo '[bylt_form id="' . (int) $form['id'] . '"] '; $this->form_start( 'delete', $form['id'], 'style="display:inline-block;margin-left:12px"' ); echo '
'; } } /* --------------------------------------------------------------------- * Entries * ------------------------------------------------------------------- */ private static function summary( array $e, $form ) { $bits = array(); foreach ( $form ? $form['fields'] : array() as $f ) { if ( in_array( $f['type'], array( 'html', 'email', 'hidden', 'consent' ), true ) || in_array( $f['key'], array( 'name', 'full_name', 'first_name' ), true ) || empty( $e['data'][ $f['key'] ] ) ) { continue; } $bits[] = Bylt_Forms_Mailer::text( $e['data'][ $f['key'] ] ); if ( count( $bits ) >= 2 ) { break; } } return wp_trim_words( implode( ' · ', $bits ), 18 ); } private function render_entries() { // phpcs:disable WordPress.Security.NonceVerification -- read-only filters. $form_id = isset( $_GET['form_id'] ) ? absint( $_GET['form_id'] ) : 0; $status = isset( $_GET['status'] ) ? sanitize_key( wp_unslash( $_GET['status'] ) ) : ''; $search = isset( $_GET['s'] ) ? sanitize_text_field( wp_unslash( $_GET['s'] ) ) : ''; $paged = isset( $_GET['paged'] ) ? max( 1, absint( $_GET['paged'] ) ) : 1; // phpcs:enable $forms = array(); foreach ( Bylt_Forms_Store::all() as $f ) { $forms[ $f['id'] ] = $f; } echo '
'; echo ' '; if ( $form_id ) { $args = array( 'action' => self::ACTION, 'do' => 'export_entries', 'id' => '', 'form_id' => $form_id, 'status' => $status ); echo ' ' . esc_html__( 'Export CSV', 'byltcommerce-toolkit' ) . ''; } echo '
'; $res = Bylt_Forms_Store::entries( array( 'form_id' => $form_id, 'status' => $status, 'search' => $search, 'page' => $paged ) ); $this->form_start( 'bulk' ); echo '

'; echo ''; if ( ! $res['items'] ) { echo ''; } foreach ( $res['items'] as $e ) { $f = isset( $forms[ $e['form_id'] ] ) ? $forms[ $e['form_id'] ] : null; $who = $e['email'] ? $e['email'] : __( '(no email)', 'byltcommerce-toolkit' ); $name = ''; foreach ( array( 'name', 'full_name', 'first_name' ) as $k ) { if ( ! empty( $e['data'][ $k ] ) ) { $name = Bylt_Forms_Mailer::text( $e['data'][ $k ] ); break; } } echo ''; echo ''; echo ''; echo ''; echo ''; } echo '
' . esc_html__( 'From', 'byltcommerce-toolkit' ) . '' . esc_html__( 'Entry', 'byltcommerce-toolkit' ) . '' . esc_html__( 'Form', 'byltcommerce-toolkit' ) . '' . esc_html__( 'Received', 'byltcommerce-toolkit' ) . '
' . esc_html__( 'No entries yet.', 'byltcommerce-toolkit' ) . '
' . ( 'new' === $e['status'] ? '' : '' ) . esc_html( $name ? $name : $who ) . ( 'new' === $e['status'] ? '' : '' ) . '' . ( $name ? '
' . esc_html( $who ) . '' : '' ) . ( 'spam' === $e['status'] ? ' (' . esc_html__( 'spam', 'byltcommerce-toolkit' ) . ')' : '' ) . '
' . esc_html( self::summary( $e, $f ) ) . '' . esc_html( $f ? $f['name'] : '#' . $e['form_id'] ) . '' . esc_html( get_date_from_gmt( $e['created_gmt'], get_option( 'date_format' ) . ' ' . get_option( 'time_format' ) ) ) . '
'; $pages = (int) ceil( $res['total'] / 50 ); if ( $pages > 1 ) { echo '
' . paginate_links( array( 'base' => add_query_arg( 'paged', '%#%' ), 'format' => '', 'current' => $paged, 'total' => $pages ) ) . '
'; // phpcs:ignore WordPress.Security.EscapeOutput } } private function render_entry( $id ) { $e = Bylt_Forms_Store::entry( $id ); echo '

← ' . esc_html__( 'All entries', 'byltcommerce-toolkit' ) . '

'; if ( ! $e ) { echo '

' . esc_html__( 'Entry not found.', 'byltcommerce-toolkit' ) . '

'; return; } if ( 'new' === $e['status'] ) { Bylt_Forms_Store::set_status( $e['id'], 'read' ); } $form = Bylt_Forms_Store::get( $e['form_id'] ); /* translators: 1: form name, 2: entry number */ echo '

' . esc_html( sprintf( __( '%1$s — entry #%2$d', 'byltcommerce-toolkit' ), $form ? $form['name'] : '#' . $e['form_id'], $e['id'] ) ) . '

'; echo ''; $files = Bylt_Forms_Store::entry_files( $e ); foreach ( Bylt_Forms_Mailer::rows( $form ? $form : array( 'fields' => array() ), $e['data'] ) as $key => $r ) { $cell = nl2br( esc_html( $r[1] ) ); if ( isset( $files[ $key ] ) ) { $cell = Bylt_Forms_Files::path( $files[ $key ] ) ? ' ' . esc_html( $r[1] ) . '' : esc_html( $r[1] ) . ' (' . esc_html__( 'file no longer available', 'byltcommerce-toolkit' ) . ')'; } echo ''; // phpcs:ignore WordPress.Security.EscapeOutput -- escaped above. } echo '
' . esc_html( $r[0] ) . '' . $cell . '

'; echo esc_html( get_date_from_gmt( $e['created_gmt'], get_option( 'date_format' ) . ' ' . get_option( 'time_format' ) ) ); if ( $e['page_url'] ) { echo ' · ' . esc_html__( 'Sent from this page', 'byltcommerce-toolkit' ) . ''; } if ( $e['product_id'] && function_exists( 'wc_get_product' ) && wc_get_product( $e['product_id'] ) ) { echo ' · ' . esc_html__( 'Product', 'byltcommerce-toolkit' ) . ': ' . esc_html( wc_get_product( $e['product_id'] )->get_name() ) . ''; } if ( $e['user_id'] && get_userdata( $e['user_id'] ) ) { echo ' · ' . esc_html__( 'Customer', 'byltcommerce-toolkit' ) . ': ' . esc_html( get_userdata( $e['user_id'] )->display_name ) . ''; } if ( $e['ip'] ) { echo ' · IP ' . esc_html( $e['ip'] ); } echo '

'; do_action( 'bylt_forms_entry_actions', $e, $form ); if ( $e['email'] ) { $subject = $form ? 'Re: ' . $form['name'] : ''; echo '' . esc_html__( 'Reply by email', 'byltcommerce-toolkit' ) . ' '; } echo '

'; $this->form_start( 'entry_status', $e['id'], 'style="display:inline-block;margin-right:8px"' ); echo ''; $this->form_start( 'entry_status', $e['id'], 'style="display:inline-block;margin-right:8px"' ); echo ''; $this->form_start( 'entry_delete', $e['id'], 'style="display:inline-block"' ); echo ''; } /* --------------------------------------------------------------------- * Import / export, settings * ------------------------------------------------------------------- */ private function render_io() { $forms = Bylt_Forms_Store::all(); echo '
'; echo '

' . esc_html__( 'Export forms', 'byltcommerce-toolkit' ) . '

' . esc_html__( 'A JSON file you can import on another site (or keep as a backup).', 'byltcommerce-toolkit' ) . '

'; $this->form_start( 'export_forms' ); if ( ! $forms ) { echo '

' . esc_html__( 'No forms yet.', 'byltcommerce-toolkit' ) . '

'; } foreach ( $forms as $f ) { echo ''; } echo ''; echo '

'; echo '

' . esc_html__( 'Export entries', 'byltcommerce-toolkit' ) . '

' . esc_html__( 'CSV opens in Excel, Numbers or Google Sheets. JSON keeps everything for importing back.', 'byltcommerce-toolkit' ) . '

'; $this->form_start( 'export_entries' ); echo '

'; echo '

'; echo '

' . esc_html__( 'Import', 'byltcommerce-toolkit' ) . '

' . esc_html__( 'A BYLTCommerce forms JSON file (forms, with or without entries), or a CSV of entries for one form. Importing the same file twice doesn\'t duplicate entries.', 'byltcommerce-toolkit' ) . '

'; $this->form_start( 'import', '', 'enctype="multipart/form-data"' ); echo '

'; echo '

'; echo '


' . esc_html__( 'Column headings are matched to field labels or keys; "Submitted" and "Status" columns are used if present.', 'byltcommerce-toolkit' ) . '

'; echo '

'; echo '
'; } private function render_settings() { $s = $this->forms->settings(); $this->form_start( 'settings' ); echo ''; echo '

' . esc_html__( 'Entries are included in Tools → Export Personal Data and Erase Personal Data (matched by email).', 'byltcommerce-toolkit' ) . '

'; submit_button(); echo ''; } /* --------------------------------------------------------------------- * Actions * ------------------------------------------------------------------- */ private function back( array $args, $msg, $error = false ) { if ( $error ) { $args['err'] = 1; } wp_safe_redirect( self::url( array_merge( $args, array( 'msg' => $msg ) ) ) ); exit; } private static function download( $filename, $type, $content ) { nocache_headers(); header( 'Content-Type: ' . $type . '; charset=utf-8' ); header( 'Content-Disposition: attachment; filename=' . $filename ); echo "\xEF\xBB\xBF" === substr( $content, 0, 3 ) || 'application/json' === $type ? $content : "\xEF\xBB\xBF" . $content; // phpcs:ignore WordPress.Security.EscapeOutput -- file download. exit; } /** Turn the editor's posted rows into fields. */ public static function fields_from_post( array $rows ) { $out = array(); foreach ( $rows as $r ) { if ( ! is_array( $r ) ) { continue; } if ( isset( $r['type'] ) && 'html' === $r['type'] ) { $r['help'] = isset( $r['help_html'] ) ? $r['help_html'] : ''; } unset( $r['help_html'] ); $r['required'] = ! empty( $r['required'] ); $r['enabled'] = ! isset( $r['enabled'] ) || '0' !== (string) $r['enabled']; $out[] = $r; } return $out; } public function handle() { $do = isset( $_REQUEST['do'] ) ? sanitize_key( wp_unslash( $_REQUEST['do'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification $id = isset( $_REQUEST['id'] ) ? sanitize_key( wp_unslash( $_REQUEST['id'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification check_admin_referer( self::ACTION . '_' . $do . '_' . $id ); if ( ! current_user_can( Bylt_Admin::cap() ) ) { wp_die( esc_html__( 'You are not allowed to do that.', 'byltcommerce-toolkit' ) ); } $req = wp_unslash( $_REQUEST ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput -- sanitized by the store per field. switch ( $do ) { case 'save': $fid = Bylt_Forms_Store::save( array( 'id' => (int) $id, 'name' => isset( $req['name'] ) ? $req['name'] : '', 'fields' => self::fields_from_post( isset( $req['fields'] ) ? (array) $req['fields'] : array() ), 'settings' => isset( $req['settings'] ) ? (array) $req['settings'] : array(), ) ); $this->forms->audit( 'form_saved', sprintf( 'Form #%d saved', $fid ) ); $this->back( array( 'form' => $fid ), __( 'Form saved.', 'byltcommerce-toolkit' ) ); break; case 'make_page': $form = Bylt_Forms_Store::get( (int) $id ); if ( $form ) { $page = wp_insert_post( array( 'post_type' => 'page', 'post_status' => 'publish', 'post_title' => $form['name'], 'post_content' => '', ) ); if ( $page && ! is_wp_error( $page ) ) { $form['settings']['page_id'] = $page; Bylt_Forms_Store::save( $form ); $this->back( array( 'form' => $form['id'] ), __( 'Page created and published.', 'byltcommerce-toolkit' ) ); } } $this->back( array(), __( 'Couldn\'t create the page.', 'byltcommerce-toolkit' ), true ); break; case 'delete': Bylt_Forms_Store::delete( (int) $id ); $this->forms->audit( 'form_deleted', sprintf( 'Form #%d and its entries deleted', (int) $id ) ); $this->back( array(), __( 'Form deleted.', 'byltcommerce-toolkit' ) ); break; case 'bulk': $ids = isset( $req['ids'] ) ? array_map( 'absint', (array) $req['ids'] ) : array(); $bulk = isset( $req['bulk'] ) ? sanitize_key( $req['bulk'] ) : ''; if ( 'delete' === $bulk ) { $n = Bylt_Forms_Store::delete_entries( $ids ); } else { $n = Bylt_Forms_Store::set_status( $ids, $bulk ); } /* translators: %d: count */ $this->back( array( 'tab' => 'entries' ), sprintf( _n( '%d entry updated.', '%d entries updated.', $n, 'byltcommerce-toolkit' ), $n ) ); break; case 'entry_status': Bylt_Forms_Store::set_status( (int) $id, isset( $req['status'] ) ? sanitize_key( $req['status'] ) : 'read' ); $this->back( 'new' === ( isset( $req['status'] ) ? $req['status'] : '' ) ? array( 'tab' => 'entries' ) : array( 'entry' => (int) $id ), __( 'Entry updated.', 'byltcommerce-toolkit' ) ); break; case 'entry_delete': Bylt_Forms_Store::delete_entries( array( (int) $id ) ); $this->back( array( 'tab' => 'entries' ), __( 'Entry deleted.', 'byltcommerce-toolkit' ) ); break; case 'export_forms': $ids = isset( $req['form_ids'] ) ? array_map( 'absint', (array) $req['form_ids'] ) : array(); $json = Bylt_Forms_IO::export_json( $ids, ! empty( $req['with_entries'] ) ); self::download( 'bylt-forms-' . gmdate( 'Y-m-d' ) . '.json', 'application/json', $json ); break; case 'export_entries': $fid = isset( $req['form_id'] ) ? absint( $req['form_id'] ) : 0; $status = isset( $req['status'] ) ? sanitize_key( $req['status'] ) : ''; $form = Bylt_Forms_Store::get( $fid ); if ( ! $form ) { $this->back( array( 'tab' => 'io' ), __( 'Choose a form.', 'byltcommerce-toolkit' ), true ); } $slug = sanitize_title( $form['name'] ) . '-entries-' . gmdate( 'Y-m-d' ); if ( isset( $req['format'] ) && 'json' === $req['format'] ) { self::download( $slug . '.json', 'application/json', Bylt_Forms_IO::export_json( array( $fid ), true, $this->entry_filter( $status ) ) ); } self::download( $slug . '.csv', 'text/csv', Bylt_Forms_IO::export_csv( $fid, $this->entry_filter( $status ) ) ); break; case 'import': $file = isset( $_FILES['file'] ) ? $_FILES['file'] : null; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput if ( ! $file || ! empty( $file['error'] ) || ! is_uploaded_file( $file['tmp_name'] ) ) { $this->back( array( 'tab' => 'io' ), __( 'Choose a file to import.', 'byltcommerce-toolkit' ), true ); } $name = strtolower( sanitize_file_name( $file['name'] ) ); if ( '.csv' === substr( $name, -4 ) ) { $r = Bylt_Forms_IO::import_csv( isset( $req['form_id'] ) ? absint( $req['form_id'] ) : 0, $file['tmp_name'] ); if ( is_wp_error( $r ) ) { $this->back( array( 'tab' => 'io' ), $r->get_error_message(), true ); } /* translators: 1: imported, 2: skipped, 3: matched columns */ $this->back( array( 'tab' => 'io' ), sprintf( __( 'Imported %1$d entries (%2$d already there). Matched columns: %3$s.', 'byltcommerce-toolkit' ), $r['entries'], $r['skipped'], implode( ', ', $r['matched'] ) ) ); } $r = Bylt_Forms_IO::import_json( file_get_contents( $file['tmp_name'] ), isset( $req['mode'] ) && 'copy' === $req['mode'] ? 'copy' : 'merge' ); // phpcs:ignore WordPress.WP.AlternativeFunctions if ( is_wp_error( $r ) ) { $this->back( array( 'tab' => 'io' ), $r->get_error_message(), true ); } $this->forms->audit( 'forms_import', sprintf( 'Imported %d forms and %d entries', $r['forms_added'], $r['entries'] ) ); /* translators: 1: new forms, 2: existing forms, 3: entries, 4: skipped */ $this->back( array( 'tab' => 'io' ), sprintf( __( 'Added %1$d forms, matched %2$d existing, imported %3$d entries (%4$d skipped or already there).', 'byltcommerce-toolkit' ), $r['forms_added'], $r['forms_reused'], $r['entries'], $r['skipped'] ) ); break; case 'settings': $this->forms->update_settings( array( 'retention_days' => isset( $req['retention_days'] ) ? max( 0, (int) $req['retention_days'] ) : 0 ) ); $this->back( array( 'tab' => 'settings' ), __( 'Settings saved.', 'byltcommerce-toolkit' ) ); break; } $this->back( array(), '' ); } /** Entry filter for exports: a status, or everything except spam. */ private function entry_filter( $status ) { return $status ? array( 'status' => $status ) : array( 'not_status' => 'spam' ); } }