Skip to content
This repository was archived by the owner on Apr 29, 2019. It is now read-only.

Commit 0fa2560

Browse files
author
olysenko
committed
Merge remote-tracking branch 'origin/MAGETWO-95848' into chaika_november
2 parents 18185e6 + 729fc53 commit 0fa2560

File tree

2 files changed

+176
-23
lines changed

2 files changed

+176
-23
lines changed

app/code/Magento/ConfigurableProduct/Model/Product/Configuration/Item/ItemProductResolver.php

Lines changed: 33 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,17 @@
1313
use Magento\Catalog\Model\Product\Configuration\Item\ItemResolverInterface;
1414
use Magento\Framework\App\Config\ScopeConfigInterface;
1515
use Magento\Catalog\Model\Product;
16+
use Magento\Store\Model\ScopeInterface;
1617

1718
/**
18-
* {@inheritdoc}
19+
* Resolves the product from a configured item.
1920
*/
2021
class ItemProductResolver implements ItemResolverInterface
2122
{
2223
/**
2324
* Path in config to the setting which defines if parent or child product should be used to generate a thumbnail.
2425
*/
25-
const CONFIG_THUMBNAIL_SOURCE = 'checkout/cart/configurable_product_image';
26+
public const CONFIG_THUMBNAIL_SOURCE = 'checkout/cart/configurable_product_image';
2627

2728
/**
2829
* @var ScopeConfigInterface
@@ -38,27 +39,21 @@ public function __construct(ScopeConfigInterface $scopeConfig)
3839
}
3940

4041
/**
41-
* {@inheritdoc}
42+
* Get the final product from a configured item by product type and selection.
43+
*
44+
* @param ItemInterface $item
45+
* @return ProductInterface
4246
*/
43-
public function getFinalProduct(ItemInterface $item) : ProductInterface
47+
public function getFinalProduct(ItemInterface $item): ProductInterface
4448
{
4549
/**
4650
* Show parent product thumbnail if it must be always shown according to the related setting in system config
4751
* or if child thumbnail is not available.
4852
*/
49-
$parentProduct = $item->getProduct();
50-
$finalProduct = $parentProduct;
53+
$finalProduct = $item->getProduct();
5154
$childProduct = $this->getChildProduct($item);
52-
if ($childProduct !== $parentProduct) {
53-
$configValue = $this->scopeConfig->getValue(
54-
self::CONFIG_THUMBNAIL_SOURCE,
55-
\Magento\Store\Model\ScopeInterface::SCOPE_STORE
56-
);
57-
$childThumb = $childProduct->getData('thumbnail');
58-
$finalProduct =
59-
($configValue == Thumbnail::OPTION_USE_PARENT_IMAGE) || (!$childThumb || $childThumb == 'no_selection')
60-
? $parentProduct
61-
: $childProduct;
55+
if ($childProduct !== null && $this->isUseChildProduct($childProduct)) {
56+
$finalProduct = $childProduct;
6257
}
6358
return $finalProduct;
6459
}
@@ -67,15 +62,30 @@ public function getFinalProduct(ItemInterface $item) : ProductInterface
6762
* Get item configurable child product.
6863
*
6964
* @param ItemInterface $item
70-
* @return Product
65+
* @return Product | null
7166
*/
72-
private function getChildProduct(ItemInterface $item) : Product
67+
private function getChildProduct(ItemInterface $item): ?Product
7368
{
69+
/** @var \Magento\Quote\Model\Quote\Item\Option $option */
7470
$option = $item->getOptionByCode('simple_product');
75-
$product = $item->getProduct();
76-
if ($option) {
77-
$product = $option->getProduct();
78-
}
79-
return $product;
71+
return $option ? $option->getProduct() : null;
72+
}
73+
74+
/**
75+
* Is need to use child product
76+
*
77+
* @param Product $childProduct
78+
* @return bool
79+
*/
80+
private function isUseChildProduct(Product $childProduct): bool
81+
{
82+
$configValue = $this->scopeConfig->getValue(
83+
self::CONFIG_THUMBNAIL_SOURCE,
84+
ScopeInterface::SCOPE_STORE
85+
);
86+
$childThumb = $childProduct->getData('thumbnail');
87+
return $configValue !== Thumbnail::OPTION_USE_PARENT_IMAGE
88+
&& $childThumb !== null
89+
&& $childThumb !== 'no_selection';
8090
}
8191
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\ConfigurableProduct\Test\Unit\Model\Product\Configuration\Item;
9+
10+
use Magento\Catalog\Model\Config\Source\Product\Thumbnail;
11+
use Magento\Catalog\Model\Product;
12+
use Magento\Catalog\Model\Product\Configuration\Item\ItemInterface;
13+
use Magento\Catalog\Model\Product\Configuration\Item\Option\OptionInterface;
14+
use Magento\ConfigurableProduct\Model\Product\Configuration\Item\ItemProductResolver;
15+
use Magento\Framework\App\Config\ScopeConfigInterface;
16+
use Magento\Quote\Model\Quote\Item\Option;
17+
use PHPUnit\Framework\MockObject\MockObject;
18+
use PHPUnit\Framework\TestCase;
19+
20+
class ItemProductResolverTest extends TestCase
21+
{
22+
/** @var ItemProductResolver */
23+
private $model;
24+
/** @var ItemInterface | MockObject */
25+
private $item;
26+
/** @var Product | MockObject */
27+
private $parentProduct;
28+
/** @var ScopeConfigInterface | MockObject */
29+
private $scopeConfig;
30+
/** @var OptionInterface | MockObject */
31+
private $option;
32+
/** @var Product | MockObject */
33+
private $childProduct;
34+
35+
/**
36+
* Set up method
37+
*/
38+
protected function setUp()
39+
{
40+
parent::setUp();
41+
42+
$this->scopeConfig = $this->getMockBuilder(ScopeConfigInterface::class)
43+
->disableOriginalConstructor()
44+
->getMock();
45+
46+
$this->parentProduct = $this->getMockBuilder(Product::class)
47+
->disableOriginalConstructor()
48+
->getMock();
49+
$this->parentProduct
50+
->method('getSku')
51+
->willReturn('parent_product');
52+
53+
$this->childProduct = $this->getMockBuilder(Product::class)
54+
->disableOriginalConstructor()
55+
->getMock();
56+
$this->childProduct
57+
->method('getSku')
58+
->willReturn('child_product');
59+
60+
$this->option = $this->getMockBuilder(Option::class)
61+
->disableOriginalConstructor()
62+
->getMock();
63+
64+
$this->option
65+
->method('getProduct')
66+
->willReturn($this->childProduct);
67+
68+
$this->item = $this->getMockBuilder(ItemInterface::class)
69+
->disableOriginalConstructor()
70+
->getMock();
71+
72+
$this->item
73+
->expects($this->once())
74+
->method('getProduct')
75+
->willReturn($this->parentProduct);
76+
77+
$this->model = new ItemProductResolver($this->scopeConfig);
78+
}
79+
80+
/**
81+
* Test for deleted child product from configurable product
82+
*/
83+
public function testGetFinalProductChildIsNull(): void
84+
{
85+
$this->scopeConfig->expects($this->never())->method('getValue');
86+
$this->childProduct->expects($this->never())->method('getData');
87+
88+
$this->item->expects($this->once())
89+
->method('getOptionByCode')
90+
->willReturn(null);
91+
92+
$finalProduct = $this->model->getFinalProduct($this->item);
93+
$this->assertEquals(
94+
$this->parentProduct->getSku(),
95+
$finalProduct->getSku()
96+
);
97+
}
98+
99+
/**
100+
* Tests child product from configurable product
101+
*
102+
* @dataProvider provideScopeConfig
103+
* @param string $expectedSku
104+
* @param string $scopeValue
105+
* @param string | null $thumbnail
106+
*/
107+
public function testGetFinalProductChild($expectedSku, $scopeValue, $thumbnail): void
108+
{
109+
$this->item->expects($this->once())
110+
->method('getOptionByCode')
111+
->willReturn($this->option);
112+
113+
$this->childProduct
114+
->expects($this->once())
115+
->method('getData')
116+
->willReturn($thumbnail);
117+
118+
$this->scopeConfig->expects($this->once())
119+
->method('getValue')
120+
->willReturn($scopeValue);
121+
122+
$finalProduct = $this->model->getFinalProduct($this->item);
123+
$this->assertEquals($expectedSku, $finalProduct->getSku());
124+
}
125+
126+
/**
127+
* Dataprovider for scope test
128+
* @return array
129+
*/
130+
public function provideScopeConfig(): array
131+
{
132+
return [
133+
['child_product', Thumbnail::OPTION_USE_OWN_IMAGE, 'thumbnail'],
134+
['parent_product', Thumbnail::OPTION_USE_PARENT_IMAGE, 'thumbnail'],
135+
136+
['parent_product', Thumbnail::OPTION_USE_OWN_IMAGE, null],
137+
['parent_product', Thumbnail::OPTION_USE_OWN_IMAGE, 'no_selection'],
138+
139+
['parent_product', Thumbnail::OPTION_USE_PARENT_IMAGE, null],
140+
['parent_product', Thumbnail::OPTION_USE_PARENT_IMAGE, 'no_selection'],
141+
];
142+
}
143+
}

0 commit comments

Comments
 (0)