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 / global-checkout / class.php

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

481 lines 12.5 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace Sellkit\Global_Checkout;
4
5 defined( 'ABSPATH' ) || exit;
6
7 use Elementor\Plugin as Elementor;
8 use Sellkit\Funnel\Steps\Checkout as CheckoutStep;
9
10 /**
11 * Checkout.
12 *
13 * @SuppressWarnings(PHPMD.NPathComplexity)
14 * @SuppressWarnings(PHPMD.CyclomaticComplexity)
15 * @SuppressWarnings(PHPMD.UnusedPrivateMethod)
16 * @SuppressWarnings(PHPMD.ExcessiveClassComplexity)
17 * @since 1.7.4
18 */
19 class Checkout {
20 const SELLKIT_GLOBAL_CHECKOUT_OPTION = 'sellkit_global_checkout_id';
21 const SELLKIT_GLOBAL_CHECKOUT_HEADER_FOOTER_TEMPLATE = 'sellkit_global_checkout_header_footer_templates';
22
23 /**
24 * Current post ID.
25 *
26 * @since 2.3.0
27 * @var null|integer
28 */
29 public $post_id = null;
30
31 /**
32 * Construct.
33 *
34 * @since 1.7.4
35 */
36 public function __construct() {
37 add_action( 'wp', [ $this, 'checkout_block_bump_query_var' ] );
38 add_action( 'wp', [ $this, 'init_sellkit_global_checkout' ] );
39 add_action( 'wp_ajax_handle_sellkit_global_checkout_ajax_requests', [ $this, 'handle_ajax_requests' ] );
40 }
41
42 /**
43 * Order bump for sellkit checkout block
44 *
45 * @since 2.3.0
46 */
47 public function checkout_block_bump_query_var() {
48 $global_checkout_id = get_option( self::SELLKIT_GLOBAL_CHECKOUT_OPTION, 0 );
49
50 $steps = get_post_meta( $global_checkout_id, 'nodes', true );
51 $bump_data = [];
52
53 if ( ! is_array( $steps ) ) {
54 return;
55 }
56
57 foreach ( $steps as $step ) {
58 $step['type'] = (array) $step['type'];
59
60 if ( 'checkout' === $step['type']['key'] ) {
61 $bump_data = ! empty( $step['bump'] ) ? $step['bump'] : [];
62 }
63 }
64
65 if ( ! empty( $bump_data ) ) {
66 $bump_data = $this->get_valid_bumps( $bump_data );
67
68 set_query_var( 'bump_data', $bump_data );
69 }
70 }
71
72 /**
73 * Init sellkit global checkout.
74 *
75 * @since 1.7.4
76 */
77 public function init_sellkit_global_checkout() {
78 $global_checkout_id = get_option( self::SELLKIT_GLOBAL_CHECKOUT_OPTION, 0 );
79
80 if (
81 0 === $global_checkout_id ||
82 'publish' !== get_post_status( (int) $global_checkout_id ) ||
83 ( function_exists( 'is_checkout' ) && ! is_checkout() )
84 ) {
85 return;
86 }
87
88 $steps = get_post_meta( $global_checkout_id, 'nodes', true );
89 $checkout_id = 0;
90 $bump_data = [];
91 $optimization_data = '';
92 $funnel_id = 0;
93
94 if ( ! is_array( $steps ) ) {
95 return;
96 }
97
98 foreach ( $steps as $step ) {
99 $step['type'] = (array) $step['type'];
100
101 if ( 'checkout' === $step['type']['key'] ) {
102 $checkout_id = $step['page_id'];
103 $bump_data = ! empty( $step['bump'] ) ? $step['bump'] : [];
104 $optimization_data = ! empty( $step['data']['optimization'] ) ? $step['data']['optimization'] : '';
105 $funnel_id = isset( $step['funnel_id'] ) ? $step['funnel_id'] : 0;
106 }
107 }
108
109 $checkout_steps = get_post_meta( $checkout_id, 'step_data', true );
110
111 if ( empty( $funnel_id ) && ! empty( $checkout_steps ) ) {
112 $funnel_id = isset( $checkout_steps['funnel_id'] ) ? $checkout_steps['funnel_id'] : 0;
113 }
114
115 if ( 0 === $checkout_id ) {
116 return;
117 }
118
119 // Remove previous content.
120 remove_all_filters( 'the_content' );
121
122 if ( defined( 'ELEMENTOR_VERSION' ) && 'elementor' === sellkit()->page_builder() ) {
123 // Set the page content.
124 add_filter( 'the_content', function() use ( $checkout_id ) {
125 ob_Start();
126 echo Elementor::instance()->frontend->get_builder_content_for_display( (int) $checkout_id, true );
127 return ob_get_clean();
128 }, 5 );
129
130 // Set sellkit canvas templates as the page template.
131 add_action( 'template_redirect', function() {
132 sellkit()->load_files( [
133 'templates/canvas'
134 ] );
135
136 exit;
137 } );
138 }
139
140 if ( 'gutenberg' === sellkit()->page_builder() ) {
141 $this->load_checkout_block_frontend();
142
143 $checkout_post = get_post( $checkout_id );
144
145 global $post;
146 $post = $checkout_post; // phpcs:ignore:WordPress.WP.GlobalVariablesOverride.OverrideProhibited
147 setup_postdata( $post );
148
149 $content = do_blocks( $post->post_content );
150
151 $content = apply_filters( 'the_content', $content );
152
153 add_filter( 'the_content', function() use ( $content ) {
154 ob_Start();
155
156 echo $content; // phpcs:ignore:WordPress.Security.EscapeOutput.OutputNotEscaped
157
158 return ob_get_clean();
159 }, 5 );
160
161 // Set sellkit canvas templates as the page template.
162 add_action( 'template_redirect', function() {
163 sellkit()->load_files( [
164 'templates/default-canvas'
165 ] );
166
167 exit;
168 } );
169 }
170
171 add_filter( 'sellkit_global_checkout_activated', function() {
172 return true;
173 } );
174
175 add_action( 'sellkit_checkout_required_hidden_fields', function() use ( $checkout_id ) {
176 ?>
177 <input type="hidden" name="sellkit_current_page_id" value="<?php echo esc_attr( $checkout_id ); ?>" >
178 <input type="hidden" name="sellkit_global_checkout_id" value="<?php echo esc_attr( $checkout_id ); ?>" >
179 <?php
180 } );
181
182 if ( ! empty( $bump_data ) ) {
183 $bump_data = $this->get_valid_bumps( $bump_data );
184
185 set_query_var( 'bump_data', $bump_data );
186 }
187
188 if ( ! empty( $optimization_data ) && CheckoutStep::apply_coupon_validation( $optimization_data ) ) {
189 foreach ( $optimization_data['auto_apply_coupons'] as $auto_apply_coupon ) {
190 wc()->cart->add_discount( get_the_title( $auto_apply_coupon['value'] ) );
191 }
192
193 wc_clear_notices();
194 }
195
196 $header_footer_templates = get_post_meta( intval( $funnel_id ), self::SELLKIT_GLOBAL_CHECKOUT_HEADER_FOOTER_TEMPLATE, true );
197
198 if ( empty( $header_footer_templates ) || ! is_array( $header_footer_templates ) ) {
199 $header_footer_templates = maybe_unserialize( $header_footer_templates );
200 }
201
202 if ( empty( $header_footer_templates ) || ! is_array( $header_footer_templates ) ) {
203 $header_footer_templates = [];
204 }
205
206 add_filter( 'sellkit_global_checkout_header_applied_id', function( $default ) use ( $header_footer_templates ) {
207 if (
208 array_key_exists( 'header', $header_footer_templates ) &&
209 array_key_exists( 'value', $header_footer_templates['header'] )
210 ) {
211 return $header_footer_templates['header']['value'];
212 }
213
214 return $default;
215 } );
216
217 add_filter( 'sellkit_global_checkout_footer_applied_id', function( $default ) use ( $header_footer_templates ) {
218 if (
219 array_key_exists( 'footer', $header_footer_templates ) &&
220 array_key_exists( 'value', $header_footer_templates['footer'] )
221 ) {
222 return $header_footer_templates['footer']['value'];
223 }
224
225 return $default;
226 } );
227 }
228
229 /**
230 * Load checkout block on frontend.
231 *
232 * @since 2.3.0
233 */
234 public function load_checkout_block_frontend() {
235 global $post;
236
237 if ( empty( $post->post_content ) ) {
238 return;
239 }
240
241 $this->post_id = $post->ID;
242
243 $block = 'blocks/checkout';
244
245 $block_data = explode( '/', $block );
246 $block_name = $block_data[1];
247
248 $class_name = str_replace( '-', ' ', $block_name );
249 $class_name = str_replace( ' ', '_', ucwords( $class_name ) );
250 $class_name = "Sellkit\blocks\Render\\{$class_name}";
251 $class_path = 'block-editor/' . $block . '/index';
252
253 sellkit()->load_files( [
254 $class_path,
255 ] );
256
257 $new_class = new $class_name( $this->post_id );
258
259 if ( ! \WP_Block_Type_Registry::get_instance()->is_registered( "sellkit-blocks/{$block_name}" ) ) {
260 $this->register_inner_blocks_by_parent( $new_class );
261 $new_class->register_block_meta();
262 }
263 }
264
265 /**
266 * Register inner blocks by parent.
267 *
268 * @param Object $parent_class Parent class name.
269 * @since 2.3.0
270 * @return void
271 */
272 private function register_inner_blocks_by_parent( $parent_class ) {
273 if ( ! method_exists( $parent_class, 'has_inner_blocks' ) ) {
274 return;
275 }
276
277 $inner_blocks = $parent_class->get_inner_block();
278
279 sellkit()->load_files( $inner_blocks );
280
281 foreach ( $inner_blocks as $key => $value ) {
282 if ( isset( $this->inner_blocks[ "blocks/{$key}" ] ) ) {
283 continue;
284 }
285
286 $inner_block_class = 'Sellkit\Blocks\Inner_Block\\' . str_replace( '-', '_', ucwords( $key ) );
287
288 if ( ! class_exists( $inner_block_class ) ) {
289 continue;
290 }
291
292 $inner_block_instance = new $inner_block_class( $this->post_id );
293 if ( ! \WP_Block_Type_Registry::get_instance()->is_registered( "sellkit-inner-blocks/{$key}" ) ) {
294 $inner_block_instance->register_block_meta();
295 }
296 }
297 }
298
299 /**
300 * Handle ajax requests.
301 *
302 * @since 1.8.9
303 */
304 public function handle_ajax_requests() {
305 check_ajax_referer( 'sellkit', 'nonce' );
306
307 if ( ! current_user_can( 'manage_options' ) ) {
308 wp_send_json_error( 'You do not have access to this section.', 'sellkit' );
309 }
310
311 $action = filter_var( $_REQUEST['sub_action'], FILTER_SANITIZE_FULL_SPECIAL_CHARS ); // phpcs:ignore
312
313 call_user_func( [ $this, $action ] );
314 }
315
316 /**
317 * Get header & footer design templates for Global checkout.
318 *
319 * @since 1.8.9
320 */
321 private function get_design_templates() {
322 $type = filter_input( INPUT_GET, 'template_type', FILTER_SANITIZE_FULL_SPECIAL_CHARS );
323 $search = filter_input( INPUT_GET, 'input_value', FILTER_SANITIZE_FULL_SPECIAL_CHARS );
324
325 $args = [
326 'post_type' => 'elementor_library',
327 'post_status' => [ 'private', 'publish' ],
328 's' => $search,
329 'posts_per_page' => -1,
330 'meta_query' => [ //phpcs:ignore
331 [
332 'key' => '_elementor_template_type',
333 'value' => $type,
334 ],
335 ],
336 ];
337
338 $posts = new \WP_Query( $args );
339
340 $values = [
341 [
342 'label' => esc_html__( 'Default', 'sellkit' ),
343 'value' => 'default',
344 ]
345 ];
346
347 if ( $posts->post_count > 0 ) {
348 foreach ( $posts->posts as $post ) {
349 $values[] = [
350 'label' => $post->post_title,
351 'value' => $post->ID,
352 ];
353 }
354
355 wp_send_json_success( $values );
356 }
357
358 wp_send_json_success( $values );
359 }
360
361 /**
362 * Save selected header/footer template id ofr the global checkout.
363 *
364 * @since 1.8.9
365 */
366 private function save_selected_template_id() {
367 $funnel_id = filter_input( INPUT_POST, 'funnel', FILTER_SANITIZE_NUMBER_INT );
368 $template_id = filter_input( INPUT_POST, 'template_id', FILTER_DEFAULT, FILTER_FORCE_ARRAY );
369 $template_type = filter_input( INPUT_POST, 'template', FILTER_SANITIZE_FULL_SPECIAL_CHARS );
370 $data = get_post_meta( $funnel_id, self::SELLKIT_GLOBAL_CHECKOUT_HEADER_FOOTER_TEMPLATE, true );
371
372 if ( empty( $data ) || ! is_array( $data ) ) {
373 $data = [];
374 }
375
376 if ( isset( $data[ $template_type ] ) ) {
377 unset( $data[ $template_type ] );
378 }
379
380 $data[ $template_type ] = [
381 'label' => ( empty( $template_id['label'] ) ) ? esc_html__( 'Search...', 'sellkit' ) : $template_id['label'],
382 'value' => ( empty( $template_id['value'] ) ) ? 0 : $template_id['value'],
383 ];
384
385 update_post_meta( $funnel_id, self::SELLKIT_GLOBAL_CHECKOUT_HEADER_FOOTER_TEMPLATE, $data );
386
387 wp_send_json_success( $data );
388 }
389
390 /**
391 * Get selected header/footer id.
392 *
393 * @since 1.8.9
394 */
395 private function get_selected_template_id() {
396 $funnel_id = filter_input( INPUT_POST, 'funnel', FILTER_SANITIZE_NUMBER_INT );
397 $data = get_post_meta( $funnel_id, self::SELLKIT_GLOBAL_CHECKOUT_HEADER_FOOTER_TEMPLATE, true );
398 $template = filter_input( INPUT_POST, 'template', FILTER_SANITIZE_FULL_SPECIAL_CHARS );
399
400 if ( empty( $data ) ) {
401 $data = [
402 'header' => [
403 'label' => esc_html__( 'Search...', 'sellkit' ),
404 'value' => 0,
405 ],
406 'footer' => [
407 'label' => esc_html__( 'Search...', 'sellkit' ),
408 'value' => 0,
409 ],
410 ];
411 }
412
413 if ( ! is_array( $data ) ) {
414 $data = maybe_unserialize( $data );
415 }
416
417 wp_send_json_success( $data );
418 }
419
420 /**
421 * Create new Elementor template.
422 *
423 * @since 1.8.9
424 */
425 private function create_new_template() {
426 $template = filter_input( INPUT_POST, 'template', FILTER_SANITIZE_FULL_SPECIAL_CHARS );
427 $post_title = filter_input( INPUT_POST, 'post_title', FILTER_SANITIZE_FULL_SPECIAL_CHARS );
428
429 $args = [
430 'post_type' => 'elementor_library',
431 'post_title' => $post_title,
432 'post_status' => 'publish',
433 'meta_input' => [
434 '_elementor_template_type' => $template,
435 '_elementor_edit_mode' => 'builder',
436 'jx-layout-type' => $template,
437 '_wp_page_template' => 'full-width.php',
438 ],
439 ];
440
441 $id = wp_insert_post( $args );
442
443 if ( intval( $id ) > 0 ) {
444 $editor_url = Elementor::$instance->documents->get( $id )->get_edit_url();
445
446 wp_send_json_success( [
447 'label' => $post_title,
448 'value' => $id,
449 'url' => $editor_url,
450 ] );
451 }
452
453 wp_send_json_error();
454 }
455
456 /**
457 * Checks all bumps and return data.
458 *
459 * @since 1.8.1
460 * @param array $bump_data Bump data.
461 * @return array
462 */
463 public function get_valid_bumps( $bump_data ) {
464 $valid_bumps = [];
465
466 foreach ( $bump_data as $bump ) {
467 $conditions = ! empty( $bump['data']['conditions'] ) ? $bump['data']['conditions'] : '';
468
469 if ( ! empty( $conditions ) && empty( sellkit_conditions_validation( $conditions ) ) ) {
470 continue;
471 }
472
473 $valid_bumps[] = $bump;
474 }
475
476 return $valid_bumps;
477 }
478 }
479
480 new Checkout();
481