Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

magento/magento2#7720 #26470

Merged
merged 11 commits into from
Sep 18, 2020
8 changes: 6 additions & 2 deletions app/code/Magento/Catalog/Model/ProductRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@
use Magento\Framework\Exception\ValidatorException;

/**
* Product Repository.
* @inheritdoc
*
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
* @SuppressWarnings(PHPMD.TooManyFields)
*/
Expand Down Expand Up @@ -543,7 +544,9 @@ public function save(ProductInterface $product, $saveOptions = false)
if (!$ignoreLinksFlag && $ignoreLinksFlag !== null) {
$productLinks = $product->getProductLinks();
}
$productDataArray['store_id'] = (int)$this->storeManager->getStore()->getId();
if (!isset($productDataArray['store_id'])) {
$productDataArray['store_id'] = (int) $this->storeManager->getStore()->getId();
}
$product = $this->initializeProductData($productDataArray, empty($existingProduct));

$this->processLinks($product, $productLinks);
Expand Down Expand Up @@ -735,6 +738,7 @@ private function getCollectionProcessor()
{
if (!$this->collectionProcessor) {
$this->collectionProcessor = \Magento\Framework\App\ObjectManager::getInstance()->get(
// phpstan:ignore "Class Magento\Catalog\Model\Api\SearchCriteria\ProductCollectionProcessor not found."
\Magento\Catalog\Model\Api\SearchCriteria\ProductCollectionProcessor::class
);
}
Expand Down
75 changes: 75 additions & 0 deletions app/code/Magento/Catalog/Test/Unit/Model/ProductRepositoryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,20 @@
use PHPUnit\Framework\TestCase;

/**
* Test for \Magento\Catalog\Model\ProductRepository.
*
* @SuppressWarnings(PHPMD.TooManyFields)
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
*/
class ProductRepositoryTest extends TestCase
{
private const STUB_STORE_ID = 1;
private const STUB_STORE_ID_GLOBAL = 0;
private const STUB_PRODUCT_ID = 100;
private const STUB_PRODUCT_NAME = 'name';
private const STUB_PRODUCT_SKU = 'sku';

/**
* @var Product|MockObject
*/
Expand Down Expand Up @@ -298,6 +306,7 @@ protected function setUp(): void
->disableOriginalConstructor()
->setMethods([])
->getMockForAbstractClass();
$storeMock->method('getId')->willReturn(self::STUB_STORE_ID);
$storeMock->expects($this->any())->method('getWebsiteId')->willReturn('1');
$storeMock->expects($this->any())->method('getCode')->willReturn(Store::ADMIN_CODE);
$this->storeManager->expects($this->any())->method('getStore')->willReturn($storeMock);
Expand Down Expand Up @@ -351,6 +360,72 @@ function ($value) {
$this->objectManager->setBackwardCompatibleProperty($this->model, 'mediaProcessor', $mediaProcessor);
}

/**
* Test save product with global store id
*
* @param array $productData
* @return void
* @dataProvider getProductData
*/
public function testSaveForAllStoreViewScope(array $productData): void
{
$this->productFactory->method('create')->willReturn($this->product);
$this->product->method('getSku')->willReturn($productData['sku']);
$this->extensibleDataObjectConverter
->expects($this->once())
->method('toNestedArray')
->willReturn($productData);
$this->resourceModel->method('getIdBySku')->willReturn(self::STUB_PRODUCT_ID);
$this->resourceModel->expects($this->once())->method('validate')->willReturn(true);
$this->product->expects($this->at(14))->method('setData')
->with('store_id', $productData['store_id']);

$this->model->save($this->product);
}

/**
* Product data provider
*
* @return array
*/
public function getProductData(): array
{
return [
[
[
'sku' => self::STUB_PRODUCT_SKU,
'name' => self::STUB_PRODUCT_NAME,
'store_id' => self::STUB_STORE_ID_GLOBAL,
],
],
];
}

/**
* Test save product without store
*
* @return void
*/
public function testSaveWithoutStoreId(): void
{
$this->productFactory->method('create')->willReturn($this->product);
$this->product->method('getSku')->willReturn($this->productData['sku']);
$this->extensibleDataObjectConverter
->expects($this->once())
->method('toNestedArray')
->willReturn($this->productData);
$this->resourceModel->method('getIdBySku')->willReturn(self::STUB_PRODUCT_ID);
$this->resourceModel->expects($this->once())->method('validate')->willReturn(true);
$this->product->expects($this->at(15))->method('setData')
->with('store_id', self::STUB_STORE_ID);

$this->model->save($this->product);
}

/**
* @expectedException \Magento\Framework\Exception\NoSuchEntityException
* @expectedExceptionMessage The product that was requested doesn't exist. Verify the product and try again.
*/
public function testGetAbsentProduct()
{
$this->expectException('Magento\Framework\Exception\NoSuchEntityException');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,12 @@
*/
class ProductRepositoryTest extends TestCase
{
private const STUB_STORE_ID = 1;
private const STUB_STORE_ID_GLOBAL = 0;
private const STUB_PRODUCT_NAME = 'Simple Product';
private const STUB_UPDATED_PRODUCT_NAME = 'updated';
private const STUB_PRODUCT_SKU = 'simple';

/**
* @var ObjectManagerInterface
*/
Expand Down Expand Up @@ -273,4 +279,55 @@ private function assertProductNotExist(string $sku): void
));
$this->productRepository->get($sku);
}

/**
* Tests product repository update
*
* @dataProvider productUpdateDataProvider
* @magentoDataFixture Magento/Catalog/_files/product_simple.php
* @param int $storeId
* @param int $checkStoreId
* @param string $expectedNameStore
* @param string $expectedNameCheckedStore
*/
public function testProductUpdate(
int $storeId,
int $checkStoreId,
string $expectedNameStore,
string $expectedNameCheckedStore
): void {
$sku = self::STUB_PRODUCT_SKU;

$product = $this->productRepository->get($sku, false, $storeId);
$product->setName(self::STUB_UPDATED_PRODUCT_NAME);
$this->productRepository->save($product);
$productNameStoreId = $this->productRepository->get($sku, false, $storeId)->getName();
$productNameCheckedStoreId = $this->productRepository->get($sku, false, $checkStoreId)->getName();

$this->assertEquals($expectedNameStore, $productNameStoreId);
$this->assertEquals($expectedNameCheckedStore, $productNameCheckedStoreId);
}

/**
* Product update data provider
*
* @return array
*/
public function productUpdateDataProvider(): array
{
return [
'Updating for global store' => [
self::STUB_STORE_ID_GLOBAL,
self::STUB_STORE_ID,
self::STUB_UPDATED_PRODUCT_NAME,
self::STUB_UPDATED_PRODUCT_NAME,
],
'Updating for store' => [
self::STUB_STORE_ID,
self::STUB_STORE_ID_GLOBAL,
self::STUB_UPDATED_PRODUCT_NAME,
self::STUB_PRODUCT_NAME,
],
];
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,10 @@ private function prepareConfigurableProduct(string $sku, string $storeCode): voi
{
$product = $this->productRepository->get($sku, false, null, true);
$productToUpdate = $product->getTypeInstance()->getUsedProductCollection($product)
->setPageSize(1)->getFirstItem();
->addStoreFilter($storeCode)
->setPageSize(1)
->getFirstItem();

$this->assertNotEmpty($productToUpdate->getData(), 'Configurable product does not have a child');
$this->executeInStoreContext->execute($storeCode, [$this, 'setProductDisabled'], $productToUpdate);
}
Expand Down