order_customization(); if ( null === $page_id ) { $page_id = self::get_page_id(); } if ( empty( $page_id ) ) { $page_id = $this->get_funnel_step_homepage_id(); if ( empty( $page_id ) ) { return; } } $this->set_funnel_data( $page_id ); if ( empty( $this->funnel_id ) ) { return; } add_action( 'wp_enqueue_scripts', [ $this, 'enqueue_funnel_frontend_script' ] ); } /** * Gets funnel step homepage id. * * @since 1.9.6 * @return int|bool */ private function get_funnel_step_homepage_id() { if ( is_admin() ) { return false; } $front_page_id = get_option( 'page_on_front', 0 ); if ( empty( $front_page_id ) ) { return false; } $scheme = ( ! empty( $_SERVER['HTTPS'] ) && 'off' !== $_SERVER['HTTPS'] ) ? 'https' : 'http'; $host = sanitize_text_field( wp_unslash( $_SERVER['HTTP_HOST'] ) ); // phpcs:ignore $request_uri = esc_url_raw( wp_unslash( $_SERVER['REQUEST_URI'] ) ); // phpcs:ignore $url = esc_url( "$scheme://$host$request_uri" ); $home_url = get_home_url() . '/'; if ( '/' !== substr( $url, -1 ) ) { $home_url = get_home_url(); } if ( $home_url !== $url ) { return false; } $post_id = url_to_postid( $url ); if ( empty( $post_id ) ) { return false; } $post_type = get_post_type( $post_id ); $status = Funnel_Homepage::check_funnel_step_status( $post_id, $post_type ); if ( $status && intval( $post_id ) === intval( $front_page_id ) ) { return $front_page_id; } return false; } /** * Class Instance. * * @since 1.1.0 * @return Sellkit_Funnel|null */ public static function get_instance() { if ( null === self::$instance ) { self::$instance = new self(); } return self::$instance; } /** * Gets funnel if the page is step otherwise do nothing. * * @since 1.1.0 * @return void * @param string $page_id Page id. */ public function set_funnel_data( $page_id ) { $this->current_step_data = get_post_meta( $page_id, 'step_data', true ); if ( empty( $this->current_step_data['funnel_id'] ) ) { return; } $is_nofollow = sellkit_get_option( 'disallow_funnels_from_search_engine' ); if ( true === (bool) $is_nofollow ) { add_action( 'wp_head', function () { echo ''; } ); } $funnel_data = (array) get_post_meta( $this->current_step_data['funnel_id'], 'nodes', true ); $is_flowchart = true; if ( empty( $funnel_data ) ) { $funnel_data = get_post_meta( $this->current_step_data['funnel_id'], 'sellkit_steps', true ); $is_flowchart = false; } $this->funnel_id = $this->current_step_data['funnel_id']; if ( false === $is_flowchart ) { $this->next_step_data = ! empty( $funnel_data[ $this->current_step_data['number'] + 1 ] ) ? $funnel_data[ $this->current_step_data['number'] + 1 ] : false; } if ( true === $is_flowchart && ! empty( $this->current_step_data['targets'] ) && ! empty( $funnel_data[ $this->current_step_data['targets'][0]['nodeId'] ] ) ) { $this->next_step_data = 'none' !== $funnel_data[ $this->current_step_data['targets'][0]['nodeId'] ] ? $funnel_data[ $this->current_step_data['targets'][0]['nodeId'] ] : false; } if ( true === $is_flowchart && ! empty( $this->current_step_data['targets'][1]['nodeId'] ) ) { $this->next_no_step_data = ! empty( $funnel_data[ $this->current_step_data['targets'][1]['nodeId'] ] ) ? $funnel_data[ $this->current_step_data['targets'][1]['nodeId'] ] : false; } $end_node_id = $this->get_end_node_id( $funnel_data ); if ( ! empty( $end_node_id ) ) { $this->end_node_step_data = $funnel_data[ $end_node_id ]; } } /** * Enqueue funnel frontend scripts. * * @since 1.1.0 * @return void */ public function enqueue_funnel_frontend_script() { $suffix = defined( 'WP_DEBUG' ) && WP_DEBUG ? '' : '.min'; wp_enqueue_script( 'funnel-frontend', sellkit()->plugin_url() . 'assets/dist/js/funnel-frontend' . $suffix . '.js', [ 'jquery', 'wp-util' ], sellkit()->version(), true ); wp_localize_script( 'funnel-frontend', 'funnel', $this->get_localize_data() ); if ( empty( sellkit_get_option( 'google_analytics' ) ) && empty( sellkit_get_option( 'facebook_pixel' ) ) ) { return; } wp_enqueue_script( 'funnel-settings-variables', sellkit()->plugin_url() . 'assets/dist/js/funnel-settings-variables' . $suffix . '.js', [ 'jquery', 'wp-util' ], sellkit()->version(), true ); } /** * Get localize data. * * @return array */ public function get_localize_data() { if ( ! empty( $this->next_step_data['page_id'] ) ) { $next_step_link = ! empty( $this->next_step_data['page_id'] ) ? get_the_permalink( $this->next_step_data['page_id'] ) : ''; if ( empty( $next_step_link ) ) { $next_step_link = add_query_arg( [ 'post_type' => Sellkit_Admin_Steps::SELLKIT_STEP_POST_TYPE, 'p' => $this->next_step_data['page_id'], ], site_url() ); } } return [ 'currentStep' => $this->current_step_data, 'nextStep' => $this->next_step_data, 'nextStepLink' => ! empty( $next_step_link ) ? $next_step_link : '', 'siteUrl' => site_url(), ]; } /** * Gets page id. * * @since 1.1.0 * @return false|int * @SuppressWarnings(PHPMD.NPathComplexity) */ public static function get_page_id() { $page_id = sellkit_htmlspecialchars( INPUT_POST, 'sellkit_current_page_id' ); $structure = get_option( 'permalink_structure' ); $post_data = filter_input( INPUT_POST, 'post_data', FILTER_DEFAULT ); if ( ! empty( $post_data ) ) { parse_str( $post_data, $post_data ); if ( ! empty( $post_data['sellkit_current_page_id'] ) ) { return (int) $post_data['sellkit_current_page_id']; } } if ( is_numeric( $page_id ) ) { return $page_id; } // Stripe Express Checkout (and similar express flows) POST to wc-ajax=checkout // without SellKit's hidden fields. Fall back to the checkout step id stored in // the WC session when the user first landed on the funnel checkout page so we // can still resolve the funnel context on the server side. The stored value is // only trusted when recent, to avoid reusing stale ids from older visits. if ( wp_doing_ajax() && function_exists( 'WC' ) && is_object( WC()->session ) ) { $session_page_id = (int) WC()->session->get( 'sellkit_current_page_id' ); $session_time = (int) WC()->session->get( 'sellkit_current_page_id_time' ); if ( $session_page_id > 0 && ( time() - $session_time ) < HOUR_IN_SECONDS ) { return $session_page_id; } } $current_url = esc_url_raw( remove_query_arg( 'order-key' ) ); if ( ! empty( $structure ) ) { $current_url = self::get_base_url( $current_url ); } if ( empty( strpos( $current_url, Funnel_Redirect::$step_base ) ) && ! empty( get_option( 'rewrite_rules' ) ) ) { return false; } if ( empty( $current_url ) ) { return false; } $page_id = sellkit_htmlspecialchars( INPUT_GET, 'p' ); $page_slug = sellkit_htmlspecialchars( INPUT_GET, 'sellkit_step' ); $page = get_page_by_path( basename( untrailingslashit( $current_url ) ), null, 'sellkit_step' ); if ( empty( $page ) && ! empty( $page_slug ) ) { $page = get_page_by_path( sanitize_text_field( $page_slug ), null, 'sellkit_step' ); } if ( empty( $page ) && empty( $page_id ) ) { return false; } if ( ! empty( $page_id ) && 'sellkit_step' === get_post_type( $page_id ) ) { return $page_id; } if ( empty( $page->ID ) ) { return false; } return $page->ID; } /** * Gets main url. * * @since 1.5.4 * @param string $url Url. * @return string */ private static function get_base_url( $url ) { $parsed = wp_parse_url( $url ); if ( empty( $parsed['query'] ) ) { return $url; } return explode( '?', $url )[0]; } /** * Customization order pages in admin area. * * @since 1.1.0 */ public function order_customization() { if ( ! is_admin() ) { return; } // Orders filters. add_filter( 'woocommerce_get_formatted_order_total', [ $this, 'add_order_type' ], 10, 2 ); add_action( 'woocommerce_admin_order_data_after_order_details', [ $this, 'show_linked_orders' ], 10, 1 ); } /** * Adding order type to order list table. * * @since 1.1.0 * @return string * @param string $formatted_total formatted total price. * @param object $order Order object. */ public function add_order_type( $formatted_total, $order ) { $screen = get_current_screen(); $is_upsell = $order->get_meta( 'sellkit_main_order_id' ); if ( ! $screen || 'edit' !== $screen->base || 'shop_order' !== $screen->post_type ) { return $formatted_total; } if ( is_numeric( $is_upsell ) ) { $formatted_total .= '
' . esc_html__( 'Sellkit Upsell', 'sellkit' ) . '
'; } return $formatted_total; } /** * Show the related between orders. * * @since 1.1.0 * @param object $order Order object. */ public function show_linked_orders( $order ) { $upsell_order_id = $order->get_meta( 'sellkit_upsell_order_id' ); $main_order_id = $order->get_meta( 'sellkit_main_order_id' ); if ( is_numeric( $main_order_id ) ) { $parent_order = wc_get_order( $main_order_id ); $order_number = $parent_order->get_order_number(); $parent_order_html = sprintf( '

%s: ', esc_html__( 'SellKit Parent Order', 'sellkit' ) ); $parent_order_html .= sprintf( '#%2s', get_edit_post_link( $main_order_id ), esc_attr( $order_number ) ); $parent_order_html .= '

'; echo wp_kses_post( $parent_order_html ); } if ( is_numeric( $upsell_order_id ) ) { $upsell_order = wc_get_order( $upsell_order_id ); $order_number = $upsell_order->get_order_number(); $upsell_order_html = sprintf( '

%s: ', esc_html__( 'SellKit Upsell Order', 'sellkit' ) ); $upsell_order_html .= sprintf( '#%2s', get_edit_post_link( $upsell_order_id ), esc_attr( $order_number ) ); $upsell_order_html .= '

'; echo wp_kses_post( $upsell_order_html ); } } /** * Gets end node. * * @since 1.5.0 * @param array $funnels Funnels array. */ public function get_end_node_id( $funnels ) { $funnels = (array) $funnels; foreach ( $funnels as $key => $funnel ) { if ( ! empty( $funnel['origin_node'] ) && 'last-node' === $funnel['origin_node'] ) { return $key; } } return false; } } if ( ! function_exists( 'sellkit_funnel' ) ) { /** * Sellkit funnel wrapper. * * @since 1.1.0 * @return Object|Sellkit_Funnel|null */ function sellkit_funnel() { return Sellkit_Funnel::get_instance(); } }