PluginProbe
UiCore Elements – Free widgets and templates for Elementor / 1.0.14
UiCore Elements – Free widgets and templates for Elementor v1.0.14
1.3.17 1.3.16 trunk 1.0.0 1.0.1 1.0.10 1.0.11 1.0.12 1.0.13 1.0.14 1.0.15 1.0.16 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.0.7 1.0.8 1.0.9 1.2.0 1.2.1 1.2.2 1.2.3 1.2.4 All 41 releases
uicore-elements / includes / utils / product-component.php

product-component.php in UiCore Elements – Free widgets and templates for Elementor 1.0.14, at includes/utils/product-component.php

275 lines 11.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 namespace UiCoreElements\Utils;
3
4 use UiCoreElements\Helper;
5 use UiCoreElements\Controls\Query;
6
7 use UiCoreElements\Utils\Meta_Trait;
8 use UiCoreElements\Utils\Post_Trait;
9
10 defined('ABSPATH') || exit();
11
12 /**
13 * Product Component
14 *
15 * @since 1.0.11
16 */
17
18 trait Product_Trait {
19
20 use Post_Trait,
21 Meta_Trait;
22
23 /**
24 * Returns the proper query args for the product loop.
25 *
26 * @param array $settings Elementor controls settings.
27 * @param array|WP_Query $default_query The default query variables.
28 *
29 * @return array|stdClass Return the products data, prepared for loop.
30 */
31 function TRAIT_query_products($settings, $default_query)
32 {
33 $post_type = $settings['product-filter_post_type'];
34
35 switch ($post_type){
36 case 'current' :
37 $query_args = $default_query;
38
39 // Set pagination
40 $query_args['paged'] = Query::get_queried_page($settings);
41
42 // Set tax filters for filter component, if enabled
43 $queried_filters = Query::get_queried_filters($settings, 'product', 'product-filter');
44 $query_args['tax_query'] = empty($queried_filters['tax_query']) ? [] : $queried_filters['tax_query'];
45 break;
46
47 //
48 case 'related' :
49 return Helper::get_product_related($settings['item_limit']['size']);
50 break;
51
52 default :
53 $query_args = Query::get_query_args('product-filter', $settings, true);
54 break;
55 }
56
57 // Set total pages
58 $query_args['total_pages'] = Query::get_total_pages($query_args);
59
60 // Hide out of stock products
61 if( $settings['hide_out_of_stock'] === 'yes' ){
62 $query_args['meta_query'] = [
63 [
64 'key' => '_stock_status',
65 'value' => 'instock',
66 'compare' => '=',
67 ]
68 ];
69 }
70
71 $this->_query = $query_args;
72
73 return wc_get_products($query_args);
74 }
75
76
77 // Render functions
78 function get_product_image(object $product)
79 {
80 if ($this->get_settings_for_display('image') !== 'yes') {
81 return;
82 }
83
84 // Get product image ID
85 $pic_id = $product->get_image_id();
86 if (!$pic_id) {
87 return;
88 }
89
90 // Get image size
91 $size = $this->get_settings_for_display('image_size_select') ?? 'uicore-medium';
92 ?>
93 <a class="ui-e-post-img-wrapp"
94 href="<?php echo esc_url($product->get_permalink()); ?>"
95 title="<?php echo esc_attr__('View Product:', 'uicore-elements') . ' ' . esc_attr($product->get_name()); ?>">
96
97 <?php if ($this->get_settings_for_display('masonry') === 'ui-e-maso') { ?>
98 <?php
99 // Get secondary image if available
100 $sec_img = $this->get_product_secondary_image( $product );
101 $classes = $sec_img ? 'ui-e-post-img ui-e-hover-hide' : 'ui-e-post-img';
102
103 // Print secondary image markup if exists
104 echo $sec_img ? wp_kses_post($sec_img) : '';
105
106 // Print main product image
107 echo wp_get_attachment_image($pic_id, $size, false, ['class' => $classes]);
108 ?>
109 <?php } else { ?>
110 <?php
111 // Get secondary image with size
112 $sec_img = $this->get_product_secondary_image( $product, $size, true );
113 echo $sec_img ? wp_kses_post($sec_img) : '';
114 ?>
115 <div class="ui-e-post-img <?php echo $sec_img ? 'ui-e-hover-hide' : ''; ?>"
116 style="background-image:url(<?php echo wp_get_attachment_image_url($pic_id, $size); ?>)">
117 </div>
118 <?php } ?>
119 </a>
120 <?php
121 }
122 function get_product_secondary_image($product, $size = 'woocommerce_thumbnail', $bg_output = false)
123 {
124 // Requested only for products with change-image animation
125 if( 'ui-e-img-anim-change' !== $this->get_settings_for_display('anim_image') ) {
126 return false;
127 }
128
129 // Get product gallery image IDs
130 $gallery_image_ids = $product->get_gallery_image_ids();
131
132 // Check if there is at least one gallery image
133 if (empty($gallery_image_ids)) {
134 return false;
135 }
136
137 // Get the first image from the gallery
138 $secondary_image_id = $gallery_image_ids[0];
139 $secondary_image_url = wp_get_attachment_image_url($secondary_image_id, $size);
140
141 // Output secondary image as <img> or background <div>
142 if ($bg_output) {
143 return sprintf(
144 '<div class="ui-e-post-img ui-e-post-img-secondary" style="background-image: url(%s);"></div>',
145 esc_url($secondary_image_url)
146 );
147 } else {
148 return wp_get_attachment_image($secondary_image_id, $size, false, [
149 'class' => 'ui-e-post-img ui-e-post-img-secondary'
150 ]);
151 }
152 }
153 function get_product_title($product)
154 {
155 if ($this->get_settings_for_display('title') !== 'yes') {
156 return;
157 }
158
159 ?>
160 <a href="<?php echo esc_url($product->get_permalink()); ?>"
161 title="<?php echo esc_attr__('View Product:', 'uicore-elements') . ' ' . esc_html($product->get_name()); ?>">
162 <h4 class="ui-e-post-title"><span><?php echo esc_html($product->get_name()); ?></span></h4>
163 </a>
164 <?php
165 }
166
167 /**
168 * Renders a product item with various settings and options.
169 * Important: any changes here should also be considered to `TRAIT_render_item()` from Post Component.
170 *
171 * @param WC_Product $product The product object.
172 * @param bool $carousel Indicates if the item needs carousel classnames.
173 * @param bool $legacy Indicates if the item is using legacy classnames.
174 * @param bool $is_ajax Indicates if the item is being rendered through REST API.
175 *
176 * @return void
177 */
178 function TRAIT_render_product($product, $carousel = false, $legacy = false, $is_ajax = false)
179 {
180 $settings = $this->get_settings_for_display();
181 $excerpt_length = $settings['excerpt_trim'];
182
183 // Classnames but checking if we the widget is APG (legacy version)
184 $item_classes = $legacy ? ['ui-e-post-item', 'ui-e-item'] : ['ui-e-item'] ; // Single item lower wrap class receptor
185 $hover_item_class = $legacy ? 'anim_item' : 'item_hover_animation'; // item hover animation class
186
187 // If widget is not carousel type, we set animations classes directly on item selector
188 if(!$carousel) {
189 $item_classes[] = 'ui-e-animations-wrp';
190 $item_classes[] = $settings['animate_items'] === 'ui-e-grid-animate' ? 'elementor-invisible' : '';
191 $item_classes[] = $settings[$hover_item_class] !== '' ? $settings[$hover_item_class] : '';
192
193 } else {
194 // Get entrance and item hover animation classes
195 $entrance = (isset($settings['animate_items']) && $settings['animate_items'] == 'ui-e-grid-animate') ? 'elementor-invisible' : '';
196 $hover = isset($settings[$hover_item_class]) ? $settings[$hover_item_class] : ''; //$settings[$hover_item_class] : null;
197 $animations = sprintf('%s %s', $entrance, $hover);
198
199 // Check if entrance or hover animation are set
200 $has_animation = !empty($entrance) || !empty($hover)
201
202 // Prints extra wrappers required by the carousel script
203 ?>
204 <div class="ui-e-wrp swiper-slide">
205 <?php if($has_animation) : ?>
206 <div class="ui-e-animations-wrp <?php echo esc_attr($animations);?>">
207 <?php endif; ?>
208
209 <?php } ?>
210
211 <div class="<?php echo esc_attr( implode(' ', $item_classes));?>">
212 <article <?php post_class('product'); ?>>
213 <div class="ui-e-post-top">
214 <?php $this->get_product_image($product); ?>
215 <?php $this->get_post_meta('top'); ?>
216 <?php
217 if($settings['button_position'] === 'ui-e-button-placement-image') {
218 $this->TRAIT_get_button(true);
219 }
220 ?>
221 </div>
222 <div class="ui-e-post-content">
223 <?php $this->get_post_meta('before_title'); ?>
224 <?php
225 if ($this->get_settings_for_display('title') === 'yes')
226 $this->get_product_title($product);
227 ?>
228 <?php $this->get_post_meta('after_title'); ?>
229 <?php
230 if ($this->get_settings_for_display('excerpt'))
231 echo wp_kses_post('<div class="ui-e-post-text">' . wp_trim_words(get_the_excerpt(), $excerpt_length) . '</div>');
232 ?>
233 <?php $this->get_post_meta('bottom'); // button
234 ?>
235 <?php
236 if( defined('UICORE_VERSION') && version_compare(UICORE_VERSION, '6.0.1', '>=') && $this->get_settings_for_display('show_swatches') === 'yes' ){
237 // ajax requests works under minimal conditions, wich means Swatches class is not present
238 if ( $is_ajax ) {
239 require_once UICORE_INCLUDES . '/woocommerce/components/class-swatches.php';
240 }
241
242 \UiCore\WooCommerce\Swatches::print_swatches($product); // from Uicore Framework
243 }
244 if ( $this->get_settings_for_display('show_button') === 'yes' ) {
245 // Add match height spacing element if carousel. May look intrusive, but is the simplest method compared
246 // to absolute positioning or catching last content element to apply margin.
247 if($carousel && $settings['match_height'] === 'yes'){
248 ?>
249 <span class="ui-e-match-height"></span>
250 <?php
251 }
252
253 if( !isset($settings['button_position']) || empty($settings['button_position']) ) {
254 $this->TRAIT_get_button(true);
255 }
256 }
257 ?>
258 </div>
259 </article>
260 </div>
261
262 <?php if($carousel) { ?>
263 </div>
264 <?php if($has_animation) : ?>
265 </div>
266 <?php endif; ?>
267
268 <?php }
269 }
270
271 // TODO: discover why using Post_Trait here forces us to have
272 // this public content_template() to avoid fatal error
273 public function content_template() {}
274 }
275