Skip to content

Commit ff38a20

Browse files
Merge branch 'MC-30333' into 2.4-develop-com-pr3
2 parents 560f15a + 367c365 commit ff38a20

File tree

2 files changed

+433
-37
lines changed

2 files changed

+433
-37
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,369 @@
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\Controller\Adminhtml\Product\Initialization;
9+
10+
use Magento\Catalog\Api\Data\ProductInterface;
11+
use Magento\Catalog\Api\ProductAttributeRepositoryInterface;
12+
use Magento\Catalog\Api\ProductRepositoryInterface;
13+
use Magento\Catalog\Controller\Adminhtml\Product\Initialization\Helper;
14+
use Magento\Catalog\Model\Product\Media\Config;
15+
use Magento\Catalog\Model\ResourceModel\Product as ProductResource;
16+
use Magento\Framework\Api\SearchCriteriaBuilder;
17+
use Magento\Framework\App\Filesystem\DirectoryList;
18+
use Magento\Framework\App\RequestInterface;
19+
use Magento\Framework\Filesystem;
20+
use Magento\Framework\Filesystem\Directory\WriteInterface;
21+
use Magento\Framework\ObjectManagerInterface;
22+
use Magento\Framework\Serialize\SerializerInterface;
23+
use Magento\Store\Model\Store;
24+
use Magento\TestFramework\Helper\Bootstrap;
25+
use PHPUnit\Framework\TestCase;
26+
27+
/**
28+
* Tests for image processing plugins for child products by saving a configurable product.
29+
*
30+
* @magentoAppArea adminhtml
31+
* @magentoDbIsolation enabled
32+
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
33+
*/
34+
class HelperTest extends TestCase
35+
{
36+
/**
37+
* @var ObjectManagerInterface
38+
*/
39+
private $objectManager;
40+
41+
/**
42+
* @var Helper
43+
*/
44+
private $helper;
45+
46+
/**
47+
* @var RequestInterface
48+
*/
49+
private $request;
50+
51+
/**
52+
* @var ProductRepositoryInterface
53+
*/
54+
private $productRepository;
55+
56+
/**
57+
* @var ProductResource
58+
*/
59+
private $productResource;
60+
61+
/**
62+
* @var ProductAttributeRepositoryInterface
63+
*/
64+
private $productAttributeRepository;
65+
66+
/**
67+
* @var SerializerInterface
68+
*/
69+
private $jsonSerializer;
70+
71+
/**
72+
* @var SearchCriteriaBuilder
73+
*/
74+
private $searchCriteriaBuilder;
75+
76+
/**
77+
* @var Config
78+
*/
79+
private $config;
80+
81+
/**
82+
* @var WriteInterface
83+
*/
84+
private $mediaDirectory;
85+
86+
/**
87+
* @var ProductInterface
88+
*/
89+
private $configurableProduct;
90+
91+
/**
92+
* @inheritdoc
93+
*/
94+
protected function setUp()
95+
{
96+
parent::setUp();
97+
$this->objectManager = Bootstrap::getObjectManager();
98+
$this->request = $this->objectManager->get(RequestInterface::class);
99+
$this->helper = $this->objectManager->create(Helper::class);
100+
$this->productRepository = $this->objectManager->get(ProductRepositoryInterface::class);
101+
$this->productRepository->cleanCache();
102+
$this->productResource =$this->objectManager->get(ProductResource::class);
103+
$this->productAttributeRepository = $this->objectManager->create(ProductAttributeRepositoryInterface::class);
104+
$this->jsonSerializer = $this->objectManager->get(SerializerInterface::class);
105+
$this->searchCriteriaBuilder = $this->objectManager->get(SearchCriteriaBuilder::class);
106+
$this->config = $this->objectManager->get(Config::class);
107+
$this->mediaDirectory = $this->objectManager->get(Filesystem::class)->getDirectoryWrite(DirectoryList::MEDIA);
108+
$this->configurableProduct = $this->productRepository->get('configurable');
109+
}
110+
111+
/**
112+
* Tests adding images with various roles to child products by saving a configurable product.
113+
*
114+
* @magentoDataFixture Magento/Catalog/_files/product_image.php
115+
* @magentoDataFixture Magento/ConfigurableProduct/_files/product_configurable.php
116+
* @dataProvider initializeDataProvider
117+
* @param array $childProducts
118+
* @param array $expectedImages
119+
* @return void
120+
*/
121+
public function testInitialize(array $childProducts, array $expectedImages): void
122+
{
123+
$this->setRequestParams($childProducts);
124+
$this->helper->initialize($this->configurableProduct);
125+
$this->assertChildProductImages($expectedImages);
126+
}
127+
128+
/**
129+
* Tests replacing images with various roles to child products by saving a configurable product.
130+
*
131+
* @magentoDataFixture Magento/Catalog/_files/product_image.php
132+
* @magentoDataFixture Magento/ConfigurableProduct/_files/product_configurable.php
133+
* @dataProvider initializeWithExistingChildImagesDataProvider
134+
* @param array $childProducts
135+
* @param array $expectedImages
136+
* @return void
137+
*/
138+
public function testInitializeWithExistingChildImages(array $childProducts, array $expectedImages): void
139+
{
140+
$this->updateChildProductsImages(
141+
[
142+
'simple_10' => '/m/a/magento_thumbnail.jpg.tmp',
143+
'simple_20' => '/m/a/magento_small_image.jpg.tmp',
144+
]
145+
);
146+
$this->setRequestParams($childProducts);
147+
$this->helper->initialize($this->configurableProduct);
148+
$this->assertChildProductImages($expectedImages);
149+
}
150+
151+
/**
152+
* @return array
153+
*/
154+
public function initializeDataProvider(): array
155+
{
156+
return [
157+
'children_with_same_image_and_roles' => [
158+
'child_products' => [
159+
'simple_10' => [
160+
'media_gallery' => $this->getMediaGallery(['ben062bdw2v' => '/m/a/magento_image.jpg.tmp']),
161+
'images' => [
162+
'/m/a/magento_image.jpg.tmp' => ['swatch_image', 'small_image', 'image', 'thumbnail'],
163+
],
164+
],
165+
'simple_20' => [
166+
'media_gallery' => $this->getMediaGallery(['ben062bdw2v' => '/m/a/magento_image.jpg.tmp']),
167+
'images' => [
168+
'/m/a/magento_image.jpg.tmp' => ['swatch_image', 'small_image', 'image', 'thumbnail'],
169+
],
170+
],
171+
],
172+
'expected_images' => [
173+
'simple_10' => [
174+
'/m/a/magento_image_1.jpg' => ['swatch_image', 'small_image', 'image', 'thumbnail'],
175+
],
176+
'simple_20' => [
177+
'/m/a/magento_image_2.jpg' => ['swatch_image', 'small_image', 'image', 'thumbnail'],
178+
],
179+
],
180+
],
181+
'children_with_different_images' => [
182+
'child_products' => [
183+
'simple_10' => [
184+
'media_gallery' => $this->getMediaGallery(['ben062bdw2v' => '/m/a/magento_image.jpg.tmp']),
185+
'images' => [
186+
'/m/a/magento_image.jpg.tmp' => ['swatch_image', 'small_image', 'image', 'thumbnail'],
187+
],
188+
],
189+
'simple_20' => [
190+
'media_gallery' => $this->getMediaGallery(
191+
['lrwuv5ukisn' => '/m/a/magento_small_image.jpg.tmp']
192+
),
193+
'images' => [
194+
'/m/a/magento_small_image.jpg.tmp' => ['swatch_image', 'small_image', 'image', 'thumbnail'],
195+
],
196+
],
197+
],
198+
'expected_images' => [
199+
'simple_10' => [
200+
'/m/a/magento_image_1.jpg' => ['swatch_image', 'small_image', 'image', 'thumbnail'],
201+
],
202+
'simple_20' => [
203+
'/m/a/magento_small_image_1.jpg' => ['swatch_image', 'small_image', 'image', 'thumbnail'],
204+
],
205+
],
206+
],
207+
'children_with_different_image_roles' => [
208+
'child_products' => [
209+
'simple_10' => [
210+
'media_gallery' => $this->getMediaGallery(
211+
[
212+
'ben062bdw2v' => '/m/a/magento_image.jpg.tmp',
213+
'lrwuv5ukisn' => '/m/a/magento_small_image.jpg.tmp',
214+
]
215+
),
216+
'images' => [
217+
'/m/a/magento_image.jpg.tmp' => ['swatch_image', 'small_image'],
218+
'/m/a/magento_small_image.jpg.tmp' => ['image', 'thumbnail'],
219+
],
220+
],
221+
'simple_20' => [
222+
'media_gallery' => $this->getMediaGallery(
223+
[
224+
'ben062bdw2v' => '/m/a/magento_image.jpg.tmp',
225+
'lrwuv5ukisn' => '/m/a/magento_small_image.jpg.tmp',
226+
]
227+
),
228+
'images' => [
229+
'/m/a/magento_small_image.jpg.tmp' => ['swatch_image', 'small_image'],
230+
'/m/a/magento_image.jpg.tmp' => ['image', 'thumbnail'],
231+
],
232+
],
233+
],
234+
'expected_images' => [
235+
'simple_10' => [
236+
'/m/a/magento_image_1.jpg' => ['swatch_image', 'small_image'],
237+
'/m/a/magento_small_image_1.jpg' => ['image', 'thumbnail'],
238+
],
239+
'simple_20' => [
240+
'/m/a/magento_small_image_2.jpg' => ['swatch_image', 'small_image'],
241+
'/m/a/magento_image_2.jpg' => ['image', 'thumbnail'],
242+
],
243+
],
244+
],
245+
];
246+
}
247+
248+
/**
249+
* @return array
250+
*/
251+
public function initializeWithExistingChildImagesDataProvider(): array
252+
{
253+
$dataProvider = $this->initializeDataProvider();
254+
unset($dataProvider['children_with_different_images'], $dataProvider['children_with_different_image_roles']);
255+
256+
return array_values($dataProvider);
257+
}
258+
259+
/**
260+
* Sets configurable product params to request.
261+
*
262+
* @param array $childProducts
263+
* @return void
264+
*/
265+
private function setRequestParams(array $childProducts): void
266+
{
267+
$matrix = $associatedProductIds = [];
268+
$attribute = $this->productAttributeRepository->get('test_configurable');
269+
270+
foreach ($childProducts as $sku => $product) {
271+
$simpleProduct = $this->productRepository->get($sku);
272+
$attributeValue = $simpleProduct->getData('test_configurable');
273+
foreach ($product['images'] as $image => $roles) {
274+
foreach ($roles as $role) {
275+
$product[$role] = $image;
276+
}
277+
}
278+
unset($product['images']);
279+
$product['configurable_attribute'] = $this->jsonSerializer->serialize(
280+
['test_configurable' => $attributeValue]
281+
);
282+
$product['variationKey'] = $attributeValue;
283+
$product['id'] = $simpleProduct->getId();
284+
$product['sku'] = $sku;
285+
$product['was_changed'] = true;
286+
$product['newProduct'] = 0;
287+
$matrix[] = $product;
288+
$associatedProductIds[] = $simpleProduct->getId();
289+
}
290+
$this->request->setParams(
291+
[
292+
'attributes' => [$attribute->getAttributeId()],
293+
'configurable-matrix-serialized' => $this->jsonSerializer->serialize($matrix),
294+
]
295+
);
296+
$this->request->setPostValue(
297+
'associated_product_ids_serialized',
298+
$this->jsonSerializer->serialize($associatedProductIds)
299+
);
300+
}
301+
302+
/**
303+
* Asserts child products images.
304+
*
305+
* @param array $expectedImages
306+
* @return void
307+
*/
308+
private function assertChildProductImages(array $expectedImages): void
309+
{
310+
$simpleIds = $this->configurableProduct->getExtensionAttributes()->getConfigurableProductLinks();
311+
$criteria = $this->searchCriteriaBuilder->addFilter('entity_id', $simpleIds, 'in')->create();
312+
foreach ($this->productRepository->getList($criteria)->getItems() as $simpleProduct) {
313+
$images = $expectedImages[$simpleProduct->getSku()];
314+
foreach ($images as $image => $roles) {
315+
foreach ($roles as $role) {
316+
$this->assertEquals($image, $simpleProduct->getData($role));
317+
}
318+
$this->assertFileExists(
319+
$this->mediaDirectory->getAbsolutePath($this->config->getBaseMediaPath() . $image)
320+
);
321+
}
322+
}
323+
}
324+
325+
/**
326+
* Returns media gallery product param.
327+
*
328+
* @param array $imageNames
329+
* @return array
330+
*/
331+
private function getMediaGallery(array $imageNames): array
332+
{
333+
$images = [];
334+
foreach ($imageNames as $key => $item) {
335+
$images[$key] = ['file' => $item, 'label' => '', 'media_type' => 'image'];
336+
}
337+
338+
return ['images' => $images];
339+
}
340+
341+
/**
342+
* Sets image to child products.
343+
*
344+
* @param array $imageNames
345+
* @return void
346+
*/
347+
private function updateChildProductsImages(array $imageNames): void
348+
{
349+
$simpleIds = $this->configurableProduct->getExtensionAttributes()->getConfigurableProductLinks();
350+
$criteria = $this->searchCriteriaBuilder->addFilter('entity_id', $simpleIds, 'in')->create();
351+
$products = $this->productRepository->getList($criteria)->getItems();
352+
foreach ($products as $simpleProduct) {
353+
$simpleProduct->setStoreId(Store::DEFAULT_STORE_ID)
354+
->setImage($imageNames[$simpleProduct->getSku()])
355+
->setSmallImage($imageNames[$simpleProduct->getSku()])
356+
->setThumbnail($imageNames[$simpleProduct->getSku()])
357+
->setSwatchImage($imageNames[$simpleProduct->getSku()])
358+
->setData(
359+
'media_gallery',
360+
[
361+
'images' => [
362+
['file' => $imageNames[$simpleProduct->getSku()], 'label' => '', 'media_type' => 'image']
363+
]
364+
]
365+
);
366+
$this->productResource->save($simpleProduct);
367+
}
368+
}
369+
}

0 commit comments

Comments
 (0)