hooks(); } return self::$instance; } /** * Register hooks. * @since 1.0.0 */ private function hooks() { add_action( 'admin_menu', array( $this, 'register_menus' ) ); add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_assets' ) ); add_action( 'admin_post_advc_change_status', array( $this, 'handle_change_status' ) ); add_action( 'admin_post_advc_toggle_important', array( $this, 'handle_toggle_important' ) ); add_action( 'admin_post_advc_delete_submission', array( $this, 'handle_delete_submission' ) ); add_action( 'admin_post_advc_update_submission', array( $this, 'handle_update_submission' ) ); add_action( 'admin_post_advc_bulk_action', array( $this, 'handle_bulk_action' ) ); add_action( 'admin_post_advc_toggle_rewarded', array( $this, 'handle_toggle_rewarded' ) ); add_action( 'admin_post_advc_save_payout', array( $this, 'handle_save_payout' ) ); add_action( 'admin_post_advc_change_stage', array( $this, 'handle_change_stage' ) ); add_action( 'admin_post_advc_export_csv', array( $this, 'handle_export_csv' ) ); add_action( 'admin_post_advc_apply_preset', array( $this, 'handle_apply_preset' ) ); add_action( 'admin_post_advc_save_field_order', array( $this, 'handle_save_field_order' ) ); add_action( 'admin_post_advc_add_field', array( $this, 'handle_add_field' ) ); add_action( 'admin_post_advc_delete_field', array( $this, 'handle_delete_field' ) ); add_action( 'admin_post_advc_restore_field', array( $this, 'handle_restore_field' ) ); add_action( 'admin_post_advc_save_page_settings', array( $this, 'handle_save_page_settings' ) ); add_action( 'admin_post_advc_use_existing_page', array( $this, 'handle_use_existing_page' ) ); add_action( 'admin_post_advc_create_page', array( $this, 'handle_create_page' ) ); add_action( 'admin_post_advc_save_general_settings', array( $this, 'handle_save_general_settings' ) ); add_action( 'wp_ajax_advc_quick_toggle_important', array( $this, 'ajax_quick_toggle_important' ) ); } /** * Register the admin menu and submenus. * @since 1.0.0 */ public function register_menus() { add_menu_page( __( 'Advisers Contacts', 'advisers-contacts' ), __( 'Advisers Contacts', 'advisers-contacts' ), advc_get_capability(), 'advisers-contacts', array( $this, 'render_submissions_screen' ), 'dashicons-email-alt', 27 ); add_submenu_page( 'advisers-contacts', __( 'Submissions', 'advisers-contacts' ), __( 'Submissions', 'advisers-contacts' ), advc_get_capability(), 'advisers-contacts', array( $this, 'render_submissions_screen' ) ); add_submenu_page( 'advisers-contacts', __( 'Referrers', 'advisers-contacts' ), __( 'Referrers', 'advisers-contacts' ), advc_get_capability(), 'advc-referrers', array( $this, 'render_referrers_screen' ) ); add_submenu_page( 'advisers-contacts', __( 'Field Builder', 'advisers-contacts' ), __( 'Field Builder', 'advisers-contacts' ), advc_get_capability(), 'advc-field-builder', array( $this, 'render_field_builder_screen' ) ); add_submenu_page( 'advisers-contacts', __( 'Contact Page', 'advisers-contacts' ), __( 'Contact Page', 'advisers-contacts' ), advc_get_capability(), 'advc-contact-page', array( $this, 'render_contact_page_screen' ) ); add_submenu_page( 'advisers-contacts', __( 'Settings', 'advisers-contacts' ), __( 'Settings', 'advisers-contacts' ), advc_get_capability(), 'advc-settings', array( $this, 'render_settings_screen' ) ); // Hidden detail screen, reached only via a row link (not shown in the menu). // An empty parent slug is the PHP 8.1-safe way to register it (null is deprecated). add_submenu_page( '', __( 'Submission Details', 'advisers-contacts' ), '', advc_get_capability(), 'advc-view-submission', array( $this, 'render_view_submission_screen' ) ); } /** * Enqueue admin CSS/JS only on the plugin's own screens. * * @since 1.0.0 * @param string $hook Current admin page hook. */ public function enqueue_assets( $hook ) { if ( strpos( $hook, 'advisers-contacts' ) === false && strpos( $hook, 'advc-' ) === false ) { return; } wp_enqueue_style( 'advc-admin', ADVC_URL . 'assets/css/admin.css', array(), ADVC_VERSION ); wp_enqueue_script( 'jquery-ui-sortable' ); wp_enqueue_script( 'advc-admin', ADVC_URL . 'assets/js/admin.js', array( 'jquery', 'jquery-ui-sortable' ), ADVC_VERSION, true ); wp_localize_script( 'advc-admin', 'advcAdmin', array( 'ajaxUrl' => admin_url( 'admin-ajax.php' ), 'nonce' => wp_create_nonce( 'advc_admin_ajax' ), 'listUrl' => admin_url( 'admin.php?page=advisers-contacts' ), 'i18n' => array( 'confirmPreset' => __( 'Switch to the Lead Generation layout? Its fields are enabled and ordered first, and the other built-in fields are switched off (not deleted).', 'advisers-contacts' ), 'confirmDelete' => __( 'Delete this submission? This cannot be undone.', 'advisers-contacts' ), 'confirmField' => __( 'Delete this field? This cannot be undone.', 'advisers-contacts' ), ), ) ); } /* ----------------------------------------------------------------- * Screens * -------------------------------------------------------------- */ /** * Submissions dashboard (WP_List_Table). * @since 1.0.0 */ public function render_submissions_screen() { if ( ! current_user_can( advc_get_capability() ) ) { wp_die( esc_html__( 'You do not have permission to access this page.', 'advisers-contacts' ) ); } require ADVC_DIR . 'includes/views/view-submissions.php'; } /** * Single submission detail/edit screen. * @since 1.0.0 */ public function render_view_submission_screen() { if ( ! current_user_can( advc_get_capability() ) ) { wp_die( esc_html__( 'You do not have permission to access this page.', 'advisers-contacts' ) ); } $id = isset( $_GET['id'] ) ? absint( $_GET['id'] ) : 0; // phpcs:ignore WordPress.Security.NonceVerification.Recommended $submission = $id ? ADVC_DB::get_submission( $id ) : null; if ( ! $submission ) { echo '

' . esc_html__( 'Submission not found', 'advisers-contacts' ) . '

'; return; } require ADVC_DIR . 'includes/views/view-submission-detail.php'; } /** * Referrers overview + drill-down. * @since 1.0.0 */ public function render_referrers_screen() { if ( ! current_user_can( advc_get_capability() ) ) { wp_die( esc_html__( 'You do not have permission to access this page.', 'advisers-contacts' ) ); } require ADVC_DIR . 'includes/views/view-referrers.php'; } /** * Drag-drop field builder. * @since 1.0.0 */ public function render_field_builder_screen() { if ( ! current_user_can( advc_get_capability() ) ) { wp_die( esc_html__( 'You do not have permission to access this page.', 'advisers-contacts' ) ); } require ADVC_DIR . 'includes/views/view-field-builder.php'; } /** * Contact Us page settings. * @since 1.0.0 */ public function render_contact_page_screen() { if ( ! current_user_can( advc_get_capability() ) ) { wp_die( esc_html__( 'You do not have permission to access this page.', 'advisers-contacts' ) ); } require ADVC_DIR . 'includes/views/view-contact-page.php'; } /** * General plugin settings. * @since 1.0.0 */ public function render_settings_screen() { if ( ! current_user_can( advc_get_capability() ) ) { wp_die( esc_html__( 'You do not have permission to access this page.', 'advisers-contacts' ) ); } require ADVC_DIR . 'includes/views/view-settings.php'; } /* ----------------------------------------------------------------- * admin-post.php handlers (form posts with full page reload) * -------------------------------------------------------------- */ /** * Change a single submission's status (approve/reject/pending). * @since 1.0.0 */ public function handle_change_status() { if ( ! current_user_can( advc_get_capability() ) ) { wp_die( esc_html__( 'You do not have permission to do this.', 'advisers-contacts' ) ); } check_admin_referer( 'advc_submissions_action', '_advc_nonce' ); $id = isset( $_POST['id'] ) ? absint( $_POST['id'] ) : 0; $status = isset( $_POST['status'] ) ? sanitize_key( wp_unslash( $_POST['status'] ) ) : ''; if ( $id && in_array( $status, array( 'pending', 'approved', 'rejected' ), true ) ) { ADVC_DB::update_submission( $id, array( 'status' => $status ) ); } $this->redirect_with_notice( wp_get_referer(), 'status_updated' ); } /** * Toggle the "important" flag. * @since 1.0.0 */ public function handle_toggle_important() { if ( ! current_user_can( advc_get_capability() ) ) { wp_die( esc_html__( 'You do not have permission to do this.', 'advisers-contacts' ) ); } check_admin_referer( 'advc_submissions_action', '_advc_nonce' ); $id = isset( $_POST['id'] ) ? absint( $_POST['id'] ) : 0; if ( $id ) { $submission = ADVC_DB::get_submission( $id ); if ( $submission ) { ADVC_DB::update_submission( $id, array( 'is_important' => $submission->is_important ? 0 : 1 ) ); } } $this->redirect_with_notice( wp_get_referer(), 'important_updated' ); } /** * Delete a submission. * @since 1.0.0 */ public function handle_delete_submission() { if ( ! current_user_can( advc_get_capability() ) ) { wp_die( esc_html__( 'You do not have permission to do this.', 'advisers-contacts' ) ); } check_admin_referer( 'advc_submissions_action', '_advc_nonce' ); $id = isset( $_POST['id'] ) ? absint( $_POST['id'] ) : 0; if ( $id ) { ADVC_DB::delete_submission( $id ); } $url = admin_url( 'admin.php?page=advisers-contacts' ); $this->redirect_with_notice( $url, 'deleted' ); } /** * Save edits made on the submission detail screen. * @since 1.0.0 */ public function handle_update_submission() { if ( ! current_user_can( advc_get_capability() ) ) { wp_die( esc_html__( 'You do not have permission to do this.', 'advisers-contacts' ) ); } check_admin_referer( 'advc_submissions_action', '_advc_nonce' ); $id = isset( $_POST['id'] ) ? absint( $_POST['id'] ) : 0; if ( ! $id ) { wp_die( esc_html__( 'Invalid submission.', 'advisers-contacts' ) ); } $fields = ADVC_Fields::get_fields(); $core = array(); $extra = array(); foreach ( $fields as $field ) { if ( in_array( $field->type, array( 'submit', 'file' ), true ) ) { continue; } $raw = isset( $_POST[ 'advc_field_' . $field->field_key ] ) ? wp_unslash( $_POST[ 'advc_field_' . $field->field_key ] ) : ''; // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Sanitized by type in ADVC_Helpers::sanitize_field_value() below; nonce verified above. $val = ADVC_Helpers::sanitize_field_value( $field->type, $raw ); if ( in_array( $field->field_key, array( 'full_name', 'mobile_number', 'email', 'subject', 'referred_by' ), true ) ) { $core[ $field->field_key ] = $val; } else { $extra[ $field->field_key ] = $val; } } $existing = ADVC_DB::get_submission( $id ); $existing_extra = $existing && $existing->field_data ? json_decode( $existing->field_data, true ) : array(); $merged_extra = array_merge( (array) $existing_extra, $extra ); $core['field_data'] = wp_json_encode( $merged_extra ); $core['lead_score'] = ADVC_Helpers::compute_lead_score( $core, $merged_extra ); ADVC_DB::update_submission( $id, $core ); $url = admin_url( 'admin.php?page=advc-view-submission&id=' . $id ); $this->redirect_with_notice( $url, 'saved' ); } /** * Bulk actions from the submissions list table. * @since 1.0.0 */ public function handle_bulk_action() { if ( ! current_user_can( advc_get_capability() ) ) { wp_die( esc_html__( 'You do not have permission to do this.', 'advisers-contacts' ) ); } check_admin_referer( 'advc_submissions_action', '_advc_nonce' ); $ids = isset( $_POST['ids'] ) ? array_map( 'absint', (array) wp_unslash( $_POST['ids'] ) ) : array(); $action = isset( $_POST['bulk_action'] ) ? sanitize_key( wp_unslash( $_POST['bulk_action'] ) ) : ''; $stages = ADVC_Helpers::stages(); foreach ( $ids as $id ) { if ( 0 === strpos( $action, 'stage_' ) && isset( $stages[ substr( $action, 6 ) ] ) ) { ADVC_DB::update_submission( $id, array( 'lead_stage' => substr( $action, 6 ) ) ); continue; } switch ( $action ) { case 'approve': ADVC_DB::update_submission( $id, array( 'status' => 'approved' ) ); break; case 'reject': ADVC_DB::update_submission( $id, array( 'status' => 'rejected' ) ); break; case 'rewarded': ADVC_DB::set_rewarded( $id, true ); break; case 'unrewarded': ADVC_DB::set_rewarded( $id, false ); break; case 'important': ADVC_DB::update_submission( $id, array( 'is_important' => 1 ) ); break; case 'unimportant': ADVC_DB::update_submission( $id, array( 'is_important' => 0 ) ); break; case 'delete': ADVC_DB::delete_submission( $id ); break; } } $this->redirect_with_notice( wp_get_referer(), 'bulk_done' ); } /** * Mark one lead as rewarded or not rewarded. * * @since 1.4.0 */ public function handle_toggle_rewarded() { if ( ! current_user_can( advc_get_capability() ) ) { wp_die( esc_html__( 'You do not have permission to do this.', 'advisers-contacts' ) ); } check_admin_referer( 'advc_submissions_action', '_advc_nonce' ); $id = isset( $_POST['id'] ) ? absint( $_POST['id'] ) : 0; $reward = ! empty( $_POST['rewarded'] ); if ( $id && ADVC_DB::get_submission( $id ) ) { ADVC_DB::set_rewarded( $id, $reward ); } $this->redirect_with_notice( wp_get_referer(), 'reward_updated' ); } /** * Save the payout details typed in for a referrer. * * @since 1.4.0 */ public function handle_save_payout() { if ( ! current_user_can( advc_get_capability() ) ) { wp_die( esc_html__( 'You do not have permission to do this.', 'advisers-contacts' ) ); } check_admin_referer( 'advc_referrers', '_advc_nonce' ); $referrer = isset( $_POST['referrer'] ) ? sanitize_text_field( wp_unslash( $_POST['referrer'] ) ) : ''; $details = isset( $_POST['payout_details'] ) ? substr( sanitize_textarea_field( wp_unslash( $_POST['payout_details'] ) ), 0, 1000 ) : ''; if ( '' !== $referrer ) { ADVC_DB::save_payout_details( $referrer, $details ); } $url = add_query_arg( array( 'page' => 'advc-referrers', 'referrer' => rawurlencode( $referrer ), ), admin_url( 'admin.php' ) ); $this->redirect_with_notice( $url, 'payout_saved' ); } /** * Move a lead to another pipeline stage. * * @since 1.3.0 */ public function handle_change_stage() { if ( ! current_user_can( advc_get_capability() ) ) { wp_die( esc_html__( 'You do not have permission to do this.', 'advisers-contacts' ) ); } check_admin_referer( 'advc_submissions_action', '_advc_nonce' ); $id = isset( $_POST['id'] ) ? absint( $_POST['id'] ) : 0; $stage = isset( $_POST['lead_stage'] ) ? sanitize_key( wp_unslash( $_POST['lead_stage'] ) ) : ''; if ( $id && array_key_exists( $stage, ADVC_Helpers::stages() ) ) { ADVC_DB::update_submission( $id, array( 'lead_stage' => $stage ) ); } $this->redirect_with_notice( wp_get_referer(), 'saved' ); } /** * Switch the form to the ready-made lead-generation layout. * * @since 1.3.0 */ public function handle_apply_preset() { if ( ! current_user_can( advc_get_capability() ) ) { wp_die( esc_html__( 'You do not have permission to do this.', 'advisers-contacts' ) ); } check_admin_referer( 'advc_field_builder', '_advc_nonce' ); ADVC_Fields::apply_lead_preset(); $this->redirect_with_notice( admin_url( 'admin.php?page=advc-field-builder' ), 'preset_applied' ); } /** * Download the submissions that match the current filters as a CSV file. * * Cells that start with a spreadsheet formula character are prefixed with * an apostrophe so a malicious submission cannot run a formula in Excel. * * @since 1.3.0 */ public function handle_export_csv() { if ( ! current_user_can( advc_get_capability() ) ) { wp_die( esc_html__( 'You do not have permission to do this.', 'advisers-contacts' ) ); } check_admin_referer( 'advc_export' ); $args = array( 'search' => isset( $_GET['s'] ) ? sanitize_text_field( wp_unslash( $_GET['s'] ) ) : '', 'status' => isset( $_GET['advc_status'] ) ? sanitize_key( wp_unslash( $_GET['advc_status'] ) ) : '', 'stage' => isset( $_GET['advc_stage'] ) ? sanitize_key( wp_unslash( $_GET['advc_stage'] ) ) : '', 'rewarded' => isset( $_GET['advc_rewarded'] ) ? sanitize_key( wp_unslash( $_GET['advc_rewarded'] ) ) : '', 'referrer' => isset( $_GET['advc_referrer'] ) ? sanitize_text_field( wp_unslash( $_GET['advc_referrer'] ) ) : '', 'date_from' => isset( $_GET['advc_date_from'] ) ? sanitize_text_field( wp_unslash( $_GET['advc_date_from'] ) ) : '', 'date_to' => isset( $_GET['advc_date_to'] ) ? sanitize_text_field( wp_unslash( $_GET['advc_date_to'] ) ) : '', 'orderby' => 'created_at', 'order' => 'DESC', 'per_page' => 500, ); $temperature = isset( $_GET['advc_temp'] ) ? sanitize_key( wp_unslash( $_GET['advc_temp'] ) ) : ''; $temps = ADVC_Helpers::temperatures(); if ( isset( $temps[ $temperature ] ) ) { $args['score_min'] = $temps[ $temperature ][1]; $args['score_max'] = $temps[ $temperature ][2]; } $fields = array(); foreach ( ADVC_Fields::get_fields() as $field ) { if ( ! in_array( $field->type, array( 'submit', 'file' ), true ) ) { $fields[] = $field; } } nocache_headers(); header( 'Content-Type: text/csv; charset=utf-8' ); header( 'Content-Disposition: attachment; filename="advisers-contacts-' . gmdate( 'Y-m-d' ) . '.csv"' ); $out = fopen( 'php://output', 'w' ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fopen -- Streaming the download to the browser, not touching the filesystem. fwrite( $out, "\xEF\xBB\xBF" ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fwrite -- UTF-8 byte order mark so Excel reads accents correctly. $header = array( 'ID', 'Date', 'Status', 'Lead Stage', 'Lead Score', 'Lead Temperature' ); foreach ( $fields as $field ) { $header[] = $field->label; } foreach ( ADVC_Helpers::tracking_keys() as $key ) { $header[] = $key; } $header[] = 'Attachments'; $header[] = 'Rewarded'; $header[] = 'Referrer Payout Details'; fputcsv( $out, $header ); $stages = ADVC_Helpers::stages(); $paged = 1; do { $args['paged'] = $paged; $result = ADVC_DB::query_submissions( $args ); foreach ( $result['items'] as $row ) { $extra = $row->field_data ? json_decode( $row->field_data, true ) : array(); $source = $row->source_data ? json_decode( $row->source_data, true ) : array(); $extra = is_array( $extra ) ? $extra : array(); $source = is_array( $source ) ? $source : array(); $line = array( $row->id, $row->created_at, $row->status, isset( $stages[ $row->lead_stage ] ) ? $stages[ $row->lead_stage ] : $row->lead_stage, $row->lead_score, ADVC_Helpers::temperature( $row->lead_score ), ); foreach ( $fields as $field ) { $line[] = isset( $row->{$field->field_key} ) ? $row->{$field->field_key} : ( isset( $extra[ $field->field_key ] ) ? $extra[ $field->field_key ] : '' ); } foreach ( ADVC_Helpers::tracking_keys() as $key ) { $line[] = isset( $source[ $key ] ) ? $source[ $key ] : ''; } $urls = array(); foreach ( ADVC_Helpers::get_attachments( $row->attachment_ids ) as $file ) { $urls[] = $file['url']; } $line[] = implode( ' ', $urls ); $line[] = $row->is_rewarded ? 'Yes' : 'No'; $line[] = $row->referred_by ? ADVC_DB::get_payout_details( $row->referred_by ) : ''; fputcsv( $out, array_map( array( $this, 'csv_safe' ), $line ) ); } ++$paged; } while ( count( $result['items'] ) === $args['per_page'] ); fclose( $out ); // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_fclose -- Closing the output stream opened above. exit; } /** * Neutralise spreadsheet formula injection in one CSV cell. * * @since 1.3.0 * * @param mixed $value Cell value. * @return string */ private function csv_safe( $value ) { $value = (string) $value; if ( '' !== $value && in_array( $value[0], array( '=', '+', '-', '@', "\t", "\r" ), true ) ) { return "'" . $value; } return $value; } /** * Save drag-drop order + enabled/required toggles from the field builder. * @since 1.0.0 */ public function handle_save_field_order() { if ( ! current_user_can( advc_get_capability() ) ) { wp_die( esc_html__( 'You do not have permission to do this.', 'advisers-contacts' ) ); } check_admin_referer( 'advc_field_builder', '_advc_nonce' ); $rows = isset( $_POST['fields'] ) ? wp_unslash( $_POST['fields'] ) : array(); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Decoded and every value sanitized in ADVC_Fields::save_order(); nonce verified above. if ( is_string( $rows ) ) { $rows = json_decode( $rows, true ); } if ( is_array( $rows ) ) { ADVC_Fields::save_order( $rows ); } $url = admin_url( 'admin.php?page=advc-field-builder' ); $this->redirect_with_notice( $url, 'fields_saved' ); } /** * Add a new custom field. * @since 1.0.0 */ public function handle_add_field() { if ( ! current_user_can( advc_get_capability() ) ) { wp_die( esc_html__( 'You do not have permission to do this.', 'advisers-contacts' ) ); } check_admin_referer( 'advc_field_builder', '_advc_nonce' ); $result = ADVC_Fields::add_field( array( 'label' => isset( $_POST['label'] ) ? sanitize_text_field( wp_unslash( $_POST['label'] ) ) : '', 'type' => isset( $_POST['type'] ) ? sanitize_key( wp_unslash( $_POST['type'] ) ) : 'text', 'options' => isset( $_POST['options'] ) ? sanitize_textarea_field( wp_unslash( $_POST['options'] ) ) : '', 'placeholder' => isset( $_POST['placeholder'] ) ? sanitize_text_field( wp_unslash( $_POST['placeholder'] ) ) : '', 'help_text' => isset( $_POST['help_text'] ) ? sanitize_text_field( wp_unslash( $_POST['help_text'] ) ) : '', 'width' => isset( $_POST['width'] ) ? sanitize_key( wp_unslash( $_POST['width'] ) ) : 'full', 'required' => ! empty( $_POST['required'] ), ) ); $url = admin_url( 'admin.php?page=advc-field-builder' ); $this->redirect_with_notice( $url, is_wp_error( $result ) ? 'error' : 'field_added' ); } /** * Delete any field (default or custom) from the form. * @since 1.0.0 */ public function handle_delete_field() { if ( ! current_user_can( advc_get_capability() ) ) { wp_die( esc_html__( 'You do not have permission to do this.', 'advisers-contacts' ) ); } check_admin_referer( 'advc_field_builder', '_advc_nonce' ); $id = isset( $_POST['id'] ) ? absint( $_POST['id'] ) : 0; ADVC_Fields::delete_field( $id ); $url = admin_url( 'admin.php?page=advc-field-builder' ); $this->redirect_with_notice( $url, 'field_deleted' ); } /** * Restore a previously deleted default field. * * @since 1.1.0 */ public function handle_restore_field() { if ( ! current_user_can( advc_get_capability() ) ) { wp_die( esc_html__( 'You do not have permission to do this.', 'advisers-contacts' ) ); } check_admin_referer( 'advc_field_builder', '_advc_nonce' ); $key = isset( $_POST['field_key'] ) ? sanitize_key( wp_unslash( $_POST['field_key'] ) ) : ''; $result = $key ? ADVC_Fields::restore_field( $key ) : new WP_Error( 'advc_missing_key', __( 'Missing field key.', 'advisers-contacts' ) ); $url = admin_url( 'admin.php?page=advc-field-builder' ); $this->redirect_with_notice( $url, is_wp_error( $result ) ? 'error' : 'field_restored' ); } /** * Save Contact Us page settings. * @since 1.0.0 */ public function handle_save_page_settings() { if ( ! current_user_can( advc_get_capability() ) ) { wp_die( esc_html__( 'You do not have permission to do this.', 'advisers-contacts' ) ); } check_admin_referer( 'advc_contact_page', '_advc_nonce' ); $requested = isset( $_POST['page_slug'] ) ? sanitize_title( wp_unslash( $_POST['page_slug'] ) ) : ''; $saved = ADVC_Page::update_page( isset( $_POST['page_title'] ) ? sanitize_text_field( wp_unslash( $_POST['page_title'] ) ) : '', $requested, isset( $_POST['page_content'] ) ? wp_kses_post( wp_unslash( $_POST['page_content'] ) ) : '' ); if ( false === $saved ) { $notice = 'page_error'; } elseif ( '' !== $requested && $saved !== $requested ) { $notice = 'slug_adjusted'; } else { $notice = 'page_saved'; } $this->redirect_with_notice( admin_url( 'admin.php?page=advc-contact-page' ), $notice ); } /** * Use an existing page as the contact page. * * @since 1.4.1 */ public function handle_use_existing_page() { if ( ! current_user_can( advc_get_capability() ) ) { wp_die( esc_html__( 'You do not have permission to do this.', 'advisers-contacts' ) ); } check_admin_referer( 'advc_contact_page', '_advc_nonce' ); $page_id = isset( $_POST['existing_page'] ) ? absint( $_POST['existing_page'] ) : 0; $ok = $page_id && ADVC_Page::use_existing_page( $page_id ); $this->redirect_with_notice( admin_url( 'admin.php?page=advc-contact-page' ), $ok ? 'page_linked' : 'page_error' ); } /** * Create a fresh contact page on request. * * @since 1.4.1 */ public function handle_create_page() { if ( ! current_user_can( advc_get_capability() ) ) { wp_die( esc_html__( 'You do not have permission to do this.', 'advisers-contacts' ) ); } check_admin_referer( 'advc_contact_page', '_advc_nonce' ); $ok = current_user_can( 'publish_pages' ) && ADVC_Page::create_page(); $this->redirect_with_notice( admin_url( 'admin.php?page=advc-contact-page' ), $ok ? 'page_created' : 'page_error' ); } /** * Save general settings. * @since 1.0.0 */ public function handle_save_general_settings() { if ( ! current_user_can( advc_get_capability() ) ) { wp_die( esc_html__( 'You do not have permission to do this.', 'advisers-contacts' ) ); } check_admin_referer( 'advc_settings', '_advc_nonce' ); update_option( 'advc_default_country_code', isset( $_POST['default_country_code'] ) ? preg_replace( '/\D+/', '', sanitize_text_field( wp_unslash( $_POST['default_country_code'] ) ) ) : '91' ); // Digits only, e.g. 91. update_option( 'advc_per_page', isset( $_POST['per_page'] ) ? max( 5, absint( wp_unslash( $_POST['per_page'] ) ) ) : 20 ); update_option( 'advc_form_title', isset( $_POST['form_title'] ) ? sanitize_text_field( wp_unslash( $_POST['form_title'] ) ) : '' ); update_option( 'advc_form_intro', isset( $_POST['form_intro'] ) ? sanitize_textarea_field( wp_unslash( $_POST['form_intro'] ) ) : '' ); update_option( 'advc_success_message', isset( $_POST['success_message'] ) ? sanitize_textarea_field( wp_unslash( $_POST['success_message'] ) ) : '' ); $theme = isset( $_POST['theme'] ) ? sanitize_key( wp_unslash( $_POST['theme'] ) ) : 'blue'; update_option( 'advc_theme', array_key_exists( $theme, ADVC_Helpers::themes() ) ? $theme : 'blue' ); if ( isset( $_POST['services'] ) ) { ADVC_Fields::set_options( 'service_interested', sanitize_textarea_field( wp_unslash( $_POST['services'] ) ) ); } update_option( 'advc_share_enabled', empty( $_POST['share_enabled'] ) ? '' : '1' ); update_option( 'advc_notify_enabled', empty( $_POST['notify_enabled'] ) ? '' : '1' ); update_option( 'advc_notify_email', isset( $_POST['notify_email'] ) ? sanitize_email( wp_unslash( $_POST['notify_email'] ) ) : '' ); update_option( 'advc_autoreply_enabled', empty( $_POST['autoreply_enabled'] ) ? '' : '1' ); update_option( 'advc_autoreply_subject', isset( $_POST['autoreply_subject'] ) ? sanitize_text_field( wp_unslash( $_POST['autoreply_subject'] ) ) : '' ); update_option( 'advc_autoreply_body', isset( $_POST['autoreply_body'] ) ? sanitize_textarea_field( wp_unslash( $_POST['autoreply_body'] ) ) : '' ); $url = admin_url( 'admin.php?page=advc-settings' ); $this->redirect_with_notice( $url, 'settings_saved' ); } /* ----------------------------------------------------------------- * AJAX * -------------------------------------------------------------- */ /** * Quick "mark important" star toggle from the list table, no reload. * @since 1.0.0 */ public function ajax_quick_toggle_important() { check_ajax_referer( 'advc_admin_ajax', 'nonce' ); if ( ! current_user_can( advc_get_capability() ) ) { wp_send_json_error( array( 'message' => __( 'Permission denied.', 'advisers-contacts' ) ), 403 ); } $id = isset( $_POST['id'] ) ? absint( $_POST['id'] ) : 0; $submission = $id ? ADVC_DB::get_submission( $id ) : null; if ( ! $submission ) { wp_send_json_error( array( 'message' => __( 'Submission not found.', 'advisers-contacts' ) ), 404 ); } $new_value = $submission->is_important ? 0 : 1; ADVC_DB::update_submission( $id, array( 'is_important' => $new_value ) ); wp_send_json_success( array( 'important' => (bool) $new_value ) ); } /* ----------------------------------------------------------------- * Internal helpers * -------------------------------------------------------------- */ /** * Redirect back to a wp-admin screen with a notice query arg. * * @since 1.0.0 * @param string $url Target URL. * @param string $notice Notice key. */ private function redirect_with_notice( $url, $notice ) { $url = $url ? $url : admin_url( 'admin.php?page=advisers-contacts' ); wp_safe_redirect( add_query_arg( 'advc_notice', $notice, $url ) ); exit; } }