Skip to content

Commit 4e14f2e

Browse files
Merge pull request #582 from magento-frontend/pr-develop
Fixed issues: - MAGETWO-59579: [Github #6943] grunt exec:<theme> doesn't work with @import</theme> - MAGETWO-57210: [github #6195, #4101] Gallery doesn't show all images added to configurable options - MAGETWO-59003: Js file version regenerated in browser on every page reload in develop mode
2 parents b56df96 + 50be841 commit 4e14f2e

File tree

14 files changed

+296
-258
lines changed

14 files changed

+296
-258
lines changed

app/code/Magento/ConfigurableProduct/view/frontend/templates/product/view/type/options/configurable.phtml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ $_attributes = $block->decorateArray($block->getAllowAttributes());
3535
"#product_addtocart_form": {
3636
"configurable": {
3737
"spConfig": <?php /* @escapeNotVerified */ echo $block->getJsonConfig() ?>,
38-
"onlyMainImg": <?php /* @escapeNotVerified */ echo $block->getVar('change_only_base_image', 'Magento_ConfigurableProduct') ?: 'false'; ?>
38+
"gallerySwitchStrategy": "<?php /* @escapeNotVerified */ echo $block->getVar('gallery_switch_strategy',
39+
'Magento_ConfigurableProduct') ?: 'replace'; ?>"
3940
}
4041
}
4142
}

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

Lines changed: 43 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,16 @@ define([
2929
mediaGallerySelector: '[data-gallery-role=gallery-placeholder]',
3030
mediaGalleryInitial: null,
3131
slyOldPriceSelector: '.sly-old-price',
32-
onlyMainImg: false
32+
33+
/**
34+
* Defines the mechanism of how images of a gallery should be
35+
* updated when user switches between configurations of a product.
36+
*
37+
* As for now value of this option can be either 'replace' or 'prepend'.
38+
*
39+
* @type {String}
40+
*/
41+
gallerySwitchStrategy: 'replace'
3342
},
3443

3544
/**
@@ -85,10 +94,10 @@ define([
8594

8695
this.inputSimpleProduct = this.element.find(options.selectSimpleProduct);
8796

88-
gallery.on('gallery:loaded', function () {
89-
var galleryObject = gallery.data('gallery');
90-
options.mediaGalleryInitial = galleryObject.returnCurrentImages();
91-
});
97+
gallery.data('gallery') ?
98+
this._onGalleryLoaded(gallery) :
99+
gallery.on('gallery:loaded', this._onGalleryLoaded.bind(this, gallery));
100+
92101
},
93102

94103
/**
@@ -259,46 +268,33 @@ define([
259268
*/
260269
_changeProductImage: function () {
261270
var images,
262-
initialImages = $.extend(true, [], this.options.mediaGalleryInitial),
271+
initialImages = this.options.mediaGalleryInitial,
263272
galleryObject = $(this.options.mediaGallerySelector).data('gallery');
264273

265-
if (this.options.spConfig.images[this.simpleProduct]) {
266-
images = $.extend(true, [], this.options.spConfig.images[this.simpleProduct]);
274+
if (!galleryObject) {
275+
return;
267276
}
268277

269-
function updateGallery(imagesArr) {
270-
var imgToUpdate,
271-
mainImg;
278+
images = this.options.spConfig.images[this.simpleProduct];
272279

273-
mainImg = imagesArr.filter(function (img) {
274-
return img.isMain;
275-
});
280+
if (images) {
281+
if (this.options.gallerySwitchStrategy === 'prepend') {
282+
images = images.concat(initialImages);
283+
}
276284

277-
imgToUpdate = mainImg.length ? mainImg[0] : imagesArr[0];
278-
galleryObject.updateDataByIndex(0, imgToUpdate);
279-
galleryObject.seek(1);
280-
}
285+
images = $.extend(true, [], images);
281286

282-
if (galleryObject) {
283-
if (images) {
284-
images.map(function (img) {
285-
img.type = 'image';
286-
});
287+
images.forEach(function (img) {
288+
img.type = 'image';
289+
});
287290

288-
if (this.options.onlyMainImg) {
289-
updateGallery(images);
290-
} else {
291-
galleryObject.updateData(images)
292-
}
293-
} else {
294-
if (this.options.onlyMainImg) {
295-
updateGallery(initialImages);
296-
} else {
297-
galleryObject.updateData(this.options.mediaGalleryInitial);
298-
$(this.options.mediaGallerySelector).AddFotoramaVideoEvents();
299-
}
300-
}
291+
galleryObject.updateData(images);
292+
} else {
293+
galleryObject.updateData(initialImages);
294+
$(this.options.mediaGallerySelector).AddFotoramaVideoEvents();
301295
}
296+
297+
galleryObject.first();
302298
},
303299

304300
/**
@@ -506,8 +502,18 @@ define([
506502
} else {
507503
$(this.options.slyOldPriceSelector).hide();
508504
}
509-
}
505+
},
510506

507+
/**
508+
* Callback which fired after gallery gets initialized.
509+
*
510+
* @param {HTMLElement} element - DOM element associated with gallery.
511+
*/
512+
_onGalleryLoaded: function (element) {
513+
var galleryObject = element.data('gallery');
514+
515+
this.options.mediaGalleryInitial = galleryObject.returnCurrentImages();
516+
}
511517
});
512518

513519
return $.mage.configurable;

app/code/Magento/Swatches/view/frontend/templates/product/view/renderer.phtml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@
1616
"jsonSwatchConfig": <?php /* @escapeNotVerified */
1717
echo $swatchOptions = $block->getJsonSwatchConfig(); ?>,
1818
"mediaCallback": "<?php /* @escapeNotVerified */ echo $block->getMediaCallback() ?>",
19-
"onlyMainImg": <?php /* @escapeNotVerified */ echo $block->getVar('change_only_base_image',
20-
'Magento_Swatches') ?: 'false'; ?>
19+
"gallerySwitchStrategy": "<?php /* @escapeNotVerified */ echo $block->getVar('gallery_switch_strategy',
20+
'Magento_ConfigurableProduct') ?: 'replace'; ?>"
2121
}
2222
}
2323
}

