PluginProbe
SellKit – Funnel builder and checkout optimizer for WooCommerce to sell more, faster / 2.7.0
SellKit – Funnel builder and checkout optimizer for WooCommerce to sell more, faster v2.7.0
2.7.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 All 43 releases
← All changes | includes/admin/class-steps.php +184 -19 1.3.22.7.0 View file →
@@ -5,8 +5,10 @@
5 5 /**
6 6 * Steps class.
7 7 *
8 8 * @since 1.1.0
9 + * @SuppressWarnings(PHPMD.ExcessiveClassComplexity)
10 + * @SuppressWarnings(PHPMD.CyclomaticComplexity)
9 11 */
10 12 class Sellkit_Admin_Steps {
11 13
12 14 /**
@@ -57,11 +59,35 @@
57 59 add_filter( 'template_include', [ $this, 'load_page_template' ], 10 );
58 60 add_action( 'wp_ajax_sellkit_steps_get_coupons', [ $this, 'get_coupons' ] );
59 61 add_action( 'wp_loaded', [ $this, 'sellkit_steps_flush_rules' ] );
60 62 add_action( 'sellkit_after_toggle_status_sellkit-funnels', [ $this, 'update_steps_post_status' ], 10, 2 );
63 + add_action( 'sellkit_funnels_after_delete_posts_sellkit-funnels', [ $this, 'remove_steps_pages' ], 10, 1 );
64 +
65 + add_action( 'wp_loaded', [ $this, 'sellkit_set_sellkit_translation_mode' ] );
61 66 }
62 67
63 68 /**
69 + * Removes steps pages.
70 + *
71 + * @since 1.5.4
72 + * @return void
73 + * @param array $post Posts.
74 + */
75 + public function remove_steps_pages( $post ) {
76 + $nodes = get_post_meta( $post['ID'], 'nodes' );
77 +
78 + if ( empty( $nodes[0] ) ) {
79 + return;
80 + }
81 +
82 + foreach ( $nodes[0] as $node ) {
83 + if ( isset( $node['page_id'] ) ) {
84 + wp_delete_post( $node['page_id'] );
85 + }
86 + }
87 + }
88 +
89 + /**
64 90 * Get default funnels.
65 91 *
66 92 * @since 1.1.0
67 93 */
@@ -69,9 +95,13 @@
69 95 return [
70 96 'sales-page' => esc_html__( 'Sales Page', 'sellkit' ),
71 97 'checkout' => esc_html__( 'Checkout', 'sellkit' ),
72 98 'thankyou' => esc_html__( 'Thank You', 'sellkit' ),
99 + 'decision' => esc_html__( 'Condition', 'sellkit' ),
73 100 'upsell' => esc_html__( 'Upsell', 'sellkit' ),
101 + 'downsell' => esc_html__( 'Downsell', 'sellkit' ),
102 + 'optin-confirmation' => esc_html__( 'Opt-in Confirmation', 'sellkit' ),
103 + 'optin' => esc_html__( 'Opt-in', 'sellkit' ),
74 104 ];
75 105 }
76 106
77 107 /**
@@ -85,9 +115,17 @@
85 115 foreach ( $steps as $step_number => $step ) {
86 116 $step['funnel_id'] = $funnel_id;
87 117 $step['number'] = $step_number;
88 118
89 - update_post_meta( $step['page_id'], 'step_data', $step );
119 + if ( array_key_exists( 'page_id', $step ) ) {
120 + $translated_step = apply_filters( 'wpml_object_id', $step['page_id'], 'sellkit_step', true ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- WPML API.
121 +
122 + if ( $step['page_id'] !== $translated_step ) {
123 + update_post_meta( $translated_step, 'step_data', $step );
124 + }
125 +
126 + update_post_meta( $step['page_id'], 'step_data', $step );
127 + }
90 128 }
91 129 }
92 130
93 131 /**
@@ -187,9 +225,9 @@
187 225 wp_send_json_error( __( 'Please install and activate WooCommerce.', 'sellkit' ) );
188 226 }
189 227
190 228 if ( empty( $products_id ) ) {
191 - wp_send_json_error( __( 'Please send some product ids' ) );
229 + wp_send_json_error( __( 'Please send some product ids', 'sellkit' ) );
192 230 }
193 231
194 232 $products_id = is_array( $products_id ) ? $products_id : [ $products_id ];
195 233
@@ -196,12 +234,17 @@
196 234 foreach ( $products_id as $product_id ) {
197 235 $product = wc_get_product( $product_id );
198 236
199 237 if ( empty( $product ) ) {
200 - wp_send_json_error( __( 'Product does not exist', 'sellkit' ) );
201 238 continue;
202 239 }
203 240
241 + $data = $product->get_data();
242 +
243 + if ( 'trash' === $data['status'] ) {
244 + continue;
245 + }
246 +
204 247 $attributes = $product->get_attributes();
205 248 $label = $product->get_title();
206 249
207 250 if ( $product->get_type() === 'variation' ) {
@@ -226,37 +269,118 @@
226 269 * Filter step data before saving.
227 270 *
228 271 * @since 1.1.0
229 272 * @param string $post_id Post id.
273 + * @SuppressWarnings(PHPMD.NPathComplexity)
230 274 */
231 275 public function after_create_step_callback( $post_id ) {
232 - $steps = get_post_meta( $post_id, 'sellkit_steps', true );
233 - $last_step = end( $steps );
276 + $sub_action_data = sellkit_post( 'sub_action_data' );
277 + $origin_node = isset( $sub_action_data['origin_node'] ) ? $sub_action_data['origin_node'] : '';
278 + $target_node = ! empty( $sub_action_data['target_node'] ) ? $sub_action_data['target_node'] : null;
279 + $target_index = isset( $sub_action_data['target_index'] ) ? $sub_action_data['target_index'] : 0;
280 + $nodes = get_post_meta( $post_id, 'nodes', true );
281 + $last_node = end( $nodes );
234 282
235 - array_pop( $steps );
283 + array_pop( $nodes );
236 284
237 - $new_step_id = wp_insert_post( [
285 + $new_node_id = wp_insert_post( [
238 286 'post_type' => self::SELLKIT_STEP_POST_TYPE,
239 - 'post_title' => $last_step['title'],
240 - 'post_name' => sanitize_title( $last_step['title'] ),
287 + 'post_title' => $last_node['title'],
288 + 'post_name' => sanitize_title( $last_node['title'] ),
241 289 'post_status' => 'publish',
242 290 ] );
243 291
244 - $last_step['page_id'] = $new_step_id;
245 - $last_step['slug'] = get_post_field( 'post_name', $new_step_id );
292 + $current_target = [ 'nodeId' => $target_node ];
293 + $last_node['page_id'] = $new_node_id;
294 + $last_node['slug'] = get_post_field( 'post_name', $new_node_id );
295 + $last_node['targets'] = ! is_null( $target_node ) ? [ $current_target ] : [];
246 296
247 - $step_data = $last_step;
248 - $step_data['funnel_id'] = $post_id;
249 - $step_data['number'] = count( $steps );
297 + if (
298 + 'decision' === $last_node['type']['key'] && ! is_null( $target_node ) ||
299 + 'upsell' === $last_node['type']['key'] && ! is_null( $target_node ) ||
300 + 'downsell' === $last_node['type']['key'] && ! is_null( $target_node )
301 + ) {
302 + $last_node['targets'] = [
303 + $current_target,
304 + $current_target
305 + ];
306 + }
250 307
251 - update_post_meta( $new_step_id, 'step_data', $step_data );
308 + // Adding current target info the the step.
309 + $last_node['current_target_index'] = $target_index;
252 310
253 - $new_steps = array_merge( $steps, [ $last_step ] );
311 + if ( 'last-node' === $origin_node ) {
312 + $first_end_path_node_key = self::get_first_end_path_node_key( $nodes );
313 + $last_node['origin_node'] = 'last-node';
254 314
255 - update_post_meta( $post_id, 'sellkit_steps', $new_steps );
315 + if ( $first_end_path_node_key ) {
316 + unset( $nodes[ $first_end_path_node_key ]['origin_node'] );
317 + }
318 + }
319 +
320 + $node_data = $last_node;
321 + $node_data['funnel_id'] = $post_id;
322 + $node_data['number'] = count( $nodes );
323 +
324 + update_post_meta( $new_node_id, 'step_data', $node_data );// it should be updated.
325 +
326 + $old_node_keys = array_keys( $nodes );
327 + $nodes[ end( $old_node_keys ) + 1 ] = $last_node;
328 + $keys = array_keys( $nodes );
329 +
330 + if (
331 + 'last-node' !== $origin_node && ! empty( $nodes[ $origin_node ] ) &&
332 + 'decision' !== $nodes[ $origin_node ]['type']['key'] &&
333 + 'upsell' !== $nodes[ $origin_node ]['type']['key'] &&
334 + 'downsell' !== $nodes[ $origin_node ]['type']['key']
335 + ) {
336 + $nodes[ $origin_node ]['targets'] = [ [ 'nodeId' => strval( end( $keys ) ) ] ];
337 + }
338 +
339 + if (
340 + 'last-node' !== $origin_node && isset( $nodes[ $origin_node ]['type'] ) &&
341 + (
342 + 'decision' === $nodes[ $origin_node ]['type']['key'] ||
343 + 'upsell' === $nodes[ $origin_node ]['type']['key'] ||
344 + 'downsell' === $nodes[ $origin_node ]['type']['key']
345 + )
346 + ) {
347 + if ( is_array( $nodes[ $origin_node ]['targets'] ) && empty( $nodes[ $origin_node ]['targets'][0] ) ) {
348 + $nodes[ $origin_node ]['targets'][0] = ! empty( $target_node ) ? [ 'nodeId' => $target_node ] : null;
349 + }
350 +
351 + if ( is_array( $nodes[ $origin_node ]['targets'] ) && empty( $nodes[ $origin_node ]['targets'][1] ) ) {
352 + $nodes[ $origin_node ]['targets'][1] = ! empty( $target_node ) ? [ 'nodeId' => $target_node ] : null;
353 + }
354 +
355 + $nodes[ $origin_node ]['targets'][ (int) $target_index ] = [ 'nodeId' => strval( end( $old_node_keys ) + 1 ) ];
356 + }
357 +
358 + if ( '' === $origin_node && null === $target_node ) {
359 + update_post_meta( $post_id, 'nodes', [ 1 => $last_node ] );
360 + return;
361 + }
362 +
363 + update_post_meta( $post_id, 'nodes', $nodes );
256 364 }
257 365
258 366 /**
367 + * Gets last node origin node
368 + *
369 + * @param array $nodes Nodes.
370 + * @since 1.5.0
371 + */
372 + public static function get_first_end_path_node_key( $nodes ) {
373 + foreach ( $nodes as $key => $node ) {
374 + if ( ! empty( $node['origin_node'] ) && 'last-node' === $node['origin_node'] ) {
375 + return $key;
376 + }
377 + }
378 +
379 + return false;
380 + }
381 +
382 + /**
259 383 * Loading page templates.
260 384 *
261 385 * @since 1.1.0
262 386 * @param string $template Template name.
@@ -268,8 +392,12 @@
268 392 if ( 'string' !== gettype( $template ) || ! is_object( $post ) || self::SELLKIT_STEP_POST_TYPE !== $post->post_type ) {
269 393 return $template;
270 394 }
271 395
396 + if ( has_blocks( $post ) ) {
397 + return $template;
398 + }
399 +
272 400 remove_action( 'wp_head', 'adjacent_posts_rel_link_wp_head' );
273 401 add_filter( 'next_post_rel_link', '__return_empty_string' );
274 402 add_filter( 'previous_post_rel_link', '__return_empty_string' );
275 403
@@ -349,12 +477,12 @@
349 477 if ( get_post_field( 'post_name', $page_id ) === $slug ) {
350 478 return;
351 479 }
352 480
353 - $post_data = get_post_meta( $funnel_id, 'sellkit_steps', true );
481 + $post_data = get_post_meta( $funnel_id, 'nodes', true );
354 482 $post_data[ $selected_step ]['slug'] = get_post_field( 'post_name', $page_id );
355 483
356 - update_post_meta( $funnel_id, 'sellkit_steps', $post_data );
484 + update_post_meta( $funnel_id, 'nodes', $post_data );
357 485 }
358 486
359 487 /**
360 488 * Delete step page id.
@@ -393,8 +521,12 @@
393 521 */
394 522 public function update_steps_post_status( $funnel_id, $new_status ) {
395 523 $steps = get_post_meta( $funnel_id, 'sellkit_steps', true );
396 524
525 + if ( ! is_array( $steps ) ) {
526 + return;
527 + }
528 +
397 529 foreach ( $steps as $step ) {
398 530 if ( $step['page_id'] === $funnel_id ) {
399 531 continue;
400 532 }
@@ -402,8 +534,41 @@
402 534 wp_update_post(array(
403 535 'ID' => $step['page_id'],
404 536 'post_status' => $new_status,
405 537 ) );
538 + }
539 + }
540 +
541 + /**
542 + * Make SellKit custom post types translatable by default and set step_data custom field to "Copy".
543 + *
544 + * @since 2.3.2
545 + */
546 + public function sellkit_set_sellkit_translation_mode() {
547 + if ( function_exists( 'wpml_load_settings_helper' ) ) {
548 + global $sitepress;
549 +
550 + if ( $sitepress instanceof SitePress ) {
551 + $settings_helper = wpml_load_settings_helper();
552 +
553 + $post_types = [
554 + 'sellkit_step',
555 + 'sellkit-discount',
556 + 'sellkit-coupon',
557 + 'sellkit-alert',
558 + ];
559 +
560 + foreach ( $post_types as $post_type ) {
561 + $settings_helper->set_post_type_translatable( $post_type );
562 + $settings_helper->set_post_type_translation_unlocked_option( $post_type, true );
563 +
564 + if ( class_exists( '\WPML\Settings\PostType\Automatic' ) ) {
565 + \WPML\Settings\PostType\Automatic::set( $post_type, true );
566 + }
567 + }
568 +
569 + do_action( 'wpml_save_custom_field_translation_option', 'step_data', WPML_COPY_CUSTOM_FIELD ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- WPML API.
570 + }
406 571 }
407 572 }
408 573 }
409 574