PluginProbe
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler / 1.5.0
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler v1.5.0
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.0, at app/Modules/Templating/Bricks/Elements/ProductsCollection.php

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