control_groups['query'] = [ 'title' => esc_html__('Query', 'fluent-cart'), 'tab' => 'content', ]; $this->control_groups['fields'] = [ 'title' => esc_html__('Fields', 'fluent-cart'), 'tab' => 'content', ]; $this->control_groups['display'] = [ 'title' => esc_html__('Display', 'fluent-cart'), 'tab' => 'content', ]; $this->control_groups['filter'] = [ 'title' => esc_html__('Filter', 'fluent-cart'), 'tab' => 'content', ]; $this->control_groups['widgets'] = [ 'title' => esc_html__('Widgets', 'fluent-cart'), 'tab' => 'widgets', ]; } public function set_controls() { // LAYOUT $this->controls['viewMode'] = [ 'tab' => 'content', 'group' => 'display', 'label' => esc_html__('View Mode', 'fluent-cart'), 'type' => 'select', 'options' => [ 'grid' => esc_html__('Grid', 'fluent-cart'), 'list' => esc_html__('List', 'fluent-cart'), ], 'placeholder' => esc_html__('Grid', 'fluent-cart'), 'rerender' => true, ]; $this->controls['showViewSwitcher'] = [ 'tab' => 'content', 'group' => 'display', 'label' => esc_html__('Show View Switcher', 'fluent-cart'), 'type' => 'checkbox', 'inline' => true, 'default' => true, ]; $this->controls['paginationType'] = [ 'tab' => 'content', 'group' => 'display', 'label' => esc_html__('Pagination Type', 'fluent-cart'), 'type' => 'select', 'options' => [ 'scroll' => esc_html__('Scroll', 'fluent-cart'), 'numbers' => esc_html__('Numbers', 'fluent-cart'), ], 'placeholder' => esc_html__('Numbers', 'fluent-cart'), ]; $this->controls['columns'] = [ 'tab' => 'content', 'label' => esc_html__('Columns', 'fluent-cart'), 'type' => 'number', 'min' => 1, 'max' => 5, 'breakpoints' => true, 'placeholder' => 4, 'rerender' => true, ]; $this->controls['gap'] = [ 'tab' => 'content', 'label' => esc_html__('Gap', 'fluent-cart'), 'type' => 'number', 'units' => true, 'css' => [ [ 'selector' => $this->cssRoot, 'property' => 'gap', ], ], 'placeholder' => 30, ]; $this->controls['posts_per_page'] = [ 'tab' => 'content', 'label' => esc_html__('Products per page', 'fluent-cart'), 'type' => 'number', 'min' => 1, 'max' => 100, 'placeholder' => 10, 'step' => 1, ]; $this->controls['is_main_query'] = [ 'tab' => 'content', 'label' => esc_html__('Is main query', 'fluent-cart'), 'type' => 'checkbox', 'inline' => true, ]; // QUERY $this->controls['orderby'] = [ 'tab' => 'content', 'label' => esc_html__('Order by', 'fluent-cart'), 'type' => 'select', // id|date|title|price 'options' => [ 'price' => esc_html__('Price', 'fluent-cart'), 'title' => esc_html__('Product Name', 'fluent-cart'), 'date' => esc_html__('Published date', 'fluent-cart'), 'id' => esc_html__('Product ID', 'fluent-cart') ], 'inline' => true, 'placeholder' => esc_html__('Default', 'fluent-cart'), ]; $this->controls['order'] = [ 'tab' => 'content', 'label' => esc_html__('Order', 'fluent-cart'), 'type' => 'select', 'options' => [ 'ASC' => esc_html__('Ascending', 'fluent-cart'), 'DESC' => esc_html__('Descending', 'fluent-cart'), ], 'inline' => true, 'placeholder' => esc_html__('Descending', 'fluent-cart'), ]; $this->controls['main_query_info'] = [ 'tab' => 'content', 'group' => 'query', 'type' => 'info', 'content' => esc_html__('The query settings will be ignored when Is main query is enabled.', 'fluent-cart'), ]; $this->controls['productType'] = [ 'tab' => 'content', 'group' => 'query', 'label' => esc_html__('Product type', 'fluent-cart'), 'type' => 'select', // physical|digital|subscription|onetime|simple|variations 'options' => [ 'simple' => esc_html__('Simple', 'fluent-cart'), 'physical' => esc_html__('Physical', 'fluent-cart'), 'digital' => esc_html__('Digital', 'fluent-cart'), 'variations' => esc_html__('Variations', 'fluent-cart'), 'ontime' => esc_html__('One-time', 'fluent-cart'), 'subscription' => esc_html__('Subscriptions', 'fluent-cart'), ], 'multiple' => false, 'placeholder' => esc_html__('all product types', 'fluent-cart'), ]; $this->controls['include'] = [ 'tab' => 'content', 'group' => 'query', 'label' => esc_html__('Include', 'fluent-cart'), 'type' => 'select', 'optionsAjax' => [ 'action' => 'bricks_get_posts', 'postType' => 'fluent-products', ], 'multiple' => true, 'searchable' => true, 'placeholder' => esc_html__('Select products', 'fluent-cart'), ]; //phpcs:ignore WordPressVIPMinimum.Performance.WPQueryParams.PostNotIn_exclude $this->controls['exclude'] = [ 'tab' => 'content', 'group' => 'query', 'label' => esc_html__('Exclude', 'fluent-cart'), 'type' => 'select', 'optionsAjax' => [ 'action' => 'bricks_get_posts', 'postType' => 'fluent-products', ], 'multiple' => true, 'searchable' => true, 'placeholder' => esc_html__('Select products', 'fluent-cart'), ]; $this->controls['categories'] = [ 'tab' => 'content', 'group' => 'query', 'label' => esc_html__('Product categories', 'fluent-cart'), 'type' => 'select', 'options' => BricksHelper::getCategoriesOptions(), 'multiple' => true, ]; $this->controls['onSale'] = [ 'tab' => 'content', 'group' => 'query', 'label' => esc_html__('On sale Products only', 'fluent-cart'), 'type' => 'checkbox', ]; $this->controls['allowOutOfStock'] = [ 'tab' => 'content', 'group' => 'query', 'label' => esc_html__('Allow Out Of Stock', 'fluent-cart'), 'type' => 'checkbox', ]; // FILTER $this->controls['enableFilter'] = [ 'tab' => 'content', 'group' => 'filter', 'label' => esc_html__('Enable Filter', 'fluent-cart'), 'type' => 'checkbox', 'inline' => true, ]; $this->controls['enableSortBy'] = [ 'tab' => 'content', 'group' => 'filter', 'label' => esc_html__('Enable Sort By', 'fluent-cart'), 'type' => 'checkbox', 'inline' => true, 'default' => true, 'required' => ['enableFilter', '=', true], ]; $this->controls['liveFilter'] = [ 'tab' => 'content', 'group' => 'filter', 'label' => esc_html__('Live Filter', 'fluent-cart'), 'type' => 'checkbox', 'inline' => true, 'required' => ['enableFilter', '=', true], ]; $this->controls['wildcardFilter'] = [ 'tab' => 'content', 'group' => 'filter', 'label' => esc_html__('Wildcard Filter', 'fluent-cart'), 'type' => 'checkbox', 'inline' => true, 'required' => ['enableFilter', '=', true], ]; $this->controls['productCategories'] = [ 'tab' => 'content', 'group' => 'filter', 'label' => esc_html__( 'Product Categories', 'fluent-cart' ), 'type' => 'checkbox', 'inline' => true, 'required' => ['enableFilter', '=', true], ]; $this->controls['displayNameCategories'] = [ 'tab' => 'content', 'group' => 'filter', 'label' => esc_html__('Display Name', 'fluent-cart'), 'type' => 'text', 'placeholder' => esc_html__('Custom filter label', 'fluent-cart'), 'required' => [ ['enableFilter', '=', true], ['productCategories', '=', true], ], ]; $this->controls['productBrands'] = [ 'tab' => 'content', 'group' => 'filter', 'label' => esc_html__( 'Product Brands', 'fluent-cart' ), 'type' => 'checkbox', 'inline' => true, 'required' => ['enableFilter', '=', true], ]; $this->controls['displayNameBrands'] = [ 'tab' => 'content', 'group' => 'filter', 'label' => esc_html__('Display Name', 'fluent-cart'), 'type' => 'text', 'placeholder' => esc_html__('Custom filter label', 'fluent-cart'), 'required' => [ ['enableFilter', '=', true], ['productBrands', '=', true], ], ]; $this->controls['priceRange'] = [ 'tab' => 'content', 'group' => 'filter', 'label' => esc_html__( 'Price Range', 'fluent-cart' ), 'type' => 'checkbox', 'inline' => true, 'required' => ['enableFilter', '=', true], ]; $this->controls['displayNamePriceRange'] = [ 'tab' => 'content', 'group' => 'filter', 'label' => esc_html__('Display Name', 'fluent-cart'), 'type' => 'text', 'placeholder' => esc_html__('Custom filter label', 'fluent-cart'), 'required' => [ ['enableFilter', '=', true], ['priceRange', '=', true], ], ]; // FIELDS $fields = $this->get_post_fields(); // Remove field settings unset($fields['fields']['fields']['overlay']); unset($fields['fields']['fields']['dynamicPadding']); unset($fields['fields']['fields']['dynamicBackground']); unset($fields['fields']['fields']['dynamicBorder']); // Set fields defaults fields set $fields['fields']['default'] = [ [ 'dynamicData' => '{fct_product_image:link}', 'id' => Helpers::generate_random_id(false), ], [ 'dynamicData' => '{fct_product_title:linked}', 'tag' => 'h5', 'id' => Helpers::generate_random_id(false), ], [ 'dynamicData' => '{fct_product_excerpt}', 'tag' => 'p', 'id' => Helpers::generate_random_id(false), ], [ 'dynamicData' => '{fct_product_price}', 'id' => Helpers::generate_random_id(false), ], [ 'dynamicData' => '{fct_product_button}', 'id' => Helpers::generate_random_id(false), ] ]; $this->controls = array_replace_recursive($this->controls, $fields); $this->controls['linkProduct'] = [ 'tab' => 'content', 'group' => 'fields', 'label' => esc_html__('Link entire product', 'fluent-cart'), 'type' => 'checkbox', 'inline' => true, 'description' => esc_html__('Only added if none of your product fields contains any links.', 'fluent-cart'), ]; } public function render() { $settings = $this->settings; $this->setBricksQuery(); $columns = $this->normalizeColumns(Arr::get($settings, 'columns', 4)); $viewMode = Arr::get($settings, 'viewMode', 'grid'); $showViewSwitcher = !empty($settings['showViewSwitcher']); $paginationType = Arr::get($settings, 'paginationType', 'numbers'); $isMainQuery = Arr::get($settings, 'is_main_query', false) && $this->is_frontend; $perPage = (int)Arr::get($settings, 'posts_per_page', 10); $enableFilter = !empty($settings['enableFilter']); $priceRange = !empty($settings['priceRange']); $liveFilter = !empty($settings['liveFilter']); $this->storeSettingsTransient($settings); if ($perPage <= 0) { $perPage = 10; } if ($perPage > 100) { $perPage = 100; } $args = $this->buildQueryArgs( $settings, $isMainQuery, $perPage, $viewMode ); $productsQuery = (new ProductQuery($args)); $products = $productsQuery->get(); $defaultFilters = $productsQuery->getDefaultFilters(); $ajaxDefaultFilters = $this->getAjaxDefaultFilters( $defaultFilters, $settings ); $filters = $this->getFilters($settings); $wrapperClass = 'fct-products-wrapper-inner ' . ($viewMode === 'list' ? 'mode-list' : 'mode-grid') . (!$enableFilter ? ' fct-full-container-width' : ''); $wrapperAttributes = [ 'class' => $wrapperClass, 'data-fluent-cart-product-wrapper-inner' => '', 'data-per-page' => $perPage, 'data-order-type' => Arr::get($defaultFilters, 'sort_type'), 'data-live-filter' => $liveFilter, 'data-paginator' => esc_attr($paginationType), 'data-default-filters' => wp_json_encode($ajaxDefaultFilters) ]; $productWrapperClasses = [ 'fct-products-wrapper', 'fct-brick-products-wrapper', ]; if (!$this->is_frontend) { $productWrapperClasses[] = 'fct-bricks-editor-mode'; } $rendererConfig = [ 'view_mode' => $viewMode, 'enable_wildcard_filter' => !empty($settings['wildcardFilter']), 'custom_filters' => [ 'enabled' => $enableFilter, 'price_range' => $priceRange, 'live_filter' => $liveFilter ], ]; // Only override enable_sort_by if explicitly set in settings (key exists) if (array_key_exists('enableSortBy', $settings)) { $rendererConfig['enable_sort_by'] = !empty($settings['enableSortBy']); } $shopAppRenderer = new ShopAppRenderer($products, $rendererConfig); ?>