PluginProbe ʕ •ᴥ•ʔ
ShopPress – Shop Builder for Elementor and WooCommerce / trunk
ShopPress – Shop Builder for Elementor and WooCommerce vtrunk
shop-press / Modules / Compare.php
shop-press / Modules Last commit date
VariationSwatches 1 week ago Wishlist 1 week ago AdminMessage.php 1 week ago AjaxSearch.php 1 week ago Backorder.php 1 week ago CatalogMode.php 1 year ago Compare.php 1 week ago DefaultTemplates.php 2 years ago FlashSalesCountdown.php 1 year ago MenuCart.php 4 months ago MobilePanel.php 1 week ago MultiStep.php 1 year ago Notifications.php 1 week ago QuickView.php 1 week ago RecentlyViewedProducts.php 1 year ago RenameLabel.php 4 months ago Shopify.php 1 year ago SingleAjaxAddToCart.php 1 week ago SizeChart.php 1 week ago StickyAddToCart.php 1 week ago
Compare.php
656 lines
1 <?php
2 /**
3 * Compare.
4 *
5 * @package ShopPress
6 */
7
8 namespace ShopPress\Modules;
9
10 defined( 'ABSPATH' ) || exit;
11
12 class Compare {
13 /**
14 * Init hooks.
15 *
16 * @since 1.0.0
17 */
18 public static function init() {
19
20 if ( self::is_compare_builder() || self::is_static_compare() ) {
21
22 $compare_location_single = sp_get_module_settings( 'compare', 'location_product_page' )['value'] ?? '';
23 $compare_location_archive = sp_get_module_settings( 'compare', 'location_products_loop' )['value'] ?? '';
24
25 self::setup_cookie();
26 add_action( 'init', array( __CLASS__, 'add_rewrite_rules' ) );
27 add_filter( 'query_vars', array( __CLASS__, 'add_query_vars' ) );
28 add_filter( 'body_class', array( __CLASS__, 'filter_body_class' ) );
29 add_action( 'wp_enqueue_scripts', array( __CLASS__, 'enqueue' ), 99 );
30 add_filter( 'shoppress_frontend_localize', array( __CLASS__, 'filter_localize' ), 10, 1 );
31 add_shortcode( 'shoppress-compare-page', array( __CLASS__, 'render_compare_page' ) );
32 add_filter( 'template_include', array( __CLASS__, 'full_template' ) );
33
34 add_action( 'wp_ajax_AddCompare', array( __CLASS__, 'add_to_compare_by_ajax' ) );
35 add_action( 'wp_ajax_nopriv_AddCompare', array( __CLASS__, 'add_to_compare_by_ajax' ) );
36
37 if ( ! empty( $compare_location_single ) && false === sp_is_template_active( 'single' ) ) {
38 add_action( $compare_location_single, array( __CLASS__, 'compare_output' ) );
39 }
40
41 if ( ! empty( $compare_location_archive ) ) {
42 add_action( $compare_location_archive, array( __CLASS__, 'compare_output' ) );
43 }
44 }
45
46 add_filter( 'shoppress/elementor/widgets', array( __CLASS__, 'add_compare_widgets' ), 9 );
47 }
48
49 /**
50 * Return compare page url.
51 *
52 * @since 1.2.0
53 *
54 * @return mixed
55 */
56 public static function get_compare_page_url() {
57 $page_id = sp_get_module_settings( 'compare', 'compare_page' )['value'] ?? '';
58
59 return get_permalink( $page_id );
60 }
61
62 /**
63 * Add to the compare.
64 *
65 * @param int $product_id
66 *
67 * @since 1.2.0
68 */
69 public static function add_to_compare( $product_id = null ) {
70
71 $user_id = get_current_user_id();
72 if ( $user_id ) {
73 $compare = get_user_meta( $user_id, 'shoppress_woo_compare', true );
74 if ( ! $compare ) {
75 update_user_meta( $user_id, 'shoppress_woo_compare', array( $product_id ) );
76 } else {
77 if ( ! in_array( $product_id, $compare ) ) {
78 $product = wc_get_product( $product_id );
79 if ( is_a( $product, '\WC_Product' ) ) {
80 $compare[] = $product_id;
81 }
82 }
83
84 update_user_meta( $user_id, 'shoppress_woo_compare', $compare );
85 }
86
87 return $compare;
88 }
89
90 return false;
91 }
92
93 /**
94 * Remove from the compare.
95 *
96 * @param int $product_id
97 *
98 * @since 1.2.0
99 */
100 public static function remove_from_compare( $product_id = null ) {
101
102 $user_id = get_current_user_id();
103 if ( $user_id ) {
104 $compare = get_user_meta( $user_id, 'shoppress_woo_compare', true );
105 if ( $compare ) {
106 if ( in_array( $product_id, $compare ) ) {
107 foreach ( $compare as $k => $v ) {
108 if ( $product_id == $v ) {
109 unset( $compare[ $k ] );
110 }
111 }
112 }
113 update_user_meta( $user_id, 'shoppress_woo_compare', $compare );
114 }
115
116 return $compare;
117 }
118
119 return false;
120 }
121
122 /**
123 * Add to the compare.
124 *
125 * @since 1.2.0
126 */
127 public static function add_to_compare_by_ajax() {
128
129 check_ajax_referer( 'shoppress_nonce', 'nonce' );
130 $static_compare_title = sp_get_module_settings( 'compare', 'add_label' );
131 $static_compare_remove_title = sp_get_module_settings( 'compare', 'remove_label' );
132 $limit_the_number_of_products = sp_get_module_settings( 'compare', 'limit_the_number_of_products', 4 );
133 $social_share = sp_get_module_settings( 'compare', 'social_share' );
134 $social_media = sp_get_module_settings( 'compare', 'social_media' );
135 $compare = self::get_compare_product_ids();
136 $user_id = get_current_user_id();
137
138 if ( ! isset( $_POST['product_id'] ) ) {
139 wp_die();
140 }
141 $Product = sanitize_text_field( wp_unslash( $_POST['product_id'] ) );
142
143 if ( 'clear_all' === $Product ) {
144 if ( $user_id ) {
145 update_user_meta( $user_id, 'shoppress_woo_compare', array() );
146 }
147
148 wp_send_json_success(
149 array(
150 'message' => __( 'Products removed from compare.', 'shop-press' ),
151 'message_type' => 'success',
152 'compare_label' => $static_compare_title,
153 'status' => 'no',
154 'button_url' => self::get_compare_page_url(),
155 'button_text' => __( 'View Compare', 'shop-press' ),
156 'popup_html' => '',
157 'items_count' => 0,
158 ),
159 200
160 );
161 }
162
163 $is_in_compare = in_array( $Product, $compare );
164
165 if ( is_array( $compare ) && count( $compare ) >= $limit_the_number_of_products && ! $is_in_compare ) {
166 wp_send_json_error(
167 array(
168 'status' => 'no',
169 'message' => sprintf(
170 /* translators: %s: maximum number of products */
171 __( 'You can add up to %s products', 'shop-press' ),
172 $limit_the_number_of_products
173 ),
174 'message_type' => 'error',
175 'button_url' => self::get_compare_page_url(),
176 'button_text' => __( 'View Compare', 'shop-press' ),
177 ),
178 500
179 );
180 }
181
182 if ( is_user_logged_in() ) {
183
184 if ( ! $is_in_compare ) {
185 $action = static::add_to_compare( $Product );
186 $result = 'added';
187 } elseif ( $is_in_compare ) {
188 $action = static::remove_from_compare( $Product );
189 $result = 'removed';
190 }
191
192 if ( is_wp_error( $action ) ) {
193 wp_send_json_error(
194 array(
195 'message' => $action->get_error_message(),
196 'message_type' => 'error',
197 ),
198 500
199 );
200 }
201 } elseif ( ! $is_in_compare ) {
202
203 $result = 'removed';
204 } elseif ( $is_in_compare ) {
205 $result = 'added';
206 }
207
208 $popup_html = '';
209 if ( sp_get_module_settings( 'compare', 'display_popup_after_update' ) ) {
210 $popup_html = self::compare_popup_output();
211 }
212
213 $updated_compare_items = self::get_compare_product_ids();
214
215 if ( 'added' === $result ) {
216
217 wp_send_json_success(
218 array(
219 'message' => __( 'Product added to compare', 'shop-press' ),
220 'message_type' => 'success',
221 'compare_label' => $static_compare_remove_title,
222 'status' => 'yes',
223 'button_url' => self::get_compare_page_url(),
224 'button_text' => __( 'View Compare', 'shop-press' ),
225 'popup_html' => $popup_html,
226 'items_count' => count( $updated_compare_items ),
227 'share_link' => $social_share && ! empty( $social_media ) ? self::get_compare_share_link( $updated_compare_items ) : '',
228 ),
229 200
230 );
231 } elseif ( 'removed' === $result ) {
232
233 wp_send_json_success(
234 array(
235 'message' => __( 'Product removed from compare.', 'shop-press' ),
236 'message_type' => 'success',
237 'compare_label' => $static_compare_title,
238 'status' => 'no',
239 'button_url' => self::get_compare_page_url(),
240 'button_text' => __( 'View Compare', 'shop-press' ),
241 'popup_html' => $popup_html,
242 'items_count' => count( $updated_compare_items ),
243 'share_link' => $social_share && ! empty( $social_media ) ? self::get_compare_share_link( $updated_compare_items ) : '',
244 ),
245 200
246 );
247 }
248
249 wp_die();
250 }
251
252 /**
253 * Adds the compare widgets to the existing list of widgets.
254 *
255 * @param array $widgets The array of widgets.
256 *
257 * @since 1.2.0
258 *
259 * @return array The updated array of widgets.
260 */
261 public static function add_compare_widgets( $widgets ) {
262 $widgets['single-compare'] = array(
263 'editor_type' => 'single',
264 'class_name' => 'Compare',
265 'is_pro' => false,
266 'path_key' => 'single-product/compare',
267 );
268
269 $widgets['compare'] = array(
270 'editor_type' => 'compare',
271 'class_name' => 'ProductsCompare',
272 'is_pro' => false,
273 'path_key' => 'compare/compare',
274 );
275
276 $widgets['loop-compare'] = array(
277 'editor_type' => 'loop',
278 'class_name' => 'LoopBuilder\Compare',
279 'is_pro' => false,
280 'path_key' => 'loop/compare',
281 );
282
283 return $widgets;
284 }
285
286 /**
287 * Enqueue Scripts.
288 *
289 * @since 1.0.0
290 */
291 public static function enqueue() {
292 $builder_id = sp_get_template_settings( 'compare', 'page_builder' );
293 if ( self::is_compare_page() && 'block_editor' === sp_get_builder_type( $builder_id ) ) {
294
295 add_filter(
296 'styler/block_editor/post_id',
297 function () {
298 return sp_get_template_settings( 'compare', 'page_builder' );
299 }
300 );
301 }
302
303 wp_enqueue_script( 'sp-compare' );
304 wp_enqueue_style( 'sp-pr-general' );
305
306 if ( is_rtl() ) {
307 wp_enqueue_style( 'sp-pr-general-rtl' );
308 }
309
310 $is_display_popup = sp_get_module_settings( 'compare', 'display_popup_after_update' );
311 if ( self::is_compare_page() || $is_display_popup ) {
312 wp_enqueue_style( 'sp-compare' );
313
314 if ( is_rtl() ) {
315 wp_enqueue_style( 'sp-compare-rtl' );
316 }
317 }
318 }
319
320 /**
321 * Check compare builder.
322 *
323 * @since 1.0.0
324 *
325 * @return bool
326 */
327 public static function is_compare_builder() {
328 return sp_get_template_settings( 'compare', 'status' ) && sp_get_template_settings( 'compare', 'page_builder' ) ? true : false;
329 }
330
331 /**
332 * Check static compare.
333 *
334 * @since 1.0.0
335 *
336 * @return bool
337 */
338 public static function is_static_compare() {
339 return sp_get_module_settings( 'compare', 'status' ) && ! self::is_compare_builder() ? true : false;
340 }
341
342 /**
343 * Return compare page id.
344 *
345 * @since 1.4.0
346 *
347 * @return int
348 */
349 public static function get_compare_page_id() {
350
351 return sp_get_module_settings( 'compare', 'compare_page', false )['value'] ?? null;
352 }
353
354 /**
355 * Return compare page slug.
356 *
357 * @since 1.4.0
358 *
359 * @return string
360 */
361 public static function get_compare_page_slug() {
362
363 $compare_page_id = self::get_compare_page_id();
364 $compare = $compare_page_id ? get_post( $compare_page_id ) : false;
365
366 return is_a( $compare, '\WP_Post' ) ? $compare->post_name : 'compare';
367 }
368
369 /**
370 * Check compare page.
371 *
372 * @since 1.0.0
373 */
374 public static function is_compare_page() {
375 $compare_page_id = self::get_compare_page_id();
376 return get_the_ID() === $compare_page_id;
377 }
378
379 /**
380 * body class.
381 *
382 * @since 1.2.0
383 *
384 * @return array
385 */
386 public static function filter_body_class( $classes ) {
387
388 if ( self::is_compare_page() ) {
389
390 return array_merge( $classes, array( 'woocommerce woocommerce-page ' ) );
391 }
392
393 return $classes;
394 }
395
396 /**
397 * Set Cookie.
398 *
399 * @since 1.0.0
400 */
401 public static function setup_cookie() {
402 if ( ! isset( $_COOKIE['shoppress_woo_compare'] ) ) {
403 @setcookie( 'shoppress_woo_compare', json_encode( array( 0 ) ), time() + ( 10 * 365 * 24 * 60 * 60 ), '/' );
404 }
405 }
406
407 /**
408 * Update Localize.
409 *
410 * @since 1.0.0
411 */
412 public static function filter_localize( $localize ) {
413
414 $compare_title = sp_get_module_settings( 'compare', 'add_label' );
415 $compare_remove_title = sp_get_module_settings( 'compare', 'remove_label' );
416 $localize['compare'] = array(
417 'add' => array(
418 'message' => __( 'Product added to compare', 'shop-press' ),
419 'compare_label' => $compare_remove_title,
420 'button_text' => __( 'View Compare', 'shop-press' ),
421 'button_url' => self::get_compare_page_url(),
422 'status' => 'yes',
423 ),
424 'remove' => array(
425 'message' => __( 'Product removed from compare', 'shop-press' ),
426 'compare_label' => $compare_title,
427 'button_text' => __( 'View Compare', 'shop-press' ),
428 'button_url' => self::get_compare_page_url(),
429 'status' => 'no',
430 ),
431 'display_popup_after_update' => sp_get_module_settings( 'compare', 'display_popup_after_update' ),
432 );
433
434 return $localize;
435 }
436
437 /**
438 * Get the compare.
439 *
440 * @since 1.0.0
441 *
442 * @return array compare.
443 */
444 public static function get_compare_product_ids( $limit = -1 ) {
445
446 $user_id = get_current_user_id();
447
448 if ( $user_id ) {
449 $Compare = get_user_meta( $user_id, 'shoppress_woo_compare', true );
450 if ( $Compare == '' ) {
451 $Compare = array();
452 }
453 } else {
454 if ( ! isset( $_COOKIE['shoppress_woo_compare'] ) ) {
455 $Compare = false;
456 } else {
457 // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- JSON cookie, output validated via is_array
458 $Compare = json_decode( wp_unslash( $_COOKIE['shoppress_woo_compare'] ), true );
459 $Compare = is_array( $Compare ) ? $Compare : false;
460 }
461 }
462
463 if ( ! empty( $Compare ) && is_array( $Compare ) ) {
464
465 // check if is product
466 foreach ( $Compare as $key => $ID ) {
467 $product = wc_get_product( $ID );
468 if ( ! is_a( $product, '\WC_Product' ) ) {
469 unset( $Compare[ $key ] );
470 }
471 }
472
473 if ( is_numeric( $limit ) && -1 !== $limit ) {
474 return array_slice( $Compare, 0, $limit );
475 }
476 return $Compare;
477 }
478 return array();
479 }
480
481 /**
482 * Get compare products.
483 *
484 * @since 1.3.7
485 *
486 * @return array
487 */
488 public static function get_compare_products( $limit = -1 ) {
489
490 $products = array();
491 $product_ids = self::get_compare_product_ids( $limit );
492 if ( ! empty( $product_ids ) && is_array( $product_ids ) ) {
493
494 foreach ( $product_ids as $product_id ) {
495
496 $products[ $product_id ] = wc_get_product( $product_id );
497 }
498 }
499
500 return $products;
501 }
502
503 /**
504 * Compare output.
505 *
506 * @since 1.0.0
507 */
508 public static function compare_output() {
509 global $shoppress_cross_sell_popup;
510 // Do not display the variations in cross-sell popup
511 if ( $shoppress_cross_sell_popup ) {
512 return;
513 }
514
515 $product_id = get_the_ID();
516 $Comparelist = self::get_compare_product_ids();
517 $Comparelist = is_array( $Comparelist ) && in_array( $product_id, $Comparelist ) ? 'yes' : 'no';
518 $label = 'yes' === $Comparelist ? sp_get_module_settings( 'compare', 'remove_label' ) : sp_get_module_settings( 'compare', 'add_label' );
519 ?>
520
521 <div class="sp-single-compare sp-product-compare sp-compare-button sp-compare-button-wrapper" data-product_id="<?php echo esc_attr( $product_id ); ?>" data-status="<?php echo esc_attr( $Comparelist ); ?>">
522 <div class="sp-compare-button-loop">
523 <span class="sp-compare-icon">
524 <?php echo wp_kses( sp_get_svg_icon( 'compare' ), sp_allowd_svg_tags() ); ?>
525 </span>
526 <?php if ( ! empty( $label ) ) { ?>
527 <span class="sp-compare-label"><?php echo wp_kses( $label, wp_kses_allowed_html( 'post' ) ); ?></span>
528 <?php } ?>
529 </div>
530 </div>
531 <?php
532 }
533
534 /**
535 * Compare popup output.
536 *
537 * @since 1.2.0
538 *
539 * @return string
540 */
541 public static function compare_popup_output() {
542 ob_start();
543 echo '<div class="sp-compare-popup shoppress-compare-popup-wrap">
544 <div class="sp-popup-con"> <div class="sp-compare-close-popup"> <svg xmlns="http://www.w3.org/2000/svg" width="10" height="10" viewBox="0 0 10 10" > <path d="M9.79.21a.717.717,0,0,1,0,1.014L5.956,5.057,9.674,8.776A.717.717,0,0,1,8.66,9.79L4.942,6.072l-3.6,3.6A.717.717,0,0,1,.326,8.66l3.6-3.6L.21,1.34A.717.717,0,0,1,1.224.326L4.942,4.043,8.776.21A.717.717,0,0,1,9.79.21Z" fill="#7f8da0" /> </svg> </div>';
545 echo wp_kses_post( self::render_compare_page() );
546
547 echo '</div>
548 </div>';
549 return ob_get_clean();
550 }
551
552 /**
553 * Render compare page content.
554 *
555 * @param array $atts
556 *
557 * @since 1.2.0
558 *
559 * @return string
560 */
561 public static function render_compare_page( $atts = array() ) {
562 ob_start();
563
564 wp_enqueue_style( 'sp-compare' );
565
566 if ( is_rtl() ) {
567 wp_enqueue_style( 'sp-compare-rtl' );
568 }
569
570 wp_enqueue_script( 'sp-compare' );
571
572 do_action( 'shoppress/before_compare' );
573
574 echo '<div id="shoppress-wrap" class="shoppress-wrap">';
575 if ( self::is_compare_builder() ) {
576
577 $builder_id = sp_get_template_settings( 'compare', 'page_builder' );
578
579 // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
580 echo sp_get_builder_content( $builder_id );
581 } else {
582
583 load_template( sp_get_template_path( 'compare/compare-template' ) );
584 }
585 echo '</div>';
586
587 do_action( 'shoppress/after_compare' );
588
589 return ob_get_clean();
590 }
591
592 /**
593 * Get full template.
594 *
595 * @since 1.2.0
596 */
597 public static function full_template( $template ) {
598
599 if ( self::is_compare_page() ) {
600 $template = sp_get_template_path( 'full-template' );
601 }
602
603 return $template;
604 }
605
606 /**
607 * Add rewrite rules
608 *
609 * @since 1.4.0
610 *
611 * @return void
612 */
613 public static function add_rewrite_rules() {
614
615 $compare_page_slug = self::get_compare_page_slug();
616
617 add_rewrite_rule( $compare_page_slug . '/view/(.*)/page/(.*)?', 'index.php?view=$matches[1]&paged=$matches[2]&pagename=' . $compare_page_slug, 'top' );
618 add_rewrite_rule( $compare_page_slug . '/view/(.*)?', 'index.php?view=$matches[1]&pagename=' . $compare_page_slug, 'top' );
619 }
620
621 /**
622 * Add query vars
623 *
624 * @param array $vars
625 *
626 * @since 1.4.0
627 *
628 * @return array
629 */
630 public static function add_query_vars( $vars ) {
631
632 $vars['view'] = 'view';
633
634 return $vars;
635 }
636
637 /**
638 * Return Compare Share Link
639 *
640 * @param int[] $product_ids
641 *
642 * @since 1.4.0
643 *
644 * @return string
645 */
646 public static function get_compare_share_link( $product_ids ) {
647
648 $url = self::get_compare_page_url();
649
650 $compare_key = base64_encode( implode( ',', $product_ids ) );
651 $url .= 'view/' . $compare_key . '/';
652
653 return $url;
654 }
655 }
656