From 7c9547e369c78baecac01e245a8989a6cfb85616 Mon Sep 17 00:00:00 2001 From: vnayda Date: Wed, 5 Oct 2016 14:39:30 +0300 Subject: [PATCH 01/11] MAGETWO-52717: [GitHub] Configurable product disabling lowest price associated product still shows its price #4419 -- fix main select builder --- .../Product/BaseSelectProcessorInterface.php | 25 ++++++ .../Product/CompositeBaseSelectProcessor.php | 49 ++++++++++ ...LinkedProductSelectBuilderByIndexPrice.php | 31 +++++-- .../LinkedProductSelectBuilderByBasePrice.php | 23 +++-- ...nkedProductSelectBuilderBySpecialPrice.php | 23 +++-- .../LinkedProductSelectBuilderByTierPrice.php | 24 +++-- .../Product/StatusBaseSelectProcessor.php | 61 +++++++++++++ app/code/Magento/Catalog/etc/di.xml | 8 ++ .../StockStatusBaseSelectProcessor.php | 61 +++++++++++++ .../StockStatusBaseSelectProcessorTest.php | 89 +++++++++++++++++++ app/code/Magento/CatalogInventory/etc/di.xml | 7 ++ ...ProductSelectBuilderByCatalogRulePrice.php | 49 ++++++---- 12 files changed, 404 insertions(+), 46 deletions(-) create mode 100644 app/code/Magento/Catalog/Model/ResourceModel/Product/BaseSelectProcessorInterface.php create mode 100644 app/code/Magento/Catalog/Model/ResourceModel/Product/CompositeBaseSelectProcessor.php create mode 100644 app/code/Magento/Catalog/Model/ResourceModel/Product/StatusBaseSelectProcessor.php create mode 100644 app/code/Magento/CatalogInventory/Model/ResourceModel/Product/StockStatusBaseSelectProcessor.php create mode 100644 app/code/Magento/CatalogInventory/Test/Unit/Model/ResourceModel/Product/StockStatusBaseSelectProcessorTest.php diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product/BaseSelectProcessorInterface.php b/app/code/Magento/Catalog/Model/ResourceModel/Product/BaseSelectProcessorInterface.php new file mode 100644 index 0000000000000..aedd68eff6c43 --- /dev/null +++ b/app/code/Magento/Catalog/Model/ResourceModel/Product/BaseSelectProcessorInterface.php @@ -0,0 +1,25 @@ +baseSelectProcessors = $baseSelectProcessors; + } + + /** + * @param Select $select + * @return Select + */ + public function process(Select $select) + { + foreach ($this->baseSelectProcessors as $baseSelectProcessor) { + $select = $baseSelectProcessor->process($select); + } + return $select; + } +} diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product/Indexer/LinkedProductSelectBuilderByIndexPrice.php b/app/code/Magento/Catalog/Model/ResourceModel/Product/Indexer/LinkedProductSelectBuilderByIndexPrice.php index ea72691ea0039..c2029606c11ba 100644 --- a/app/code/Magento/Catalog/Model/ResourceModel/Product/Indexer/LinkedProductSelectBuilderByIndexPrice.php +++ b/app/code/Magento/Catalog/Model/ResourceModel/Product/Indexer/LinkedProductSelectBuilderByIndexPrice.php @@ -6,7 +6,8 @@ namespace Magento\Catalog\Model\ResourceModel\Product\Indexer; use Magento\Catalog\Api\Data\ProductInterface; -use Magento\Catalog\Model\Product; +use Magento\Catalog\Model\ResourceModel\Product\BaseSelectProcessorInterface; +use Magento\Framework\App\ObjectManager; use Magento\Framework\DB\Select; use Magento\Catalog\Model\ResourceModel\Product\LinkedProductSelectBuilderInterface; @@ -32,22 +33,31 @@ class LinkedProductSelectBuilderByIndexPrice implements LinkedProductSelectBuild */ private $metadataPool; + /** + * @var BaseSelectProcessorInterface + */ + private $baseSelectProcessor; + /** * @param \Magento\Store\Model\StoreManagerInterface $storeManager * @param \Magento\Framework\App\ResourceConnection $resourceConnection * @param \Magento\Customer\Model\Session $customerSession * @param \Magento\Framework\EntityManager\MetadataPool $metadataPool + * @param BaseSelectProcessorInterface $baseSelectProcessor */ public function __construct( \Magento\Store\Model\StoreManagerInterface $storeManager, \Magento\Framework\App\ResourceConnection $resourceConnection, \Magento\Customer\Model\Session $customerSession, - \Magento\Framework\EntityManager\MetadataPool $metadataPool + \Magento\Framework\EntityManager\MetadataPool $metadataPool, + BaseSelectProcessorInterface $baseSelectProcessor = null ) { $this->storeManager = $storeManager; $this->resource = $resourceConnection; $this->customerSession = $customerSession; $this->metadataPool = $metadataPool; + $this->baseSelectProcessor = (null !== $baseSelectProcessor) + ? $baseSelectProcessor : ObjectManager::getInstance()->get(BaseSelectProcessorInterface::class); } /** @@ -58,24 +68,27 @@ public function build($productId) $linkField = $this->metadataPool->getMetadata(ProductInterface::class)->getLinkField(); $productTable = $this->resource->getTableName('catalog_product_entity'); - return [$this->resource->getConnection()->select() + $priceSelect = $this->resource->getConnection()->select() ->from(['parent' => $productTable], '') ->joinInner( ['link' => $this->resource->getTableName('catalog_product_relation')], "link.parent_id = parent.$linkField", [] )->joinInner( - ['child' => $productTable], - "child.entity_id = link.child_id", - ['entity_id'] + [BaseSelectProcessorInterface::PRODUCT_TABLE_ALIAS => $productTable], + sprintf('%s.%s = link.child_id', BaseSelectProcessorInterface::PRODUCT_TABLE_ALIAS, $linkField), + [$linkField] )->joinInner( ['t' => $this->resource->getTableName('catalog_product_index_price')], - 't.entity_id = child.entity_id', + sprintf('t.entity_id = %s.%s', BaseSelectProcessorInterface::PRODUCT_TABLE_ALIAS, $linkField), [] - )->where('parent.entity_id = ? ', $productId) + )->where("parent.{$linkField} = ?", $productId) ->where('t.website_id = ?', $this->storeManager->getStore()->getWebsiteId()) ->where('t.customer_group_id = ?', $this->customerSession->getCustomerGroupId()) ->order('t.min_price ' . Select::SQL_ASC) - ->limit(1)]; + ->limit(1); + $priceSelect = $this->baseSelectProcessor->process($priceSelect); + + return [$priceSelect]; } } diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product/LinkedProductSelectBuilderByBasePrice.php b/app/code/Magento/Catalog/Model/ResourceModel/Product/LinkedProductSelectBuilderByBasePrice.php index d325ab1a9a08d..0473f30ce482c 100644 --- a/app/code/Magento/Catalog/Model/ResourceModel/Product/LinkedProductSelectBuilderByBasePrice.php +++ b/app/code/Magento/Catalog/Model/ResourceModel/Product/LinkedProductSelectBuilderByBasePrice.php @@ -7,6 +7,7 @@ use Magento\Catalog\Api\Data\ProductInterface; use Magento\Catalog\Model\Product; +use Magento\Framework\App\ObjectManager; use Magento\Framework\DB\Select; use Magento\Store\Model\Store; @@ -37,25 +38,34 @@ class LinkedProductSelectBuilderByBasePrice implements LinkedProductSelectBuilde */ private $metadataPool; + /** + * @var BaseSelectProcessorInterface + */ + private $baseSelectProcessor; + /** * @param \Magento\Store\Model\StoreManagerInterface $storeManager * @param \Magento\Framework\App\ResourceConnection $resourceConnection * @param \Magento\Eav\Model\Config $eavConfig * @param \Magento\Catalog\Helper\Data $catalogHelper * @param \Magento\Framework\EntityManager\MetadataPool $metadataPool + * @param BaseSelectProcessorInterface $baseSelectProcessor */ public function __construct( \Magento\Store\Model\StoreManagerInterface $storeManager, \Magento\Framework\App\ResourceConnection $resourceConnection, \Magento\Eav\Model\Config $eavConfig, \Magento\Catalog\Helper\Data $catalogHelper, - \Magento\Framework\EntityManager\MetadataPool $metadataPool + \Magento\Framework\EntityManager\MetadataPool $metadataPool, + BaseSelectProcessorInterface $baseSelectProcessor = null ) { $this->storeManager = $storeManager; $this->resource = $resourceConnection; $this->eavConfig = $eavConfig; $this->catalogHelper = $catalogHelper; $this->metadataPool = $metadataPool; + $this->baseSelectProcessor = (null !== $baseSelectProcessor) + ? $baseSelectProcessor : ObjectManager::getInstance()->get(BaseSelectProcessorInterface::class); } /** @@ -74,18 +84,19 @@ public function build($productId) "link.parent_id = parent.$linkField", [] )->joinInner( - ['child' => $productTable], - "child.entity_id = link.child_id", - ['entity_id'] + [BaseSelectProcessorInterface::PRODUCT_TABLE_ALIAS => $productTable], + sprintf('%s.%s = link.child_id', BaseSelectProcessorInterface::PRODUCT_TABLE_ALIAS, $linkField), + [$linkField] )->joinInner( ['t' => $priceAttribute->getBackendTable()], - "t.$linkField = child.$linkField", + sprintf('t.%s = %s.%1$s', $linkField, BaseSelectProcessorInterface::PRODUCT_TABLE_ALIAS), [] - )->where('parent.entity_id = ? ', $productId) + )->where("parent.{$linkField} = ?", $productId) ->where('t.attribute_id = ?', $priceAttribute->getAttributeId()) ->where('t.value IS NOT NULL') ->order('t.value ' . Select::SQL_ASC) ->limit(1); + $priceSelect = $this->baseSelectProcessor->process($priceSelect); $priceSelectDefault = clone $priceSelect; $priceSelectDefault->where('t.store_id = ?', Store::DEFAULT_STORE_ID); diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product/LinkedProductSelectBuilderBySpecialPrice.php b/app/code/Magento/Catalog/Model/ResourceModel/Product/LinkedProductSelectBuilderBySpecialPrice.php index 792a8f5b86d10..6b1cd879d782c 100644 --- a/app/code/Magento/Catalog/Model/ResourceModel/Product/LinkedProductSelectBuilderBySpecialPrice.php +++ b/app/code/Magento/Catalog/Model/ResourceModel/Product/LinkedProductSelectBuilderBySpecialPrice.php @@ -7,6 +7,7 @@ use Magento\Catalog\Api\Data\ProductInterface; use Magento\Catalog\Model\Product; +use Magento\Framework\App\ObjectManager; use Magento\Framework\DB\Select; use Magento\Store\Model\Store; @@ -47,6 +48,11 @@ class LinkedProductSelectBuilderBySpecialPrice implements LinkedProductSelectBui */ private $metadataPool; + /** + * @var BaseSelectProcessorInterface + */ + private $baseSelectProcessor; + /** * @param \Magento\Store\Model\StoreManagerInterface $storeManager * @param \Magento\Framework\App\ResourceConnection $resourceConnection @@ -55,6 +61,7 @@ class LinkedProductSelectBuilderBySpecialPrice implements LinkedProductSelectBui * @param \Magento\Framework\Stdlib\DateTime $dateTime * @param \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate * @param \Magento\Framework\EntityManager\MetadataPool $metadataPool + * @param BaseSelectProcessorInterface $baseSelectProcessor */ public function __construct( \Magento\Store\Model\StoreManagerInterface $storeManager, @@ -63,7 +70,8 @@ public function __construct( \Magento\Catalog\Helper\Data $catalogHelper, \Magento\Framework\Stdlib\DateTime $dateTime, \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate, - \Magento\Framework\EntityManager\MetadataPool $metadataPool + \Magento\Framework\EntityManager\MetadataPool $metadataPool, + BaseSelectProcessorInterface $baseSelectProcessor = null ) { $this->storeManager = $storeManager; $this->resource = $resourceConnection; @@ -72,6 +80,8 @@ public function __construct( $this->dateTime = $dateTime; $this->localeDate = $localeDate; $this->metadataPool = $metadataPool; + $this->baseSelectProcessor = (null !== $baseSelectProcessor) + ? $baseSelectProcessor : ObjectManager::getInstance()->get(BaseSelectProcessorInterface::class); } /** @@ -95,12 +105,12 @@ public function build($productId) "link.parent_id = parent.$linkField", [] )->joinInner( - ['child' => $productTable], - "child.entity_id = link.child_id", - ['entity_id'] + [BaseSelectProcessorInterface::PRODUCT_TABLE_ALIAS => $productTable], + sprintf('%s.%s = link.child_id', BaseSelectProcessorInterface::PRODUCT_TABLE_ALIAS, $linkField), + [$linkField] )->joinInner( ['t' => $specialPriceAttribute->getBackendTable()], - "t.$linkField = child.$linkField", + sprintf('t.%s = %s.%1$s', $linkField, BaseSelectProcessorInterface::PRODUCT_TABLE_ALIAS), [] )->joinLeft( ['special_from' => $specialPriceFromDate->getBackendTable()], @@ -116,7 +126,7 @@ public function build($productId) $specialPriceToDate->getAttributeId() ), '' - )->where('parent.entity_id = ? ', $productId) + )->where("parent.{$linkField} = ?", $productId) ->where('t.attribute_id = ?', $specialPriceAttribute->getAttributeId()) ->where('t.value IS NOT NULL') ->where( @@ -127,6 +137,7 @@ public function build($productId) $currentDate )->order('t.value ' . Select::SQL_ASC) ->limit(1); + $specialPrice = $this->baseSelectProcessor->process($specialPrice); $specialPriceDefault = clone $specialPrice; $specialPriceDefault->where('t.store_id = ?', Store::DEFAULT_STORE_ID); diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product/LinkedProductSelectBuilderByTierPrice.php b/app/code/Magento/Catalog/Model/ResourceModel/Product/LinkedProductSelectBuilderByTierPrice.php index d2d6d89c0a2a5..5ad93c67598d7 100644 --- a/app/code/Magento/Catalog/Model/ResourceModel/Product/LinkedProductSelectBuilderByTierPrice.php +++ b/app/code/Magento/Catalog/Model/ResourceModel/Product/LinkedProductSelectBuilderByTierPrice.php @@ -6,7 +6,7 @@ namespace Magento\Catalog\Model\ResourceModel\Product; use Magento\Catalog\Api\Data\ProductInterface; -use Magento\Catalog\Model\Product; +use Magento\Framework\App\ObjectManager; use Magento\Framework\DB\Select; class LinkedProductSelectBuilderByTierPrice implements LinkedProductSelectBuilderInterface @@ -41,25 +41,34 @@ class LinkedProductSelectBuilderByTierPrice implements LinkedProductSelectBuilde */ private $metadataPool; + /** + * @var BaseSelectProcessorInterface + */ + private $baseSelectProcessor; + /** * @param \Magento\Store\Model\StoreManagerInterface $storeManager * @param \Magento\Framework\App\ResourceConnection $resourceConnection * @param \Magento\Customer\Model\Session $customerSession * @param \Magento\Catalog\Helper\Data $catalogHelper * @param \Magento\Framework\EntityManager\MetadataPool $metadataPool + * @param BaseSelectProcessorInterface $baseSelectProcessor */ public function __construct( \Magento\Store\Model\StoreManagerInterface $storeManager, \Magento\Framework\App\ResourceConnection $resourceConnection, \Magento\Customer\Model\Session $customerSession, \Magento\Catalog\Helper\Data $catalogHelper, - \Magento\Framework\EntityManager\MetadataPool $metadataPool + \Magento\Framework\EntityManager\MetadataPool $metadataPool, + BaseSelectProcessorInterface $baseSelectProcessor = null ) { $this->storeManager = $storeManager; $this->resource = $resourceConnection; $this->customerSession = $customerSession; $this->catalogHelper = $catalogHelper; $this->metadataPool = $metadataPool; + $this->baseSelectProcessor = (null !== $baseSelectProcessor) + ? $baseSelectProcessor : ObjectManager::getInstance()->get(BaseSelectProcessorInterface::class); } /** @@ -77,18 +86,19 @@ public function build($productId) "link.parent_id = parent.$linkField", [] )->joinInner( - ['child' => $productTable], - "child.entity_id = link.child_id", - ['entity_id'] + [BaseSelectProcessorInterface::PRODUCT_TABLE_ALIAS => $productTable], + sprintf('%s.%s = link.child_id', BaseSelectProcessorInterface::PRODUCT_TABLE_ALIAS, $linkField), + [$linkField] )->joinInner( ['t' => $this->resource->getTableName('catalog_product_entity_tier_price')], - "t.$linkField = child.$linkField", + sprintf('t.%s = %s.%1$s', $linkField, BaseSelectProcessorInterface::PRODUCT_TABLE_ALIAS), [] - )->where('parent.entity_id = ? ', $productId) + )->where("parent.{$linkField} = ?", $productId) ->where('t.all_groups = 1 OR customer_group_id = ?', $this->customerSession->getCustomerGroupId()) ->where('t.qty = ?', 1) ->order('t.value ' . Select::SQL_ASC) ->limit(1); + $priceSelect = $this->baseSelectProcessor->process($priceSelect); $priceSelectDefault = clone $priceSelect; $priceSelectDefault->where('t.website_id = ?', self::DEFAULT_WEBSITE_ID); diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product/StatusBaseSelectProcessor.php b/app/code/Magento/Catalog/Model/ResourceModel/Product/StatusBaseSelectProcessor.php new file mode 100644 index 0000000000000..656998113fdb9 --- /dev/null +++ b/app/code/Magento/Catalog/Model/ResourceModel/Product/StatusBaseSelectProcessor.php @@ -0,0 +1,61 @@ +eavConfig = $eavConfig; + $this->metadataPool = $metadataPool; + } + + /** + * @param Select $select + * @return Select + */ + public function process(Select $select) + { + $linkField = $this->metadataPool->getMetadata(ProductInterface::class)->getLinkField(); + $statusAttribute = $this->eavConfig->getAttribute(Product::ENTITY, ProductInterface::STATUS); + + $select->join( + ['status_attr' => $statusAttribute->getBackendTable()], + sprintf('status_attr.%s = %s.%1$s', $linkField, self::PRODUCT_TABLE_ALIAS), + [] + ) + ->where('status_attr.attribute_id = ?', $statusAttribute->getAttributeId()) + ->where('status_attr.value = ?', Status::STATUS_ENABLED); + + return $select; + } +} diff --git a/app/code/Magento/Catalog/etc/di.xml b/app/code/Magento/Catalog/etc/di.xml index b355dd2601c3d..37e5cf22807e4 100644 --- a/app/code/Magento/Catalog/etc/di.xml +++ b/app/code/Magento/Catalog/etc/di.xml @@ -834,4 +834,12 @@ Magento\Eav\Model\Api\SearchCriteria\CollectionProcessor + + + + + Magento\Catalog\Model\ResourceModel\Product\StatusBaseSelectProcessor + + + diff --git a/app/code/Magento/CatalogInventory/Model/ResourceModel/Product/StockStatusBaseSelectProcessor.php b/app/code/Magento/CatalogInventory/Model/ResourceModel/Product/StockStatusBaseSelectProcessor.php new file mode 100644 index 0000000000000..4d37be99ce4a1 --- /dev/null +++ b/app/code/Magento/CatalogInventory/Model/ResourceModel/Product/StockStatusBaseSelectProcessor.php @@ -0,0 +1,61 @@ +resource = $resource; + $this->metadataPool = $metadataPool; + } + + /** + * Add stock item filter to selects + * + * @param Select $select + * @return Select + */ + public function process(Select $select) + { + $linkField = $this->metadataPool->getMetadata(ProductInterface::class)->getLinkField(); + $stockStatusTable = $this->resource->getTableName('cataloginventory_stock_status'); + + /** @var Select $select */ + $select->join( + ['stock' => $stockStatusTable], + sprintf('stock.product_id = %s.%s', BaseSelectProcessorInterface::PRODUCT_TABLE_ALIAS, $linkField), + [] + ) + ->where('stock.stock_status = ?', Stock::STOCK_IN_STOCK); + return $select; + } +} diff --git a/app/code/Magento/CatalogInventory/Test/Unit/Model/ResourceModel/Product/StockStatusBaseSelectProcessorTest.php b/app/code/Magento/CatalogInventory/Test/Unit/Model/ResourceModel/Product/StockStatusBaseSelectProcessorTest.php new file mode 100644 index 0000000000000..eafe5bfdcf2db --- /dev/null +++ b/app/code/Magento/CatalogInventory/Test/Unit/Model/ResourceModel/Product/StockStatusBaseSelectProcessorTest.php @@ -0,0 +1,89 @@ +resource = $this->getMockBuilder(ResourceConnection::class)->disableOriginalConstructor()->getMock(); + $this->metadataPool = $this->getMockBuilder(MetadataPool::class)->disableOriginalConstructor()->getMock(); + $this->select = $this->getMockBuilder(Select::class)->disableOriginalConstructor()->getMock(); + + $this->stockStatusBaseSelectProcessor = (new ObjectManager($this))->getObject( + StockStatusBaseSelectProcessor::class, + [ + 'resource' => $this->resource, + 'metadataPool' => $this->metadataPool, + ] + ); + } + + public function testProcess() + { + $linkField = 'link_field'; + $tableName = 'table_name'; + + $metadata = $this->getMock(EntityMetadataInterface::class); + $metadata->expects($this->once()) + ->method('getLinkField') + ->willReturn($linkField); + $this->metadataPool->expects($this->once()) + ->method('getMetadata') + ->with(ProductInterface::class) + ->willReturn($metadata); + + $this->resource->expects($this->once()) + ->method('getTableName') + ->with('cataloginventory_stock_status') + ->willReturn($tableName); + + $this->select->expects($this->once()) + ->method('join') + ->with( + ['stock' => $tableName], + sprintf('stock.product_id = %s.%s', BaseSelectProcessorInterface::PRODUCT_TABLE_ALIAS, $linkField), + [] + ) + ->willReturnSelf(); + $this->select->expects($this->once()) + ->method('where') + ->with('stock.stock_status = ?', Stock::STOCK_IN_STOCK) + ->willReturnSelf(); + + $this->stockStatusBaseSelectProcessor->process($this->select); + } +} diff --git a/app/code/Magento/CatalogInventory/etc/di.xml b/app/code/Magento/CatalogInventory/etc/di.xml index 71b42ef89f73c..e3ca5c01cedab 100644 --- a/app/code/Magento/CatalogInventory/etc/di.xml +++ b/app/code/Magento/CatalogInventory/etc/di.xml @@ -79,4 +79,11 @@ Magento\CatalogInventory\Model\Indexer\Stock\Processor + + + + Magento\CatalogInventory\Model\ResourceModel\Product\StockStatusBaseSelectProcessor + + + diff --git a/app/code/Magento/CatalogRule/Model/ResourceModel/Product/LinkedProductSelectBuilderByCatalogRulePrice.php b/app/code/Magento/CatalogRule/Model/ResourceModel/Product/LinkedProductSelectBuilderByCatalogRulePrice.php index 7d8d44dcbb68a..e61ea0c98186a 100644 --- a/app/code/Magento/CatalogRule/Model/ResourceModel/Product/LinkedProductSelectBuilderByCatalogRulePrice.php +++ b/app/code/Magento/CatalogRule/Model/ResourceModel/Product/LinkedProductSelectBuilderByCatalogRulePrice.php @@ -6,7 +6,8 @@ namespace Magento\CatalogRule\Model\ResourceModel\Product; use Magento\Catalog\Api\Data\ProductInterface; -use Magento\Catalog\Model\Product; +use Magento\Catalog\Model\ResourceModel\Product\BaseSelectProcessorInterface; +use Magento\Framework\App\ObjectManager; use Magento\Framework\DB\Select; use Magento\Catalog\Model\ResourceModel\Product\LinkedProductSelectBuilderInterface; @@ -42,6 +43,11 @@ class LinkedProductSelectBuilderByCatalogRulePrice implements LinkedProductSelec */ private $metadataPool; + /** + * @var BaseSelectProcessorInterface + */ + private $baseSelectProcessor; + /** * @param \Magento\Store\Model\StoreManagerInterface $storeManager * @param \Magento\Framework\App\ResourceConnection $resourceConnection @@ -49,6 +55,7 @@ class LinkedProductSelectBuilderByCatalogRulePrice implements LinkedProductSelec * @param \Magento\Framework\Stdlib\DateTime $dateTime * @param \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate * @param \Magento\Framework\EntityManager\MetadataPool $metadataPool + * @param BaseSelectProcessorInterface $baseSelectProcessor */ public function __construct( \Magento\Store\Model\StoreManagerInterface $storeManager, @@ -56,7 +63,8 @@ public function __construct( \Magento\Customer\Model\Session $customerSession, \Magento\Framework\Stdlib\DateTime $dateTime, \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate, - \Magento\Framework\EntityManager\MetadataPool $metadataPool + \Magento\Framework\EntityManager\MetadataPool $metadataPool, + BaseSelectProcessorInterface $baseSelectProcessor = null ) { $this->storeManager = $storeManager; $this->resource = $resourceConnection; @@ -64,6 +72,8 @@ public function __construct( $this->dateTime = $dateTime; $this->localeDate = $localeDate; $this->metadataPool = $metadataPool; + $this->baseSelectProcessor = (null !== $baseSelectProcessor) + ? $baseSelectProcessor : ObjectManager::getInstance()->get(BaseSelectProcessorInterface::class); } /** @@ -76,25 +86,28 @@ public function build($productId) $linkField = $this->metadataPool->getMetadata(ProductInterface::class)->getLinkField(); $productTable = $this->resource->getTableName('catalog_product_entity'); - return [$this->resource->getConnection()->select() - ->from(['parent' => $productTable], '') - ->joinInner( - ['link' => $this->resource->getTableName('catalog_product_relation')], - "link.parent_id = parent.$linkField", - [] - )->joinInner( - ['child' => $productTable], - "child.entity_id = link.child_id", - ['entity_id'] - )->joinInner( - ['t' => $this->resource->getTableName('catalogrule_product_price')], - 't.product_id = child.entity_id', - [] - )->where('parent.entity_id = ? ', $productId) + $priceSelect = $this->resource->getConnection()->select() + ->from(['parent' => $productTable], '') + ->joinInner( + ['link' => $this->resource->getTableName('catalog_product_relation')], + "link.parent_id = parent.$linkField", + [] + )->joinInner( + [BaseSelectProcessorInterface::PRODUCT_TABLE_ALIAS => $productTable], + sprintf('%s.%s = link.child_id', BaseSelectProcessorInterface::PRODUCT_TABLE_ALIAS, $linkField), + [$linkField] + )->joinInner( + ['t' => $this->resource->getTableName('catalogrule_product_price')], + sprintf('t.product_id = %s.%s', BaseSelectProcessorInterface::PRODUCT_TABLE_ALIAS, $linkField), + [] + )->where("parent.{$linkField} = ?", $productId) ->where('t.website_id = ?', $this->storeManager->getStore()->getWebsiteId()) ->where('t.customer_group_id = ?', $this->customerSession->getCustomerGroupId()) ->where('t.rule_date = ?', $currentDate) ->order('t.rule_price ' . Select::SQL_ASC) - ->limit(1)]; + ->limit(1); + $priceSelect = $this->baseSelectProcessor->process($priceSelect); + + return [$priceSelect]; } } From eacec0e946bf53f58bd30a4483a84d00f4efd9f8 Mon Sep 17 00:00:00 2001 From: vnayda Date: Wed, 5 Oct 2016 15:48:26 +0300 Subject: [PATCH 02/11] MAGETWO-52717: [GitHub] Configurable product disabling lowest price associated product still shows its price #4419 -- refactoring -- test coverage --- .../CompositeBaseSelectProcessorTest.php | 54 +++++++++ .../Product/StatusBaseSelectProcessorTest.php | 102 +++++++++++++++++ .../Price/ConfigurableOptionsProvider.php | 37 +----- .../Price/ConfigurablePriceResolver.php | 26 ++--- .../Price/ConfigurableRegularPrice.php | 18 ++- .../Price/LowestPriceOptionsProvider.php | 63 ++++++++++ .../LowestPriceOptionsProviderInterface.php | 20 ++++ .../Pricing/Render/FinalPriceBox.php | 16 ++- .../Price/ConfigurablePriceResolverTest.php | 26 +++-- .../Unit/Pricing/Render/FinalPriceBoxTest.php | 26 +++-- .../Magento/ConfigurableProduct/etc/di.xml | 2 + .../Price/LowestPriceOptionProviderTest.php | 81 +++++++++++++ .../configurable_product_with_two_simple.php | 108 ++++++++++++++++++ 13 files changed, 494 insertions(+), 85 deletions(-) create mode 100644 app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/Product/CompositeBaseSelectProcessorTest.php create mode 100644 app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/Product/StatusBaseSelectProcessorTest.php create mode 100644 app/code/Magento/ConfigurableProduct/Pricing/Price/LowestPriceOptionsProvider.php create mode 100644 app/code/Magento/ConfigurableProduct/Pricing/Price/LowestPriceOptionsProviderInterface.php create mode 100644 dev/tests/integration/testsuite/Magento/ConfigurableProduct/Pricing/Price/LowestPriceOptionProviderTest.php create mode 100644 dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/configurable_product_with_two_simple.php diff --git a/app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/Product/CompositeBaseSelectProcessorTest.php b/app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/Product/CompositeBaseSelectProcessorTest.php new file mode 100644 index 0000000000000..d296474c202f0 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/Product/CompositeBaseSelectProcessorTest.php @@ -0,0 +1,54 @@ +objectManager = new ObjectManager($this); + } + + /** + * @expectedException \Magento\Framework\Exception\InputException + */ + public function testInitializeWithWrongProcessorInstance() + { + $processorValid = $this->getMock(BaseSelectProcessorInterface::class); + $processorInvalid = $this->getMock(\stdClass::class); + + $this->objectManager->getObject(CompositeBaseSelectProcessor::class, [ + 'baseSelectProcessors' => [$processorValid, $processorInvalid], + ]); + } + + public function testProcess() + { + $select = $this->getMockBuilder(Select::class)->disableOriginalConstructor()->getMock(); + + $processorFirst = $this->getMock(BaseSelectProcessorInterface::class); + $processorFirst->expects($this->once())->method('process')->with($select)->willReturn($select); + + $processorSecond = $this->getMock(BaseSelectProcessorInterface::class); + $processorSecond->expects($this->once())->method('process')->with($select)->willReturn($select); + + /** @var CompositeBaseSelectProcessor $baseSelectProcessors */ + $baseSelectProcessors = $this->objectManager->getObject(CompositeBaseSelectProcessor::class, [ + 'baseSelectProcessors' => [$processorFirst, $processorSecond], + ]); + $this->assertEquals($select, $baseSelectProcessors->process($select)); + } +} diff --git a/app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/Product/StatusBaseSelectProcessorTest.php b/app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/Product/StatusBaseSelectProcessorTest.php new file mode 100644 index 0000000000000..0909f754a01c2 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Unit/Model/ResourceModel/Product/StatusBaseSelectProcessorTest.php @@ -0,0 +1,102 @@ +eavConfig = $this->getMockBuilder(Config::class)->disableOriginalConstructor()->getMock(); + $this->metadataPool = $this->getMockBuilder(MetadataPool::class)->disableOriginalConstructor()->getMock(); + $this->select = $this->getMockBuilder(Select::class)->disableOriginalConstructor()->getMock(); + + $this->statusBaseSelectProcessor = (new ObjectManager($this))->getObject(StatusBaseSelectProcessor::class, [ + 'eavConfig' => $this->eavConfig, + 'metadataPool' => $this->metadataPool, + ]); + } + + public function testProcess() + { + $linkField = 'link_field'; + $backendTable = 'backend_table'; + $attributeId = 'attribute_id'; + + $metadata = $this->getMock(EntityMetadataInterface::class); + $metadata->expects($this->once()) + ->method('getLinkField') + ->willReturn($linkField); + $this->metadataPool->expects($this->once()) + ->method('getMetadata') + ->with(ProductInterface::class) + ->willReturn($metadata); + + $statusAttribute = $this->getMockBuilder(AttributeInterface::class) + ->setMethods(['getBackendTable', 'getAttributeId']) + ->getMock(); + $statusAttribute->expects($this->once()) + ->method('getBackendTable') + ->willReturn($backendTable); + $statusAttribute->expects($this->once()) + ->method('getAttributeId') + ->willReturn($attributeId); + $this->eavConfig->expects($this->once()) + ->method('getAttribute') + ->with(Product::ENTITY, ProductInterface::STATUS) + ->willReturn($statusAttribute); + + $this->select->expects($this->once()) + ->method('join') + ->with( + ['status_attr' => $backendTable], + sprintf('status_attr.%s = %s.%1$s', $linkField, BaseSelectProcessorInterface::PRODUCT_TABLE_ALIAS), + [] + ) + ->willReturnSelf(); + $this->select->expects($this->at(1)) + ->method('where') + ->with('status_attr.attribute_id = ?', $attributeId) + ->willReturnSelf(); + $this->select->expects($this->at(2)) + ->method('where') + ->with('status_attr.value = ?', Status::STATUS_ENABLED) + ->willReturnSelf(); + + $this->assertEquals($this->select, $this->statusBaseSelectProcessor->process($this->select)); + } +} diff --git a/app/code/Magento/ConfigurableProduct/Pricing/Price/ConfigurableOptionsProvider.php b/app/code/Magento/ConfigurableProduct/Pricing/Price/ConfigurableOptionsProvider.php index dcb75fe725dc2..872538d9babab 100644 --- a/app/code/Magento/ConfigurableProduct/Pricing/Price/ConfigurableOptionsProvider.php +++ b/app/code/Magento/ConfigurableProduct/Pricing/Price/ConfigurableOptionsProvider.php @@ -18,26 +18,6 @@ class ConfigurableOptionsProvider implements ConfigurableOptionsProviderInterfac /** @var Configurable */ private $configurable; - /** - * @var RequestSafetyInterface - */ - private $requestSafety; - - /** - * @var ResourceConnection - */ - private $resource; - - /** - * @var LinkedProductSelectBuilderInterface - */ - private $linkedProductSelectBuilder; - - /** - * @var CollectionFactory - */ - private $collectionFactory; - /** * @var ProductInterface[] */ @@ -49,6 +29,7 @@ class ConfigurableOptionsProvider implements ConfigurableOptionsProviderInterfac * @param LinkedProductSelectBuilderInterface $linkedProductSelectBuilder * @param CollectionFactory $collectionFactory * @param RequestSafetyInterface $requestSafety + * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ public function __construct( Configurable $configurable, @@ -58,10 +39,6 @@ public function __construct( RequestSafetyInterface $requestSafety ) { $this->configurable = $configurable; - $this->resource = $resourceConnection; - $this->linkedProductSelectBuilder = $linkedProductSelectBuilder; - $this->collectionFactory = $collectionFactory; - $this->requestSafety = $requestSafety; } /** @@ -70,17 +47,7 @@ public function __construct( public function getProducts(ProductInterface $product) { if (!isset($this->products[$product->getId()])) { - if ($this->requestSafety->isSafeMethod()) { - $productIds = $this->resource->getConnection()->fetchCol( - '(' . implode(') UNION (', $this->linkedProductSelectBuilder->build($product->getId())) . ')' - ); - - $this->products[$product->getId()] = $this->collectionFactory->create() - ->addAttributeToSelect(['price', 'special_price']) - ->addIdFilter($productIds); - } else { - $this->products[$product->getId()] = $this->configurable->getUsedProducts($product); - } + $this->products[$product->getId()] = $this->configurable->getUsedProducts($product); } return $this->products[$product->getId()]; } diff --git a/app/code/Magento/ConfigurableProduct/Pricing/Price/ConfigurablePriceResolver.php b/app/code/Magento/ConfigurableProduct/Pricing/Price/ConfigurablePriceResolver.php index 75d08b5aa419b..68e82ed76a23f 100644 --- a/app/code/Magento/ConfigurableProduct/Pricing/Price/ConfigurablePriceResolver.php +++ b/app/code/Magento/ConfigurableProduct/Pricing/Price/ConfigurablePriceResolver.php @@ -6,7 +6,6 @@ namespace Magento\ConfigurableProduct\Pricing\Price; -use Magento\Catalog\Model\Product; use Magento\ConfigurableProduct\Model\Product\Type\Configurable; use Magento\Framework\App\ObjectManager; use Magento\Framework\Pricing\PriceCurrencyInterface; @@ -29,23 +28,27 @@ class ConfigurablePriceResolver implements PriceResolverInterface protected $configurable; /** - * @var ConfigurableOptionsProviderInterface + * @var LowestPriceOptionsProviderInterface */ - private $configurableOptionsProvider; + private $lowestPriceOptionsProvider; /** * @param PriceResolverInterface $priceResolver * @param Configurable $configurable * @param PriceCurrencyInterface $priceCurrency + * @param LowestPriceOptionsProviderInterface $lowestPriceOptionsProvider */ public function __construct( PriceResolverInterface $priceResolver, Configurable $configurable, - PriceCurrencyInterface $priceCurrency + PriceCurrencyInterface $priceCurrency, + LowestPriceOptionsProviderInterface $lowestPriceOptionsProvider = null ) { $this->priceResolver = $priceResolver; $this->configurable = $configurable; $this->priceCurrency = $priceCurrency; + $this->lowestPriceOptionsProvider = $lowestPriceOptionsProvider ?: + ObjectManager::getInstance()->get(LowestPriceOptionsProviderInterface::class); } /** @@ -57,7 +60,7 @@ public function resolvePrice(\Magento\Framework\Pricing\SaleableInterface $produ { $price = null; - foreach ($this->getConfigurableOptionsProvider()->getProducts($product) as $subProduct) { + foreach ($this->lowestPriceOptionsProvider->getProducts($product) as $subProduct) { $productPrice = $this->priceResolver->resolvePrice($subProduct); $price = $price ? min($price, $productPrice) : $productPrice; } @@ -69,17 +72,4 @@ public function resolvePrice(\Magento\Framework\Pricing\SaleableInterface $produ return (float)$price; } - - /** - * @return \Magento\ConfigurableProduct\Pricing\Price\ConfigurableOptionsProviderInterface - * @deprecated - */ - private function getConfigurableOptionsProvider() - { - if (null === $this->configurableOptionsProvider) { - $this->configurableOptionsProvider = ObjectManager::getInstance() - ->get(ConfigurableOptionsProviderInterface::class); - } - return $this->configurableOptionsProvider; - } } diff --git a/app/code/Magento/ConfigurableProduct/Pricing/Price/ConfigurableRegularPrice.php b/app/code/Magento/ConfigurableProduct/Pricing/Price/ConfigurableRegularPrice.php index 14b788258ab75..7a710e2caacc9 100644 --- a/app/code/Magento/ConfigurableProduct/Pricing/Price/ConfigurableRegularPrice.php +++ b/app/code/Magento/ConfigurableProduct/Pricing/Price/ConfigurableRegularPrice.php @@ -44,22 +44,31 @@ class ConfigurableRegularPrice extends AbstractPrice implements ConfigurableRegu */ private $configurableOptionsProvider; + /** + * @var LowestPriceOptionsProviderInterface + */ + private $lowestPriceOptionsProvider; + /** * @param \Magento\Framework\Pricing\SaleableInterface $saleableItem * @param float $quantity * @param \Magento\Framework\Pricing\Adjustment\CalculatorInterface $calculator * @param \Magento\Framework\Pricing\PriceCurrencyInterface $priceCurrency * @param PriceResolverInterface $priceResolver + * @param LowestPriceOptionsProviderInterface $lowestPriceOptionsProvider */ public function __construct( \Magento\Framework\Pricing\SaleableInterface $saleableItem, $quantity, \Magento\Framework\Pricing\Adjustment\CalculatorInterface $calculator, \Magento\Framework\Pricing\PriceCurrencyInterface $priceCurrency, - PriceResolverInterface $priceResolver + PriceResolverInterface $priceResolver, + LowestPriceOptionsProviderInterface $lowestPriceOptionsProvider = null ) { parent::__construct($saleableItem, $quantity, $calculator, $priceCurrency); $this->priceResolver = $priceResolver; + $this->lowestPriceOptionsProvider = $lowestPriceOptionsProvider ?: + ObjectManager::getInstance()->get(LowestPriceOptionsProviderInterface::class); } /** @@ -88,7 +97,6 @@ public function getAmount() public function getMaxRegularAmount() { if (null === $this->maxRegularAmount) { - $this->maxRegularAmount = $this->doGetMaxRegularAmount(); $this->maxRegularAmount = $this->doGetMaxRegularAmount() ?: false; } return $this->maxRegularAmount; @@ -96,7 +104,7 @@ public function getMaxRegularAmount() } /** - * Get max regular amount. Template method + * Get max regular amount * * @return \Magento\Framework\Pricing\Amount\AmountInterface */ @@ -124,14 +132,14 @@ public function getMinRegularAmount() } /** - * Get min regular amount. Template method + * Get min regular amount * * @return \Magento\Framework\Pricing\Amount\AmountInterface */ protected function doGetMinRegularAmount() { $minAmount = null; - foreach ($this->getUsedProducts() as $product) { + foreach ($this->lowestPriceOptionsProvider->getProducts($this->product) as $product) { $childPriceAmount = $product->getPriceInfo()->getPrice(self::PRICE_CODE)->getAmount(); if (!$minAmount || ($childPriceAmount->getValue() < $minAmount->getValue())) { $minAmount = $childPriceAmount; diff --git a/app/code/Magento/ConfigurableProduct/Pricing/Price/LowestPriceOptionsProvider.php b/app/code/Magento/ConfigurableProduct/Pricing/Price/LowestPriceOptionsProvider.php new file mode 100644 index 0000000000000..1b758866100eb --- /dev/null +++ b/app/code/Magento/ConfigurableProduct/Pricing/Price/LowestPriceOptionsProvider.php @@ -0,0 +1,63 @@ +resource = $resourceConnection; + $this->linkedProductSelectBuilder = $linkedProductSelectBuilder; + $this->collectionFactory = $collectionFactory; + } + + /** + * {@inheritdoc} + */ + public function getProducts(ProductInterface $product) + { + $productIds = $this->resource->getConnection()->fetchCol( + '(' . implode(') UNION (', $this->linkedProductSelectBuilder->build($product->getId())) . ')' + ); + + $lowestPriceChildProducts = $this->collectionFactory->create() + ->addAttributeToSelect(['price', 'special_price']) + ->addIdFilter($productIds) + ->getItems(); + return $lowestPriceChildProducts; + } +} diff --git a/app/code/Magento/ConfigurableProduct/Pricing/Price/LowestPriceOptionsProviderInterface.php b/app/code/Magento/ConfigurableProduct/Pricing/Price/LowestPriceOptionsProviderInterface.php new file mode 100644 index 0000000000000..8d260c3073587 --- /dev/null +++ b/app/code/Magento/ConfigurableProduct/Pricing/Price/LowestPriceOptionsProviderInterface.php @@ -0,0 +1,20 @@ +configurableOptionsProvider = $configurableOptionsProvider; parent::__construct($context, $saleableItem, $price, $rendererPool, $data); + $this->lowestPriceOptionsProvider = $lowestPriceOptionsProvider ?: + ObjectManager::getInstance()->get(LowestPriceOptionsProviderInterface::class); } /** @@ -48,7 +54,7 @@ public function __construct( public function hasSpecialPrice() { $product = $this->getSaleableItem(); - foreach ($this->configurableOptionsProvider->getProducts($product) as $subProduct) { + foreach ($this->lowestPriceOptionsProvider->getProducts($product) as $subProduct) { $regularPrice = $subProduct->getPriceInfo()->getPrice(RegularPrice::PRICE_CODE)->getValue(); $finalPrice = $subProduct->getPriceInfo()->getPrice(FinalPrice::PRICE_CODE)->getValue(); if ($finalPrice < $regularPrice) { diff --git a/app/code/Magento/ConfigurableProduct/Test/Unit/Pricing/Price/ConfigurablePriceResolverTest.php b/app/code/Magento/ConfigurableProduct/Test/Unit/Pricing/Price/ConfigurablePriceResolverTest.php index 0e2cfc0630226..8db61bb5e0a43 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Unit/Pricing/Price/ConfigurablePriceResolverTest.php +++ b/app/code/Magento/ConfigurableProduct/Test/Unit/Pricing/Price/ConfigurablePriceResolverTest.php @@ -5,13 +5,15 @@ */ namespace Magento\ConfigurableProduct\Test\Unit\Pricing\Price; -use Magento\ConfigurableProduct\Pricing\Price\ConfigurableOptionsProviderInterface; +use Magento\ConfigurableProduct\Pricing\Price\LowestPriceOptionsProviderInterface; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; class ConfigurablePriceResolverTest extends \PHPUnit_Framework_TestCase { - /** @var ConfigurableOptionsProviderInterface */ - private $cofigurableOptionProvider; + /** + * @var LowestPriceOptionsProviderInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $lowestPriceOptionsProvider; /** * @var \Magento\ConfigurableProduct\Pricing\Price\ConfigurablePriceResolver @@ -19,12 +21,12 @@ class ConfigurablePriceResolverTest extends \PHPUnit_Framework_TestCase protected $resolver; /** - * @var PHPUnit_Framework_MockObject_MockObject | \Magento\ConfigurableProduct\Model\Product\Type\Configurable + * @var \PHPUnit_Framework_MockObject_MockObject | \Magento\ConfigurableProduct\Model\Product\Type\Configurable */ protected $configurable; /** - * @var PHPUnit_Framework_MockObject_MockObject | \Magento\ConfigurableProduct\Pricing\Price\PriceResolverInterface + * @var \PHPUnit_Framework_MockObject_MockObject | \Magento\ConfigurableProduct\Pricing\Price\PriceResolverInterface */ protected $priceResolver; @@ -36,8 +38,7 @@ protected function setUp() $className = \Magento\ConfigurableProduct\Pricing\Price\PriceResolverInterface::class; $this->priceResolver = $this->getMockForAbstractClass($className, [], '', false, true, true, ['resolvePrice']); - $this->cofigurableOptionProvider = $this->getMockBuilder(ConfigurableOptionsProviderInterface::class) - ->disableOriginalConstructor()->getMock(); + $this->lowestPriceOptionsProvider = $this->getMock(LowestPriceOptionsProviderInterface::class); $objectManager = new ObjectManager($this); $this->resolver = $objectManager->getObject( @@ -45,7 +46,7 @@ protected function setUp() [ 'priceResolver' => $this->priceResolver, 'configurable' => $this->configurable, - 'configurableOptionsProvider' => $this->cofigurableOptionProvider, + 'lowestPriceOptionsProvider' => $this->lowestPriceOptionsProvider, ] ); } @@ -63,7 +64,7 @@ public function testResolvePriceWithNoPrices() $product->expects($this->once())->method('getSku')->willReturn('Kiwi'); - $this->cofigurableOptionProvider->expects($this->once())->method('getProducts')->willReturn([]); + $this->lowestPriceOptionsProvider->expects($this->once())->method('getProducts')->willReturn([]); $this->resolver->resolvePrice($product); } @@ -83,8 +84,11 @@ public function testResolvePrice($expectedValue) $product->expects($this->never())->method('getSku'); - $this->cofigurableOptionProvider->expects($this->once())->method('getProducts')->willReturn([$product]); - $this->priceResolver->expects($this->atLeastOnce())->method('resolvePrice')->willReturn($price); + $this->lowestPriceOptionsProvider->expects($this->once())->method('getProducts')->willReturn([$product]); + $this->priceResolver->expects($this->once()) + ->method('resolvePrice') + ->with($product) + ->willReturn($price); $this->assertEquals($expectedValue, $this->resolver->resolvePrice($product)); } diff --git a/app/code/Magento/ConfigurableProduct/Test/Unit/Pricing/Render/FinalPriceBoxTest.php b/app/code/Magento/ConfigurableProduct/Test/Unit/Pricing/Render/FinalPriceBoxTest.php index 4dbcfed531525..b102e1d81f48e 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Unit/Pricing/Render/FinalPriceBoxTest.php +++ b/app/code/Magento/ConfigurableProduct/Test/Unit/Pricing/Render/FinalPriceBoxTest.php @@ -7,8 +7,9 @@ use Magento\Catalog\Pricing\Price\FinalPrice; use Magento\Catalog\Pricing\Price\RegularPrice; -use Magento\ConfigurableProduct\Pricing\Price\ConfigurableOptionsProviderInterface; +use Magento\ConfigurableProduct\Pricing\Price\LowestPriceOptionsProviderInterface; use Magento\ConfigurableProduct\Pricing\Render\FinalPriceBox; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; class FinalPriceBoxTest extends \PHPUnit_Framework_TestCase { @@ -33,9 +34,9 @@ class FinalPriceBoxTest extends \PHPUnit_Framework_TestCase private $rendererPool; /** - * @var ConfigurableOptionsProviderInterface|\PHPUnit_Framework_MockObject_MockObject + * @var LowestPriceOptionsProviderInterface|\PHPUnit_Framework_MockObject_MockObject */ - private $configurableOptionsProvider; + private $lowestPriceOptionsProvider; /** * @var FinalPriceBox @@ -59,15 +60,18 @@ protected function setUp() ->disableOriginalConstructor() ->getMock(); - $this->configurableOptionsProvider = $this->getMockBuilder(ConfigurableOptionsProviderInterface::class) + $this->lowestPriceOptionsProvider = $this->getMockBuilder(LowestPriceOptionsProviderInterface::class) ->getMockForAbstractClass(); - $this->model = new FinalPriceBox( - $this->context, - $this->saleableItem, - $this->price, - $this->rendererPool, - $this->configurableOptionsProvider + $this->model = (new ObjectManager($this))->getObject( + FinalPriceBox::class, + [ + 'context' => $this->context, + 'saleableItem' => $this->saleableItem, + 'price' => $this->price, + 'rendererPool' => $this->rendererPool, + 'lowestPriceOptionsProvider' => $this->lowestPriceOptionsProvider, + ] ); } @@ -115,7 +119,7 @@ public function testHasSpecialPrice( ->method('getPriceInfo') ->willReturn($priceInfoMock); - $this->configurableOptionsProvider->expects($this->once()) + $this->lowestPriceOptionsProvider->expects($this->once()) ->method('getProducts') ->with($this->saleableItem) ->willReturn([$productMock]); diff --git a/app/code/Magento/ConfigurableProduct/etc/di.xml b/app/code/Magento/ConfigurableProduct/etc/di.xml index 89b271de838f9..e3178629f824c 100644 --- a/app/code/Magento/ConfigurableProduct/etc/di.xml +++ b/app/code/Magento/ConfigurableProduct/etc/di.xml @@ -13,6 +13,8 @@ + + diff --git a/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Pricing/Price/LowestPriceOptionProviderTest.php b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Pricing/Price/LowestPriceOptionProviderTest.php new file mode 100644 index 0000000000000..c0bc6c9871dc1 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Pricing/Price/LowestPriceOptionProviderTest.php @@ -0,0 +1,81 @@ +productRepository = Bootstrap::getObjectManager()->get(ProductRepositoryInterface::class); + $this->lowestPriceOptionsProvider = Bootstrap::getObjectManager()->get( + LowestPriceOptionsProviderInterface::class + ); + } + + /** + * @magentoDataFixture Magento/ConfigurableProduct/_files/configurable_product_with_two_simple.php + */ + public function testGetProductsIfOneOfChildIsDisabled() + { + $configurableProduct = $this->productRepository->get('configurable_product_with_two_simple'); + $lowestPriceChildrenProducts = $this->lowestPriceOptionsProvider->getProducts($configurableProduct); + $this->assertCount(1, $lowestPriceChildrenProducts); + $lowestPriceChildrenProduct = reset($lowestPriceChildrenProducts); + $this->assertEquals(10, $lowestPriceChildrenProduct->getPrice()); + + // load full aggregation root + $lowestPriceChildProduct = $this->productRepository->get($lowestPriceChildrenProduct->getSku()); + $lowestPriceChildProduct->setStatus(Status::STATUS_DISABLED); + $this->productRepository->save($lowestPriceChildProduct); + + $lowestPriceChildrenProducts = $this->lowestPriceOptionsProvider->getProducts($configurableProduct); + $this->assertCount(1, $lowestPriceChildrenProducts); + $lowestPriceChildrenProduct = reset($lowestPriceChildrenProducts); + $this->assertEquals(20, $lowestPriceChildrenProduct->getPrice()); + } + + /** + * @magentoDataFixture Magento/ConfigurableProduct/_files/configurable_product_with_two_simple.php + */ + public function testGetProductsIfOneOfChildIsOutOfStock() + { + $configurableProduct = $this->productRepository->get('configurable_product_with_two_simple'); + $lowestPriceChildrenProducts = $this->lowestPriceOptionsProvider->getProducts($configurableProduct); + $this->assertCount(1, $lowestPriceChildrenProducts); + $lowestPriceChildrenProduct = reset($lowestPriceChildrenProducts); + $this->assertEquals(10, $lowestPriceChildrenProduct->getPrice()); + + // load full aggregation root + $lowestPriceChildProduct = $this->productRepository->get($lowestPriceChildrenProduct->getSku()); + $stockItem = $lowestPriceChildProduct->getExtensionAttributes()->getStockItem(); + $stockItem->setIsInStock(false); + // TODO: Need to delete next string after MAGETWO-59315 fixing + $lowestPriceChildProduct->setStockData(['is_in_stock' => 0, 'qty' => 0]); + $this->productRepository->save($lowestPriceChildProduct); + + $lowestPriceChildrenProducts = $this->lowestPriceOptionsProvider->getProducts($configurableProduct); + $this->assertCount(1, $lowestPriceChildrenProducts); + $lowestPriceChildrenProduct = reset($lowestPriceChildrenProducts); + $this->assertEquals(20, $lowestPriceChildrenProduct->getPrice()); + } +} diff --git a/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/configurable_product_with_two_simple.php b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/configurable_product_with_two_simple.php new file mode 100644 index 0000000000000..f28918f39dc83 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/configurable_product_with_two_simple.php @@ -0,0 +1,108 @@ +get(DataObjectHelper::class); +$productFactory = $objectManager->get(ProductInterfaceFactory::class); +/** @var ProductRepositoryInterface $productRepository */ +$productRepository = Bootstrap::getObjectManager()->get(ProductRepositoryInterface::class); +/** @var CategorySetup $installer */ +$installer = Bootstrap::getObjectManager()->create(CategorySetup::class); +/** @var Factory $optionsFactory */ +$optionsFactory = Bootstrap::getObjectManager()->create(Factory::class); + +/** @var AttributeOptionInterface[] $options */ +$options = $attribute->getOptions(); +$attributeSetId = $installer->getAttributeSetId('catalog_product', 'Default'); +$configurableProductLinks = []; +$attributeValues = []; +$i = 1; +array_shift($options); // remove the first option which is empty +foreach ($options as $option) { + /** @var ProductInterface $simpleProduct */ + $simpleProduct = $productFactory->create(); + $dataObjectHelper->populateWithArray( + $simpleProduct, + [ + ProductInterface::TYPE_ID => Type::TYPE_VIRTUAL, + ProductInterface::ATTRIBUTE_SET_ID => $attributeSetId, + 'website_ids' => [1], + ProductInterface::NAME => 'Configurable Option' . $option->getLabel(), + ProductInterface::SKU => 'sku_' . ($i * 10), + ProductInterface::PRICE => ($i * 10), + ProductInterface::VISIBILITY => Visibility::VISIBILITY_NOT_VISIBLE, + ProductInterface::STATUS => Status::STATUS_ENABLED, + ProductInterface::CUSTOM_ATTRIBUTES => [ + [ + 'attribute_code' => $attribute->getAttributeCode(), + 'value' => $option->getValue(), + ], + ], + ProductInterface::EXTENSION_ATTRIBUTES_KEY => [ + 'stock_item' => [ + StockItemInterface::QTY => 1000, + StockItemInterface::IS_IN_STOCK => true, + ], + ], + ], + ProductInterface::class + ); + $simpleProduct = $productRepository->save($simpleProduct); + + $configurableProductLinks[] = $simpleProduct->getId(); + $attributeValues[] = [ + 'label' => 'test', + 'attribute_id' => $attribute->getId(), + 'value_index' => $option->getValue(), + ]; + $i++; +} + +/** @var ProductInterface $configurableProduct */ +$configurableProduct = $productFactory->create(); +$dataObjectHelper->populateWithArray( + $configurableProduct, + [ + ProductInterface::TYPE_ID => 'configurable', + ProductInterface::ATTRIBUTE_SET_ID => $attributeSetId, + 'website_ids' => [1], + ProductInterface::NAME => 'Configurable Product', + ProductInterface::SKU => 'configurable_product_with_two_simple', + ProductInterface::VISIBILITY => Visibility::VISIBILITY_BOTH, + ProductInterface::STATUS => Status::STATUS_ENABLED, + ], + ProductInterface::class +); +$extensionAttributes = $configurableProduct->getExtensionAttributes(); +$configurableProductOptions = $optionsFactory->create([ + [ + 'attribute_id' => $attribute->getId(), + 'code' => $attribute->getAttributeCode(), + 'label' => $attribute->getStoreLabel(), + 'position' => '0', + 'values' => $attributeValues, + ], +]); +$extensionAttributes->setConfigurableProductOptions($configurableProductOptions); +$extensionAttributes->setConfigurableProductLinks($configurableProductLinks); +$configurableProduct->setExtensionAttributes($extensionAttributes); + +$configurableProduct = $productRepository->save($configurableProduct); From 0027ad74fb8ed566493320ee0cdceff476bd812d Mon Sep 17 00:00:00 2001 From: vnayda Date: Wed, 5 Oct 2016 16:18:00 +0300 Subject: [PATCH 03/11] MAGETWO-52717: [GitHub] Configurable product disabling lowest price associated product still shows its price #4419 -- fix static tests --- app/code/Magento/ConfigurableProduct/etc/di.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/app/code/Magento/ConfigurableProduct/etc/di.xml b/app/code/Magento/ConfigurableProduct/etc/di.xml index e3178629f824c..b4d63d9d0245f 100644 --- a/app/code/Magento/ConfigurableProduct/etc/di.xml +++ b/app/code/Magento/ConfigurableProduct/etc/di.xml @@ -13,7 +13,6 @@ - From 59d4251ce488f454c4840268b313e87af91a237a Mon Sep 17 00:00:00 2001 From: Yaroslav Onischenko Date: Thu, 6 Oct 2016 12:51:41 +0300 Subject: [PATCH 04/11] MAGETWO-59315: Non consistent save Product Stock Item via Web API and repository directly --- .../Model/Product/Attribute/Backend/Stock.php | 2 +- .../Product/Attribute/Backend/StockTest.php | 13 ++++++ .../Api/StockItemSaveTest.php | 43 +++++++++++++++++++ 3 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 dev/tests/integration/testsuite/Magento/CatalogInventory/Api/StockItemSaveTest.php diff --git a/app/code/Magento/Catalog/Model/Product/Attribute/Backend/Stock.php b/app/code/Magento/Catalog/Model/Product/Attribute/Backend/Stock.php index 5c3fd4730aaed..0bb468b77ee6e 100644 --- a/app/code/Magento/Catalog/Model/Product/Attribute/Backend/Stock.php +++ b/app/code/Magento/Catalog/Model/Product/Attribute/Backend/Stock.php @@ -59,7 +59,7 @@ public function beforeSave($object) if (isset($stockData['qty']) && $stockData['qty'] === '') { $stockData['qty'] = null; } - if ($object->getStockData() !== null || $stockData !== null) { + if ($object->getStockData() !== null && $stockData !== null) { $object->setStockData(array_replace((array)$object->getStockData(), (array)$stockData)); } $object->unsetData($this->getAttribute()->getAttributeCode()); diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Product/Attribute/Backend/StockTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Product/Attribute/Backend/StockTest.php index ec9cb624db79a..32d62fd7a998e 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/Product/Attribute/Backend/StockTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/Product/Attribute/Backend/StockTest.php @@ -125,4 +125,17 @@ public function testBeforeSaveQtyIsZero() $stockData = $object->getStockData(); $this->assertEquals(0, $stockData['qty']); } + + public function testBeforeSaveNoStockData() + { + $object = new \Magento\Framework\DataObject( + [ + self::ATTRIBUTE_NAME => ['is_in_stock' => 1, 'qty' => 0] + ] + ); + + $this->model->beforeSave($object); + $this->assertNull($object->getStockData()); + $this->assertNull($object->getData(self::ATTRIBUTE_NAME)); + } } diff --git a/dev/tests/integration/testsuite/Magento/CatalogInventory/Api/StockItemSaveTest.php b/dev/tests/integration/testsuite/Magento/CatalogInventory/Api/StockItemSaveTest.php new file mode 100644 index 0000000000000..a633b2370839f --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/CatalogInventory/Api/StockItemSaveTest.php @@ -0,0 +1,43 @@ +get(ProductRepositoryInterface::class); + /** @var ProductInterface $product */ + $product = $productRepository->get('simple'); + + /** @var ProductExtensionInterface $ea */ + $ea = $product->getExtensionAttributes(); + $ea->getStockItem()->setQty(555); + $productRepository->save($product); + + $product = $productRepository->get('simple'); + $this->assertEquals(555, $product->getExtensionAttributes()->getStockItem()->getQty()); + + $stockItem = $product->getExtensionAttributes()->getStockItem(); + $stockItem->setQty(200); + /** @var StockItemRepositoryInterface $stockItemRepository */ + $stockItemRepository = $objectManager->get(StockItemRepositoryInterface::class); + $stockItemRepository->save($stockItem); + $this->assertEquals(200, $product->getExtensionAttributes()->getStockItem()->getQty()); + + $product = $productRepository->get('simple'); + $this->assertEquals(200, $product->getExtensionAttributes()->getStockItem()->getQty()); + } +} From a86ea1cea3f20b8302a459b34d6fa7179face497 Mon Sep 17 00:00:00 2001 From: vnayda Date: Thu, 6 Oct 2016 13:12:25 +0300 Subject: [PATCH 05/11] MAGETWO-52717: [GitHub] Configurable product disabling lowest price associated product still shows its price #4419 -- fix integration tests --- ...LinkedProductSelectBuilderByIndexPrice.php | 8 +++---- .../LinkedProductSelectBuilderByBasePrice.php | 6 ++--- ...nkedProductSelectBuilderBySpecialPrice.php | 6 ++--- .../LinkedProductSelectBuilderByTierPrice.php | 6 ++--- .../StockStatusBaseSelectProcessor.php | 2 +- ...ProductSelectBuilderByCatalogRulePrice.php | 6 ++--- ...rable_product_with_two_simple_rollback.php | 23 +++++++++++++++++++ 7 files changed, 40 insertions(+), 17 deletions(-) create mode 100644 dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/configurable_product_with_two_simple_rollback.php diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product/Indexer/LinkedProductSelectBuilderByIndexPrice.php b/app/code/Magento/Catalog/Model/ResourceModel/Product/Indexer/LinkedProductSelectBuilderByIndexPrice.php index c2029606c11ba..3aa6642c82d84 100644 --- a/app/code/Magento/Catalog/Model/ResourceModel/Product/Indexer/LinkedProductSelectBuilderByIndexPrice.php +++ b/app/code/Magento/Catalog/Model/ResourceModel/Product/Indexer/LinkedProductSelectBuilderByIndexPrice.php @@ -76,13 +76,13 @@ public function build($productId) [] )->joinInner( [BaseSelectProcessorInterface::PRODUCT_TABLE_ALIAS => $productTable], - sprintf('%s.%s = link.child_id', BaseSelectProcessorInterface::PRODUCT_TABLE_ALIAS, $linkField), - [$linkField] + sprintf('%s.entity_id = link.child_id', BaseSelectProcessorInterface::PRODUCT_TABLE_ALIAS), + ['entity_id'] )->joinInner( ['t' => $this->resource->getTableName('catalog_product_index_price')], - sprintf('t.entity_id = %s.%s', BaseSelectProcessorInterface::PRODUCT_TABLE_ALIAS, $linkField), + sprintf('t.entity_id = %s.entity_id', BaseSelectProcessorInterface::PRODUCT_TABLE_ALIAS), [] - )->where("parent.{$linkField} = ?", $productId) + )->where('parent.entity_id = ?', $productId) ->where('t.website_id = ?', $this->storeManager->getStore()->getWebsiteId()) ->where('t.customer_group_id = ?', $this->customerSession->getCustomerGroupId()) ->order('t.min_price ' . Select::SQL_ASC) diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product/LinkedProductSelectBuilderByBasePrice.php b/app/code/Magento/Catalog/Model/ResourceModel/Product/LinkedProductSelectBuilderByBasePrice.php index 0473f30ce482c..7caa72b367979 100644 --- a/app/code/Magento/Catalog/Model/ResourceModel/Product/LinkedProductSelectBuilderByBasePrice.php +++ b/app/code/Magento/Catalog/Model/ResourceModel/Product/LinkedProductSelectBuilderByBasePrice.php @@ -85,13 +85,13 @@ public function build($productId) [] )->joinInner( [BaseSelectProcessorInterface::PRODUCT_TABLE_ALIAS => $productTable], - sprintf('%s.%s = link.child_id', BaseSelectProcessorInterface::PRODUCT_TABLE_ALIAS, $linkField), - [$linkField] + sprintf('%s.entity_id = link.child_id', BaseSelectProcessorInterface::PRODUCT_TABLE_ALIAS, $linkField), + ['entity_id'] )->joinInner( ['t' => $priceAttribute->getBackendTable()], sprintf('t.%s = %s.%1$s', $linkField, BaseSelectProcessorInterface::PRODUCT_TABLE_ALIAS), [] - )->where("parent.{$linkField} = ?", $productId) + )->where('parent.entity_id = ?', $productId) ->where('t.attribute_id = ?', $priceAttribute->getAttributeId()) ->where('t.value IS NOT NULL') ->order('t.value ' . Select::SQL_ASC) diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product/LinkedProductSelectBuilderBySpecialPrice.php b/app/code/Magento/Catalog/Model/ResourceModel/Product/LinkedProductSelectBuilderBySpecialPrice.php index 6b1cd879d782c..fb8dbd4a30d6d 100644 --- a/app/code/Magento/Catalog/Model/ResourceModel/Product/LinkedProductSelectBuilderBySpecialPrice.php +++ b/app/code/Magento/Catalog/Model/ResourceModel/Product/LinkedProductSelectBuilderBySpecialPrice.php @@ -106,8 +106,8 @@ public function build($productId) [] )->joinInner( [BaseSelectProcessorInterface::PRODUCT_TABLE_ALIAS => $productTable], - sprintf('%s.%s = link.child_id', BaseSelectProcessorInterface::PRODUCT_TABLE_ALIAS, $linkField), - [$linkField] + sprintf('%s.entity_id = link.child_id', BaseSelectProcessorInterface::PRODUCT_TABLE_ALIAS), + ['entity_id'] )->joinInner( ['t' => $specialPriceAttribute->getBackendTable()], sprintf('t.%s = %s.%1$s', $linkField, BaseSelectProcessorInterface::PRODUCT_TABLE_ALIAS), @@ -126,7 +126,7 @@ public function build($productId) $specialPriceToDate->getAttributeId() ), '' - )->where("parent.{$linkField} = ?", $productId) + )->where('parent.entity_id = ?', $productId) ->where('t.attribute_id = ?', $specialPriceAttribute->getAttributeId()) ->where('t.value IS NOT NULL') ->where( diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product/LinkedProductSelectBuilderByTierPrice.php b/app/code/Magento/Catalog/Model/ResourceModel/Product/LinkedProductSelectBuilderByTierPrice.php index 5ad93c67598d7..25bf83f837de7 100644 --- a/app/code/Magento/Catalog/Model/ResourceModel/Product/LinkedProductSelectBuilderByTierPrice.php +++ b/app/code/Magento/Catalog/Model/ResourceModel/Product/LinkedProductSelectBuilderByTierPrice.php @@ -87,13 +87,13 @@ public function build($productId) [] )->joinInner( [BaseSelectProcessorInterface::PRODUCT_TABLE_ALIAS => $productTable], - sprintf('%s.%s = link.child_id', BaseSelectProcessorInterface::PRODUCT_TABLE_ALIAS, $linkField), - [$linkField] + sprintf('%s.entity_id = link.child_id', BaseSelectProcessorInterface::PRODUCT_TABLE_ALIAS), + ['entity_id'] )->joinInner( ['t' => $this->resource->getTableName('catalog_product_entity_tier_price')], sprintf('t.%s = %s.%1$s', $linkField, BaseSelectProcessorInterface::PRODUCT_TABLE_ALIAS), [] - )->where("parent.{$linkField} = ?", $productId) + )->where('parent.entity_id = ?', $productId) ->where('t.all_groups = 1 OR customer_group_id = ?', $this->customerSession->getCustomerGroupId()) ->where('t.qty = ?', 1) ->order('t.value ' . Select::SQL_ASC) diff --git a/app/code/Magento/CatalogInventory/Model/ResourceModel/Product/StockStatusBaseSelectProcessor.php b/app/code/Magento/CatalogInventory/Model/ResourceModel/Product/StockStatusBaseSelectProcessor.php index 4d37be99ce4a1..a1175a3b3e1c1 100644 --- a/app/code/Magento/CatalogInventory/Model/ResourceModel/Product/StockStatusBaseSelectProcessor.php +++ b/app/code/Magento/CatalogInventory/Model/ResourceModel/Product/StockStatusBaseSelectProcessor.php @@ -52,7 +52,7 @@ public function process(Select $select) /** @var Select $select */ $select->join( ['stock' => $stockStatusTable], - sprintf('stock.product_id = %s.%s', BaseSelectProcessorInterface::PRODUCT_TABLE_ALIAS, $linkField), + sprintf('stock.product_id = %s.entity_id', BaseSelectProcessorInterface::PRODUCT_TABLE_ALIAS), [] ) ->where('stock.stock_status = ?', Stock::STOCK_IN_STOCK); diff --git a/app/code/Magento/CatalogRule/Model/ResourceModel/Product/LinkedProductSelectBuilderByCatalogRulePrice.php b/app/code/Magento/CatalogRule/Model/ResourceModel/Product/LinkedProductSelectBuilderByCatalogRulePrice.php index e61ea0c98186a..55b76eb225028 100644 --- a/app/code/Magento/CatalogRule/Model/ResourceModel/Product/LinkedProductSelectBuilderByCatalogRulePrice.php +++ b/app/code/Magento/CatalogRule/Model/ResourceModel/Product/LinkedProductSelectBuilderByCatalogRulePrice.php @@ -94,13 +94,13 @@ public function build($productId) [] )->joinInner( [BaseSelectProcessorInterface::PRODUCT_TABLE_ALIAS => $productTable], - sprintf('%s.%s = link.child_id', BaseSelectProcessorInterface::PRODUCT_TABLE_ALIAS, $linkField), - [$linkField] + sprintf('%s.entity_id = link.child_id', BaseSelectProcessorInterface::PRODUCT_TABLE_ALIAS), + ['entity_id'] )->joinInner( ['t' => $this->resource->getTableName('catalogrule_product_price')], sprintf('t.product_id = %s.%s', BaseSelectProcessorInterface::PRODUCT_TABLE_ALIAS, $linkField), [] - )->where("parent.{$linkField} = ?", $productId) + )->where('parent.entity_id = ?', $productId) ->where('t.website_id = ?', $this->storeManager->getStore()->getWebsiteId()) ->where('t.customer_group_id = ?', $this->customerSession->getCustomerGroupId()) ->where('t.rule_date = ?', $currentDate) diff --git a/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/configurable_product_with_two_simple_rollback.php b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/configurable_product_with_two_simple_rollback.php new file mode 100644 index 0000000000000..6d538fc859a78 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/configurable_product_with_two_simple_rollback.php @@ -0,0 +1,23 @@ +get(ProductRepositoryInterface::class); + +foreach (['sku_10', 'sku_20', 'configurable_product_with_two_simple'] as $sku) { + try { + $product = $productRepository->get($sku, false, null, true); + $productRepository->delete($product); + } catch (NoSuchEntityException $e) { + //Product already removed + } +} + +require __DIR__ . '/configurable_attribute_rollback.php'; From 31edc6252ec8b72556f43afcbcc07859955b86c9 Mon Sep 17 00:00:00 2001 From: vnayda Date: Thu, 6 Oct 2016 13:40:37 +0300 Subject: [PATCH 06/11] MAGETWO-52717: [GitHub] Configurable product disabling lowest price associated product still shows its price #4419 -- fix static tests --- .../Product/StockStatusBaseSelectProcessor.php | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/app/code/Magento/CatalogInventory/Model/ResourceModel/Product/StockStatusBaseSelectProcessor.php b/app/code/Magento/CatalogInventory/Model/ResourceModel/Product/StockStatusBaseSelectProcessor.php index a1175a3b3e1c1..fbc91b4d3e5b9 100644 --- a/app/code/Magento/CatalogInventory/Model/ResourceModel/Product/StockStatusBaseSelectProcessor.php +++ b/app/code/Magento/CatalogInventory/Model/ResourceModel/Product/StockStatusBaseSelectProcessor.php @@ -23,19 +23,12 @@ class StockStatusBaseSelectProcessor implements BaseSelectProcessorInterface */ private $resource; - /** - * @var MetadataPool - */ - private $metadataPool; - /** * @param ResourceConnection $resource - * @param MetadataPool $metadataPool */ - public function __construct(ResourceConnection $resource, MetadataPool $metadataPool) + public function __construct(ResourceConnection $resource) { $this->resource = $resource; - $this->metadataPool = $metadataPool; } /** @@ -46,7 +39,6 @@ public function __construct(ResourceConnection $resource, MetadataPool $metadata */ public function process(Select $select) { - $linkField = $this->metadataPool->getMetadata(ProductInterface::class)->getLinkField(); $stockStatusTable = $this->resource->getTableName('cataloginventory_stock_status'); /** @var Select $select */ From 97c54833566f949b1857d4000fbbc7243f653a59 Mon Sep 17 00:00:00 2001 From: vnayda Date: Thu, 6 Oct 2016 13:45:19 +0300 Subject: [PATCH 07/11] MAGETWO-52717: [GitHub] Configurable product disabling lowest price associated product still shows its price #4419 -- fix unit tests --- .../StockStatusBaseSelectProcessorTest.php | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/app/code/Magento/CatalogInventory/Test/Unit/Model/ResourceModel/Product/StockStatusBaseSelectProcessorTest.php b/app/code/Magento/CatalogInventory/Test/Unit/Model/ResourceModel/Product/StockStatusBaseSelectProcessorTest.php index eafe5bfdcf2db..1499f26b7b5c2 100644 --- a/app/code/Magento/CatalogInventory/Test/Unit/Model/ResourceModel/Product/StockStatusBaseSelectProcessorTest.php +++ b/app/code/Magento/CatalogInventory/Test/Unit/Model/ResourceModel/Product/StockStatusBaseSelectProcessorTest.php @@ -22,11 +22,6 @@ class StockStatusBaseSelectProcessorTest extends \PHPUnit_Framework_TestCase */ private $resource; - /** - * @var MetadataPool|\PHPUnit_Framework_MockObject_MockObject - */ - private $metadataPool; - /** * @var Select|\PHPUnit_Framework_MockObject_MockObject */ @@ -40,32 +35,20 @@ class StockStatusBaseSelectProcessorTest extends \PHPUnit_Framework_TestCase protected function setUp() { $this->resource = $this->getMockBuilder(ResourceConnection::class)->disableOriginalConstructor()->getMock(); - $this->metadataPool = $this->getMockBuilder(MetadataPool::class)->disableOriginalConstructor()->getMock(); $this->select = $this->getMockBuilder(Select::class)->disableOriginalConstructor()->getMock(); $this->stockStatusBaseSelectProcessor = (new ObjectManager($this))->getObject( StockStatusBaseSelectProcessor::class, [ 'resource' => $this->resource, - 'metadataPool' => $this->metadataPool, ] ); } public function testProcess() { - $linkField = 'link_field'; $tableName = 'table_name'; - $metadata = $this->getMock(EntityMetadataInterface::class); - $metadata->expects($this->once()) - ->method('getLinkField') - ->willReturn($linkField); - $this->metadataPool->expects($this->once()) - ->method('getMetadata') - ->with(ProductInterface::class) - ->willReturn($metadata); - $this->resource->expects($this->once()) ->method('getTableName') ->with('cataloginventory_stock_status') @@ -75,7 +58,7 @@ public function testProcess() ->method('join') ->with( ['stock' => $tableName], - sprintf('stock.product_id = %s.%s', BaseSelectProcessorInterface::PRODUCT_TABLE_ALIAS, $linkField), + sprintf('stock.product_id = %s.entity_id', BaseSelectProcessorInterface::PRODUCT_TABLE_ALIAS), [] ) ->willReturnSelf(); From e4d4c2fe4783b1c1f180b059b5fbdd4e1536ed03 Mon Sep 17 00:00:00 2001 From: Yaroslav Onischenko Date: Mon, 10 Oct 2016 15:01:27 +0300 Subject: [PATCH 08/11] MAGETWO-59315: Non consistent save Product Stock Item via Web API and repository directly --- .../Magento/CatalogInventory/Api/StockItemSaveTest.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dev/tests/integration/testsuite/Magento/CatalogInventory/Api/StockItemSaveTest.php b/dev/tests/integration/testsuite/Magento/CatalogInventory/Api/StockItemSaveTest.php index a633b2370839f..0dc5c3ef620c3 100644 --- a/dev/tests/integration/testsuite/Magento/CatalogInventory/Api/StockItemSaveTest.php +++ b/dev/tests/integration/testsuite/Magento/CatalogInventory/Api/StockItemSaveTest.php @@ -20,14 +20,14 @@ public function testSave() /** @var ProductRepositoryInterface $productRepository */ $productRepository = $objectManager->get(ProductRepositoryInterface::class); /** @var ProductInterface $product */ - $product = $productRepository->get('simple'); + $product = $productRepository->get('simple', false, null, true); /** @var ProductExtensionInterface $ea */ $ea = $product->getExtensionAttributes(); $ea->getStockItem()->setQty(555); $productRepository->save($product); - $product = $productRepository->get('simple'); + $product = $productRepository->get('simple', false, null, true); $this->assertEquals(555, $product->getExtensionAttributes()->getStockItem()->getQty()); $stockItem = $product->getExtensionAttributes()->getStockItem(); @@ -37,7 +37,7 @@ public function testSave() $stockItemRepository->save($stockItem); $this->assertEquals(200, $product->getExtensionAttributes()->getStockItem()->getQty()); - $product = $productRepository->get('simple'); + $product = $productRepository->get('simple', false, null, true); $this->assertEquals(200, $product->getExtensionAttributes()->getStockItem()->getQty()); } } From 5e54a0b6f1a5ccb771c7333f777b905881f9fc7f Mon Sep 17 00:00:00 2001 From: vnayda Date: Mon, 10 Oct 2016 15:19:29 +0300 Subject: [PATCH 09/11] MAGETWO-52717: [GitHub] Configurable product disabling lowest price associated product still shows its price #4419 -- add api annotation to interfaces --- .../Model/ResourceModel/Product/BaseSelectProcessorInterface.php | 1 + .../Pricing/Price/ConfigurableOptionsProviderInterface.php | 1 + .../Pricing/Price/LowestPriceOptionsProviderInterface.php | 1 + 3 files changed, 3 insertions(+) diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product/BaseSelectProcessorInterface.php b/app/code/Magento/Catalog/Model/ResourceModel/Product/BaseSelectProcessorInterface.php index aedd68eff6c43..e6a995b654703 100644 --- a/app/code/Magento/Catalog/Model/ResourceModel/Product/BaseSelectProcessorInterface.php +++ b/app/code/Magento/Catalog/Model/ResourceModel/Product/BaseSelectProcessorInterface.php @@ -9,6 +9,7 @@ /** * Interface BaseSelectProcessorInterface + * @api */ interface BaseSelectProcessorInterface { diff --git a/app/code/Magento/ConfigurableProduct/Pricing/Price/ConfigurableOptionsProviderInterface.php b/app/code/Magento/ConfigurableProduct/Pricing/Price/ConfigurableOptionsProviderInterface.php index c7ac9446f42e3..c0f2c218cc77c 100644 --- a/app/code/Magento/ConfigurableProduct/Pricing/Price/ConfigurableOptionsProviderInterface.php +++ b/app/code/Magento/ConfigurableProduct/Pricing/Price/ConfigurableOptionsProviderInterface.php @@ -10,6 +10,7 @@ /** * Provide configurable sub-products for price calculation + * @api */ interface ConfigurableOptionsProviderInterface { diff --git a/app/code/Magento/ConfigurableProduct/Pricing/Price/LowestPriceOptionsProviderInterface.php b/app/code/Magento/ConfigurableProduct/Pricing/Price/LowestPriceOptionsProviderInterface.php index 8d260c3073587..c0989a929be55 100644 --- a/app/code/Magento/ConfigurableProduct/Pricing/Price/LowestPriceOptionsProviderInterface.php +++ b/app/code/Magento/ConfigurableProduct/Pricing/Price/LowestPriceOptionsProviderInterface.php @@ -9,6 +9,7 @@ /** * Retrieve list of products where each product contains lower price than others at least for one possible price type + * @api */ interface LowestPriceOptionsProviderInterface { From 542efa076c0ba7ac8b57853a42be361e090e9f70 Mon Sep 17 00:00:00 2001 From: vnayda Date: Tue, 11 Oct 2016 18:39:22 +0300 Subject: [PATCH 10/11] MAGETWO-52717: [GitHub] Configurable product disabling lowest price associated product still shows its price #4419 -- fix integration tests -- fix problem with default store id resolving --- app/code/Magento/Catalog/etc/di.xml | 11 +- app/code/Magento/Store/Model/StoreManager.php | 2 +- .../Price/LowestPriceOptionProviderTest.php | 41 +++++-- .../configurable_product_with_two_simple.php | 108 ------------------ ...rable_product_with_two_simple_rollback.php | 23 ---- 5 files changed, 36 insertions(+), 149 deletions(-) delete mode 100644 dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/configurable_product_with_two_simple.php delete mode 100644 dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/configurable_product_with_two_simple_rollback.php diff --git a/app/code/Magento/Catalog/etc/di.xml b/app/code/Magento/Catalog/etc/di.xml index 256b824bc7403..6b39520ae021e 100644 --- a/app/code/Magento/Catalog/etc/di.xml +++ b/app/code/Magento/Catalog/etc/di.xml @@ -839,9 +839,10 @@ - - - Magento\Catalog\Model\ResourceModel\Product\StatusBaseSelectProcessor - - + + + Magento\Catalog\Model\ResourceModel\Product\StatusBaseSelectProcessor + + + diff --git a/app/code/Magento/Store/Model/StoreManager.php b/app/code/Magento/Store/Model/StoreManager.php index c34f4e1bd2a58..166de823ad4a7 100644 --- a/app/code/Magento/Store/Model/StoreManager.php +++ b/app/code/Magento/Store/Model/StoreManager.php @@ -150,7 +150,7 @@ public function isSingleStoreMode() public function getStore($storeId = null) { if (!isset($storeId) || '' === $storeId || $storeId === true) { - if (!$this->currentStoreId) { + if (null === $this->currentStoreId) { \Magento\Framework\Profiler::start('store.resolve'); $this->currentStoreId = $this->storeResolver->getCurrentStoreId(); \Magento\Framework\Profiler::stop('store.resolve'); diff --git a/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Pricing/Price/LowestPriceOptionProviderTest.php b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Pricing/Price/LowestPriceOptionProviderTest.php index c0bc6c9871dc1..a7c857936e0c0 100644 --- a/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Pricing/Price/LowestPriceOptionProviderTest.php +++ b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Pricing/Price/LowestPriceOptionProviderTest.php @@ -7,13 +7,17 @@ use Magento\Catalog\Api\ProductRepositoryInterface; use Magento\Catalog\Model\Product\Attribute\Source\Status; +use Magento\Store\Model\Store; +use Magento\Store\Model\StoreManagerInterface; use Magento\TestFramework\Helper\Bootstrap; -/** - * @magentoAppIsolation enabled - */ class LowestPriceOptionProviderTest extends \PHPUnit_Framework_TestCase { + /** + * @var StoreManagerInterface + */ + private $storeManager; + /** * @var LowestPriceOptionsProviderInterface */ @@ -26,6 +30,7 @@ class LowestPriceOptionProviderTest extends \PHPUnit_Framework_TestCase protected function setUp() { + $this->storeManager = Bootstrap::getObjectManager()->get(StoreManagerInterface::class); $this->productRepository = Bootstrap::getObjectManager()->get(ProductRepositoryInterface::class); $this->lowestPriceOptionsProvider = Bootstrap::getObjectManager()->get( LowestPriceOptionsProviderInterface::class @@ -33,20 +38,29 @@ protected function setUp() } /** - * @magentoDataFixture Magento/ConfigurableProduct/_files/configurable_product_with_two_simple.php + * @magentoDataFixture Magento/ConfigurableProduct/_files/product_configurable.php */ public function testGetProductsIfOneOfChildIsDisabled() { - $configurableProduct = $this->productRepository->get('configurable_product_with_two_simple'); + $configurableProduct = $this->productRepository->getById(1, false, null, true); $lowestPriceChildrenProducts = $this->lowestPriceOptionsProvider->getProducts($configurableProduct); $this->assertCount(1, $lowestPriceChildrenProducts); $lowestPriceChildrenProduct = reset($lowestPriceChildrenProducts); $this->assertEquals(10, $lowestPriceChildrenProduct->getPrice()); // load full aggregation root - $lowestPriceChildProduct = $this->productRepository->get($lowestPriceChildrenProduct->getSku()); + $lowestPriceChildProduct = $this->productRepository->get( + $lowestPriceChildrenProduct->getSku(), + false, + null, + true + ); $lowestPriceChildProduct->setStatus(Status::STATUS_DISABLED); + // update in global scope + $currentStoreId = $this->storeManager->getStore()->getId(); + $this->storeManager->setCurrentStore(Store::DEFAULT_STORE_ID); $this->productRepository->save($lowestPriceChildProduct); + $this->storeManager->setCurrentStore($currentStoreId); $lowestPriceChildrenProducts = $this->lowestPriceOptionsProvider->getProducts($configurableProduct); $this->assertCount(1, $lowestPriceChildrenProducts); @@ -55,22 +69,25 @@ public function testGetProductsIfOneOfChildIsDisabled() } /** - * @magentoDataFixture Magento/ConfigurableProduct/_files/configurable_product_with_two_simple.php + * @magentoDataFixture Magento/ConfigurableProduct/_files/product_configurable.php */ public function testGetProductsIfOneOfChildIsOutOfStock() { - $configurableProduct = $this->productRepository->get('configurable_product_with_two_simple'); + $configurableProduct = $this->productRepository->getById(1, false, null, true); $lowestPriceChildrenProducts = $this->lowestPriceOptionsProvider->getProducts($configurableProduct); $this->assertCount(1, $lowestPriceChildrenProducts); $lowestPriceChildrenProduct = reset($lowestPriceChildrenProducts); $this->assertEquals(10, $lowestPriceChildrenProduct->getPrice()); // load full aggregation root - $lowestPriceChildProduct = $this->productRepository->get($lowestPriceChildrenProduct->getSku()); + $lowestPriceChildProduct = $this->productRepository->get( + $lowestPriceChildrenProduct->getSku(), + false, + null, + true + ); $stockItem = $lowestPriceChildProduct->getExtensionAttributes()->getStockItem(); - $stockItem->setIsInStock(false); - // TODO: Need to delete next string after MAGETWO-59315 fixing - $lowestPriceChildProduct->setStockData(['is_in_stock' => 0, 'qty' => 0]); + $stockItem->setIsInStock(0); $this->productRepository->save($lowestPriceChildProduct); $lowestPriceChildrenProducts = $this->lowestPriceOptionsProvider->getProducts($configurableProduct); diff --git a/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/configurable_product_with_two_simple.php b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/configurable_product_with_two_simple.php deleted file mode 100644 index f28918f39dc83..0000000000000 --- a/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/configurable_product_with_two_simple.php +++ /dev/null @@ -1,108 +0,0 @@ -get(DataObjectHelper::class); -$productFactory = $objectManager->get(ProductInterfaceFactory::class); -/** @var ProductRepositoryInterface $productRepository */ -$productRepository = Bootstrap::getObjectManager()->get(ProductRepositoryInterface::class); -/** @var CategorySetup $installer */ -$installer = Bootstrap::getObjectManager()->create(CategorySetup::class); -/** @var Factory $optionsFactory */ -$optionsFactory = Bootstrap::getObjectManager()->create(Factory::class); - -/** @var AttributeOptionInterface[] $options */ -$options = $attribute->getOptions(); -$attributeSetId = $installer->getAttributeSetId('catalog_product', 'Default'); -$configurableProductLinks = []; -$attributeValues = []; -$i = 1; -array_shift($options); // remove the first option which is empty -foreach ($options as $option) { - /** @var ProductInterface $simpleProduct */ - $simpleProduct = $productFactory->create(); - $dataObjectHelper->populateWithArray( - $simpleProduct, - [ - ProductInterface::TYPE_ID => Type::TYPE_VIRTUAL, - ProductInterface::ATTRIBUTE_SET_ID => $attributeSetId, - 'website_ids' => [1], - ProductInterface::NAME => 'Configurable Option' . $option->getLabel(), - ProductInterface::SKU => 'sku_' . ($i * 10), - ProductInterface::PRICE => ($i * 10), - ProductInterface::VISIBILITY => Visibility::VISIBILITY_NOT_VISIBLE, - ProductInterface::STATUS => Status::STATUS_ENABLED, - ProductInterface::CUSTOM_ATTRIBUTES => [ - [ - 'attribute_code' => $attribute->getAttributeCode(), - 'value' => $option->getValue(), - ], - ], - ProductInterface::EXTENSION_ATTRIBUTES_KEY => [ - 'stock_item' => [ - StockItemInterface::QTY => 1000, - StockItemInterface::IS_IN_STOCK => true, - ], - ], - ], - ProductInterface::class - ); - $simpleProduct = $productRepository->save($simpleProduct); - - $configurableProductLinks[] = $simpleProduct->getId(); - $attributeValues[] = [ - 'label' => 'test', - 'attribute_id' => $attribute->getId(), - 'value_index' => $option->getValue(), - ]; - $i++; -} - -/** @var ProductInterface $configurableProduct */ -$configurableProduct = $productFactory->create(); -$dataObjectHelper->populateWithArray( - $configurableProduct, - [ - ProductInterface::TYPE_ID => 'configurable', - ProductInterface::ATTRIBUTE_SET_ID => $attributeSetId, - 'website_ids' => [1], - ProductInterface::NAME => 'Configurable Product', - ProductInterface::SKU => 'configurable_product_with_two_simple', - ProductInterface::VISIBILITY => Visibility::VISIBILITY_BOTH, - ProductInterface::STATUS => Status::STATUS_ENABLED, - ], - ProductInterface::class -); -$extensionAttributes = $configurableProduct->getExtensionAttributes(); -$configurableProductOptions = $optionsFactory->create([ - [ - 'attribute_id' => $attribute->getId(), - 'code' => $attribute->getAttributeCode(), - 'label' => $attribute->getStoreLabel(), - 'position' => '0', - 'values' => $attributeValues, - ], -]); -$extensionAttributes->setConfigurableProductOptions($configurableProductOptions); -$extensionAttributes->setConfigurableProductLinks($configurableProductLinks); -$configurableProduct->setExtensionAttributes($extensionAttributes); - -$configurableProduct = $productRepository->save($configurableProduct); diff --git a/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/configurable_product_with_two_simple_rollback.php b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/configurable_product_with_two_simple_rollback.php deleted file mode 100644 index 6d538fc859a78..0000000000000 --- a/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/configurable_product_with_two_simple_rollback.php +++ /dev/null @@ -1,23 +0,0 @@ -get(ProductRepositoryInterface::class); - -foreach (['sku_10', 'sku_20', 'configurable_product_with_two_simple'] as $sku) { - try { - $product = $productRepository->get($sku, false, null, true); - $productRepository->delete($product); - } catch (NoSuchEntityException $e) { - //Product already removed - } -} - -require __DIR__ . '/configurable_attribute_rollback.php'; From 7f30596d6a59a1c29c657aa42e92b5d260616f22 Mon Sep 17 00:00:00 2001 From: vnayda Date: Wed, 12 Oct 2016 17:06:29 +0300 Subject: [PATCH 11/11] MAGETWO-52717: [GitHub] Configurable product disabling lowest price associated product still shows its price #4419 -- revert store resolving fix -- fix static tests --- .../Product/LinkedProductSelectBuilderBySpecialPrice.php | 3 +++ .../ResourceModel/Product/StockStatusBaseSelectProcessor.php | 2 -- .../Product/StockStatusBaseSelectProcessorTest.php | 3 --- app/code/Magento/Store/Model/StoreManager.php | 2 +- .../Pricing/Price/LowestPriceOptionProviderTest.php | 2 +- 5 files changed, 5 insertions(+), 7 deletions(-) diff --git a/app/code/Magento/Catalog/Model/ResourceModel/Product/LinkedProductSelectBuilderBySpecialPrice.php b/app/code/Magento/Catalog/Model/ResourceModel/Product/LinkedProductSelectBuilderBySpecialPrice.php index fb8dbd4a30d6d..68eaf206e293f 100644 --- a/app/code/Magento/Catalog/Model/ResourceModel/Product/LinkedProductSelectBuilderBySpecialPrice.php +++ b/app/code/Magento/Catalog/Model/ResourceModel/Product/LinkedProductSelectBuilderBySpecialPrice.php @@ -11,6 +11,9 @@ use Magento\Framework\DB\Select; use Magento\Store\Model\Store; +/** + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ class LinkedProductSelectBuilderBySpecialPrice implements LinkedProductSelectBuilderInterface { /** diff --git a/app/code/Magento/CatalogInventory/Model/ResourceModel/Product/StockStatusBaseSelectProcessor.php b/app/code/Magento/CatalogInventory/Model/ResourceModel/Product/StockStatusBaseSelectProcessor.php index fbc91b4d3e5b9..829fa8decda7d 100644 --- a/app/code/Magento/CatalogInventory/Model/ResourceModel/Product/StockStatusBaseSelectProcessor.php +++ b/app/code/Magento/CatalogInventory/Model/ResourceModel/Product/StockStatusBaseSelectProcessor.php @@ -6,12 +6,10 @@ */ namespace Magento\CatalogInventory\Model\ResourceModel\Product; -use Magento\Catalog\Api\Data\ProductInterface; use Magento\Catalog\Model\ResourceModel\Product\BaseSelectProcessorInterface; use Magento\CatalogInventory\Model\Stock; use Magento\Framework\App\ResourceConnection; use Magento\Framework\DB\Select; -use Magento\Framework\EntityManager\MetadataPool; /** * Class StockStatusBaseSelectProcessor diff --git a/app/code/Magento/CatalogInventory/Test/Unit/Model/ResourceModel/Product/StockStatusBaseSelectProcessorTest.php b/app/code/Magento/CatalogInventory/Test/Unit/Model/ResourceModel/Product/StockStatusBaseSelectProcessorTest.php index 1499f26b7b5c2..4756e42ffe602 100644 --- a/app/code/Magento/CatalogInventory/Test/Unit/Model/ResourceModel/Product/StockStatusBaseSelectProcessorTest.php +++ b/app/code/Magento/CatalogInventory/Test/Unit/Model/ResourceModel/Product/StockStatusBaseSelectProcessorTest.php @@ -5,14 +5,11 @@ */ namespace Magento\CatalogInventory\Test\Unit\Model\ResourceModel\Product; -use Magento\Catalog\Api\Data\ProductInterface; use Magento\Catalog\Model\ResourceModel\Product\BaseSelectProcessorInterface; use Magento\CatalogInventory\Model\ResourceModel\Product\StockStatusBaseSelectProcessor; use Magento\CatalogInventory\Model\Stock; use Magento\Framework\App\ResourceConnection; use Magento\Framework\DB\Select; -use Magento\Framework\EntityManager\EntityMetadataInterface; -use Magento\Framework\EntityManager\MetadataPool; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; class StockStatusBaseSelectProcessorTest extends \PHPUnit_Framework_TestCase diff --git a/app/code/Magento/Store/Model/StoreManager.php b/app/code/Magento/Store/Model/StoreManager.php index 166de823ad4a7..c34f4e1bd2a58 100644 --- a/app/code/Magento/Store/Model/StoreManager.php +++ b/app/code/Magento/Store/Model/StoreManager.php @@ -150,7 +150,7 @@ public function isSingleStoreMode() public function getStore($storeId = null) { if (!isset($storeId) || '' === $storeId || $storeId === true) { - if (null === $this->currentStoreId) { + if (!$this->currentStoreId) { \Magento\Framework\Profiler::start('store.resolve'); $this->currentStoreId = $this->storeResolver->getCurrentStoreId(); \Magento\Framework\Profiler::stop('store.resolve'); diff --git a/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Pricing/Price/LowestPriceOptionProviderTest.php b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Pricing/Price/LowestPriceOptionProviderTest.php index a7c857936e0c0..50787c7962412 100644 --- a/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Pricing/Price/LowestPriceOptionProviderTest.php +++ b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/Pricing/Price/LowestPriceOptionProviderTest.php @@ -58,7 +58,7 @@ public function testGetProductsIfOneOfChildIsDisabled() $lowestPriceChildProduct->setStatus(Status::STATUS_DISABLED); // update in global scope $currentStoreId = $this->storeManager->getStore()->getId(); - $this->storeManager->setCurrentStore(Store::DEFAULT_STORE_ID); + $this->storeManager->setCurrentStore(Store::ADMIN_CODE); $this->productRepository->save($lowestPriceChildProduct); $this->storeManager->setCurrentStore($currentStoreId);