PluginProbe ʕ •ᴥ•ʔ
ShopPress – Shop Builder for Elementor and WooCommerce / trunk
ShopPress – Shop Builder for Elementor and WooCommerce vtrunk
shop-press / Modules / SizeChart.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
SizeChart.php
576 lines
1 <?php
2 /**
3 * Size Chart.
4 *
5 * @package ShopPress
6 */
7
8 namespace ShopPress\Modules;
9
10 defined( 'ABSPATH' ) || exit;
11
12 use Elementor\Plugin;
13
14 class SizeChart {
15 /**
16 * Init.
17 *
18 * @since 1.2.0
19 */
20 public static function init() {
21
22 if ( ! self::is_size_chart() ) {
23 return;
24 }
25
26 $chart_as = sp_get_module_settings( 'size_chart', 'chart_as' )['value'] ?? '';
27 $button_position = sp_get_module_settings( 'size_chart', 'button_position' )['value'] ?? '';
28
29 add_action( 'init', array( __CLASS__, 'register_post_type' ), 9 );
30 add_filter( 'shoppress/api/get_post', array( __CLASS__, 'add_meta_fields' ), 9, 3 );
31 add_filter( 'shoppress/api/post/default_post_fields', array( __CLASS__, 'update_post_fields' ), 9, 2 );
32
33 if ( 'tab' === $chart_as ) {
34 add_filter( 'woocommerce_product_tabs', array( __CLASS__, 'add_size_chart_tab' ) );
35 } elseif ( 'button-popup' === $chart_as && ! empty( $button_position ) && false === sp_is_template_active( 'single' ) ) {
36
37 add_action( $button_position, array( __CLASS__, 'display_size_chart_button' ) );
38 }
39 add_filter( 'shoppress/elementor/widgets', array( __CLASS__, 'add_elementor_widget' ), 9 );
40 }
41
42 /**
43 * Check if Size Chart is enabled.
44 *
45 * @since 1.2.0
46 *
47 * @return bool
48 */
49 public static function is_size_chart() {
50
51 return sp_get_module_settings( 'size_chart', 'status' );
52 }
53
54 /**
55 * Register post type.
56 *
57 * @since 1.2.0
58 *
59 * @return void
60 */
61 public static function register_post_type() {
62
63 register_post_type(
64 'shoppress_size_chart',
65 array(
66 'labels' => array(
67 'name' => __( 'Size Chart', 'shop-press' ),
68 'singular_name' => __( 'Size Chart', 'shop-press' ),
69 ),
70 'public' => true,
71 'show_ui' => true,
72 'show_in_menu' => false,
73 'can_export' => true,
74 'rewrite' => false,
75 'show_in_nav_menus' => false,
76 'exclude_from_search' => true,
77 'show_in_rest' => true,
78 'supports' => array( 'title', 'editor', 'elementor' ),
79 )
80 );
81 }
82
83 /**
84 * Return meta fields.
85 *
86 * @since 1.2.0
87 *
88 * @return array
89 */
90 public static function get_meta_fields() {
91
92 return array(
93 'status',
94 'title',
95 'product_categories_operator',
96 'product_categories',
97 'products_operator',
98 'products',
99 'image',
100 'content_type',
101 );
102 }
103
104 /**
105 * Update the default post fields.
106 *
107 * @param array $default_post_fields
108 * @param string $post_type
109 *
110 * @since 1.4.3
111 *
112 * @return array
113 */
114 public static function update_post_fields( $default_post_fields, $post_type ) {
115
116 if ( 'shoppress_size_chart' !== $post_type ) {
117 return $default_post_fields;
118 }
119
120 $default_post_fields = array_diff( $default_post_fields, array( 'post_content' ) );
121
122 return $default_post_fields;
123 }
124
125 /**
126 * Add meta fields.
127 *
128 * @param array $post_data
129 * @param int $post_id
130 * @param string $post_type
131 *
132 * @since 1.2.0
133 *
134 * @return array
135 */
136 public static function add_meta_fields( $post_data, $post_id, $post_type ) {
137
138 if ( 'shoppress_size_chart' !== $post_type ) {
139 return $post_data;
140 }
141
142 $post_data['meta_fields'] = array(
143 'status' => array(
144 'title' => __( 'Enable', 'shop-press' ),
145 'name' => 'status',
146 'component' => 'switch',
147 ),
148 'products' => array(
149 'title' => __( 'Products', 'shop-press' ),
150 'component' => 'group_fields',
151 'full_row' => true,
152 'className' => array( 'sp-group-field-half' ),
153 'fields' => array(
154 'products_operator' => array(
155 'name' => 'products_operator',
156 'component' => 'select',
157 'is_clearable' => true,
158 'default' => array(
159 'value' => 'all',
160 'label' => __( 'All Products', 'shop-press' ),
161 ),
162 'options' => array(
163 array(
164 'value' => 'all',
165 'label' => __( 'All Products', 'shop-press' ),
166 ),
167 array(
168 'label' => __( 'Include', 'shop-press' ),
169 'value' => 'include',
170 ),
171 array(
172 'label' => __( 'Exclude', 'shop-press' ),
173 'value' => 'exclude',
174 ),
175 ),
176 ),
177 'products' => array(
178 'name' => 'products',
179 'placeholder' => __( 'Search products...', 'shop-press' ),
180 'is_searchable' => true,
181 'is_multi' => true,
182 'component' => 'select_product',
183 'conditions' => array(
184 'parent' => 'meta',
185 'terms' => array(
186 array(
187 'name' => 'products_operator',
188 'operator' => '!==',
189 'value' => 'all',
190 ),
191 ),
192 ),
193 ),
194 ),
195 ),
196 'product_categories' => array(
197 'title' => __( 'Categories', 'shop-press' ),
198 'component' => 'group_fields',
199 'full_row' => true,
200 'className' => array( 'sp-group-field-half' ),
201 'fields' => array(
202 'product_categories_operator' => array(
203 'name' => 'product_categories_operator',
204 'component' => 'select',
205 'is_clearable' => true,
206 'default' => array(
207 'value' => 'all',
208 'label' => __( 'All Categories', 'shop-press' ),
209 ),
210 'options' => array(
211 array(
212 'value' => 'all',
213 'label' => __( 'All Categories', 'shop-press' ),
214 ),
215 array(
216 'label' => __( 'Include', 'shop-press' ),
217 'value' => 'include',
218 ),
219 array(
220 'label' => __( 'Exclude', 'shop-press' ),
221 'value' => 'exclude',
222 ),
223 ),
224 ),
225 'product_categories' => array(
226 'name' => 'product_categories',
227 'placeholder' => __( 'Search categories...', 'shop-press' ),
228 'is_searchable' => true,
229 'is_multi' => true,
230 'component' => 'select_product_category',
231 'conditions' => array(
232 'parent' => 'meta',
233 'terms' => array(
234 array(
235 'name' => 'product_categories_operator',
236 'operator' => '!==',
237 'value' => 'all',
238 ),
239 ),
240 ),
241 ),
242 ),
243 ),
244 'content_divider' => array(
245 'title' => __( 'Content', 'shop-press' ),
246 'component' => 'divider',
247 ),
248 'content_type_field' => array(
249 'component' => 'group_fields',
250 'full_row' => true,
251 'fields' => array(
252 'content_type' => array(
253 'name' => 'content_type',
254 'component' => 'toggle_radio',
255 'default' => 'upload_image',
256 'options' => array(
257 array(
258 'label' => __( 'Image', 'shop-press' ),
259 'value' => 'upload_image',
260 ),
261 array(
262 'label' => __( 'Page Builder', 'shop-press' ),
263 'value' => 'page_builder',
264 ),
265 ),
266 ),
267 'image' => array(
268 'title' => __( 'Upload Image (Chart)', 'shop-press' ),
269 'name' => 'image',
270 'component' => 'image',
271 'conditions' => array(
272 'parent' => 'meta',
273 'terms' => array(
274 array(
275 'name' => 'content_type',
276 'operator' => '===',
277 'value' => 'upload_image',
278 ),
279 ),
280 ),
281 ),
282 'page_builder' => array(
283 'name' => 'page_builder',
284 'component' => 'single_template',
285 'conditions' => array(
286 'parent' => 'meta',
287 'terms' => array(
288 array(
289 'name' => 'content_type',
290 'operator' => '===',
291 'value' => 'page_builder',
292 ),
293 ),
294 ),
295 ),
296 ),
297 ),
298 );
299
300 return $post_data;
301 }
302
303 /**
304 * Add chart size tab to single product.
305 *
306 * @param array $tabs
307 *
308 * @since 1.2.0
309 *
310 * @return array
311 */
312 public static function add_size_chart_tab( $tabs ) {
313
314 if ( is_sp_quick_view_ajax() ) {
315 return $tabs;
316 }
317
318 $product_id = get_the_ID();
319 $size_chart = static::get_available_size_chart( $product_id );
320 if ( empty( $size_chart ) ) {
321 return $tabs;
322 }
323
324 $tab_priority = sp_get_module_settings( 'size_chart', 'tab_priority', 100 );
325 $tabs['shoppress_size_chart'] = array(
326 'title' => __( 'Size Chart', 'shop-press' ),
327 'priority' => $tab_priority,
328 'callback' => array( __CLASS__, 'display_size_chart_tab_content' ),
329 );
330
331 return $tabs;
332 }
333
334 /**
335 * Display chart size.
336 *
337 * @param int $product_id
338 *
339 * @since 1.2.0
340 *
341 * @return string
342 */
343 public static function display_size_chart( $product_id ) {
344
345 $size_chart = static::get_available_size_chart( $product_id );
346 if ( empty( $size_chart ) ) {
347 return;
348 }
349
350 $image_url = sp_get_image_url( $size_chart['image'] );
351 $size_chart_id = $size_chart['id'];
352 $content_type = $size_chart['content_type'] ?? '';
353
354 if ( empty( $content_type ) ) {
355 return;
356 }
357
358 if ( 'page_builder' === $content_type ) {
359
360 if ( did_action( 'elementor/loaded' ) && Plugin::$instance->documents->get( $size_chart_id )->is_built_with_elementor() ) {
361
362 echo wp_kses_post( Plugin::instance()->frontend->get_builder_content_for_display( $size_chart_id, false ) );
363 } else {
364
365 $content = get_post_field( 'post_content', $size_chart_id );
366 echo wp_kses_post( do_blocks( $content ) );
367 }
368 } elseif ( 'upload_image' === $content_type && ! empty( $image_url ) ) {
369
370 return '<p><img src="' . esc_url_raw( $image_url ) . '"/></p>';
371 }
372 }
373
374
375 /**
376 * Add chart size tab to single product.
377 *
378 * @since 1.2.0
379 */
380 public static function display_size_chart_tab_content() {
381
382 $product_id = get_the_ID();
383 echo wp_kses_post( static::display_size_chart( $product_id ) );
384 }
385
386 /**
387 * Display size chart button.
388 *
389 * @param array $atts
390 *
391 * @since 1.2.0
392 */
393 public static function display_size_chart_button( $atts = array() ) {
394
395 if ( is_sp_quick_view_ajax() ) {
396 return;
397 }
398
399 global $shoppress_sticky_add_to_cart;
400 if ( $shoppress_sticky_add_to_cart ) {
401 return;
402 }
403 $product_id = get_the_ID();
404
405 $size_chart = static::get_available_size_chart( $product_id );
406 if ( empty( $size_chart ) ) {
407 return;
408 }
409
410 wp_enqueue_script( 'sp-size-chart' );
411 wp_enqueue_style( 'sp-size-chart' );
412
413 $label = $atts['label'] ?? __( 'Size Chart', 'shop-press' );
414 $icon = $atts['icon'] ?? '';
415 ?>
416 <button class="sp-size-chart <?php echo esc_attr( $icon ? 'has-icon' : '' ); ?>">
417 <?php echo $icon ? wp_kses( $icon, sp_allowd_svg_tags() ) : ''; ?>
418 <?php echo esc_html( $label ); ?>
419 </button>
420 <div class="size-chart-overlay sp-popup-overlay" style="display:none;">
421 <div class="size-chart-content sp-popup-content">
422 <div class="size-chart-close sp-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>
423 <?php echo wp_kses_post( static::display_size_chart( $product_id ) ); ?>
424 </div>
425 </div>
426 <?php
427 }
428
429 /**
430 * Return size charts
431 *
432 * @since 1.2.0
433 *
434 * @return array
435 */
436 public static function get_size_charts() {
437 $args = array(
438 'post_type' => 'shoppress_size_chart',
439 'posts_per_page' => 200,
440 'fields' => 'ids',
441 );
442 $size_charts_ids = get_posts( $args );
443
444 $size_charts = array();
445 $meta_keys = self::get_meta_fields();
446 foreach ( $size_charts_ids as $size_chart_id ) {
447
448 foreach ( $meta_keys as $meta_key ) {
449 $size_charts[ $size_chart_id ][ $meta_key ] = get_post_meta( $size_chart_id, $meta_key, true );
450 }
451 }
452
453 return $size_charts;
454 }
455
456 /**
457 * Return size charts
458 *
459 * @param int $product_id
460 *
461 * @since 1.2.0
462 *
463 * @return array
464 */
465 public static function get_available_size_charts( $product_id = 0 ) {
466 $_size_charts = self::get_size_charts();
467 $size_charts = array();
468 if ( ! is_array( $_size_charts ) ) {
469 return $size_charts;
470 }
471
472 $user_id = get_current_user_id();
473 if ( $user_id ) {
474 $user = get_userdata( $user_id );
475 $user_roles = $user->roles;
476 }
477
478 if ( $product_id ) {
479
480 $product = wc_get_product( $product_id );
481 $parent_id = $product->get_parent_id();
482 $product_id = $parent_id ? $parent_id : $product_id;
483 }
484
485 foreach ( $_size_charts as $key => $size_chart ) {
486
487 $status = $size_chart['status'] ?? false;
488 $image = $size_chart['image'] ?? false;
489 $content_type = $size_chart['content_type'] ?? false;
490
491 if ( empty( $size_chart ) || ! $status && ( ! $image || ! $content_type ) ) {
492 continue;
493 }
494
495 $product_categories_operator = $size_chart['product_categories_operator']['value'] ?? 'all';
496 $size_chart['product_categories_operator'] = $product_categories_operator;
497 $size_chart['product_categories'] = isset( $size_chart['product_categories'] ) && is_array( $size_chart['product_categories'] ) ? array_column( $size_chart['product_categories'], 'value' ) : array();
498
499 $products_operator = $size_chart['products_operator']['value'] ?? 'all';
500 $size_chart['products_operator'] = $products_operator;
501 $size_chart['products'] = is_array( $size_chart['products'] ) ? array_column( $size_chart['products'], 'value' ) : array();
502 $size_chart['content_type'] = $size_chart['content_type'] ?? '';
503 $size_chart['id'] = $key;
504
505 if ( $product_id ) {
506
507 $product_category_ids = wp_get_post_terms( $product_id, 'product_cat', array( 'fields' => 'ids' ) );
508 $product_categories_intersect = array_intersect( $product_category_ids, $size_chart['product_categories'] );
509
510 if (
511 ! empty( $size_chart['product_categories'] )
512 &&
513 (
514 ( 'include' == $product_categories_operator && empty( $product_categories_intersect ) )
515 ||
516 ( 'exclude' == $product_categories_operator && ! empty( $product_categories_intersect ) )
517 )
518 ) {
519 continue;
520 }
521
522 if (
523 ! empty( $size_chart['products'] )
524 &&
525 (
526 ( 'include' == $products_operator && ! in_array( $product_id, $size_chart['products'] ) )
527 ||
528 ( 'exclude' == $products_operator && in_array( $product_id, $size_chart['products'] ) )
529 )
530 ) {
531 continue;
532 }
533 }
534
535 $size_charts[ $key ] = $size_chart;
536 }
537
538 return $size_charts;
539 }
540
541 /**
542 * Return size chart
543 *
544 * @param int $product_id
545 *
546 * @since 1.2.0
547 *
548 * @return array|false
549 */
550 public static function get_available_size_chart( $product_id = 0 ) {
551
552 $size_charts = static::get_available_size_charts( $product_id );
553
554 return is_array( $size_charts ) && count( $size_charts ) ? current( $size_charts ) : false;
555 }
556
557 /**
558 * Add Add elementor widgets.
559 *
560 * @since 1.2.0
561 *
562 * @return array
563 */
564 public static function add_elementor_widget( $widgets ) {
565
566 $widgets['single-size-chart'] = array(
567 'editor_type' => 'single',
568 'class_name' => 'SizeChart',
569 'is_pro' => false,
570 'path_key' => 'single-product/size-chart',
571 );
572
573 return $widgets;
574 }
575 }
576