id ) { return; } if ( empty( $_GET['settings-updated'] ) ) { return; } $variant = sanitize_key( wp_unslash( $_GET['settings-updated'] ) ); $message = ( 'reset' === $variant ) ? __( 'Settings reset to defaults.', 'advanced-form-integration' ) : __( 'Settings saved.', 'advanced-form-integration' ); printf( '

%s

', esc_html( $message ) ); } /** * Add a "Documentation" Help tab + a Help-sidebar with the KB * link to every AFI admin screen. The Help tab is the * WordPress-native place for "where to learn more about this * page" content — users already know to look there. * * @param WP_Screen $screen */ public function register_help_tabs( $screen ) { if ( empty( $screen ) || empty( $screen->id ) ) { return; } // Match every AFI page: the toplevel + each submenu suffix. $afi_screens = array( 'toplevel_page_advanced-form-integration', 'afi_page_advanced-form-integration-new', 'afi_page_advanced-form-integration-settings', 'afi_page_advanced-form-integration-log', 'afi_page_advanced-form-integration-import-export', 'afi_page_advanced-form-integration-help', ); if ( ! in_array( $screen->id, $afi_screens, true ) ) { return; } $kb_url = 'https://advancedformintegration.com/docs/afi/'; $screen->add_help_tab( array( 'id' => 'adfoin_overview', 'title' => __( 'Overview', 'advanced-form-integration' ), 'content' => '

' . esc_html__( 'Advanced Form Integration sends form submissions from popular WordPress form plugins to dozens of CRMs, email-marketing tools, and webhooks — without writing any code.', 'advanced-form-integration' ) . '

' . '

' . sprintf( /* translators: %s: link to documentation */ wp_kses( __( 'For setup walkthroughs, supported platforms, and troubleshooting tips, visit the Knowledge Base.', 'advanced-form-integration' ), array( 'a' => array( 'href' => array(), 'target' => array(), 'rel' => array() ) ) ), esc_url( $kb_url ) ) . '

', ) ); $screen->set_help_sidebar( '

' . esc_html__( 'For more information:', 'advanced-form-integration' ) . '

' . '

' . esc_html__( 'Knowledge Base', 'advanced-form-integration' ) . '

' . '

' . esc_html__( 'Get Help (in-plugin)', 'advanced-form-integration' ) . '

' ); } /** * Persist screen-meta value for the log list table's per-page setting. */ public function adfoin_log_table_set_option( $status, $option, $value ) { if ( 'adfoin_log_per_page' == $option ) return $value; return $status; } /** * Persist the integrations-list per-page screen option (legacy * filter name; pre-5.4.2 cores). */ public function adfoin_integrations_set_option( $status, $option, $value ) { if ( 'adfoin_integrations_per_page' === $option ) { return (int) $value; } return $status; } /** * Per-option filter (WP 5.4.2+). $status here is the raw incoming * value, not a bool, so we just clamp + return. */ public function adfoin_integrations_set_option_v2( $value ) { return (int) $value; } /** * Register the admin menu. * * @return void */ public function admin_menu() { global $submenu; $hook1 = add_menu_page( esc_html__( 'Advanced Form Integration', 'advanced-form-integration' ), esc_html__( 'AFI', 'advanced-form-integration' ), 'manage_options', 'advanced-form-integration', array( $this, 'adfoin_routing' ), 'data:image/svg+xml;base64,' . base64_encode( ' ' ) ); add_submenu_page( 'advanced-form-integration', esc_html__( 'Advanced Form Integration', 'advanced-form-integration' ), esc_html__( 'Integrations', 'advanced-form-integration' ), 'manage_options', 'advanced-form-integration', array( $this, 'adfoin_routing' ) ); $hook2 = add_submenu_page( 'advanced-form-integration', esc_html__( 'Integrations', 'advanced-form-integration' ), esc_html__( 'Add New', 'advanced-form-integration' ), 'manage_options', 'advanced-form-integration-new', array( $this, 'adfoin_new_integration' ) ); $hook3 = add_submenu_page( 'advanced-form-integration', esc_html__( 'Settings', 'advanced-form-integration' ), esc_html__( 'Settings', 'advanced-form-integration'), 'manage_options', 'advanced-form-integration-settings', array( $this,'adfoin_settings') ); $hook4 = add_submenu_page( 'advanced-form-integration', esc_html__( 'Log', 'advanced-form-integration' ), esc_html__( 'Log', 'advanced-form-integration'), 'manage_options', 'advanced-form-integration-log', array( $this,'adfoin_log') ); $hook5 = add_submenu_page( 'advanced-form-integration', esc_html__( 'Export / Import', 'advanced-form-integration' ), esc_html__( 'Export / Import', 'advanced-form-integration'), 'manage_options', 'advanced-form-integration-import-export', array( $this,'adfoin_import_export' ) ); add_submenu_page( 'advanced-form-integration', esc_html__( 'Get Help', 'advanced-form-integration' ), esc_html__( 'Get Help', 'advanced-form-integration'), 'manage_options', 'advanced-form-integration-help', array( $this,'adfoin_get_help') ); add_action( 'admin_head-' . $hook1, array( $this, 'enqueue_assets' ) ); add_action( 'admin_head-' . $hook2, array( $this, 'enqueue_assets' ) ); add_action( 'admin_head-' . $hook3, array( $this, 'enqueue_assets' ) ); add_action( 'admin_head-' . $hook4, array( $this, 'enqueue_assets' ) ); add_action( 'admin_head-' . $hook5, array( $this, 'enqueue_assets' ) ); // Add screen options for log page add_action( "load-$hook4", array( $this, 'adfoin_log_screen_options' ) ); // Add screen options for the integrations list page (top-level // hook). Suppressed for the edit/duplicate flows since those // aren't list views — only the action=list default needs it. add_action( "load-$hook1", array( $this, 'adfoin_integrations_screen_options' ) ); } /** * Add screen options for log list table */ public function adfoin_log_screen_options() { if ( isset( $_GET['action'] ) && 'view' == $_GET['action'] ) { return; } $option = 'per_page'; $args = array( 'label' => esc_html__( 'Logs per page', 'advanced-form-integration' ), 'default' => 20, 'option' => 'adfoin_log_per_page' ); add_screen_option( $option, $args ); } /** * Screen Options tab for the integrations list page. WP renders * the tab automatically once the option is registered; users can * change per-page count and column visibility from there. The * value is read in Advanced_Form_Integration_List_Table::prepare_items * via $this->get_items_per_page(). * * Skipped on edit/duplicate sub-actions so the tab doesn't show * an irrelevant "per page" knob next to the form. */ public function adfoin_integrations_screen_options() { $action = isset( $_GET['action'] ) ? sanitize_text_field( wp_unslash( $_GET['action'] ) ) : ''; if ( '' !== $action && 'list' !== $action ) { return; } add_screen_option( 'per_page', array( 'label' => esc_html__( 'Integrations per page', 'advanced-form-integration' ), 'default' => 20, 'option' => 'adfoin_integrations_per_page', ) ); } public function enqueue_assets() { wp_enqueue_script( 'adfoin-vuejs' ); // Determine current page context $page = isset( $_GET['page'] ) ? sanitize_text_field( wp_unslash( $_GET['page'] ) ) : ''; $action = isset( $_GET['action'] ) ? sanitize_text_field( wp_unslash( $_GET['action'] ) ) : ''; // Shared Vue components (registered globally before the app boots) wp_enqueue_script( 'adfoin-searchable-select', ADVANCED_FORM_INTEGRATION_ASSETS . '/js/components/searchable-select.js', array( 'adfoin-vuejs' ), ADVANCED_FORM_INTEGRATION_VERSION, true ); // Always load core utilities wp_enqueue_script( 'adfoin-core', ADVANCED_FORM_INTEGRATION_ASSETS . '/js/core.js', array( 'adfoin-vuejs', 'adfoin-searchable-select' ), ADVANCED_FORM_INTEGRATION_VERSION, true ); // Load triggers and actions only on new/edit integration pages $needs_integration_scripts = ( $page === 'advanced-form-integration-new' || ( $page === 'advanced-form-integration' && $action === 'edit' ) ); if ( $needs_integration_scripts ) { // Version-stamp the editor scripts with their file mtime so an // updated triggers.js/app.js busts the browser cache automatically, // without waiting for a plugin version bump. $triggers_path = ADVANCED_FORM_INTEGRATION_PATH . '/assets/js/triggers.js'; $app_path = ADVANCED_FORM_INTEGRATION_PATH . '/assets/js/app.js'; $triggers_ver = ADVANCED_FORM_INTEGRATION_VERSION . '.' . ( file_exists( $triggers_path ) ? filemtime( $triggers_path ) : '0' ); $app_ver = ADVANCED_FORM_INTEGRATION_VERSION . '.' . ( file_exists( $app_path ) ? filemtime( $app_path ) : '0' ); // Load trigger components (always needed for new/edit) wp_enqueue_script( 'adfoin-triggers', ADVANCED_FORM_INTEGRATION_ASSETS . '/js/triggers.js', array( 'adfoin-core' ), $triggers_ver, true ); // Load Vue app initialization (handles lazy loading of action components) wp_enqueue_script( 'adfoin-app', ADVANCED_FORM_INTEGRATION_ASSETS . '/js/app.js', array( 'adfoin-triggers' ), $app_ver, true ); // Action components are now loaded one platform at a time from // platforms//-component.js when the user picks // an action provider. Triggered from app.js via // adfoinComponentLoader.loadPlatform(actionProviderId). } // Settings page: load the General-tab JS (platform filter + checkbox-row highlight). // Both behaviors no-op on tabs without the target elements, so it's safe to load // for the entire Settings screen rather than gating per tab. if ( $page === 'advanced-form-integration-settings' ) { wp_enqueue_script( 'adfoin-settings-general', ADVANCED_FORM_INTEGRATION_ASSETS . '/js/settings-general.js', array(), ADVANCED_FORM_INTEGRATION_VERSION, true ); wp_localize_script( 'adfoin-settings-general', 'adfoinSettingsGeneral', array( 'ajaxUrl' => admin_url( 'admin-ajax.php' ), 'testEmailNonce' => wp_create_nonce( 'adfoin_send_test_email' ), 'i18n' => array( 'sending' => __( 'Sending...', 'advanced-form-integration' ), 'testEmailError' => __( 'Failed to send test email.', 'advanced-form-integration' ), 'resetConfirm' => __( 'Reset all General Settings toggles to defaults? Platform activations will not be affected.', 'advanced-form-integration' ), ), ) ); } // Allow plugins to add custom scripts do_action( 'adfoin_custom_script' ); // For settings, log, and list pages - only load core (no action components needed) // This significantly reduces load time on these pages } /** * Display the Tasks page. * * @return void */ public function adfoin_routing() { require_once ADVANCED_FORM_INTEGRATION_INCLUDES . '/class-adfoin-list-table.php'; $action = isset( $_GET['action'] ) ? sanitize_key( wp_unslash( $_GET['action'] ) ) : 'list'; $id = isset( $_GET['id'] ) ? intval( wp_unslash( $_GET['id'] ) ) : 0; switch ( $action ) { case 'edit': $this->adfoin_edit( $id ); break; case 'duplicate': $this->adfoin_duplicate_integration($id); break; default: $this->adfoin_list_page() ; break; } } /* * This function generates the list of connections */ public function adfoin_list_page() { $list_table = new Advanced_Form_Integration_List_Table(); $list_table->prepare_items(); // ---- Admin notice for bulk-action redirects (?bulk_done=…) ---- if ( ! empty( $_GET['bulk_done'] ) ) { $bulk_done = sanitize_key( wp_unslash( $_GET['bulk_done'] ) ); $messages = array( 'activated' => __( 'Integrations activated.', 'advanced-form-integration' ), 'deactivated' => __( 'Integrations deactivated.', 'advanced-form-integration' ), 'activate' => __( 'Integrations activated.', 'advanced-form-integration' ), 'deactivate' => __( 'Integrations deactivated.', 'advanced-form-integration' ), 'duplicated' => __( 'Integration duplicated.', 'advanced-form-integration' ), 'deleted' => __( 'Integrations deleted.', 'advanced-form-integration' ), ); if ( isset( $messages[ $bulk_done ] ) ) { printf( '

%s

', esc_html( $messages[ $bulk_done ] ) ); } } // The duplicated row IDs come back as ?duplicated=12 or // ?duplicated=12,15,18 — JS picks them up and adds a // .afi-row-highlight class to the matching for a brief // fade-in effect. $highlight_ids = array(); if ( ! empty( $_GET['duplicated'] ) ) { $highlight_ids = array_filter( array_map( 'intval', explode( ',', sanitize_text_field( wp_unslash( $_GET['duplicated'] ) ) ) ) ); } ?>
views(); ?>
s in extra_tablenav() and don't need a // hidden field. if ( ! empty( $_GET['view'] ) ) { printf( '', esc_attr( sanitize_key( wp_unslash( $_GET['view'] ) ) ) ); } $list_table->search_box( __( 'Search Integrations', 'advanced-form-integration' ), 'adfoin-integration' ); $list_table->display(); ?>
adfoin_log_view( $id ); break; default: $this->adfoin_log_list_page() ; break; } } /* * Get Help Submenu View */ public function adfoin_get_help( $value = '' ) { include ADVANCED_FORM_INTEGRATION_VIEWS . '/get_help.php'; } /* * This function generates the list of connections */ public function adfoin_log_list_page() { $clear_nonce = wp_create_nonce( 'adfoin_clear_all_logs_nonce' ); ?>
prepare_items(); $list_table->search_box( __( 'Search Log', 'advanced-form-integration' ), 'afi-log-search' ); $list_table->views(); $list_table->display(); ?>
prefix . 'adfoin_log'; $wpdb->query( "TRUNCATE TABLE {$table}" ); advanced_form_integration_redirect( admin_url( 'admin.php?page=advanced-form-integration-log&cleared=1' ) ); exit; } /* * Handles log view */ public function adfoin_log_view( $id='' ) { if ( $id ) { require_once ADVANCED_FORM_INTEGRATION_VIEWS . '/view_log.php'; } } /* * Relation Status Change adfoin_status */ public function adfoin_duplicate_integration( $id = '' ) { // verify nonce if ( ! isset( $_GET['_wpnonce'] ) || ! wp_verify_nonce( wp_unslash( $_GET['_wpnonce'] ), 'adfoin_duplicate_integration_nonce' ) ) { wp_die( 'Security check' ); } // Shared duplication logic — see Advanced_Form_Integration_Integration::duplicate(). $new_id = ( new Advanced_Form_Integration_Integration() )->duplicate( $id ); // Carry the new ID + a "duplicated" flag back to the listing so the row // can highlight briefly and an admin notice can confirm the action. $redirect = admin_url( 'admin.php?page=advanced-form-integration' ); if ( $new_id ) { $redirect = add_query_arg( 'bulk_done', 'duplicated', $redirect ); $redirect = add_query_arg( 'duplicated', (int) $new_id, $redirect ); } advanced_form_integration_redirect( $redirect ); exit; } }