PluginProbe
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler / 1.5.3
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler v1.5.3
1.6.6 1.6.5 1.6.4 1.6.3 1.6.2 1.6.1 1.6.0 1.5.4 1.5.5 1.5.3 1.5.2 1.5.1 1.5.0 1.4.2 1.4.1 1.4.0 1.3.28 1.3.27 1.3.26 1.3.25 1.3.23 1.3.22 1.3.21 1.3.20 1.3.19 All 49 releases
fluent-cart / app / Modules / Templating / Bricks / Elements / ProductsCollection.php

ProductsCollection.php in FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler 1.5.3, at app/Modules/Templating/Bricks/Elements/ProductsCollection.php

787 lines 26.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace FluentCart\App\Modules\Templating\Bricks\Elements;
4
5 use Bricks\Custom_Render_Element;
6 use Bricks\Helpers;
7 use Bricks\Query;
8 use FluentCart\App\Modules\Data\ProductDataSetup;
9 use FluentCart\App\Modules\Data\ProductQuery;
10 use FluentCart\App\Modules\Templating\AssetLoader;
11 use FluentCart\App\Modules\Templating\Bricks\BricksHelper;
12 use FluentCart\App\Services\Renderer\RenderHelper;
13 use FluentCart\App\Services\Renderer\ShopAppRenderer;
14 use FluentCart\Framework\Support\Arr;
15 use FluentCart\App\Services\Renderer\ProductFilterRender;
16
17 if (!defined('ABSPATH')) exit; // Exit if accessed directly
18
19 class ProductsCollection extends Custom_Render_Element
20 {
21 public $category = 'fluent-cart';
22 public $name = 'fct-products';
23 public $icon = 'ti-archive fluent-cart-element-icon';
24
25 protected $cssRoot = '.fct-products-wrapper-inner .fct-products-container';
26
27 public function enqueue_scripts()
28 {
29 AssetLoader::loadProductArchiveAssets();
30
31 do_action('fluent_cart/advanced_variation/enqueue_assets');
32 }
33
34 public function get_label()
35 {
36 return esc_html__('Products', 'fluent-cart');
37 }
38
39 public function set_control_groups()
40 {
41 $this->control_groups['query'] = [
42 'title' => esc_html__('Query', 'fluent-cart'),
43 'tab' => 'content',
44 ];
45
46 $this->control_groups['fields'] = [
47 'title' => esc_html__('Fields', 'fluent-cart'),
48 'tab' => 'content',
49 ];
50
51 $this->control_groups['display'] = [
52 'title' => esc_html__('Display', 'fluent-cart'),
53 'tab' => 'content',
54 ];
55
56 $this->control_groups['filter'] = [
57 'title' => esc_html__('Filter', 'fluent-cart'),
58 'tab' => 'content',
59 ];
60
61 $this->control_groups['widgets'] = [
62 'title' => esc_html__('Widgets', 'fluent-cart'),
63 'tab' => 'widgets',
64 ];
65 }
66
67 public function set_controls()
68 {
69 // LAYOUT
70 $this->controls['viewMode'] = [
71 'tab' => 'content',
72 'group' => 'display',
73 'label' => esc_html__('View Mode', 'fluent-cart'),
74 'type' => 'select',
75 'options' => [
76 'grid' => esc_html__('Grid', 'fluent-cart'),
77 'list' => esc_html__('List', 'fluent-cart'),
78 ],
79 'placeholder' => esc_html__('Grid', 'fluent-cart'),
80 'rerender' => true,
81 ];
82
83 $this->controls['showViewSwitcher'] = [
84 'tab' => 'content',
85 'group' => 'display',
86 'label' => esc_html__('Show View Switcher', 'fluent-cart'),
87 'type' => 'checkbox',
88 'inline' => true,
89 'default' => true,
90 ];
91
92 $this->controls['paginationType'] = [
93 'tab' => 'content',
94 'group' => 'display',
95 'label' => esc_html__('Pagination Type', 'fluent-cart'),
96 'type' => 'select',
97 'options' => [
98 'scroll' => esc_html__('Scroll', 'fluent-cart'),
99 'numbers' => esc_html__('Numbers', 'fluent-cart'),
100 ],
101 'placeholder' => esc_html__('Numbers', 'fluent-cart'),
102 ];
103
104 $this->controls['columns'] = [
105 'tab' => 'content',
106 'label' => esc_html__('Columns', 'fluent-cart'),
107 'type' => 'number',
108 'min' => 1,
109 'max' => 5,
110 'breakpoints' => true,
111 'placeholder' => 4,
112 'rerender' => true,
113 ];
114
115 $this->controls['gap'] = [
116 'tab' => 'content',
117 'label' => esc_html__('Gap', 'fluent-cart'),
118 'type' => 'number',
119 'units' => true,
120 'css' => [
121 [
122 'selector' => $this->cssRoot,
123 'property' => 'gap',
124 ],
125 ],
126 'placeholder' => 30,
127 ];
128
129 $this->controls['posts_per_page'] = [
130 'tab' => 'content',
131 'label' => esc_html__('Products per page', 'fluent-cart'),
132 'type' => 'number',
133 'min' => 1,
134 'max' => 100,
135 'placeholder' => 10,
136 'step' => 1,
137 ];
138
139 $this->controls['is_main_query'] = [
140 'tab' => 'content',
141 'label' => esc_html__('Is main query', 'fluent-cart'),
142 'type' => 'checkbox',
143 'inline' => true,
144 ];
145
146 // QUERY
147 $this->controls['orderby'] = [
148 'tab' => 'content',
149 'label' => esc_html__('Order by', 'fluent-cart'),
150 'type' => 'select',
151 // id|date|title|price
152 'options' => [
153 'price' => esc_html__('Price', 'fluent-cart'),
154 'title' => esc_html__('Product Name', 'fluent-cart'),
155 'date' => esc_html__('Published date', 'fluent-cart'),
156 'id' => esc_html__('Product ID', 'fluent-cart')
157 ],
158 'inline' => true,
159 'placeholder' => esc_html__('Default', 'fluent-cart'),
160 ];
161
162 $this->controls['order'] = [
163 'tab' => 'content',
164 'label' => esc_html__('Order', 'fluent-cart'),
165 'type' => 'select',
166 'options' => [
167 'ASC' => esc_html__('Ascending', 'fluent-cart'),
168 'DESC' => esc_html__('Descending', 'fluent-cart'),
169 ],
170 'inline' => true,
171 'placeholder' => esc_html__('Descending', 'fluent-cart'),
172 ];
173
174 $this->controls['main_query_info'] = [
175 'tab' => 'content',
176 'group' => 'query',
177 'type' => 'info',
178 'content' => esc_html__('The query settings will be ignored when Is main query is enabled.', 'fluent-cart'),
179 ];
180
181 $this->controls['productType'] = [
182 'tab' => 'content',
183 'group' => 'query',
184 'label' => esc_html__('Product type', 'fluent-cart'),
185 'type' => 'select',
186 // physical|digital|subscription|onetime|simple|variations
187 'options' => [
188 'simple' => esc_html__('Simple', 'fluent-cart'),
189 'physical' => esc_html__('Physical', 'fluent-cart'),
190 'digital' => esc_html__('Digital', 'fluent-cart'),
191 'variations' => esc_html__('Variations', 'fluent-cart'),
192 'ontime' => esc_html__('One-time', 'fluent-cart'),
193 'subscription' => esc_html__('Subscriptions', 'fluent-cart'),
194 ],
195 'multiple' => false,
196 'placeholder' => esc_html__('all product types', 'fluent-cart'),
197 ];
198
199 $this->controls['include'] = [
200 'tab' => 'content',
201 'group' => 'query',
202 'label' => esc_html__('Include', 'fluent-cart'),
203 'type' => 'select',
204 'optionsAjax' => [
205 'action' => 'bricks_get_posts',
206 'postType' => 'fluent-products',
207 ],
208 'multiple' => true,
209 'searchable' => true,
210 'placeholder' => esc_html__('Select products', 'fluent-cart'),
211 ];
212
213 //phpcs:ignore WordPressVIPMinimum.Performance.WPQueryParams.PostNotIn_exclude
214 $this->controls['exclude'] = [
215 'tab' => 'content',
216 'group' => 'query',
217 'label' => esc_html__('Exclude', 'fluent-cart'),
218 'type' => 'select',
219 'optionsAjax' => [
220 'action' => 'bricks_get_posts',
221 'postType' => 'fluent-products',
222 ],
223 'multiple' => true,
224 'searchable' => true,
225 'placeholder' => esc_html__('Select products', 'fluent-cart'),
226 ];
227
228 $this->controls['categories'] = [
229 'tab' => 'content',
230 'group' => 'query',
231 'label' => esc_html__('Product categories', 'fluent-cart'),
232 'type' => 'select',
233 'options' => BricksHelper::getCategoriesOptions(),
234 'multiple' => true,
235 ];
236
237 $this->controls['onSale'] = [
238 'tab' => 'content',
239 'group' => 'query',
240 'label' => esc_html__('On sale Products only', 'fluent-cart'),
241 'type' => 'checkbox',
242 ];
243
244 $this->controls['allowOutOfStock'] = [
245 'tab' => 'content',
246 'group' => 'query',
247 'label' => esc_html__('Allow Out Of Stock', 'fluent-cart'),
248 'type' => 'checkbox',
249 ];
250
251 // FILTER
252 $this->controls['enableFilter'] = [
253 'tab' => 'content',
254 'group' => 'filter',
255 'label' => esc_html__('Enable Filter', 'fluent-cart'),
256 'type' => 'checkbox',
257 'inline' => true,
258 ];
259
260 $this->controls['enableSortBy'] = [
261 'tab' => 'content',
262 'group' => 'filter',
263 'label' => esc_html__('Enable Sort By', 'fluent-cart'),
264 'type' => 'checkbox',
265 'inline' => true,
266 'default' => true,
267 'required' => ['enableFilter', '=', true],
268 ];
269
270 $this->controls['liveFilter'] = [
271 'tab' => 'content',
272 'group' => 'filter',
273 'label' => esc_html__('Live Filter', 'fluent-cart'),
274 'type' => 'checkbox',
275 'inline' => true,
276 'required' => ['enableFilter', '=', true],
277 ];
278
279 $this->controls['wildcardFilter'] = [
280 'tab' => 'content',
281 'group' => 'filter',
282 'label' => esc_html__('Wildcard Filter', 'fluent-cart'),
283 'type' => 'checkbox',
284 'inline' => true,
285 'required' => ['enableFilter', '=', true],
286 ];
287
288 $this->controls['productCategories'] = [
289 'tab' => 'content',
290 'group' => 'filter',
291 'label' => esc_html__( 'Product Categories', 'fluent-cart' ),
292 'type' => 'checkbox',
293 'inline' => true,
294 'required' => ['enableFilter', '=', true],
295 ];
296
297 $this->controls['displayNameCategories'] = [
298 'tab' => 'content',
299 'group' => 'filter',
300 'label' => esc_html__('Display Name', 'fluent-cart'),
301 'type' => 'text',
302 'placeholder' => esc_html__('Custom filter label', 'fluent-cart'),
303 'required' => [
304 ['enableFilter', '=', true],
305 ['productCategories', '=', true],
306 ],
307 ];
308
309 $this->controls['productBrands'] = [
310 'tab' => 'content',
311 'group' => 'filter',
312 'label' => esc_html__( 'Product Brands', 'fluent-cart' ),
313 'type' => 'checkbox',
314 'inline' => true,
315 'required' => ['enableFilter', '=', true],
316 ];
317
318 $this->controls['displayNameBrands'] = [
319 'tab' => 'content',
320 'group' => 'filter',
321 'label' => esc_html__('Display Name', 'fluent-cart'),
322 'type' => 'text',
323 'placeholder' => esc_html__('Custom filter label', 'fluent-cart'),
324 'required' => [
325 ['enableFilter', '=', true],
326 ['productBrands', '=', true],
327 ],
328 ];
329
330 $this->controls['priceRange'] = [
331 'tab' => 'content',
332 'group' => 'filter',
333 'label' => esc_html__( 'Price Range', 'fluent-cart' ),
334 'type' => 'checkbox',
335 'inline' => true,
336 'required' => ['enableFilter', '=', true],
337 ];
338
339 $this->controls['displayNamePriceRange'] = [
340 'tab' => 'content',
341 'group' => 'filter',
342 'label' => esc_html__('Display Name', 'fluent-cart'),
343 'type' => 'text',
344 'placeholder' => esc_html__('Custom filter label', 'fluent-cart'),
345 'required' => [
346 ['enableFilter', '=', true],
347 ['priceRange', '=', true],
348 ],
349 ];
350
351 // FIELDS
352 $fields = $this->get_post_fields();
353
354 // Remove field settings
355 unset($fields['fields']['fields']['overlay']);
356 unset($fields['fields']['fields']['dynamicPadding']);
357 unset($fields['fields']['fields']['dynamicBackground']);
358 unset($fields['fields']['fields']['dynamicBorder']);
359
360 // Set fields defaults fields set
361 $fields['fields']['default'] = [
362 [
363 'dynamicData' => '{fct_product_image:link}',
364 'id' => Helpers::generate_random_id(false),
365 ],
366 [
367 'dynamicData' => '{fct_product_title:linked}',
368 'tag' => 'h5',
369 'id' => Helpers::generate_random_id(false),
370 ],
371 [
372 'dynamicData' => '{fct_product_excerpt}',
373 'tag' => 'p',
374 'id' => Helpers::generate_random_id(false),
375 ],
376 [
377 'dynamicData' => '{fct_product_price}',
378 'id' => Helpers::generate_random_id(false),
379 ],
380 [
381 'dynamicData' => '{fct_product_button}',
382 'id' => Helpers::generate_random_id(false),
383 ]
384 ];
385
386 $this->controls = array_replace_recursive($this->controls, $fields);
387
388 $this->controls['linkProduct'] = [
389 'tab' => 'content',
390 'group' => 'fields',
391 'label' => esc_html__('Link entire product', 'fluent-cart'),
392 'type' => 'checkbox',
393 'inline' => true,
394 'description' => esc_html__('Only added if none of your product fields contains any links.', 'fluent-cart'),
395 ];
396 }
397
398 public function render()
399 {
400 $settings = $this->settings;
401
402 $this->setBricksQuery();
403
404 $columns = $this->normalizeColumns(Arr::get($settings, 'columns', 4));
405
406 $viewMode = Arr::get($settings, 'viewMode', 'grid');
407 $showViewSwitcher = !empty($settings['showViewSwitcher']);
408 $paginationType = Arr::get($settings, 'paginationType', 'numbers');
409 $isMainQuery = Arr::get($settings, 'is_main_query', false) && $this->is_frontend;
410 $perPage = (int)Arr::get($settings, 'posts_per_page', 10);
411 $enableFilter = !empty($settings['enableFilter']);
412 $priceRange = !empty($settings['priceRange']);
413 $liveFilter = !empty($settings['liveFilter']);
414
415 $this->storeSettingsTransient($settings);
416
417 if ($perPage <= 0) {
418 $perPage = 10;
419 }
420
421 if ($perPage > 100) {
422 $perPage = 100;
423 }
424
425 $args = $this->buildQueryArgs(
426 $settings,
427 $isMainQuery,
428 $perPage,
429 $viewMode
430 );
431
432 $productsQuery = (new ProductQuery($args));
433 $products = $productsQuery->get();
434 $defaultFilters = $productsQuery->getDefaultFilters();
435 $ajaxDefaultFilters = $this->getAjaxDefaultFilters(
436 $defaultFilters,
437 $settings
438 );
439
440 $filters = $this->getFilters($settings);
441
442 $wrapperClass = 'fct-products-wrapper-inner ' . ($viewMode === 'list' ? 'mode-list' : 'mode-grid') . (!$enableFilter ? ' fct-full-container-width' : '');
443
444 $wrapperAttributes = [
445 'class' => $wrapperClass,
446 'data-fluent-cart-product-wrapper-inner' => '',
447 'data-per-page' => $perPage,
448 'data-order-type' => Arr::get($defaultFilters, 'sort_type'),
449 'data-live-filter' => $liveFilter,
450 'data-paginator' => esc_attr($paginationType),
451 'data-default-filters' => wp_json_encode($ajaxDefaultFilters)
452 ];
453
454 $productWrapperClasses = [
455 'fct-products-wrapper',
456 'fct-brick-products-wrapper',
457 ];
458
459 if (!$this->is_frontend) {
460 $productWrapperClasses[] = 'fct-bricks-editor-mode';
461 }
462
463 $rendererConfig = [
464 'view_mode' => $viewMode,
465 'enable_wildcard_filter' => !empty($settings['wildcardFilter']),
466 'custom_filters' => [
467 'enabled' => $enableFilter,
468 'price_range' => $priceRange,
469 'live_filter' => $liveFilter
470 ],
471 ];
472
473 // Only override enable_sort_by if explicitly set in settings (key exists)
474 if (array_key_exists('enableSortBy', $settings)) {
475 $rendererConfig['enable_sort_by'] = !empty($settings['enableSortBy']);
476 }
477
478 $shopAppRenderer = new ShopAppRenderer($products, $rendererConfig);
479
480 ?>
481 <div
482 <?php
483 //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- render_attributes() handles escaping internally
484 echo $this->render_attributes('_root');
485 ?>
486 >
487 <div
488 <?php
489 //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- render_attributes() handles escaping internally
490 echo $this->render_attributes('wrapper');
491 ?>
492 >
493 <div
494 class="<?php echo esc_attr(implode(' ', $productWrapperClasses)); ?>"
495 data-fluent-cart-shop-app
496 data-fluent-cart-product-wrapper
497 >
498 <!-- View switcher -->
499 <?php
500 if ($showViewSwitcher) {
501 $shopAppRenderer->renderViewSwitcher();
502 }
503 ?>
504
505 <!-- Products Container -->
506 <div <?php RenderHelper::renderAtts($wrapperAttributes); ?>>
507 <!-- Filter render here -->
508 <?php
509 if ($enableFilter) {
510 $productFilterRenderer = new ProductFilterRender($filters);
511 $shopAppRenderer->renderFilter($productFilterRenderer);
512 }
513 ?>
514
515 <!-- Products -->
516 <div
517 data-fluent-cart-shop-app-product-list
518 class="fct-products-container grid-columns-<?php echo esc_attr($columns); ?>"
519 >
520 <?php $this->renderProducts($products); ?>
521 </div>
522
523 <div class="fluent-cart-product-loader loader-hidden" data-fluent-cart-product-loader>
524 <div class="fluent-cart-product-spinner"></div>
525 </div>
526
527 </div>
528
529 <!-- Pagination -->
530 <?php
531 if ($paginationType !== 'scroll') {
532 $this->renderPagination(
533 $products,
534 $defaultFilters,
535 $paginationType,
536 $perPage,
537 $viewMode
538 );
539 }
540 ?>
541
542
543 </div>
544 </div>
545 </div>
546
547 <?php
548 }
549
550 /**
551 * Normalize columns count.
552 */
553 private function normalizeColumns($columns)
554 {
555 $columns = (int)$columns;
556
557 if (!$columns) {
558 return 4;
559 }
560
561 if ($columns > 5) {
562 return 5;
563 }
564
565 return $columns;
566 }
567
568 /**
569 * Store settings in transient.
570 */
571 private function storeSettingsTransient($settings)
572 {
573 $uuid = 'fc_bx_collection_' . $this->uid;
574 if (!get_transient($uuid)) {
575 // save the settings as transient
576 set_transient($uuid, $settings, 48 * HOUR_IN_SECONDS);
577 }
578 }
579
580 /**
581 * Build query args.
582 */
583 private function buildQueryArgs($settings, $isMainQuery, $perPage, $viewMode) {
584 $args = array_filter([
585 'paginate' => 'simple',
586 'is_main_query' => $isMainQuery,
587 'sort_by' => Arr::get($settings, 'orderby', 'date'),
588 'sort_type' => Arr::get($settings, 'order', 'desc'),
589 'per_page' => $perPage,
590 'view_mode' => $viewMode,
591 ]);
592
593 if (!$isMainQuery) {
594 $includeIds = Arr::get($settings, 'include', []);
595 if ($includeIds) {
596 $args['include_ids'] = $includeIds;
597 }
598
599 $excludeIds = Arr::get($settings, 'exclude', []);
600 if ($excludeIds) {
601 $args['exclude_ids'] = $excludeIds;
602 }
603
604 $productType = Arr::get($settings, 'productType', []);
605 if ($productType) {
606 $args['product_type'] = $productType;
607 }
608
609 $onSale = Arr::get($settings, 'onSale', false);
610
611 if ($onSale) {
612 $args['on_sale'] = true;
613 }
614
615 $allowOutOfStock = Arr::get($settings, 'allowOutOfStock', false);
616 if ($allowOutOfStock) {
617 $args['allow_out_of_stock'] = true;
618 }
619
620 $categories = Arr::get($settings, 'categories', []);
621 if ($categories) {
622 //phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query
623 $args['tax_query'] = [
624 'product-categories' => $categories,
625 ];
626 }
627 }
628
629 return $args;
630 }
631
632 /**
633 * Render product loop.
634 */
635
636 private function renderProducts($products) {
637 ProductDataSetup::setProductsCache($products);
638
639 $postIndex = 1;
640
641 foreach ($products as $product) {
642 $post = get_post($product->ID);
643
644 setup_postdata($post);
645
646 $this->set_loop_object($post);
647
648 $this->render_fields($post, $postIndex);
649
650 $this->next_iteration();
651
652 $postIndex++;
653 }
654
655 wp_reset_postdata();
656
657 $this->end_iteration();
658 }
659
660 /**
661 * Render pagination.
662 */
663 private function renderPagination(
664 $products,
665 $defaultFilters,
666 $paginationType,
667 $perPage,
668 $viewMode
669 ) {
670 $renderer = new ShopAppRenderer(
671 [
672 'products' => $products,
673 'total' => $products->total(),
674 ],
675 [
676 'default_filters' => $defaultFilters,
677 'pagination_type' => $paginationType,
678 'per_page' => $perPage,
679 'view_mode' => $viewMode,
680 ]
681 );
682
683 $renderer->renderPaginator();
684 }
685
686 /**
687 * Get available product filters.
688 */
689 private function getFilters(array $settings): array
690 {
691 $categoriesLabel = !empty($settings['displayNameCategories']) ? $settings['displayNameCategories'] : __('Product Categories', 'fluent-cart');
692 $brandsLabel = !empty($settings['displayNameBrands']) ? $settings['displayNameBrands'] : __('Product Brands', 'fluent-cart');
693 $priceRangeLabel = !empty($settings['displayNamePriceRange']) ? $settings['displayNamePriceRange'] : __('Price', 'fluent-cart');
694
695 $filters = [
696 'product-categories' => [
697 'filter_type' => 'options',
698 'is_meta' => true,
699 'label' => $categoriesLabel,
700 'enabled' => !empty($settings['productCategories']),
701 'multiple' => false,
702 ],
703 'product-brands' => [
704 'filter_type' => 'options',
705 'is_meta' => true,
706 'label' => $brandsLabel,
707 'enabled' => !empty($settings['productBrands']),
708 'multiple' => false,
709 ],
710 'price_range' => [
711 'filter_type' => 'range',
712 'is_meta' => false,
713 'label' => $priceRangeLabel,
714 'enabled' => !empty($settings['priceRange'])
715 ],
716 ];
717
718 return $filters;
719 }
720
721 private function setBricksQuery()
722 {
723 $query_object = new Query(
724 [
725 'id' => $this->id,
726 'name' => $this->name,
727 'settings' => $this->settings,
728 ]
729 );
730
731 // Set $bricks_query (@since 1.10.2)
732 $this->set_bricks_query($query_object);
733 $this->start_iteration();
734 }
735
736 public function render_fields($post, $post_index)
737 {
738 BricksHelper::renderCollectionCard($this->settings, $post, $post_index, $this->uid);
739 }
740
741 public function renderAjaxContents($products, $settings)
742 {
743
744 $this->settings = $settings;
745
746 $this->setBricksQuery();
747
748 ProductDataSetup::setProductsCache($products);
749 $postIndex = 1;
750 foreach ($products as $product) {
751 $post = get_post($product->ID);
752 setup_postdata($post);
753 $this->set_loop_object($post);
754 $this->render_fields($post, $postIndex);
755 $this->next_iteration();
756 $postIndex++;
757 }
758 wp_reset_postdata();
759
760 $this->end_iteration();
761 }
762
763 private function getAjaxDefaultFilters(array $defaultFilters, array $settings): array
764 {
765 $filters = [];
766 $taxQuery = Arr::get($defaultFilters, 'tax_query', []);
767
768 if (!empty($taxQuery)) {
769 foreach ($taxQuery as $taxonomy => $termIds) {
770 $filters[$taxonomy] = $termIds;
771 }
772 }
773
774 $allowOutOfStock = Arr::get($settings, 'allowOutOfStock', false);
775 if ($allowOutOfStock) {
776 $filters['allow_out_of_stock'] = true;
777 }
778
779 if (!empty($filters)) {
780 $filters['enabled'] = true;
781 }
782
783 return $filters;
784 }
785
786 }
787