Skip to content

Commit

Permalink
Merge pull request #6807 from magento-l3/PR-20210423
Browse files Browse the repository at this point in the history
PR-L320210423
  • Loading branch information
dhorytskyi authored May 7, 2021
2 parents 710b9cc + 8e6a5b1 commit 94f5b99
Show file tree
Hide file tree
Showing 19 changed files with 506 additions and 100 deletions.
30 changes: 30 additions & 0 deletions app/code/Magento/Catalog/Model/Product/Option/Repository.php
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ public function save(\Magento\Catalog\Api\Data\ProductCustomOptionInterface $opt
$option->setData('product_id', $product->getData($metadata->getLinkField()));
$option->setData('store_id', $product->getStoreId());

$backedOptions = $option->getValues();
if ($option->getOptionId()) {
$options = $product->getOptions();
if (!$options) {
Expand All @@ -174,6 +175,9 @@ public function save(\Magento\Catalog\Api\Data\ProductCustomOptionInterface $opt
}
$originalValues = $persistedOption->getValues();
$newValues = $option->getData('values');
if (!$newValues) {
$newValues = $this->getOptionValues($option);
}
if ($newValues) {
if (isset($originalValues)) {
$newValues = $this->markRemovedValues($newValues, $originalValues);
Expand All @@ -182,6 +186,8 @@ public function save(\Magento\Catalog\Api\Data\ProductCustomOptionInterface $opt
}
}
$option->save();
// Required for API response data consistency
$option->setValues($backedOptions);
return $option;
}

Expand Down Expand Up @@ -249,4 +255,28 @@ private function getHydratorPool()
}
return $this->hydratorPool;
}

/**
* Get Option values from property
*
* Gets Option values stored in property, modifies for needed format and clears the property
*
* @param \Magento\Catalog\Api\Data\ProductCustomOptionInterface $option
* @return array|null
*/
private function getOptionValues(\Magento\Catalog\Api\Data\ProductCustomOptionInterface $option): ?array
{
if ($option->getValues() === null) {
return null;
}

$optionValues = [];

foreach ($option->getValues() as $optionValue) {
$optionValues[] = $optionValue->getData();
}
$option->setValues(null);

return $optionValues;
}
}
2 changes: 2 additions & 0 deletions app/code/Magento/Catalog/Model/Product/Type.php
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,8 @@ public function factory($product)

$typeModel = $this->_productTypePool->get($typeModelName);
$typeModel->setConfig($types[$typeId]);
$typeModel->setTypeId($typeId);

return $typeModel;
}

