diff --git a/vendor/magento/module-inventory-catalog-search/Model/Indexer/FilterProductByStatusAndStock.php b/vendor/magento/module-inventory-catalog-search/Model/Indexer/FilterProductByStatusAndStock.php new file mode 100644 index 00000000000..c6eb906fe86 --- /dev/null +++ b/vendor/magento/module-inventory-catalog-search/Model/Indexer/FilterProductByStatusAndStock.php @@ -0,0 +1,75 @@ +storeManager->getStore($storeId); + $this->stockStatusFilter->process( + $select, + 'e', + 'stock', + (int)$store->getWebsiteId() + ); + $this->applySelectModifiers($select, $store); + + return $select; + } + + /** + * Iterate product type modifier to the select + * + * @param Select $select + * @param Store $store + * @return void + */ + private function applySelectModifiers(Select $select, Store $store): void + { + foreach ($this->selectModifiersPool as $selectModifier) { + $selectModifier->modify($select, $store); + } + } +} diff --git a/vendor/magento/module-inventory-catalog-search/Model/Indexer/FilterProductByStock.php b/vendor/magento/module-inventory-catalog-search/Model/Indexer/FilterProductByStock.php deleted file mode 100644 index 36851f4b134..00000000000 --- a/vendor/magento/module-inventory-catalog-search/Model/Indexer/FilterProductByStock.php +++ /dev/null @@ -1,83 +0,0 @@ -storeRepository = $storeRepository; - $this->stockStatusFilter = $stockStatusFilter; - $this->selectModifiersPool = $selectModifiersPool; - } - - /** - * Return filtered product by stock status for product indexer - * - * @param Select $select - * @param int $storeId - * @return Select - */ - public function execute(Select $select, int $storeId): Select - { - $store = $this->storeRepository->getById($storeId); - $this->stockStatusFilter->execute( - $select, - 'e', - StockStatusFilterInterface::TABLE_ALIAS, - (int) $store->getWebsiteId() - ); - $this->applySelectModifiers($select, $storeId); - - return $select; - } - - /** - * Applying filters to select via select modifiers - * - * @param Select $select - * @param int $storeId - * @return void - */ - private function applySelectModifiers(Select $select, int $storeId): void - { - foreach ($this->selectModifiersPool as $selectModifier) { - $selectModifier->modify($select, $storeId); - } - } -} diff --git a/vendor/magento/module-inventory-catalog-search/Model/Indexer/FilteringSalableProductSelectBuilderInterface.php b/vendor/magento/module-inventory-catalog-search/Model/Indexer/FilteringSalableProductSelectBuilderInterface.php new file mode 100644 index 00000000000..afd2cb8a890 --- /dev/null +++ b/vendor/magento/module-inventory-catalog-search/Model/Indexer/FilteringSalableProductSelectBuilderInterface.php @@ -0,0 +1,34 @@ +stockStatusFilter->execute($select, $productTableAliasAlias, $stockStatusTableAlias, $websiteId); + } +} diff --git a/vendor/magento/module-inventory-catalog-search/Plugin/CatalogSearch/Model/Indexer/ChildProductFilterByInventoryStockPlugin.php b/vendor/magento/module-inventory-catalog-search/Plugin/CatalogSearch/Model/Indexer/ChildProductFilterByInventoryStockPlugin.php index ed240f333f4..84eb9fec18e 100644 --- a/vendor/magento/module-inventory-catalog-search/Plugin/CatalogSearch/Model/Indexer/ChildProductFilterByInventoryStockPlugin.php +++ b/vendor/magento/module-inventory-catalog-search/Plugin/CatalogSearch/Model/Indexer/ChildProductFilterByInventoryStockPlugin.php @@ -11,7 +11,7 @@ use Magento\CatalogInventory\Api\StockConfigurationInterface; use Magento\CatalogSearch\Model\Indexer\Fulltext\Action\GetSearchableProductsSelect; use Magento\Framework\DB\Select; use Magento\Framework\Exception\NoSuchEntityException; -use Magento\InventoryCatalogSearch\Model\Indexer\FilterProductByStock; +use Magento\InventoryCatalogSearch\Model\Indexer\FilterProductByStatusAndStock; /** * Filter composite products by enabled child product stock status. @@ -24,17 +24,17 @@ class ChildProductFilterByInventoryStockPlugin private $stockConfiguration; /** - * @var FilterProductByStock + * @var FilterProductByStatusAndStock */ private $filterProductByStock; /** * @param StockConfigurationInterface $stockConfiguration - * @param FilterProductByStock $filterProductByStock + * @param FilterProductByStatusAndStock $filterProductByStock */ public function __construct( StockConfigurationInterface $stockConfiguration, - FilterProductByStock $filterProductByStock + FilterProductByStatusAndStock $filterProductByStock ) { $this->stockConfiguration = $stockConfiguration; $this->filterProductByStock = $filterProductByStock; @@ -54,9 +54,8 @@ class ChildProductFilterByInventoryStockPlugin GetSearchableProductsSelect $subject, Select $result, int $storeId - ): Select - { - if ($this->stockConfiguration->isShowOutOfStock($storeId) || empty($result)) { + ): Select { + if ($this->stockConfiguration->isShowOutOfStock($storeId)) { return $result; } return $this->filterProductByStock->execute($result, $storeId); diff --git a/vendor/magento/module-inventory-catalog-search-bundle-product/Model/CatalogSearch/Indexer/BundleChildStockStatusModifier.php b/vendor/magento/module-inventory-catalog-search-bundle-product/Model/CatalogSearch/Indexer/BundleChildStockStatusModifier.php deleted file mode 100644 index f20fe87ca4f..00000000000 --- a/vendor/magento/module-inventory-catalog-search-bundle-product/Model/CatalogSearch/Indexer/BundleChildStockStatusModifier.php +++ /dev/null @@ -1,144 +0,0 @@ -metadataPool = $metadataPool; - $this->resourceConnection = $resourceConnection; - $this->productAttributeRepository = $productAttributeRepository; - $this->storeRepository = $storeRepository; - $this->stockStatusResource = $stockStatusResource; - } - - /** - * @inheritdoc - */ - public function modify(Select $select, int $storeId): void - { - $connection = $this->resourceConnection->getConnection(); - $metadata = $this->metadataPool->getMetadata(ProductInterface::class); - $linkField = $metadata->getLinkField(); - $optionsAvailabilitySelect = $connection->select()->from( - ['bundle_options' => $this->resourceConnection->getTableName('catalog_product_bundle_option')], - [] - )->joinInner( - ['bundle_selections' => $this->resourceConnection->getTableName('catalog_product_bundle_selection')], - 'bundle_selections.option_id = bundle_options.option_id', - [] - )->joinInner( - // table alias must be "e" for joining the stock status - ['e' => $this->resourceConnection->getTableName('catalog_product_entity')], - 'e.entity_id = bundle_selections.product_id', - [] - )->group( - ['bundle_options.parent_id', 'bundle_options.option_id'] - ); - - $statusAttribute = $this->productAttributeRepository->get(ProductInterface::STATUS); - $optionsAvailabilitySelect->joinLeft( - ['child_status_global' => $statusAttribute->getBackendTable()], - "child_status_global.{$linkField} = e.{$linkField}" - . " AND child_status_global.attribute_id = {$statusAttribute->getAttributeId()}" - . " AND child_status_global.store_id = 0", - [] - )->joinLeft( - ['child_status_store' => $statusAttribute->getBackendTable()], - "child_status_store.{$linkField} = e.{$linkField}" - . " AND child_status_store.attribute_id = {$statusAttribute->getAttributeId()}" - . " AND child_status_store.store_id = {$storeId}", - [] - ); - - $store = $this->storeRepository->getById($storeId); - $this->stockStatusResource->addStockStatusToSelect($optionsAvailabilitySelect, $store->getWebsite()); - $columns = array_column($optionsAvailabilitySelect->getPart(Select::COLUMNS), 1, 2); - $isSalableColumn = $columns['is_salable']; - - $optionAvailabilityExpr = sprintf( - 'IFNULL(child_status_store.value, child_status_global.value) != %s AND %s = 1', - Status::STATUS_DISABLED, - $isSalableColumn - ); - $isOptionSalableExpr = new \Zend_Db_Expr('MAX(' . $optionAvailabilityExpr . ')'); - $isRequiredOptionUnsalable = $connection->getCheckSql( - 'required = 1 AND ' . $isOptionSalableExpr . ' = 0', - '1', - '0' - ); - $optionsAvailabilitySelect->columns([ - 'parent_id' => 'bundle_options.parent_id', - 'required' => 'bundle_options.required', - 'is_available' => $isOptionSalableExpr, - 'is_required_and_unavailable' => $isRequiredOptionUnsalable, - ]); - - $existsSelect = $connection->select() - ->from($optionsAvailabilitySelect) - ->where("parent_id = e.{$linkField}") - ->group('parent_id') - ->having(new \Zend_Db_Expr('(MAX(is_available) = 1 AND MAX(is_required_and_unavailable) = 0)')); - $typeBundle = Type::TYPE_CODE; - $select->where( - "e.type_id != '{$typeBundle}' OR EXISTS ({$existsSelect->assemble()})" - ); - } -} diff --git a/vendor/magento/module-inventory-catalog-search-bundle-product/Model/CatalogSearch/Indexer/BundleChildStockStatusMultiStoreModifier.php b/vendor/magento/module-inventory-catalog-search-bundle-product/Model/CatalogSearch/Indexer/BundleChildStockStatusMultiStoreModifier.php new file mode 100644 index 00000000000..5bb319414c2 --- /dev/null +++ b/vendor/magento/module-inventory-catalog-search-bundle-product/Model/CatalogSearch/Indexer/BundleChildStockStatusMultiStoreModifier.php @@ -0,0 +1,110 @@ +resource->getConnection(); + $metadata = $this->metadataPool->getMetadata(ProductInterface::class); + $linkField = $metadata->getLinkField(); + $statusAttribute = $this->productAttributeRepository->get(ProductInterface::STATUS); + $existsSelect = $connection->select()->from( + ['product_link_bundle' => $this->resource->getTableName('catalog_product_bundle_selection')], + [new \Zend_Db_Expr('1')] + )->where( + "product_link_bundle.parent_product_id = e.{$linkField}" + ); + $existsSelect->join( + ['bundle_product_child' => $this->resource->getTableName('catalog_product_entity')], + 'bundle_product_child.entity_id = product_link_bundle.product_id', + [] + ); + + $existsSelect->join( + ['bundle_at_status_default' => $this->resource->getTableName($statusAttribute->getBackendTable())], + "bundle_product_child.{$linkField} = bundle_at_status_default.{$linkField} AND " + . "bundle_at_status_default.attribute_id = {$statusAttribute->getId()} AND " + . "bundle_at_status_default.store_id = " . Store::DEFAULT_STORE_ID, + [] + ); + + $valueCondition = $connection->getCheckSql( + 'bundle_at_status.value_id > 0', + 'bundle_at_status.value', + 'bundle_at_status_default.value' + ); + $existsSelect->joinLeft( + ['bundle_at_status' => $this->resource->getTableName($statusAttribute->getBackendTable())], + implode( + ' ' . Select::SQL_AND . ' ', + [ + 'bundle_at_status.' . $linkField . ' = bundle_at_status_default.' . $linkField, + $connection->prepareSqlCondition('bundle_at_status.store_id', $store->getId()), + $connection->prepareSqlCondition( + 'bundle_at_status.attribute_id', + $statusAttribute->getAttributeId() + ), + ] + ), + [] + )->where("{$valueCondition} = " . Status::STATUS_ENABLED); + + $this->stockStatusFilter->process( + $existsSelect, + 'bundle_product_child', + 'stock_status_index_child', + (int)$store->getWebsiteId() + ); + + $typeBundle = Type::TYPE_CODE; + $select->where( + "e.type_id != '{$typeBundle}' OR EXISTS ({$existsSelect->assemble()})" + ); + } +} diff --git a/vendor/magento/module-inventory-catalog-search-bundle-product/etc/di.xml b/vendor/magento/module-inventory-catalog-search-bundle-product/etc/di.xml index 86ffea24672..bfef3d862de 100644 --- a/vendor/magento/module-inventory-catalog-search-bundle-product/etc/di.xml +++ b/vendor/magento/module-inventory-catalog-search-bundle-product/etc/di.xml @@ -6,10 +6,10 @@ */ --> - + - Magento\InventoryCatalogSearchBundleProduct\Model\CatalogSearch\Indexer\BundleChildStockStatusModifier + Magento\InventoryCatalogSearchBundleProduct\Model\CatalogSearch\Indexer\BundleChildStockStatusMultiStoreModifier diff --git a/vendor/magento/module-inventory-catalog-search-configurable-product/Model/CatalogSearch/Indexer/ConfigurableChildStockStatusModifier.php b/vendor/magento/module-inventory-catalog-search-configurable-product/Model/CatalogSearch/Indexer/ConfigurableChildStockStatusModifier.php deleted file mode 100644 index e8682d665da..00000000000 --- a/vendor/magento/module-inventory-catalog-search-configurable-product/Model/CatalogSearch/Indexer/ConfigurableChildStockStatusModifier.php +++ /dev/null @@ -1,122 +0,0 @@ -metadataPool = $metadataPool; - $this->resourceConnection = $resourceConnection; - $this->productAttributeRepository = $productAttributeRepository; - $this->storeRepository = $storeRepository; - $this->stockStatusFilter = $stockStatusFilter; - } - - /** - * @inheritdoc - */ - public function modify(Select $select, int $storeId): void - { - $connection = $this->resourceConnection->getConnection(); - $metadata = $this->metadataPool->getMetadata(ProductInterface::class); - $linkField = $metadata->getLinkField(); - $existsSelect = $connection->select()->from( - ['product_link_configurable' => $this->resourceConnection->getTableName('catalog_product_super_link')], - [new \Zend_Db_Expr('1')] - )->where( - "product_link_configurable.parent_id = e.{$linkField}" - ); - $existsSelect->join( - ['product_child' => $this->resourceConnection->getTableName('catalog_product_entity')], - 'product_child.entity_id = product_link_configurable.product_id', - [] - ); - - $statusAttribute = $this->productAttributeRepository->get(ProductInterface::STATUS); - $existsSelect->joinLeft( - ['child_status_global' => $statusAttribute->getBackendTable()], - "child_status_global.{$linkField} = product_child.{$linkField}" - . " AND child_status_global.attribute_id = {$statusAttribute->getAttributeId()}" - . " AND child_status_global.store_id = 0", - [] - )->joinLeft( - ['child_status_store' => $statusAttribute->getBackendTable()], - "child_status_store.{$linkField} = product_child.{$linkField}" - . " AND child_status_store.attribute_id = {$statusAttribute->getAttributeId()}" - . " AND child_status_store.store_id = {$storeId}", - [] - )->where( - 'IFNULL(child_status_store.value, child_status_global.value) != ' . Status::STATUS_DISABLED - ); - - $store = $this->storeRepository->getById($storeId); - $this->stockStatusFilter->execute( - $existsSelect, - 'product_child', - StockStatusFilterInterface::TABLE_ALIAS, - (int) $store->getWebsiteId() - ); - - $typeConfigurable = Configurable::TYPE_CODE; - $select->where( - "e.type_id != '{$typeConfigurable}' OR EXISTS ({$existsSelect->assemble()})" - ); - } -} diff --git a/vendor/magento/module-inventory-catalog-search-configurable-product/Model/CatalogSearch/Indexer/ConfigurableChildStockStatusMultiStoreModifier.php b/vendor/magento/module-inventory-catalog-search-configurable-product/Model/CatalogSearch/Indexer/ConfigurableChildStockStatusMultiStoreModifier.php new file mode 100644 index 00000000000..cf8b9993a28 --- /dev/null +++ b/vendor/magento/module-inventory-catalog-search-configurable-product/Model/CatalogSearch/Indexer/ConfigurableChildStockStatusMultiStoreModifier.php @@ -0,0 +1,110 @@ +resource->getConnection(); + $metadata = $this->metadataPool->getMetadata(ProductInterface::class); + $linkField = $metadata->getLinkField(); + $statusAttribute = $this->productAttributeRepository->get(ProductInterface::STATUS); + $existsSelect = $connection->select()->from( + ['product_link_configurable' => $this->resource->getTableName('catalog_product_super_link')], + [new \Zend_Db_Expr('1')] + )->where( + "product_link_configurable.parent_id = e.{$linkField}" + ); + $existsSelect->join( + ['configurable_product_child' => $this->resource->getTableName('catalog_product_entity')], + 'configurable_product_child.entity_id = product_link_configurable.product_id', + [] + ); + + $existsSelect->join( + ['configurable_at_status_default' => $this->resource->getTableName($statusAttribute->getBackendTable())], + "configurable_product_child.{$linkField} = configurable_at_status_default.{$linkField} AND " + . "configurable_at_status_default.attribute_id = {$statusAttribute->getId()} AND " + . "configurable_at_status_default.store_id = " . Store::DEFAULT_STORE_ID, + [] + ); + + $valueCondition = $connection->getCheckSql( + 'configurable_at_status.value_id > 0', + 'configurable_at_status.value', + 'configurable_at_status_default.value' + ); + $existsSelect->joinLeft( + ['configurable_at_status' => $this->resource->getTableName($statusAttribute->getBackendTable())], + implode( + ' ' . Select::SQL_AND . ' ', + [ + 'configurable_at_status.' . $linkField . ' = configurable_at_status_default.' . $linkField, + $connection->prepareSqlCondition('configurable_at_status.store_id', $store->getId()), + $connection->prepareSqlCondition( + 'configurable_at_status.attribute_id', + $statusAttribute->getAttributeId() + ), + ] + ), + [] + )->where("{$valueCondition} = " . Status::STATUS_ENABLED); + + $this->stockStatusFilter->process( + $existsSelect, + 'configurable_product_child', + 'stock_status_index_child', + (int)$store->getWebsiteId() + ); + + $typeConfigurable = Configurable::TYPE_CODE; + $select->where( + "e.type_id != '{$typeConfigurable}' OR EXISTS ({$existsSelect->assemble()})" + ); + } +} diff --git a/vendor/magento/module-inventory-catalog-search-configurable-product/etc/di.xml b/vendor/magento/module-inventory-catalog-search-configurable-product/etc/di.xml index 4d79ece0367..a44f2721c69 100644 --- a/vendor/magento/module-inventory-catalog-search-configurable-product/etc/di.xml +++ b/vendor/magento/module-inventory-catalog-search-configurable-product/etc/di.xml @@ -6,10 +6,10 @@ */ --> - + - Magento\InventoryCatalogSearchConfigurableProduct\Model\CatalogSearch\Indexer\ConfigurableChildStockStatusModifier + Magento\InventoryCatalogSearchConfigurableProduct\Model\CatalogSearch\Indexer\ConfigurableChildStockStatusMultiStoreModifier