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

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