rest_url( 'wp-ai-workflows/v1' ), 'nonce' => wp_create_nonce( 'wp_rest' ), 'siteUrl' => get_site_url(), 'assetsUrl' => WP_AI_WORKFLOWS_PLUGIN_URL . 'assets', 'isViewer' => true, ) ); } if ( ! empty( $css_files ) ) { wp_register_style( 'wp-ai-workflows-viewer', WP_AI_WORKFLOWS_PLUGIN_URL . 'build/static/css/' . basename( $css_files[0] ), array(), WP_AI_WORKFLOWS_PRO_VERSION ); } } /** * Enqueue all necessary assets */ public function enqueue_assets() { if ( ! $this->script_loaded ) { // Enqueue React first wp_enqueue_script( 'react' ); wp_enqueue_script( 'react-dom' ); // Then enqueue our scripts wp_enqueue_script( 'wp-ai-workflows-viewer' ); wp_enqueue_style( 'wp-ai-workflows-viewer' ); $this->script_loaded = true; } } /** * Check if current device is mobile * * @return boolean True if mobile, false otherwise */ private function is_mobile() { // Check server-side if possible using User-Agent if ( isset( $_SERVER['HTTP_USER_AGENT'] ) ) { $user_agent = sanitize_text_field( wp_unslash( $_SERVER['HTTP_USER_AGENT'] ) ); if ( preg_match( '/(android|iphone|ipod|ipad|blackberry|webos|windows\s+phone)/i', $user_agent ) ) { return true; } } // We can't reliably detect all mobile devices server-side, // so we'll also use JS for client-side detection return false; } /** * Render the workflow preview shortcode * * @param array $atts Shortcode attributes * @return string HTML output */ public function render_workflow_preview( $atts ) { // Parse shortcode attributes $atts = shortcode_atts( array( 'id' => 0, // Workflow ID 'height' => '500px', // Height of the viewer 'dark_mode' => 'false', // Dark mode toggle 'show_minimap' => 'true', // Show minimap toggle 'show_controls' => 'true', // Show controls toggle 'nodes_draggable' => 'false', // Allow node dragging 'nodes_connectable' => 'false', // Allow node connecting 'elements_selectable' => 'false', // Allow element selection 'show_sidebar' => 'false', // Show simplified sidebar 'allow_pan_zoom' => 'true', // Allow pan and zoom 'show_toolbar' => 'false', // Show toolbar 'allow_download' => 'false', // Allow workflow download 'hide_on_mobile' => 'false', // Hide on mobile devices 'hide_powered_by' => 'false', // Hide powered by text 'overlay_text' => 'Click to Explore Workflow', // Text for the overlay ), $atts, 'wp_ai_workflow_preview' ); // Generate a unique ID for this instance $viewer_id = 'workflow-viewer-' . uniqid(); // Check for mobile and hide_on_mobile setting $hide_on_mobile = $atts['hide_on_mobile'] === 'true'; $is_mobile = $this->is_mobile(); // Mobile detection script that runs before any workflow data is loaded $mobile_detection_script = ''; $mobile_message = ''; if ( $hide_on_mobile ) { // Add a script to detect mobile devices on the client side $mobile_detection_script = ''; // Create mobile message $mobile_message = ''; } // If we're on mobile and hide_on_mobile is true, just return the mobile message if ( $is_mobile && $hide_on_mobile ) { return $mobile_detection_script . $mobile_message; } // Validate workflow ID if ( empty( $atts['id'] ) ) { return '
Invalid workflow ID
'; } // Get workflow data $workflow_data = $this->get_workflow_data( $atts['id'] ); if ( ! $workflow_data ) { return '
Workflow not found or not accessible
'; } // Enqueue necessary scripts and styles $this->enqueue_assets(); // Auto-enable toolbar if download is enabled if ( $atts['allow_download'] === 'true' && $atts['show_toolbar'] === 'false' ) { $atts['show_toolbar'] = 'true'; } // Convert string booleans to actual booleans for the config $config = array( 'workflowData' => $workflow_data, 'height' => esc_attr( $atts['height'] ), 'darkMode' => $atts['dark_mode'] === 'true', 'showMinimap' => $atts['show_minimap'] === 'true', 'showControls' => $atts['show_controls'] === 'true', 'nodesDraggable' => $atts['nodes_draggable'] === 'true', 'nodesConnectable' => $atts['nodes_connectable'] === 'true', 'elementsSelectable' => $atts['elements_selectable'] === 'true', 'showSidebar' => $atts['show_sidebar'] === 'true', 'allowPanZoom' => $atts['allow_pan_zoom'] === 'true', 'showToolbar' => $atts['show_toolbar'] === 'true', 'allowDownload' => $atts['allow_download'] === 'true', 'hideOnMobile' => $hide_on_mobile, 'hidePoweredBy' => $atts['hide_powered_by'] === 'true', 'overlayText' => esc_attr( $atts['overlay_text'] ), ); // Encode the config for the data attribute $encoded_config = base64_encode( wp_json_encode( $config ) ); // Conditional loading script - only load workflow data if not on mobile $conditional_loading_script = ''; if ( $hide_on_mobile ) { $conditional_loading_script = ''; } else { // If hide_on_mobile is false, always initialize $conditional_loading_script = ''; } // Return container HTML with proper styling and conditional loading $output = $mobile_detection_script . $mobile_message; $output .= sprintf( '
Loading workflow preview...
', esc_attr( $viewer_id ), esc_attr( $atts['id'] ), esc_attr( $encoded_config ), esc_attr( $atts['height'] ) ); $output .= $conditional_loading_script; return $output; } /** * Get workflow data from the options table * * @param string $workflow_id The workflow ID * @return array|null Workflow data or null if not found */ private function get_workflow_data( $workflow_id ) { // Get workflow using DBAL $workflow = WP_AI_Workflows_Workflow_DBAL::get_workflow_by_id( $workflow_id ); if ( ! $workflow ) { WP_AI_Workflows_Utilities::debug_log( 'Workflow not found', 'error', array( 'workflow_id' => $workflow_id, ) ); return null; } return $workflow; } }