Skip to content

Commit c8b676e

Browse files
committed
Merge remote-tracking branch 'frontend/PR_04july' into PRS
2 parents 52adc40 + c2166b3 commit c8b676e

File tree

23 files changed

+781
-225
lines changed

23 files changed

+781
-225
lines changed

app/code/Magento/Catalog/Block/Product/View/Gallery.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,8 @@ public function getGalleryImagesJson()
118118
'caption' => $image->getLabel(),
119119
'position' => $image->getPosition(),
120120
'isMain' => $this->isMainImage($image),
121+
'type' => str_replace('external-', '', $image->getMediaType()),
122+
'videoUrl' => $image->getVideoUrl(),
121123
];
122124
}
123125
if (empty($imagesItems)) {
@@ -128,6 +130,8 @@ public function getGalleryImagesJson()
128130
'caption' => '',
129131
'position' => '0',
130132
'isMain' => true,
133+
'type' => 'image',
134+
'videoUrl' => null,
131135
];
132136
}
133137
return json_encode($imagesItems);
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
namespace Magento\ConfigurableProduct\Block\Plugin\Product\Media;
7+
8+
use Magento\ConfigurableProduct\Model\Product\Type\Configurable;
9+
use Magento\Catalog\Model\Product;
10+
use Magento\Framework\Serialize\Serializer\Json;
11+
12+
/**
13+
* Provides a serialized media gallery data for configurable product options.
14+
*/
15+
class Gallery
16+
{
17+
/**
18+
* @var Json
19+
*/
20+
private $json;
21+
22+
/**
23+
* @param Json $json
24+
*/
25+
public function __construct(
26+
Json $json
27+
) {
28+
$this->json = $json;
29+
}
30+
31+
/**
32+
* @param \Magento\Catalog\Block\Product\View\Gallery $subject
33+
* @param string $result
34+
* @return string
35+
*/
36+
public function afterGetOptionsMediaGalleryDataJson(
37+
\Magento\Catalog\Block\Product\View\Gallery $subject,
38+
$result
39+
) {
40+
$result = $this->json->unserialize($result);
41+
$parentProduct = $subject->getProduct();
42+
if ($parentProduct->getTypeId() == Configurable::TYPE_CODE) {
43+
/** @var Configurable $productType */
44+
$productType = $parentProduct->getTypeInstance();
45+
$products = $productType->getUsedProducts($parentProduct);
46+
/** @var Product $product */
47+
foreach ($products as $product) {
48+
$key = $product->getId();
49+
$result[$key] = $this->getProductGallery($product);
50+
}
51+
}
52+
return $this->json->serialize($result);
53+
}
54+
55+
/**
56+
* @param Product $product
57+
* @return array
58+
*/
59+
private function getProductGallery($product)
60+
{
61+
$result = [];
62+
$images = $product->getMediaGalleryImages();
63+
foreach ($images as $image) {
64+
$result[] = [
65+
'mediaType' => $image->getMediaType(),
66+
'videoUrl' => $image->getVideoUrl(),
67+
'isBase' => $product->getImage() == $image->getFile(),
68+
];
69+
}
70+
return $result;
71+
}
72+
}