Expand Down
3 changes: 3 additions & 0 deletions app/code/Magento/Catalog/Model/Product/Type/AbstractType.php
Original file line number Diff line number Diff line change
Expand Up @@ -752,6 +752,9 @@ protected function _removeNotApplicableAttributes($product)
*/
public function beforeSave($product)
{
if (!$product->getTypeId()) {
$product->setTypeId($this->_typeId);
}
$this->_removeNotApplicableAttributes($product);
$product->canAffectOptions(true);
return $this;
Expand Down
2 changes: 1 addition & 1 deletion app/code/Magento/Catalog/Model/ProductIdLocator.php
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ public function retrieveProductIdsBySkus(array $skus)
private function truncateToLimit()
{
if (count($this->idsBySku) > $this->idsLimit) {
$this->idsBySku = array_slice($this->idsBySku, round($this->idsLimit / -2));
$this->idsBySku = array_slice($this->idsBySku, $this->idsLimit * -1, null, true);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ public function testSave()
->getMock();
$optionCollection->expects($this->once())->method('getProductOptions')->willReturn([$this->optionMock]);
$this->optionCollectionFactory->expects($this->once())->method('create')->willReturn($optionCollection);
$this->optionMock->expects($this->once())->method('getValues')->willReturn([
$this->optionMock->expects($this->exactly(2))->method('getValues')->willReturn([
$originalValue1,
$originalValue2,
$originalValue3
Expand Down Expand Up @@ -291,7 +291,7 @@ public function testSaveWhenOptionTypeWasChanged()
->getMock();
$optionCollection->expects($this->once())->method('getProductOptions')->willReturn([$this->optionMock]);
$this->optionCollectionFactory->expects($this->once())->method('create')->willReturn($optionCollection);
$this->optionMock->expects($this->once())->method('getValues')->willReturn(null);
$this->optionMock->expects($this->exactly(2))->method('getValues')->willReturn(null);
$this->assertEquals($this->optionMock, $this->optionRepository->save($this->optionMock));
}
}
168 changes: 109 additions & 59 deletions app/code/Magento/Catalog/Test/Unit/Model/ProductIdLocatorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
use Magento\Catalog\Model\ResourceModel\Product\CollectionFactory;
use Magento\Framework\EntityManager\EntityMetadataInterface;
use Magento\Framework\EntityManager\MetadataPool;
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;

Expand All @@ -23,94 +22,145 @@
class ProductIdLocatorTest extends TestCase
{
/**
* @var MetadataPool|MockObject
* @var int
*/
private $metadataPool;
private $idsLimit;

/**
* @var CollectionFactory|MockObject
* @var string
*/
private $collectionFactory;
private $linkField;

/**
* @var Collection|MockObject
*/
private $collection;

/**
* @var ProductIdLocator
*/
private $model;

/**
* Set up.
*
* @return void
* @inheritDoc
*/
protected function setUp(): void
{
$this->metadataPool = $this->getMockBuilder(MetadataPool::class)
->setMethods(['getMetadata'])
->disableOriginalConstructor()
->getMock();
$this->collectionFactory = $this
->getMockBuilder(CollectionFactory::class)
$metadataPool = $this->createMock(MetadataPool::class);
$collectionFactory = $this->getMockBuilder(CollectionFactory::class)
->setMethods(['create'])
->disableOriginalConstructor()
->getMock();
$this->idsLimit = 4;

$objectManager = new ObjectManager($this);
$this->model = $objectManager->getObject(
ProductIdLocator::class,
[
'metadataPool' => $this->metadataPool,
'collectionFactory' => $this->collectionFactory,
]
);
$this->linkField = 'entity_id';
$metaDataInterface = $this->createMock(EntityMetadataInterface::class);
$metaDataInterface->method('getLinkField')
->willReturn($this->linkField);
$metadataPool->method('getMetadata')
->with(ProductInterface::class)
->willReturn($metaDataInterface);

$this->collection = $this->createMock(Collection::class);
$collectionFactory->method('create')
->willReturn($this->collection);

$this->model = new ProductIdLocator($metadataPool, $collectionFactory, $this->idsLimit);
}

/**
* Test retrieve
*/
public function testRetrieveProductIdsBySkus()
{
$skus = ['sku_1', 'sku_2'];
$collection = $this->getMockBuilder(Collection::class)
->setMethods(
[
'getItems',
'addFieldToFilter',
'setPageSize',
'getLastPageNumber',
'setCurPage',
'clear'
]
)
->disableOriginalConstructor()
->getMock();

$product = $this->getMockBuilder(ProductInterface::class)
->setMethods(['getSku', 'getData', 'getTypeId'])
->disableOriginalConstructor()
->getMockForAbstractClass();
$metaDataInterface = $this->getMockBuilder(EntityMetadataInterface::class)
->setMethods(['getLinkField'])
->disableOriginalConstructor()
->getMockForAbstractClass();
$this->collectionFactory->expects($this->once())->method('create')->willReturn($collection);
$collection->expects($this->once())->method('addFieldToFilter')
->with(ProductInterface::SKU, ['in' => $skus])->willReturnSelf();
$collection->expects($this->atLeastOnce())->method('getItems')->willReturn([$product]);
$collection->expects($this->atLeastOnce())->method('setPageSize')->willReturnSelf();
$collection->expects($this->atLeastOnce())->method('getLastPageNumber')->willReturn(1);
$collection->expects($this->atLeastOnce())->method('setCurPage')->with(1)->willReturnSelf();
$collection->expects($this->atLeastOnce())->method('clear')->willReturnSelf();
$this->metadataPool
->expects($this->once())
->method('getMetadata')
->with(ProductInterface::class)
->willReturn($metaDataInterface);
$metaDataInterface->expects($this->once())->method('getLinkField')->willReturn('entity_id');
$product->expects($this->once())->method('getSku')->willReturn('sku_1');
$product->expects($this->once())->method('getData')->with('entity_id')->willReturn(1);
$product->expects($this->once())->method('getTypeId')->willReturn('simple');
$product->method('getSku')
->willReturn('sku_1');
$product->method('getData')
->with($this->linkField)
->willReturn(1);
$product->method('getTypeId')
->willReturn('simple');

$this->collection->expects($this->once())
->method('addFieldToFilter')
->with(ProductInterface::SKU, ['in' => $skus])
->willReturnSelf();
$this->collection->expects($this->atLeastOnce())
->method('getItems')
->willReturn([$product]);
$this->collection->expects($this->atLeastOnce())
->method('setPageSize')
->willReturnSelf();
$this->collection->expects($this->atLeastOnce())
->method('getLastPageNumber')
->willReturn(1);
$this->collection->expects($this->atLeastOnce())
->method('setCurPage')
->with(1)
->willReturnSelf();
$this->collection->expects($this->atLeastOnce())
->method('clear')
->willReturnSelf();

$this->assertEquals(
['sku_1' => [1 => 'simple']],
$this->model->retrieveProductIdsBySkus($skus)
);
}

public function testRetrieveProductIdsWithNumericSkus()
{
$skus = ['111', '222', '333', '444', '555'];
$products = [];
foreach ($skus as $sku) {
$product = $this->getMockBuilder(ProductInterface::class)
->setMethods(['getSku', 'getData', 'getTypeId'])
->disableOriginalConstructor()
->getMockForAbstractClass();
$product->method('getSku')
->willReturn($sku);
$product->method('getData')
->with($this->linkField)
->willReturn((int) $sku);
$product->method('getTypeId')
->willReturn('simple');
$products[] = $product;
}

$this->collection->expects($this->atLeastOnce())
->method('addFieldToFilter')
->withConsecutive([ProductInterface::SKU, ['in' => $skus]], [ProductInterface::SKU, ['in' => ['1']]])
->willReturnSelf();
$this->collection->expects($this->atLeastOnce())
->method('getItems')
->willReturnOnConsecutiveCalls($products, []);
$this->collection->expects($this->atLeastOnce())
->method('setPageSize')
->willReturnSelf();
$this->collection->expects($this->atLeastOnce())
->method('getLastPageNumber')
->willReturn(1);
$this->collection->expects($this->atLeastOnce())
->method('setCurPage')
->with(1)
->willReturnSelf();
$this->collection->expects($this->atLeastOnce())
->method('clear')
->willReturnSelf();

$this->assertEquals(
[
'111' => [111 => 'simple'],
'222' => [222 => 'simple'],
'333' => [333 => 'simple'],
'444' => [444 => 'simple'],
'555' => [555 => 'simple'],
],
$this->model->retrieveProductIdsBySkus($skus)
);
$this->assertEmpty($this->model->retrieveProductIdsBySkus(['1']));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);

namespace Magento\CatalogImportExport\Model\Export\Product;

use Magento\Catalog\Model\ResourceModel\Product\Collection;
use Magento\CatalogImportExport\Model\Export\ProductFilterInterface;

/**
* Website filter for products export
*/
class WebsiteFilter implements ProductFilterInterface
{
private const NAME = 'website_id';

/**
* @inheritDoc
*/
public function filter(Collection $collection, array $filters): Collection
{
if (!isset($filters[self::NAME])) {
return $collection;
}

$collection->addWebsiteFilter($filters[self::NAME]);

return $collection;
}
}
1 change: 1 addition & 0 deletions app/code/Magento/CatalogImportExport/etc/di.xml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
<argument name="filters" xsi:type="array">
<item name="category_ids" xsi:type="object">Magento\CatalogImportExport\Model\Export\Product\CategoryFilter</item>
<item name="quantity_and_stock_status" xsi:type="object">Magento\CatalogImportExport\Model\Export\Product\StockStatusFilter</item>
<item name="website_ids" xsi:type="object">Magento\CatalogImportExport\Model\Export\Product\WebsiteFilter</item>
</argument>
</arguments>
</type>
Expand Down
Loading

0 comments on commit 94f5b99

Please sign in to comment.