diff --git a/src/module-elasticsuite-virtual-category/Helper/Config.php b/src/module-elasticsuite-virtual-category/Helper/Config.php new file mode 100644 index 000000000..67c9f5792 --- /dev/null +++ b/src/module-elasticsuite-virtual-category/Helper/Config.php @@ -0,0 +1,62 @@ + + * @copyright 2024 Smile + * @license Open Software License ("OSL") v. 3.0 + */ + +namespace Smile\ElasticsuiteVirtualCategory\Helper; + +use Magento\Framework\App\Config\ScopeConfigInterface; +use Magento\Store\Model\ScopeInterface; + +/** + * Smile Elasticsuite virtual category config helper. + * + * @category Smile + * @package Smile\ElasticsuiteVirtualCategory + * @author Pierre Gauthier + */ +class Config +{ + const XML_PATH_FORCE_ZERO_RESULTS_FOR_DISABLED_CATEGORIES = 'smile_elasticsuite_catalogsearch_settings/catalogsearch/' . + 'force_zero_results_for_disabled_categories'; + + /** + * @var ScopeConfigInterface + */ + private $scopeConfig; + + /** + * Constructor + * + * @param ScopeConfigInterface $scopeConfig Scope configuration. + */ + public function __construct(ScopeConfigInterface $scopeConfig) + { + $this->scopeConfig = $scopeConfig; + } + + /** + * Returns true if categories and search queries positions should be ignored for Out of Stock products. + * + * @param integer $storeId Store id + * + * @return bool + */ + public function isForceZeroResultsForDisabledCategoriesEnabled($storeId): bool + { + return $this->scopeConfig->isSetFlag( + self::XML_PATH_FORCE_ZERO_RESULTS_FOR_DISABLED_CATEGORIES, + ScopeInterface::SCOPE_STORE, + $storeId + ); + } +} diff --git a/src/module-elasticsuite-virtual-category/Model/Rule.php b/src/module-elasticsuite-virtual-category/Model/Rule.php index 86b7fa507..0c1687410 100644 --- a/src/module-elasticsuite-virtual-category/Model/Rule.php +++ b/src/module-elasticsuite-virtual-category/Model/Rule.php @@ -23,6 +23,7 @@ use Magento\Catalog\Api\Data\CategoryInterface; use Smile\ElasticsuiteVirtualCategory\Api\Data\VirtualRuleInterface; use Smile\ElasticsuiteCatalogRule\Model\Rule\Condition\Product\QueryBuilder; +use Smile\ElasticsuiteVirtualCategory\Helper\Config; use Smile\ElasticsuiteVirtualCategory\Model\ResourceModel\VirtualCategory\CollectionFactory; use Smile\ElasticsuiteCore\Search\Request\Query\QueryFactory; use Magento\Catalog\Model\CategoryFactory; @@ -87,6 +88,11 @@ class Rule extends \Smile\ElasticsuiteCatalogRule\Model\Rule implements VirtualR */ private $sharedCache; + /** + * @var Config + */ + private $config; + /** * @var Category[] */ @@ -115,6 +121,7 @@ class Rule extends \Smile\ElasticsuiteCatalogRule\Model\Rule implements VirtualR * @param StoreManagerInterface $storeManagerInterface Store Manager * @param Session $customerSession Customer session. * @param CacheInterface $cache Cache. + * @param Config $config Virtual category configuration. * @param array $data Additional data. */ public function __construct( @@ -132,6 +139,7 @@ public function __construct( StoreManagerInterface $storeManagerInterface, Session $customerSession, CacheInterface $cache, + Config $config, array $data = [] ) { $this->queryFactory = $queryFactory; @@ -142,6 +150,7 @@ public function __construct( $this->storeManager = $storeManagerInterface; $this->customerSession = $customerSession; $this->sharedCache = $cache; + $this->config = $config; parent::__construct($context, $registry, $formFactory, $localeDate, $combineConditionsFactory, $conditionDataFactory, $data); } @@ -179,13 +188,15 @@ public function getCategorySearchQuery($category, $excludedCategories = []): ?Qu { \Magento\Framework\Profiler::start('ES:Virtual Rule ' . __FUNCTION__); $categoryId = (int) (!is_object($category) ? $category : $category->getId()); + $storeId = !is_object($category) ? $this->getStoreId() : $category->getStoreId(); $cacheKey = implode( '|', [ __FUNCTION__, - !is_object($category) ? $this->getStoreId() : $category->getStoreId(), + $storeId, $categoryId, $this->customerSession->getCustomerGroupId(), + $this->config->isForceZeroResultsForDisabledCategoriesEnabled($storeId), ] ); @@ -306,6 +317,11 @@ private function buildCategorySearchQuery($category, $excludedCategories = []): if (!in_array($category->getId(), $excludedCategories)) { $excludedCategories[] = $category->getId(); + if (!$category->getIsActive() + && $this->config->isForceZeroResultsForDisabledCategoriesEnabled($this->getStoreId())) { + return $this->getNoResultsQuery(); + } + if ((bool) $category->getIsVirtualCategory() && $category->getIsActive()) { $query = $this->getVirtualCategoryQuery($category, $excludedCategories); } elseif ($category->getId() && $category->getIsActive()) { @@ -601,4 +617,17 @@ private function saveInLocalCache(int $categoryId, $query): void self::$localCache[$categoryId] = $query; } } + + /** + * Build a query that return zero products. + * + * @return QueryInterface + */ + private function getNoResultsQuery(): QueryInterface + { + return $this->queryFactory->create( + QueryInterface::TYPE_TERMS, + ['field' => 'entity_id', 'values' => [0]] + ); + } } diff --git a/src/module-elasticsuite-virtual-category/etc/adminhtml/system.xml b/src/module-elasticsuite-virtual-category/etc/adminhtml/system.xml new file mode 100644 index 000000000..e4c93bd87 --- /dev/null +++ b/src/module-elasticsuite-virtual-category/etc/adminhtml/system.xml @@ -0,0 +1,34 @@ + + + +
+ + smile_elasticsuite + Magento_Backend::smile_elasticsuite_catalogsearch + + + + + + Magento\Config\Model\Config\Source\Yesno + + + +
+
+
diff --git a/src/module-elasticsuite-virtual-category/etc/config.xml b/src/module-elasticsuite-virtual-category/etc/config.xml new file mode 100644 index 000000000..1f7870915 --- /dev/null +++ b/src/module-elasticsuite-virtual-category/etc/config.xml @@ -0,0 +1,26 @@ + + + + + + + 1 + + + + diff --git a/src/module-elasticsuite-virtual-category/i18n/en_US.csv b/src/module-elasticsuite-virtual-category/i18n/en_US.csv index 752e6baeb..66ac8a2ad 100644 --- a/src/module-elasticsuite-virtual-category/i18n/en_US.csv +++ b/src/module-elasticsuite-virtual-category/i18n/en_US.csv @@ -1,4 +1,6 @@ "Add/Remove Products","Add/Remove Products" +"Force zero results for disabled categories","Force zero results for disabled categories" +"If set to yes, any virtual category that references a disabled category in their rule or as their root category will return an empty result. Be careful modifying this option will remove all your category query cache.","If set to yes, any virtual category that references a disabled category in their rule or as their root category will return an empty result. Be careful modifying this option will remove all your category query cache." "Virtual rule","Virtual rule" "Virtual Category","Virtual Category" "Virtual Category Root","Virtual Category Root" diff --git a/src/module-elasticsuite-virtual-category/i18n/fr_FR.csv b/src/module-elasticsuite-virtual-category/i18n/fr_FR.csv index efe3cf8c6..b8c8d6c74 100644 --- a/src/module-elasticsuite-virtual-category/i18n/fr_FR.csv +++ b/src/module-elasticsuite-virtual-category/i18n/fr_FR.csv @@ -1,4 +1,6 @@ "Add/Remove Products","Ajouter/Supprimer des produits" +"Force zero results for disabled categories","Forcer un résultat vide pour les catégories désactivées" +"If set to yes, any virtual category that references a disabled category in their rule or as their root category will return an empty result. Be careful modifying this option will remove all your category query cache.","Si ce paramètre est activé, toutes catégories virtuelles qui référencent une catégorie désactivée dans leur règle ou en tant que catégorie racine retourneront un résultat vide. Attention, si vous modifiez cette option, cela va vider votre cache des requêtes de catégories." "Virtual rule","Règle à appliquer" "Virtual Category","Catégorie virtuelle" "Virtual Category Root","Racine de la catégorie virtuelle"