app/code/Magento/ConfigurableProduct/Block/Product/View/Type/Configurable.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,8 @@ protected function getOptionImages()
256256
'caption' => $image->getLabel(),
257257
'position' => $image->getPosition(),
258258
'isMain' => $image->getFile() == $product->getImage(),
259+
'type' => str_replace('external-', '', $image->getMediaType()),
260+
'videoUrl' => $image->getVideoUrl(),
259261
];
260262
}
261263
}
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
namespace Magento\ConfigurableProduct\Test\Unit\Block\Plugin\Product\Media;
7+
8+
use Magento\ConfigurableProduct\Block\Plugin\Product\Media\Gallery;
9+
use Magento\Catalog\Model\Product;
10+
use Magento\Framework\Serialize\Serializer\Json;
11+
12+
/**
13+
* Class GalleryTest
14+
*/
15+
class GalleryTest extends \PHPUnit_Framework_TestCase
16+
{
17+
18+
public function testAfterGetOptions()
19+
{
20+
$jsonMock = $this->createJsonMock();
21+
$productMock = $this->createProductMock();
22+
$galleryMock = $this->createGalleryMock();
23+
$variationProductMock = $this->createProductMock();
24+
$configurableTypeMock = $this->createConfigurableTypeMock();
25+
26+
$resultJson = '[]';
27+
$variationProductId = 1;
28+
$expectedGalleryJson = [
29+
$variationProductId => [
30+
[
31+
'mediaType' => 'type',
32+
'videoUrl' => 'url',
33+
'isBase' => true
34+
]
35+
]
36+
];
37+
$image = new \Magento\Framework\DataObject(
38+
['media_type' => 'type', 'video_url' => 'url', 'file' => 'image.jpg']
39+
);
40+
41+
$galleryMock->expects(($this->any()))->method('getProduct')->willReturn($productMock);
42+
$productMock->expects($this->once())->method('getTypeId')->willReturn('configurable');
43+
$productMock->expects($this->once())->method('getTypeInstance')->willReturn($configurableTypeMock);
44+
$configurableTypeMock->expects($this->once())->method('getUsedProducts')->with($productMock)
45+
->willReturn([$variationProductMock]);
46+
$variationProductMock->expects($this->once())->method('getId')->willReturn($variationProductId);
47+
$variationProductMock->expects($this->once())->method('getMediaGalleryImages')->willReturn([$image]);
48+
$variationProductMock->expects($this->once())->method('getImage')->willReturn('image.jpg');
49+
$jsonMock->expects($this->once())->method('serialize')->with($expectedGalleryJson)
50+
->willReturn(json_encode($expectedGalleryJson));
51+
52+
$helper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this);
53+
$plugin = $helper->getObject(
54+
Gallery::class,
55+
[
56+
'json' => $jsonMock
57+
]
58+
);
59+
$result = $plugin->afterGetOptionsMediaGalleryDataJson($galleryMock, $resultJson);
60+
$this->assertEquals(json_encode($expectedGalleryJson), $result);
61+
}
62+
63+
/**
64+
* @return \PHPUnit_Framework_MockObject_MockObject
65+
*/
66+
private function createJsonMock()
67+
{
68+
return $this->getMockBuilder(Json::class)
69+
->disableOriginalConstructor()
70+
->getMock();
71+
}
72+
73+
/**
74+
* @return \PHPUnit_Framework_MockObject_MockObject
75+
*/
76+
private function createProductMock()
77+
{
78+
return $this->getMockBuilder(Product::class)
79+
->disableOriginalConstructor()
80+
->getMock();
81+
}
82+
83+
/**
84+
* @return \PHPUnit_Framework_MockObject_MockObject
85+
*/
86+
private function createGalleryMock()
87+
{
88+
return $this->getMockBuilder(\Magento\Catalog\Block\Product\View\Gallery::class)
89+
->disableOriginalConstructor()
90+
->getMock();
91+
}
92+
93+
/**
94+
* @return \PHPUnit_Framework_MockObject_MockObject
95+
*/
96+
private function createConfigurableTypeMock()
97+
{
98+
return $this->getMockBuilder(\Magento\ConfigurableProduct\Model\Product\Type\Configurable::class)
99+
->disableOriginalConstructor()
100+
->getMock();
101+
}
102+
}

app/code/Magento/ConfigurableProduct/etc/di.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,9 @@
148148
<type name="Magento\Catalog\Model\Product\Attribute\Backend\Price">
149149
<plugin name="configurable" type="Magento\ConfigurableProduct\Model\Plugin\PriceBackend" sortOrder="100" />
150150
</type>
151+
<type name="Magento\ProductVideo\Block\Product\View\Gallery">
152+
<plugin name="product_video_gallery" type="Magento\ConfigurableProduct\Block\Plugin\Product\Media\Gallery" />
153+
</type>
151154
<type name="Magento\ConfigurableProduct\Model\Product\Type\Configurable">
152155
<arguments>
153156
<argument name="cache" xsi:type="object">Magento\Framework\App\Cache\Type\Collection</argument>

app/code/Magento/ConfigurableProduct/view/frontend/web/js/configurable.js

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,7 @@ define([
265265
} else {
266266
this._resetChildren(element);
267267
}
268+
268269
this._reloadPrice();
269270
this._displayRegularPriceBlock(this.simpleProduct);
270271
this._displayTierPriceBlock(this.simpleProduct);
@@ -273,6 +274,7 @@ define([
273274

274275
/**
275276
* Change displayed product image according to chosen options of configurable product
277+
*
276278
* @private
277279
*/
278280
_changeProductImage: function () {
@@ -292,12 +294,14 @@ define([
292294
}
293295

294296
images = $.extend(true, [], images);
295-
296-
images.forEach(function (img) {
297-
img.type = 'image';
298-
});
297+
images = this._setImageIndex(images);
299298

300299
galleryObject.updateData(images);
300+
301+
$(this.options.mediaGallerySelector).AddFotoramaVideoEvents({
302+
selectedOption: this.simpleProduct,
303+
dataMergeStrategy: this.options.gallerySwitchStrategy
304+
});
301305
} else {
302306
galleryObject.updateData(initialImages);
303307
$(this.options.mediaGallerySelector).AddFotoramaVideoEvents();
@@ -306,6 +310,23 @@ define([
306310
galleryObject.first();
307311
},
308312

313+
/**
314+
* Set correct indexes for image set.
315+
*
316+
* @param {Array} images
317+
* @private
318+
*/
319+
_setImageIndex: function (images) {
320+
var length = images.length,
321+
i;
322+
323+
for (i = 0; length > i; i++) {
324+
images[i].i = i + 1;
325+
}
326+
327+
return images;
328+
},
329+
309330
/**
310331
* For a given option element, reset all of its selectable options. Clear any selected
311332
* index, disable the option choice, and reset the option's state if necessary.

0 commit comments

Comments
 (0)