PluginProbe ʕ •ᴥ•ʔ
ShopEngine Elementor WooCommerce Builder Addon – All in One WooCommerce Solution / 1.1.0
ShopEngine Elementor WooCommerce Builder Addon – All in One WooCommerce Solution v1.1.0
4.9.1 4.9.0 2.0.0 2.1.0 2.2.0 2.2.1 2.2.2 2.3.0 2.4.0 2.5.0 2.5.1 3.0.0 3.1.0 3.1.1 4.0.0 4.0.1 4.1.0 4.1.1 4.2.0 4.2.1 4.3.0 4.3.1 4.4.0 4.5.0 4.5.1 4.6.0 4.6.1 4.6.2 4.6.3 4.6.4 4.6.5 4.6.6 4.6.7 4.6.8 4.6.9 4.7.0 4.7.1 4.7.2 4.7.3 4.7.4 4.7.5 4.7.6 4.7.7 4.7.8 4.7.9 4.8.0 4.8.1 4.8.2 4.8.3 4.8.4 4.8.5 4.8.6 4.8.7 4.8.8 4.8.9 trunk 0.1.2-beta 0.1.3-beta 0.1.4-beta 1.0.0 1.1.0 1.1.1 1.1.2 1.1.3 1.2.0 1.2.1 1.3.0 1.3.1 1.3.2 1.3.3 1.3.4 1.4.0 1.4.1 1.5.0 1.5.1 1.6.0 1.6.1 1.7.0 1.8.0 1.8.1 1.9.0
shopengine / widgets / shop.php
shopengine / widgets Last commit date
account-address 4 years ago account-dashboard 4 years ago account-details 4 years ago account-downloads 4 years ago account-form-login 4 years ago account-form-register 4 years ago account-logout 4 years ago account-navigation 4 years ago account-order-details 4 years ago account-orders 4 years ago add-to-cart 4 years ago additional-information 4 years ago advanced-search 4 years ago archive-description 4 years ago archive-products 4 years ago archive-result-count 4 years ago archive-title 4 years ago archive-view-mode 4 years ago breadcrumbs 4 years ago cart-table 4 years ago cart-totals 4 years ago categories 4 years ago checkout-coupon-form 4 years ago checkout-form-additional 4 years ago checkout-form-billing 4 years ago checkout-form-login 4 years ago checkout-form-shipping 4 years ago checkout-payment 4 years ago checkout-review-order 4 years ago checkout-shipping-methods 4 years ago cross-sells 4 years ago deal-products 4 years ago empty-cart-message 4 years ago filter-orderby 4 years ago filter-products-per-page 4 years ago filterable-product-list 4 years ago init 4 years ago product-categories 4 years ago product-category-lists 4 years ago product-description 4 years ago product-excerpt 4 years ago product-filters 4 years ago product-image 4 years ago product-list 4 years ago product-meta 4 years ago product-price 4 years ago product-rating 4 years ago product-review 4 years ago product-share 4 years ago product-sku 4 years ago product-stock 4 years ago product-tabs 4 years ago product-tags 4 years ago product-title 4 years ago recently-viewed-products 4 years ago related 4 years ago return-to-shop 4 years ago thankyou-address-details 4 years ago thankyou-order-confirm 4 years ago thankyou-order-details 4 years ago thankyou-thankyou 4 years ago up-sells 4 years ago lazy-cache.php 4 years ago manifest.php 4 years ago prod-short-code.php 5 years ago products.php 4 years ago shop.php 5 years ago widget-helper.php 4 years ago
shop.php
319 lines
1 <?php
2
3 namespace ShopEngine\Widgets;
4
5 defined('ABSPATH') || exit;
6
7 class Shop extends \WC_Shortcode_Products {
8
9 private static $_instance = null;
10 private $settings = array();
11 private $is_added_product_filter = false;
12
13
14 public function __construct($settings = array(), $type = 'products') {
15
16 $this->settings = $settings;
17 $this->type = $type;
18
19 $this->attributes = $this->parse_attributes([
20 'columns' => $settings['columns'],
21 'rows' => $settings['rows'],
22 'paginate' => $settings['paginate'],
23 'class' => $settings['class'],
24 'cache' => false,
25 ]);
26
27 $this->query_args = $this->parse_query_args();
28 }
29
30
31 protected function get_query_results() {
32
33 $results = parent::get_query_results();
34 // Start edit.
35 if($this->is_added_product_filter) {
36 remove_action('pre_get_posts', [wc()->query, 'product_query']);
37 }
38
39 // End edit.
40
41 return $results;
42 }
43
44
45 protected function parse_query_args() {
46 $settings = $this->settings;
47 $query_args = [
48 'post_type' => 'product',
49 'post_status' => 'publish',
50 'ignore_sticky_posts' => true,
51 'no_found_rows' => false === wc_string_to_bool($this->attributes['paginate']),
52 ];
53
54 if('preview' == $this->settings['query_post_type']) {
55 $query_args = $GLOBALS['wp_query']->query_vars;
56
57 // Fix for parent::get_transient_name.
58 $query_args['p'] = 0;
59 $query_args['post_type'] = 'product';
60 $query_args['post_status'] = 'publish';
61 $query_args['ignore_sticky_posts'] = true;
62 $query_args['no_found_rows'] = false === wc_string_to_bool($this->attributes['paginate']);
63 $query_args['orderby'] = '';
64 $query_args['order'] = '';
65
66 // Allow queries to run e.g. layered nav.
67 add_action('pre_get_posts', array(wc()->query, 'product_query'));
68
69 $this->is_added_product_filter = true;
70
71 } elseif('current_query' == $this->settings['query_post_type']) {
72 if(!is_page(wc_get_page_id('shop'))) {
73 $query_args = $GLOBALS['wp_query']->query_vars;
74 }
75
76 // Fix for parent::get_transient_name.
77 if(!isset($query_args['orderby'])) {
78 $query_args['orderby'] = '';
79 $query_args['order'] = '';
80 }
81
82 add_action('pre_get_posts', [wc()->query, 'product_query']);
83 $this->is_added_product_filter = true;
84
85 } else {
86 $query_args = [
87 'post_type' => 'product',
88 'post_status' => 'publish',
89 'ignore_sticky_posts' => true,
90 'no_found_rows' => false === wc_string_to_bool($this->attributes['paginate']),
91 'orderby' => $settings['orderby'],
92 'order' => strtoupper($settings['order']),
93 ];
94
95 $query_args['meta_query'] = WC()->query->get_meta_query();
96 $query_args['tax_query'] = [];
97 // @codingStandardsIgnoreEnd
98
99 // Visibility.
100 $this->set_visibility_query_args($query_args);
101
102 // SKUs.
103 $this->set_featured_query_args($query_args);
104
105 // IDs.
106 $this->set_ids_query_args($query_args);
107
108 // Set specific types query args.
109 if(method_exists($this, "set_{$this->type}_query_args")) {
110 $this->{"set_{$this->type}_query_args"}($query_args);
111 }
112
113 // Categories.
114 $this->set_categories_query_args($query_args);
115
116 // Tags.
117 $this->set_tags_query_args($query_args);
118
119 $query_args = apply_filters('woocommerce_shortcode_products_query', $query_args, $this->attributes, $this->type);
120
121 if('yes' === $settings['paginate'] && 'yes' === $settings['allow_order']) {
122 $ordering_args = WC()->query->get_catalog_ordering_args();
123 } else {
124 $ordering_args = WC()->query->get_catalog_ordering_args($query_args['orderby'], $query_args['order']);
125 }
126
127 $query_args['orderby'] = $ordering_args['orderby'];
128 $query_args['order'] = $ordering_args['order'];
129 if($ordering_args['meta_key']) {
130 $query_args['meta_key'] = $ordering_args['meta_key'];
131 }
132
133 $query_args['posts_per_page'] = intval($settings['columns'] * $settings['rows']);
134 } // End if().
135
136 if('yes' === $settings['paginate']) {
137 $page = empty($_GET['product-page']) ? 1 : absint($_GET['product-page']);
138
139 if(1 < $page) {
140 $query_args['paged'] = $page;
141 }
142
143 if('yes' !== $settings['allow_order']) {
144 remove_action('woocommerce_before_shop_loop', 'woocommerce_catalog_ordering', 30);
145 }
146
147 if('yes' !== $settings['show_result_count']) {
148 remove_action('woocommerce_before_shop_loop', 'woocommerce_result_count', 20);
149 }
150 }
151 $query_args['posts_per_page'] = intval($settings['columns'] * $settings['rows']);
152
153 // Always query only IDs.
154 $query_args['fields'] = 'ids';
155
156 return $query_args;
157 }
158
159
160 protected function set_ids_query_args(&$query_args) {
161 switch($this->settings['query_post_type']) {
162 case 'by_id':
163 $post__in = $this->settings['query_posts_ids'];
164 break;
165 case 'sale':
166 $post__in = wc_get_product_ids_on_sale();
167 break;
168 }
169
170 if(!empty($post__in)) {
171 $query_args['post__in'] = $post__in;
172 remove_action('pre_get_posts', [wc()->query, 'product_query']);
173 }
174 }
175
176
177 protected function set_categories_query_args(&$query_args) {
178 $query_type = $this->settings['query_post_type'];
179
180 if('by_id' === $query_type || 'current_query' === $query_type) {
181 return;
182 }
183
184 if(!empty($this->settings['query_product_cat_ids'])) {
185 $query_args['tax_query'][] = [
186 'taxonomy' => 'product_cat',
187 'terms' => $this->settings['query_product_cat_ids'],
188 'field' => 'term_id',
189 ];
190 }
191 }
192
193
194 protected function set_tags_query_args(&$query_args) {
195 $query_type = $this->settings['query_post_type'];
196
197 if('by_id' === $query_type || 'current_query' === $query_type) {
198 return;
199 }
200
201 if(!empty($this->settings['query_product_tag_ids'])) {
202 $query_args['tax_query'][] = [
203 'taxonomy' => 'product_tag',
204 'terms' => $this->settings['query_product_tag_ids'],
205 'field' => 'term_id',
206 'operator' => 'IN',
207 ];
208 }
209 }
210
211
212 protected function set_featured_query_args(&$query_args) {
213 if('featured' === $this->settings['query_post_type']) {
214 $product_visibility_term_ids = wc_get_product_visibility_term_ids();
215
216 $query_args['tax_query'][] = [
217 'taxonomy' => 'product_visibility',
218 'field' => 'term_taxonomy_id',
219 'terms' => [$product_visibility_term_ids['featured']],
220 ];
221 }
222 }
223
224
225 /**
226 * Loop over found products.
227 *
228 * @since 3.2.0
229 * @return string
230 */
231 protected function product_loop() {
232 $columns = absint($this->attributes['columns']);
233 $classes = $this->get_wrapper_classes($columns);
234 $products = $this->get_query_results();
235
236 ob_start();
237
238 if($products && $products->ids) {
239 // Prime caches to reduce future queries.
240 if(is_callable('_prime_post_caches')) {
241 _prime_post_caches($products->ids);
242 }
243
244 // Setup the loop.
245 wc_setup_loop(
246 array(
247 'columns' => $columns,
248 'name' => $this->type,
249 'is_shortcode' => true,
250 'is_search' => false,
251 'is_paginated' => wc_string_to_bool($this->attributes['paginate']),
252 'total' => $products->total,
253 'total_pages' => $products->total_pages,
254 'per_page' => $products->per_page,
255 'current_page' => $products->current_page,
256 )
257 );
258
259 $original_post = $GLOBALS['post'];
260
261 do_action("woocommerce_shortcode_before_{$this->type}_loop", $this->attributes);
262
263 // Fire standard shop loop hooks when paginating results so we can show result counts and so on.
264 if(wc_string_to_bool($this->attributes['paginate'])) {
265
266 if(wc_string_to_bool($this->settings['allow_order'])) {
267 woocommerce_catalog_ordering();
268 }
269 if(wc_string_to_bool($this->settings['show_result_count'])) {
270 woocommerce_result_count();
271 }
272 }
273
274 woocommerce_product_loop_start();
275
276 if(wc_get_loop_prop('total')) {
277 foreach($products->ids as $product_id) {
278 $GLOBALS['post'] = get_post($product_id); // WPCS: override ok.
279 setup_postdata($GLOBALS['post']);
280
281 // Set custom product visibility when quering hidden products.
282 add_action('woocommerce_product_is_visible', array($this, 'set_product_as_visible'));
283
284 // Render product template.
285 wc_get_template_part('content', 'product');
286
287 // Restore product visibility.
288 remove_action('woocommerce_product_is_visible', array($this, 'set_product_as_visible'));
289 }
290 }
291
292 $GLOBALS['post'] = $original_post; // WPCS: override ok.
293 woocommerce_product_loop_end();
294
295 // Fire standard shop loop hooks when paginating results so we can show result counts and so on.
296 if(wc_string_to_bool($this->attributes['paginate'])) {
297 if($this->settings['query_post_type'] == 'preview') {
298 woocommerce_pagination();
299 } else {
300 do_action('woocommerce_after_shop_loop');
301 }
302 }
303
304 do_action("woocommerce_shortcode_after_{$this->type}_loop", $this->attributes);
305
306 wp_reset_postdata();
307 wc_reset_loop();
308 } else {
309 if($this->settings['nothing_found_message']) {
310 echo '<div class="woocommerce-info elementor-nothing-found elementor-products-nothing-found">' . esc_html($this->settings['nothing_found_message']) . '</div>';
311 } else {
312 do_action("woocommerce_shortcode_{$this->type}_loop_no_results", $this->attributes);
313 }
314 }
315
316 return '<div class="' . esc_attr(implode(' ', $classes)) . '">' . ob_get_clean() . '</div>';
317 }
318
319 }