Skip to content
Snippets Groups Projects
Commit 3f4557f8 authored by Bohdan Korablov's avatar Bohdan Korablov
Browse files

Merge remote-tracking branch 'mainline/develop' into MAGETWO-56317-2

parents 90b800f4 9451efd7
No related merge requests found
Showing
with 556 additions and 46 deletions
......@@ -23,6 +23,8 @@ atlassian*
/lib/internal/flex/varien/.settings
/node_modules
/.grunt
/Gruntfile.js
/package.json
/pub/media/*.*
!/pub/media/.htaccess
......
......@@ -59,7 +59,7 @@ class Stock extends \Magento\Eav\Model\Entity\Attribute\Backend\AbstractBackend
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());
......
<?php
/**
* Copyright © 2016 Magento. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\Catalog\Model\ResourceModel\Product;
use Magento\Framework\DB\Select;
/**
* Interface BaseSelectProcessorInterface
* @api
*/
interface BaseSelectProcessorInterface
{
/**
* Product table alias
*/
const PRODUCT_TABLE_ALIAS = 'child';
/**
* @param Select $select
* @return Select
*/
public function process(Select $select);
}
<?php
/**
* Copyright © 2016 Magento. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\Catalog\Model\ResourceModel\Product;
use Magento\Framework\DB\Select;
use Magento\Framework\Exception\InputException;
/**
* Class CompositeBaseSelectProcessor
*/
class CompositeBaseSelectProcessor implements BaseSelectProcessorInterface
{
/**
* @var BaseSelectProcessorInterface[]
*/
private $baseSelectProcessors;
/**
* @param BaseSelectProcessorInterface[] $baseSelectProcessors
* @throws InputException
*/
public function __construct(
array $baseSelectProcessors
) {
foreach ($baseSelectProcessors as $baseSelectProcessor) {
if (!$baseSelectProcessor instanceof BaseSelectProcessorInterface) {
throw new InputException(
__('Processor %1 doesn\'t implement BaseSelectProcessorInterface', get_class($baseSelectProcessor))
);
}
}
$this->baseSelectProcessors = $baseSelectProcessors;
}
/**
* @param Select $select
* @return Select
*/
public function process(Select $select)
{
foreach ($this->baseSelectProcessors as $baseSelectProcessor) {
$select = $baseSelectProcessor->process($select);
}
return $select;
}
}
......@@ -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 @@ class LinkedProductSelectBuilderByIndexPrice implements LinkedProductSelectBuild
$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",
[BaseSelectProcessorInterface::PRODUCT_TABLE_ALIAS => $productTable],
sprintf('%s.entity_id = link.child_id', BaseSelectProcessorInterface::PRODUCT_TABLE_ALIAS),
['entity_id']
)->joinInner(
['t' => $this->resource->getTableName('catalog_product_index_price')],
't.entity_id = child.entity_id',
sprintf('t.entity_id = %s.entity_id', BaseSelectProcessorInterface::PRODUCT_TABLE_ALIAS),
[]
)->where('parent.entity_id = ? ', $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)
->limit(1)];
->limit(1);
$priceSelect = $this->baseSelectProcessor->process($priceSelect);
return [$priceSelect];
}
}
......@@ -7,6 +7,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;
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 @@ class LinkedProductSelectBuilderByBasePrice implements LinkedProductSelectBuilde
"link.parent_id = parent.$linkField",
[]
)->joinInner(
['child' => $productTable],
"child.entity_id = link.child_id",
[BaseSelectProcessorInterface::PRODUCT_TABLE_ALIAS => $productTable],
sprintf('%s.entity_id = link.child_id', BaseSelectProcessorInterface::PRODUCT_TABLE_ALIAS, $linkField),
['entity_id']
)->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.entity_id = ?', $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);
......
......@@ -7,9 +7,13 @@ 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;
use Magento\Store\Model\Store;
/**
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
*/
class LinkedProductSelectBuilderBySpecialPrice implements LinkedProductSelectBuilderInterface
{
/**
......@@ -47,6 +51,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 +64,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 +73,8 @@ class LinkedProductSelectBuilderBySpecialPrice implements LinkedProductSelectBui
\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 +83,8 @@ class LinkedProductSelectBuilderBySpecialPrice implements LinkedProductSelectBui
$this->dateTime = $dateTime;
$this->localeDate = $localeDate;
$this->metadataPool = $metadataPool;
$this->baseSelectProcessor = (null !== $baseSelectProcessor)
? $baseSelectProcessor : ObjectManager::getInstance()->get(BaseSelectProcessorInterface::class);
}
/**
......@@ -95,12 +108,12 @@ class LinkedProductSelectBuilderBySpecialPrice implements LinkedProductSelectBui
"link.parent_id = parent.$linkField",
[]
)->joinInner(
['child' => $productTable],
"child.entity_id = link.child_id",
[BaseSelectProcessorInterface::PRODUCT_TABLE_ALIAS => $productTable],
sprintf('%s.entity_id = link.child_id', BaseSelectProcessorInterface::PRODUCT_TABLE_ALIAS),
['entity_id']
)->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 +129,7 @@ class LinkedProductSelectBuilderBySpecialPrice implements LinkedProductSelectBui
$specialPriceToDate->getAttributeId()
),
''
)->where('parent.entity_id = ? ', $productId)
)->where('parent.entity_id = ?', $productId)
->where('t.attribute_id = ?', $specialPriceAttribute->getAttributeId())
->where('t.value IS NOT NULL')
->where(
......@@ -127,6 +140,7 @@ class LinkedProductSelectBuilderBySpecialPrice implements LinkedProductSelectBui
$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);
......
......@@ -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 @@ class LinkedProductSelectBuilderByTierPrice implements LinkedProductSelectBuilde
"link.parent_id = parent.$linkField",
[]
)->joinInner(
['child' => $productTable],
"child.entity_id = link.child_id",
[BaseSelectProcessorInterface::PRODUCT_TABLE_ALIAS => $productTable],
sprintf('%s.entity_id = link.child_id', BaseSelectProcessorInterface::PRODUCT_TABLE_ALIAS),
['entity_id']
)->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.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)
->limit(1);
$priceSelect = $this->baseSelectProcessor->process($priceSelect);
$priceSelectDefault = clone $priceSelect;
$priceSelectDefault->where('t.website_id = ?', self::DEFAULT_WEBSITE_ID);
......
<?php
/**
* Copyright © 2016 Magento. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\Catalog\Model\ResourceModel\Product;
use Magento\Catalog\Api\Data\ProductInterface;
use Magento\Catalog\Model\Product;
use Magento\Catalog\Model\Product\Attribute\Source\Status;
use Magento\Eav\Model\Config;
use Magento\Framework\DB\Select;
use Magento\Framework\EntityManager\MetadataPool;
/**
* Class StatusBaseSelectProcessor
*/
class StatusBaseSelectProcessor implements BaseSelectProcessorInterface
{
/**
* @var Config
*/
private $eavConfig;
/**
* @var MetadataPool
*/
private $metadataPool;
/**
* @param Config $eavConfig
* @param MetadataPool $metadataPool
*/
public function __construct(
Config $eavConfig,
MetadataPool $metadataPool
) {
$this->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;
}
}
......@@ -125,4 +125,17 @@ class StockTest extends \PHPUnit_Framework_TestCase
$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));
}
}
<?php
/**
* Copyright © 2016 Magento. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\Catalog\Test\Unit\Model\ResourceModel\Product;
use Magento\Catalog\Model\ResourceModel\Product\BaseSelectProcessorInterface;
use Magento\Catalog\Model\ResourceModel\Product\CompositeBaseSelectProcessor;
use Magento\Framework\DB\Select;
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
class CompositeBaseSelectProcessorTest extends \PHPUnit_Framework_TestCase
{
/**
* @var ObjectManager
*/
private $objectManager;
protected function setUp()
{
$this->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));
}
}
<?php
/**
* Copyright © 2016 Magento. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\Catalog\Test\Unit\Model\ResourceModel\Product;
use Magento\Catalog\Api\Data\ProductInterface;
use Magento\Catalog\Model\Product;
use Magento\Catalog\Model\Product\Attribute\Source\Status;
use Magento\Catalog\Model\ResourceModel\Product\BaseSelectProcessorInterface;
use Magento\Catalog\Model\ResourceModel\Product\StatusBaseSelectProcessor;
use Magento\Eav\Model\Config;
use Magento\Eav\Model\Entity\Attribute\AttributeInterface;
use Magento\Framework\DB\Select;
use Magento\Framework\EntityManager\EntityMetadataInterface;
use Magento\Framework\EntityManager\MetadataPool;
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
class StatusBaseSelectProcessorTest extends \PHPUnit_Framework_TestCase
{
/**
* @var Config|\PHPUnit_Framework_MockObject_MockObject
*/
private $eavConfig;
/**
* @var MetadataPool|\PHPUnit_Framework_MockObject_MockObject
*/
private $metadataPool;
/**
* @var Select|\PHPUnit_Framework_MockObject_MockObject
*/
private $select;
/**
* @var StatusBaseSelectProcessor
*/
private $statusBaseSelectProcessor;
protected function setUp()
{
$this->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));
}
}
......@@ -837,4 +837,12 @@
<type name="Magento\Quote\Model\Quote\Item\ToOrderItem">
<plugin name="copy_quote_files_to_order" type="Magento\Catalog\Model\Plugin\QuoteItemProductOption"/>
</type>
<preference for="Magento\Catalog\Model\ResourceModel\Product\BaseSelectProcessorInterface" type="Magento\Catalog\Model\ResourceModel\Product\CompositeBaseSelectProcessor" />
<type name="Magento\Catalog\Model\ResourceModel\Product\CompositeBaseSelectProcessor">
<arguments>
<argument name="baseSelectProcessors" xsi:type="array">
<item name="status" xsi:type="object">Magento\Catalog\Model\ResourceModel\Product\StatusBaseSelectProcessor</item>
</argument>
</arguments>
</type>
</config>
<?php
/**
*
* Copyright © 2016 Magento. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\CatalogInventory\Model\ResourceModel\Product;
use Magento\Catalog\Model\ResourceModel\Product\BaseSelectProcessorInterface;
use Magento\CatalogInventory\Model\Stock;
use Magento\Framework\App\ResourceConnection;
use Magento\Framework\DB\Select;
/**
* Class StockStatusBaseSelectProcessor
*/
class StockStatusBaseSelectProcessor implements BaseSelectProcessorInterface
{
/**
* @var ResourceConnection
*/
private $resource;
/**
* @param ResourceConnection $resource
*/
public function __construct(ResourceConnection $resource)
{
$this->resource = $resource;
}
/**
* Add stock item filter to selects
*
* @param Select $select
* @return Select
*/
public function process(Select $select)
{
$stockStatusTable = $this->resource->getTableName('cataloginventory_stock_status');
/** @var Select $select */
$select->join(
['stock' => $stockStatusTable],
sprintf('stock.product_id = %s.entity_id', BaseSelectProcessorInterface::PRODUCT_TABLE_ALIAS),
[]
)
->where('stock.stock_status = ?', Stock::STOCK_IN_STOCK);
return $select;
}
}
<?php
/**
* Copyright © 2016 Magento. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\CatalogInventory\Test\Unit\Model\ResourceModel\Product;
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\TestFramework\Unit\Helper\ObjectManager;
class StockStatusBaseSelectProcessorTest extends \PHPUnit_Framework_TestCase
{
/**
* @var ResourceConnection|\PHPUnit_Framework_MockObject_MockObject
*/
private $resource;
/**
* @var Select|\PHPUnit_Framework_MockObject_MockObject
*/
private $select;
/**
* @var StockStatusBaseSelectProcessor
*/
private $stockStatusBaseSelectProcessor;
protected function setUp()
{
$this->resource = $this->getMockBuilder(ResourceConnection::class)->disableOriginalConstructor()->getMock();
$this->select = $this->getMockBuilder(Select::class)->disableOriginalConstructor()->getMock();
$this->stockStatusBaseSelectProcessor = (new ObjectManager($this))->getObject(
StockStatusBaseSelectProcessor::class,
[
'resource' => $this->resource,
]
);
}
public function testProcess()
{
$tableName = 'table_name';
$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.entity_id', BaseSelectProcessorInterface::PRODUCT_TABLE_ALIAS),
[]
)
->willReturnSelf();
$this->select->expects($this->once())
->method('where')
->with('stock.stock_status = ?', Stock::STOCK_IN_STOCK)
->willReturnSelf();
$this->stockStatusBaseSelectProcessor->process($this->select);
}
}
......@@ -79,4 +79,11 @@
<argument name="indexerProcessor" xsi:type="object">Magento\CatalogInventory\Model\Indexer\Stock\Processor</argument>
</arguments>
</type>
<type name="Magento\Catalog\Model\ResourceModel\Product\CompositeBaseSelectProcessor">
<arguments>
<argument name="baseSelectProcessors" xsi:type="array">
<item name="stock_status" xsi:type="object">Magento\CatalogInventory\Model\ResourceModel\Product\StockStatusBaseSelectProcessor</item>
</argument>
</arguments>
</type>
</config>
......@@ -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 @@ class LinkedProductSelectBuilderByCatalogRulePrice implements LinkedProductSelec
\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 @@ class LinkedProductSelectBuilderByCatalogRulePrice implements LinkedProductSelec
$this->dateTime = $dateTime;
$this->localeDate = $localeDate;
$this->metadataPool = $metadataPool;
$this->baseSelectProcessor = (null !== $baseSelectProcessor)
? $baseSelectProcessor : ObjectManager::getInstance()->get(BaseSelectProcessorInterface::class);
}
/**
......@@ -76,25 +86,28 @@ class LinkedProductSelectBuilderByCatalogRulePrice implements LinkedProductSelec
$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.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.entity_id = ?', $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];
}
}
......@@ -44,6 +44,13 @@ define(
addressData.region.region_code = region['code'];
addressData.region.region = region['name'];
}
} else if (
!addressData.region_id
&& countryData()[addressData.country_id]
&& countryData()[addressData.country_id]['regions']
) {
addressData.region.region_code = '';
addressData.region.region = '';
}
delete addressData.region_id;
......
......@@ -22,7 +22,7 @@ define([], function () {
return {
email: addressData.email,
countryId: addressData['country_id'] || addressData.countryId || window.checkoutConfig.defaultCountryId,
regionId: regionId,
regionId: regionId || addressData.regionId,
regionCode: (addressData.region) ? addressData.region.region_code : null,
region: (addressData.region) ? addressData.region.region : null,
customerId: addressData.customer_id,
......@@ -30,7 +30,7 @@ define([], function () {
company: addressData.company,
telephone: addressData.telephone,
fax: addressData.fax,
postcode: addressData.postcode ? addressData.postcode : window.checkoutConfig.defaultPostcode,
postcode: addressData.postcode ? addressData.postcode : window.checkoutConfig.defaultPostcode || undefined,
city: addressData.city,
firstname: addressData.firstname,
lastname: addressData.lastname,
......
......@@ -176,7 +176,7 @@ define(
address;
if (this.validateAddressData(addressFlat)) {
addressFlat = $.extend(true, {}, quote.shippingAddress(), addressFlat);
addressFlat = uiRegistry.get('checkoutProvider').shippingAddress;
address = addressConverter.formAddressDataToQuoteAddress(addressFlat);
selectShippingAddress(address);
}
......
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment