diff --git a/app/code/Magento/ConfigurableProduct/Model/ResourceModel/Indexer/Stock/Configurable.php b/app/code/Magento/ConfigurableProduct/Model/ResourceModel/Indexer/Stock/Configurable.php index 6f2b989e5e9bfaa9fa91643b1958be6a99c0fdc1..794034b446f72b3e1649352f74b74b49345c7a3f 100644 --- a/app/code/Magento/ConfigurableProduct/Model/ResourceModel/Indexer/Stock/Configurable.php +++ b/app/code/Magento/ConfigurableProduct/Model/ResourceModel/Indexer/Stock/Configurable.php @@ -29,18 +29,25 @@ class Configurable extends \Magento\CatalogInventory\Model\ResourceModel\Indexer $connection = $this->getConnection(); $idxTable = $usePrimaryTable ? $this->getMainTable() : $this->getIdxTable(); $select = parent::_getStockStatusSelect($entityIds, $usePrimaryTable); + $linkField = $metadata->getLinkField(); $select->reset( \Magento\Framework\DB\Select::COLUMNS )->columns( ['e.entity_id', 'cis.website_id', 'cis.stock_id'] )->joinLeft( ['l' => $this->getTable('catalog_product_super_link')], - 'l.parent_id = e.' . $metadata->getLinkField(), + 'l.parent_id = e.' . $linkField, [] )->join( ['le' => $this->getTable('catalog_product_entity')], 'le.entity_id = l.product_id', [] + )->joinInner( + ['cpei' => $this->getTable('catalog_product_entity_int')], + 'le.' . $linkField . ' = cpei.' . $linkField + . ' AND cpei.attribute_id = ' . $this->_getAttribute('status')->getId() + . ' AND cpei.value = ' . ProductStatus::STATUS_ENABLED, + [] )->joinLeft( ['i' => $idxTable], 'i.product_id = l.product_id AND cis.website_id = i.website_id AND cis.stock_id = i.stock_id', diff --git a/dev/tests/integration/testsuite/Magento/Framework/Search/Adapter/Mysql/AdapterTest.php b/dev/tests/integration/testsuite/Magento/Framework/Search/Adapter/Mysql/AdapterTest.php index 67a6e416973493887912e2e62674108b1694c315..7f50638f469de0f8a5c392f97c74094582a432b9 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/Search/Adapter/Mysql/AdapterTest.php +++ b/dev/tests/integration/testsuite/Magento/Framework/Search/Adapter/Mysql/AdapterTest.php @@ -331,6 +331,10 @@ class AdapterTest extends \PHPUnit_Framework_TestCase * * @magentoConfigFixture current_store catalog/search/engine mysql * @dataProvider advancedSearchDataProvider + * @param string $nameQuery + * @param string $descriptionQuery + * @param array $rangeFilter + * @param int $expectedRecordsCount */ public function testSimpleAdvancedSearch( $nameQuery, @@ -445,6 +449,37 @@ class AdapterTest extends \PHPUnit_Framework_TestCase $this->assertEquals(1, $queryResponse->count()); } + /** + * @magentoDataFixture Magento/Framework/Search/_files/product_configurable_with_disabled_child.php + * @magentoConfigFixture current_store catalog/search/engine mysql + */ + public function testAdvancedSearchCompositeProductWithDisabledChild() + { + /** @var \Magento\Catalog\Model\ResourceModel\Eav\Attribute $attribute */ + $attribute = $this->objectManager->get(\Magento\Catalog\Model\ResourceModel\Eav\Attribute::class) + ->loadByCode(\Magento\Catalog\Model\Product::ENTITY, 'test_configurable'); + /** @var \Magento\Eav\Model\ResourceModel\Entity\Attribute\Option\Collection $selectOptions */ + $selectOptions = $this->objectManager + ->create(\Magento\Eav\Model\ResourceModel\Entity\Attribute\Option\Collection::class) + ->setAttributeFilter($attribute->getId()); + + $firstOption = $selectOptions->getFirstItem(); + $firstOptionId = $firstOption->getId(); + $this->requestBuilder->bind('test_configurable', $firstOptionId); + $this->requestBuilder->setRequestName('filter_out_of_stock_child'); + + $queryResponse = $this->executeQuery(); + $this->assertEquals(0, $queryResponse->count()); + + $secondOption = $selectOptions->getLastItem(); + $secondOptionId = $secondOption->getId(); + $this->requestBuilder->bind('test_configurable', $secondOptionId); + $this->requestBuilder->setRequestName('filter_out_of_stock_child'); + + $queryResponse = $this->executeQuery(); + $this->assertEquals(0, $queryResponse->count()); + } + public function dateDataProvider() { return [ diff --git a/dev/tests/integration/testsuite/Magento/Framework/Search/_files/product_configurable.php b/dev/tests/integration/testsuite/Magento/Framework/Search/_files/product_configurable.php index 590f3c8041c6d819fafa14ef7ddc4d1f2ebccbeb..37b8731fc1d4c377ffc26a16be2d4100997f7247 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/Search/_files/product_configurable.php +++ b/dev/tests/integration/testsuite/Magento/Framework/Search/_files/product_configurable.php @@ -15,7 +15,7 @@ use Magento\ConfigurableProduct\Model\Product\Type\Configurable; use Magento\Eav\Api\Data\AttributeOptionInterface; use Magento\TestFramework\Helper\Bootstrap; -\Magento\TestFramework\Helper\Bootstrap::getInstance()->reinitialize(); +Bootstrap::getInstance()->reinitialize(); require __DIR__ . '/configurable_attribute.php'; @@ -33,7 +33,7 @@ $options = $attribute->getOptions(); $attributeValues = []; $attributeSetId = $installer->getAttributeSetId('catalog_product', 'Default'); $associatedProductIds = []; -$productIds = [10, 20]; +$productIds = [1010, 1020]; array_shift($options); //remove the first option which is empty $isFirstOption = true; @@ -108,29 +108,8 @@ $extensionConfigurableAttributes->setConfigurableProductLinks($associatedProduct $product->setExtensionAttributes($extensionConfigurableAttributes); -// Remove any previously created product with the same id. -/** @var \Magento\Framework\Registry $registry */ -$registry = Bootstrap::getObjectManager()->get(\Magento\Framework\Registry::class); -$registry->unregister('isSecureArea'); -$registry->register('isSecureArea', true); -try { - $productToDelete = $productRepository->getById(1); - $productRepository->delete($productToDelete); - - /** @var \Magento\Quote\Model\ResourceModel\Quote\Item $itemResource */ - $itemResource = Bootstrap::getObjectManager()->get(\Magento\Quote\Model\ResourceModel\Quote\Item::class); - $itemResource->getConnection()->delete( - $itemResource->getMainTable(), - 'product_id = ' . $productToDelete->getId() - ); -} catch (\Exception $e) { - // Nothing to remove -} -$registry->unregister('isSecureArea'); -$registry->register('isSecureArea', false); - $product->setTypeId(Configurable::TYPE_CODE) - ->setId(1) + ->setId(1001) ->setAttributeSetId($attributeSetId) ->setWebsiteIds([1]) ->setName('Configurable Product') @@ -140,8 +119,3 @@ $product->setTypeId(Configurable::TYPE_CODE) ->setStockData(['use_config_manage_stock' => 1, 'is_in_stock' => 1]); $productRepository->save($product); -// -///** @var \Magento\Catalog\Model\Indexer\Product\Eav\Processor $eavIndexer */ -//$eavIndexer = Bootstrap::getObjectManager() -// ->get(\Magento\Catalog\Model\Indexer\Product\Eav\Processor::class); -//$eavIndexer->reindexAll(); diff --git a/dev/tests/integration/testsuite/Magento/Framework/Search/_files/product_configurable_rollback.php b/dev/tests/integration/testsuite/Magento/Framework/Search/_files/product_configurable_rollback.php index 8ba4e3abe21cc14a75a66270d22ea262dffeb788..cc585d177aedb9201faafcdef8bd57d5ea6dec73 100644 --- a/dev/tests/integration/testsuite/Magento/Framework/Search/_files/product_configurable_rollback.php +++ b/dev/tests/integration/testsuite/Magento/Framework/Search/_files/product_configurable_rollback.php @@ -16,7 +16,7 @@ $registry->register('isSecureArea', true); $productRepository = \Magento\TestFramework\Helper\Bootstrap::getObjectManager() ->get(\Magento\Catalog\Api\ProductRepositoryInterface::class); -foreach (['simple_10', 'simple_20', 'configurable'] as $sku) { +foreach (['simple_1010', 'simple_1020', 'configurable'] as $sku) { try { $product = $productRepository->get($sku, false, null, true); diff --git a/dev/tests/integration/testsuite/Magento/Framework/Search/_files/product_configurable_with_disabled_child.php b/dev/tests/integration/testsuite/Magento/Framework/Search/_files/product_configurable_with_disabled_child.php new file mode 100644 index 0000000000000000000000000000000000000000..39c9782ba712a7ed2204a61bdcd549863e202ed8 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Framework/Search/_files/product_configurable_with_disabled_child.php @@ -0,0 +1,18 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +use Magento\Catalog\Api\ProductRepositoryInterface; +use Magento\TestFramework\Helper\Bootstrap; + +require __DIR__ . '/product_configurable.php'; + +/** @var ProductRepositoryInterface $productRepository */ +$productRepository = Bootstrap::getObjectManager() + ->create(ProductRepositoryInterface::class); + +$product = $productRepository->get('simple_1020'); +$product->setStatus(\Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_DISABLED); +$productRepository->save($product); diff --git a/dev/tests/integration/testsuite/Magento/Framework/Search/_files/product_configurable_with_disabled_child_rollback.php b/dev/tests/integration/testsuite/Magento/Framework/Search/_files/product_configurable_with_disabled_child_rollback.php new file mode 100644 index 0000000000000000000000000000000000000000..58d1dcd79acde15c2d493625ca38c656ad286bb7 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Framework/Search/_files/product_configurable_with_disabled_child_rollback.php @@ -0,0 +1,7 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +require __DIR__ . '/product_configurable_rollback.php';