app/code/Magento/Swatches/view/frontend/web/js/swatch-renderer.js

Lines changed: 36 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -243,8 +243,15 @@ define([
243243
// Cache for BaseProduct images. Needed when option unset
244244
mediaGalleryInitial: [{}],
245245

246-
//
247-
onlyMainImg: false,
246+
/**
247+
* Defines the mechanism of how images of a gallery should be
248+
* updated when user switches between configurations of a product.
249+
*
250+
* As for now value of this option can be either 'replace' or 'prepend'.
251+
*
252+
* @type {String}
253+
*/
254+
gallerySwitchStrategy: 'replace',
248255

249256
// whether swatches are rendered in product list or on product page
250257
inProductList: false
@@ -295,11 +302,9 @@ define([
295302
this.element.parents('.product-item-info');
296303

297304
if (isProductViewExist) {
298-
gallery.on('gallery:loaded', function () {
299-
var galleryObject = gallery.data('gallery');
300-
301-
options.mediaGalleryInitial = galleryObject.returnCurrentImages();
302-
});
305+
gallery.data('gallery') ?
306+
this._onGalleryLoaded(gallery) :
307+
gallery.on('gallery:loaded', this._onGalleryLoaded.bind(this, gallery));
303308
} else {
304309
options.mediaGalleryInitial = [{
305310
'img': $main.find('.product-image-photo').attr('src')
@@ -1032,26 +1037,27 @@ define([
10321037
*/
10331038
updateBaseImage: function (images, context, isProductViewExist) {
10341039
var justAnImage = images[0],
1035-
updateImg,
1036-
imagesToUpdate,
1040+
initialImages = this.options.mediaGalleryInitial,
10371041
gallery = context.find(this.options.mediaGallerySelector).data('gallery'),
1038-
item;
1042+
imagesToUpdate,
1043+
isInitial;
10391044

10401045
if (isProductViewExist) {
10411046
imagesToUpdate = images.length ? this._setImageType($.extend(true, [], images)) : [];
1047+
isInitial = _.isEqual(imagesToUpdate, initialImages);
10421048

1043-
if (this.options.onlyMainImg) {
1044-
updateImg = imagesToUpdate.filter(function (img) {
1045-
return img.isMain;
1046-
});
1047-
item = updateImg.length ? updateImg[0] : imagesToUpdate[0];
1048-
gallery.updateDataByIndex(0, item);
1049+
if (this.options.gallerySwitchStrategy === 'prepend' && !isInitial) {
1050+
imagesToUpdate = imagesToUpdate.concat(initialImages);
1051+
}
10491052

1050-
gallery.seek(1);
1051-
} else {
1052-
gallery.updateData(imagesToUpdate);
1053+
gallery.updateData(imagesToUpdate);
1054+
1055+
if (isInitial) {
10531056
$(this.options.mediaGallerySelector).AddFotoramaVideoEvents();
10541057
}
1058+
1059+
gallery.first();
1060+
10551061
} else if (justAnImage && justAnImage.img) {
10561062
context.find('.product-image-photo').attr('src', justAnImage.img);
10571063
}
@@ -1127,6 +1133,17 @@ define([
11271133
}
11281134

11291135
return selectedAttributes;
1136+
},
1137+
1138+
/**
1139+
* Callback which fired after gallery gets initialized.
1140+
*
1141+
* @param {HTMLElement} element - DOM element associated with a gallery.
1142+
*/
1143+
_onGalleryLoaded: function (element) {
1144+
var galleryObject = element.data('gallery');
1145+
1146+
this.options.mediaGalleryInitial = galleryObject.returnCurrentImages();
11301147
}
11311148
});
11321149

app/design/frontend/Magento/luma/etc/view.xml

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -253,10 +253,7 @@
253253
</vars>
254254

255255
<vars module="Magento_ConfigurableProduct">
256-
<var name="change_only_base_image">true</var>
257-
</vars>
258-
<vars module="Magento_Swatches">
259-
<var name="change_only_base_image">true</var>
256+
<var name="gallery_switch_strategy">prepend</var>
260257
</vars>
261258

262259
<vars module="Js_Bundle">
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
<?php
2+
/**
3+
* Copyright © 2016 Magento. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
namespace Magento\Framework\App\View\Deployment;
7+
8+
use Magento\Framework\App\Filesystem\DirectoryList;
9+
use Magento\Framework\App\ObjectManager;
10+
use Magento\Framework\App\State;
11+
use Magento\Framework\App\View\Deployment\Version\Storage\File;
12+
use Magento\Framework\Filesystem\Directory\WriteInterface;
13+
14+
class VersionTest extends \PHPUnit_Framework_TestCase
15+
{
16+
/**
17+
* @var File
18+
*/
19+
private $fileStorage;
20+
21+
/**
22+
* @var WriteInterface
23+
*/
24+
private $directoryWrite;
25+
26+
/**
27+
* @var string
28+
*/
29+
private $fileName = 'deployed_version.txt';
30+
31+
public function setUp()
32+
{
33+
$this->fileStorage = ObjectManager::getInstance()->create(
34+
File::class,
35+
[
36+
'directoryCode' => DirectoryList::STATIC_VIEW,
37+
'fileName' => $this->fileName
38+
]
39+
);
40+
/** @var \Magento\TestFramework\App\Filesystem $filesystem */
41+
$filesystem = ObjectManager::getInstance()->get(\Magento\TestFramework\App\Filesystem::class);
42+
$this->directoryWrite = $filesystem->getDirectoryWrite(DirectoryList::STATIC_VIEW);
43+
$this->removeDeployVersionFile();
44+
}
45+
46+
/**
47+
* @param string $mode
48+
* @return Version
49+
*/
50+
public function getVersionModel($mode)
51+
{
52+
$appState = ObjectManager::getInstance()->create(
53+
State::class,
54+
[
55+
'mode' => $mode
56+
]
57+
);
58+
return ObjectManager::getInstance()->create(
59+
Version::class,
60+
[
61+
'appState' => $appState
62+
]
63+
);
64+
}
65+
66+
protected function tearDown()
67+
{
68+
$this->removeDeployVersionFile();
69+
}
70+
71+
private function removeDeployVersionFile()
72+
{
73+
if ($this->directoryWrite->isExist($this->fileName)) {
74+
$this->directoryWrite->delete($this->fileName);
75+
}
76+
}
77+
78+
/**
79+
* @expectedException \UnexpectedValueException
80+
*/
81+
public function testGetValueInProductionModeWithoutVersion()
82+
{
83+
$this->assertFalse($this->directoryWrite->isExist($this->fileName));
84+
$this->getVersionModel(State::MODE_PRODUCTION)->getValue();
85+
}
86+
87+
public function testGetValueInDeveloperMode()
88+
{
89+
$this->assertFalse($this->directoryWrite->isExist($this->fileName));
90+
$this->getVersionModel(State::MODE_DEVELOPER)->getValue();
91+
$this->assertTrue($this->directoryWrite->isExist($this->fileName));
92+
}
93+
94+
/**
95+
* Assert that version is not regenerated on each request in developer mode
96+
*/
97+
public function testGetValue()
98+
{
99+
$this->assertFalse($this->directoryWrite->isExist($this->fileName));
100+
$versionModel = $this->getVersionModel(State::MODE_DEVELOPER);
101+
$version = $versionModel->getValue();
102+
$this->assertTrue($this->directoryWrite->isExist($this->fileName));
103+
$this->assertEquals($version, $versionModel->getValue());
104+
}
105+
}

dev/tools/grunt/configs/clean.js

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ _.each(themes, function(theme, name) {
2121
"<%= path.tmp %>/cache/**/*",
2222
"<%= combo.autopath(\""+name+"\", path.pub ) %>**/*",
2323
"<%= combo.autopath(\""+name+"\", path.tmpLess) %>**/*",
24-
"<%= combo.autopath(\""+name+"\", path.tmpSource) %>**/*"
24+
"<%= combo.autopath(\""+name+"\", path.tmpSource) %>**/*",
25+
"<%= path.deployedVersion %>"
2526
]
2627
}
2728
]
@@ -56,7 +57,8 @@ var cleanOptions = {
5657
"dot": true,
5758
"src": [
5859
"<%= path.pub %>frontend/**/*",
59-
"<%= path.pub %>adminhtml/**/*"
60+
"<%= path.pub %>adminhtml/**/*",
61+
"<%= path.deployedVersion %>"
6062
]
6163
}
6264
]
@@ -73,7 +75,8 @@ var cleanOptions = {
7375
"<%= path.pub %>frontend/**/*.less",
7476
"<%= path.pub %>frontend/**/*.css",
7577
"<%= path.pub %>adminhtml/**/*.less",
76-
"<%= path.pub %>adminhtml/**/*.css"
78+
"<%= path.pub %>adminhtml/**/*.css",
79+
"<%= path.deployedVersion %>"
7780
]
7881
}
7982
]
@@ -102,7 +105,8 @@ var cleanOptions = {
102105
"src": [
103106
"<%= path.pub %>**/*.js",
104107
"<%= path.pub %>**/*.html",
105-
"<%= path.pub %>_requirejs/**/*"
108+
"<%= path.pub %>_requirejs/**/*",
109+
"<%= path.deployedVersion %>"
106110
]
107111
}
108112
]

dev/tools/grunt/configs/path.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ module.exports = {
1313
tmpLess: 'var/view_preprocessed/less/',
1414
tmpSource: 'var/view_preprocessed/source/',
1515
tmp: 'var',
16+
deployedVersion: 'pub/static/deployed_version.txt',
1617
css: {
1718
setup: 'setup/pub/styles',
1819
updater: '../magento2-updater/pub/css'

0 commit comments

Comments
 (0)