PluginProbe
SellKit – Funnel builder and checkout optimizer for WooCommerce to sell more, faster / 2.3.0
SellKit – Funnel builder and checkout optimizer for WooCommerce to sell more, faster v2.3.0
2.6.0 trunk 1.1.0 1.1.4 1.2.1 1.2.2 1.2.3 1.2.5 1.2.9 1.3.1 1.3.2 1.5.0 1.5.1 1.5.4 1.5.7 1.5.8 1.5.9 1.6.2 1.6.5 1.6.8 1.7.2 1.7.4 1.7.5 1.7.9 1.8.1 All 42 releases
sellkit / includes / funnel / class.php

class.php in SellKit – Funnel builder and checkout optimizer for WooCommerce to sell more, faster 2.3.0, at includes/funnel/class.php

448 lines 11.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 use Elementor\Utils as ElementorUtils;
4 use Sellkit\Global_Checkout\Checkout as Global_Checkout;
5
6 defined( 'ABSPATH' ) || die();
7
8 /**
9 * Class Sellkit_Funnel
10 *
11 * @since 1.1.0
12 * @SuppressWarnings(PHPMD.ExcessiveClassComplexity)
13 * @SuppressWarnings(PHPMD.NPathComplexity)
14 */
15 class Sellkit_Funnel {
16
17 /**
18 * Funnel Id.
19 *
20 * @var integer Funnel Id.
21 * @since 1.1.0
22 */
23 public $funnel_id;
24
25 /**
26 * Next step data.
27 *
28 * @var array $next_step_data.
29 * @since 1.1.0
30 */
31 public $next_step_data;
32
33 /**
34 * Next no step data.
35 *
36 * @var array $next_no_step_data.
37 * @since 1.5.0
38 */
39 public $next_no_step_data;
40
41 /**
42 * Ending node step data.
43 *
44 * @var array $end_node_step_data.
45 * @since 1.5.0
46 */
47 public $end_node_step_data;
48
49 /**
50 * The current step data.
51 *
52 * @var array $current_step_data.
53 * @since 1.1.0
54 */
55 public $current_step_data;
56
57 /**
58 * The class instance.
59 *
60 * @var Object Class instance.
61 * @since 1.1.0
62 */
63 public static $instance = null;
64
65 /**
66 * Sellkit_Funnel constructor.
67 *
68 * @param string $page_id Page Id.
69 * @since 1.1.0
70 */
71 public function __construct( $page_id = null ) {
72 $this->order_customization();
73
74 if ( null === $page_id ) {
75 $page_id = self::get_page_id();
76 }
77
78 if ( empty( $page_id ) ) {
79 $page_id = $this->get_funnel_step_homepage_id();
80
81 if ( empty( $page_id ) ) {
82 return;
83 }
84 }
85
86 $this->set_funnel_data( $page_id );
87
88 if ( empty( $this->funnel_id ) ) {
89 return;
90 }
91
92 add_action( 'wp_enqueue_scripts', [ $this, 'enqueue_funnel_frontend_script' ] );
93 }
94
95 /**
96 * Gets funnel step homepage id.
97 *
98 * @since 1.9.6
99 * @return int|bool
100 */
101 private function get_funnel_step_homepage_id() {
102 if ( is_admin() ) {
103 return false;
104 }
105
106 $front_page_id = get_option( 'page_on_front', 0 );
107
108 if ( empty( $front_page_id ) ) {
109 return false;
110 }
111
112 $scheme = ( ! empty( $_SERVER['HTTPS'] ) && 'off' !== $_SERVER['HTTPS'] ) ? 'https' : 'http';
113
114 $host = sanitize_text_field( wp_unslash( $_SERVER['HTTP_HOST'] ) ); // phpcs:ignore
115 $request_uri = esc_url_raw( wp_unslash( $_SERVER['REQUEST_URI'] ) ); // phpcs:ignore
116
117 $url = esc_url( "$scheme://$host$request_uri" );
118 $home_url = get_home_url() . '/';
119
120 if ( '/' !== substr( $url, -1 ) ) {
121 $home_url = get_home_url();
122 }
123
124 if ( $home_url !== $url ) {
125 return false;
126 }
127
128 $post_id = url_to_postid( $url );
129
130 if ( empty( $post_id ) ) {
131 return false;
132 }
133
134 $post_type = get_post_type( $post_id );
135 $status = Funnel_Homepage::check_funnel_step_status( $post_id, $post_type );
136
137 if ( $status && intval( $post_id ) === intval( $front_page_id ) ) {
138 return $front_page_id;
139 }
140
141 return false;
142 }
143
144 /**
145 * Class Instance.
146 *
147 * @since 1.1.0
148 * @return Sellkit_Funnel|null
149 */
150 public static function get_instance() {
151 if ( null === self::$instance ) {
152 self::$instance = new self();
153 }
154
155 return self::$instance;
156 }
157
158 /**
159 * Gets funnel if the page is step otherwise do nothing.
160 *
161 * @since 1.1.0
162 * @return void
163 * @param string $page_id Page id.
164 */
165 public function set_funnel_data( $page_id ) {
166 $this->current_step_data = get_post_meta( $page_id, 'step_data', true );
167
168 if ( empty( $this->current_step_data['funnel_id'] ) ) {
169 return;
170 }
171
172 $is_nofollow = sellkit_get_option( 'disallow_funnels_from_search_engine' );
173
174 if ( true === (bool) $is_nofollow ) {
175 add_action( 'wp_head', function () {
176 echo '<meta name="robots" content="noindex" />';
177 } );
178 }
179
180 $funnel_data = (array) get_post_meta( $this->current_step_data['funnel_id'], 'nodes', true );
181 $is_flowchart = true;
182
183 if ( empty( $funnel_data ) ) {
184 $funnel_data = get_post_meta( $this->current_step_data['funnel_id'], 'sellkit_steps', true );
185 $is_flowchart = false;
186 }
187
188 $this->funnel_id = $this->current_step_data['funnel_id'];
189
190 if ( false === $is_flowchart ) {
191 $this->next_step_data = ! empty( $funnel_data[ $this->current_step_data['number'] + 1 ] ) ? $funnel_data[ $this->current_step_data['number'] + 1 ] : false;
192 }
193
194 if (
195 true === $is_flowchart &&
196 ! empty( $this->current_step_data['targets'] ) &&
197 ! empty( $funnel_data[ $this->current_step_data['targets'][0]['nodeId'] ] )
198 ) {
199 $this->next_step_data = 'none' !== $funnel_data[ $this->current_step_data['targets'][0]['nodeId'] ] ? $funnel_data[ $this->current_step_data['targets'][0]['nodeId'] ] : false;
200 }
201
202 if ( true === $is_flowchart && ! empty( $this->current_step_data['targets'][1]['nodeId'] ) ) {
203 $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;
204 }
205
206 $end_node_id = $this->get_end_node_id( $funnel_data );
207
208 if ( ! empty( $end_node_id ) ) {
209 $this->end_node_step_data = $funnel_data[ $end_node_id ];
210 }
211 }
212
213 /**
214 * Enqueue funnel frontend scripts.
215 *
216 * @since 1.1.0
217 * @return void
218 */
219 public function enqueue_funnel_frontend_script() {
220 $suffix = defined( 'WP_DEBUG' ) && WP_DEBUG ? '' : '.min';
221
222 wp_enqueue_script(
223 'funnel-frontend',
224 sellkit()->plugin_url() . 'assets/dist/js/funnel-frontend' . $suffix . '.js',
225 [ 'jquery', 'wp-util' ],
226 sellkit()->version(),
227 true
228 );
229
230 wp_localize_script( 'funnel-frontend', 'funnel', $this->get_localize_data() );
231
232 if ( empty( sellkit_get_option( 'google_analytics' ) ) && empty( sellkit_get_option( 'facebook_pixel' ) ) ) {
233 return;
234 }
235
236 wp_enqueue_script(
237 'funnel-settings-variables',
238 sellkit()->plugin_url() . 'assets/dist/js/funnel-settings-variables' . $suffix . '.js',
239 [ 'jquery', 'wp-util' ],
240 sellkit()->version(),
241 true
242 );
243 }
244
245 /**
246 * Get localize data.
247 *
248 * @return array
249 */
250 public function get_localize_data() {
251 if ( ! empty( $this->next_step_data['page_id'] ) ) {
252 $next_step_link = ! empty( $this->next_step_data['page_id'] ) ? get_the_permalink( $this->next_step_data['page_id'] ) : '';
253
254 if ( empty( $next_step_link ) ) {
255 $next_step_link = add_query_arg( [
256 'post_type' => Sellkit_Admin_Steps::SELLKIT_STEP_POST_TYPE,
257 'p' => $this->next_step_data['page_id'],
258 ], site_url() );
259 }
260 }
261
262 return [
263 'currentStep' => $this->current_step_data,
264 'nextStep' => $this->next_step_data,
265 'nextStepLink' => ! empty( $next_step_link ) ? $next_step_link : '',
266 'siteUrl' => site_url(),
267 ];
268 }
269
270 /**
271 * Gets page id.
272 *
273 * @since 1.1.0
274 * @return false|int
275 * @SuppressWarnings(PHPMD.NPathComplexity)
276 */
277 public static function get_page_id() {
278 $page_id = sellkit_htmlspecialchars( INPUT_POST, 'sellkit_current_page_id' );
279 $structure = get_option( 'permalink_structure' );
280 $post_data = filter_input( INPUT_POST, 'post_data', FILTER_DEFAULT );
281
282 if ( ! empty( $post_data ) ) {
283 parse_str( $post_data, $post_data );
284
285 if ( ! empty( $post_data['sellkit_current_page_id'] ) ) {
286 return (int) $post_data['sellkit_current_page_id'];
287 }
288 }
289
290 if ( is_numeric( $page_id ) ) {
291 return $page_id;
292 }
293
294 $current_url = esc_url_raw( remove_query_arg( 'order-key' ) );
295
296 if ( ! empty( $structure ) ) {
297 $current_url = self::get_base_url( $current_url );
298 }
299
300 if ( empty( strpos( $current_url, Funnel_Redirect::$step_base ) ) && ! empty( get_option( 'rewrite_rules' ) ) ) {
301 return false;
302 }
303
304 if ( empty( $current_url ) ) {
305 return false;
306 }
307
308 $page_id = sellkit_htmlspecialchars( INPUT_GET, 'p' );
309 $page_slug = sellkit_htmlspecialchars( INPUT_GET, 'sellkit_step' );
310 $page = get_page_by_path( basename( untrailingslashit( $current_url ) ), null, 'sellkit_step' );
311
312 if ( empty( $page ) && ! empty( $page_slug ) ) {
313 $page = get_page_by_path( sanitize_text_field( $page_slug ), null, 'sellkit_step' );
314 }
315
316 if ( empty( $page ) && empty( $page_id ) ) {
317 return false;
318 }
319
320 if ( ! empty( $page_id ) && 'sellkit_step' === get_post_type( $page_id ) ) {
321 return $page_id;
322 }
323
324 if ( empty( $page->ID ) ) {
325 return false;
326 }
327
328 return $page->ID;
329 }
330
331 /**
332 * Gets main url.
333 *
334 * @since 1.5.4
335 * @param string $url Url.
336 * @return string
337 */
338 private static function get_base_url( $url ) {
339 $parsed = wp_parse_url( $url );
340
341 if ( empty( $parsed['query'] ) ) {
342 return $url;
343 }
344
345 return explode( '?', $url )[0];
346 }
347
348 /**
349 * Customization order pages in admin area.
350 *
351 * @since 1.1.0
352 */
353 public function order_customization() {
354 if ( ! is_admin() ) {
355 return;
356 }
357
358 // Orders filters.
359 add_filter( 'woocommerce_get_formatted_order_total', [ $this, 'add_order_type' ], 10, 2 );
360 add_action( 'woocommerce_admin_order_data_after_order_details', [ $this, 'show_linked_orders' ], 10, 1 );
361 }
362
363 /**
364 * Adding order type to order list table.
365 *
366 * @since 1.1.0
367 * @return string
368 * @param string $formatted_total formatted total price.
369 * @param object $order Order object.
370 */
371 public function add_order_type( $formatted_total, $order ) {
372 $screen = get_current_screen();
373 $is_upsell = $order->get_meta( 'sellkit_main_order_id' );
374
375 if ( ! $screen || 'edit' !== $screen->base || 'shop_order' !== $screen->post_type ) {
376 return $formatted_total;
377 }
378
379 if ( is_numeric( $is_upsell ) ) {
380 $formatted_total .= '<div><span>' . esc_html__( 'Sellkit Upsell', 'sellkit' ) . '</span></div>';
381 }
382
383 return $formatted_total;
384 }
385
386 /**
387 * Show the related between orders.
388 *
389 * @since 1.1.0
390 * @param object $order Order object.
391 */
392 public function show_linked_orders( $order ) {
393 $upsell_order_id = $order->get_meta( 'sellkit_upsell_order_id' );
394 $main_order_id = $order->get_meta( 'sellkit_main_order_id' );
395
396 if ( is_numeric( $main_order_id ) ) {
397 $parent_order = wc_get_order( $main_order_id );
398 $order_number = $parent_order->get_order_number();
399 $parent_order_html = sprintf( '<p class="form-field form-field-wide" style= "margin-top: 20px;"><strong>%s: </strong>', esc_html__( 'SellKit Parent Order', 'sellkit' ) );
400 $parent_order_html .= sprintf( '<span style= "display: block;"><a href="%1s"><strong>#%2s</strong></a></span>', get_edit_post_link( $main_order_id ), esc_attr( $order_number ) );
401 $parent_order_html .= '</p>';
402
403 echo wp_kses_post( $parent_order_html );
404 }
405
406 if ( is_numeric( $upsell_order_id ) ) {
407 $upsell_order = wc_get_order( $upsell_order_id );
408 $order_number = $upsell_order->get_order_number();
409 $upsell_order_html = sprintf( '<p class="form-field form-field-wide" style= "margin-top: 20px;"><strong>%s: </strong>', esc_html__( 'SellKit Upsell Order', 'sellkit' ) );
410 $upsell_order_html .= sprintf( '<span style= "display: block;"><a href="%1s"><strong>#%2s</strong></a></span>', get_edit_post_link( $upsell_order_id ), esc_attr( $order_number ) );
411 $upsell_order_html .= '</p>';
412
413 echo wp_kses_post( $upsell_order_html );
414 }
415 }
416
417 /**
418 * Gets end node.
419 *
420 * @since 1.5.0
421 * @param array $funnels Funnels array.
422 */
423 public function get_end_node_id( $funnels ) {
424 $funnels = (array) $funnels;
425
426 foreach ( $funnels as $key => $funnel ) {
427 if ( ! empty( $funnel['origin_node'] ) && 'last-node' === $funnel['origin_node'] ) {
428 return $key;
429 }
430 }
431
432 return false;
433 }
434 }
435
436 if ( ! function_exists( 'sellkit_funnel' ) ) {
437 /**
438 * Sellkit funnel wrapper.
439 *
440 * @since 1.1.0
441 * @return Object|Sellkit_Funnel|null
442 */
443 function sellkit_funnel() {
444 return Sellkit_Funnel::get_instance();
445 }
446 }
447
448