diff --git a/app/code/Magento/Catalog/Block/Product/View/GalleryOptions.php b/app/code/Magento/Catalog/Block/Product/View/GalleryOptions.php
new file mode 100644
index 0000000000000..0384c9cd9acce
--- /dev/null
+++ b/app/code/Magento/Catalog/Block/Product/View/GalleryOptions.php
@@ -0,0 +1,156 @@
+gallery = $gallery;
+ $this->jsonSerializer = $jsonSerializer;
+ parent::__construct($context, $arrayUtils, $data);
+ }
+
+ /**
+ * Retrieve gallery options in JSON format
+ *
+ * @return string
+ * @SuppressWarnings(PHPMD.CyclomaticComplexity)
+ * @SuppressWarnings(PHPMD.NPathComplexity)
+ * @SuppressWarnings(PHPMD.ElseExpression)
+ */
+ public function getOptionsJson()
+ {
+ $optionItems = null;
+
+ //Special case for gallery/nav which can be the string "thumbs/false/dots"
+ if (is_bool($this->getVar("gallery/nav"))) {
+ $optionItems['nav'] = $this->getVar("gallery/nav") ? 'true' : 'false';
+ } else {
+ $optionItems['nav'] = $this->escapeHtml($this->getVar("gallery/nav"));
+ }
+
+ $optionItems['loop'] = $this->getVar("gallery/loop");
+ $optionItems['keyboard'] = $this->getVar("gallery/keyboard");
+ $optionItems['arrows'] = $this->getVar("gallery/arrows");
+ $optionItems['allowfullscreen'] = $this->getVar("gallery/allowfullscreen");
+ $optionItems['showCaption'] = $this->getVar("gallery/caption");
+ $optionItems['width'] = (int)$this->escapeHtml(
+ $this->gallery->getImageAttribute('product_page_image_medium', 'width')
+ );
+ $optionItems['thumbwidth'] = (int)$this->escapeHtml(
+ $this->gallery->getImageAttribute('product_page_image_small', 'width')
+ );
+
+ if ($this->gallery->getImageAttribute('product_page_image_small', 'height') ||
+ $this->gallery->getImageAttribute('product_page_image_small', 'width')) {
+ $optionItems['thumbheight'] = (int)$this->escapeHtml(
+ $this->gallery->getImageAttribute('product_page_image_small', 'height') ?:
+ $this->gallery->getImageAttribute('product_page_image_small', 'width')
+ );
+ }
+
+ if ($this->gallery->getImageAttribute('product_page_image_medium', 'height') ||
+ $this->gallery->getImageAttribute('product_page_image_medium', 'width')) {
+ $optionItems['height'] = (int)$this->escapeHtml(
+ $this->gallery->getImageAttribute('product_page_image_medium', 'height') ?:
+ $this->gallery->getImageAttribute('product_page_image_medium', 'width')
+ );
+ }
+
+ if ($this->getVar("gallery/transition/duration")) {
+ $optionItems['transitionduration'] =
+ (int)$this->escapeHtml($this->getVar("gallery/transition/duration"));
+ }
+
+ $optionItems['transition'] = $this->escapeHtml($this->getVar("gallery/transition/effect"));
+ $optionItems['navarrows'] = $this->getVar("gallery/navarrows");
+ $optionItems['navtype'] = $this->escapeHtml($this->getVar("gallery/navtype"));
+ $optionItems['navdir'] = $this->escapeHtml($this->getVar("gallery/navdir"));
+
+ if ($this->getVar("gallery/thumbmargin")) {
+ $optionItems['thumbmargin'] = (int)$this->escapeHtml($this->getVar("gallery/thumbmargin"));
+ }
+
+ return $this->jsonSerializer->serialize($optionItems);
+ }
+
+ /**
+ * Retrieve gallery fullscreen options in JSON format
+ *
+ * @return string
+ * @SuppressWarnings(PHPMD.CyclomaticComplexity)
+ * @SuppressWarnings(PHPMD.NPathComplexity)
+ * @SuppressWarnings(PHPMD.ElseExpression)
+ */
+ public function getFSOptionsJson()
+ {
+ $fsOptionItems = null;
+
+ //Special case for gallery/nav which can be the string "thumbs/false/dots"
+ if (is_bool($this->getVar("gallery/fullscreen/nav"))) {
+ $fsOptionItems['nav'] = $this->getVar("gallery/fullscreen/nav") ? 'true' : 'false';
+ } else {
+ $fsOptionItems['nav'] = $this->escapeHtml($this->getVar("gallery/fullscreen/nav"));
+ }
+
+ $fsOptionItems['loop'] = $this->getVar("gallery/fullscreen/loop");
+ $fsOptionItems['navdir'] = $this->escapeHtml($this->getVar("gallery/fullscreen/navdir"));
+ $fsOptionItems['navarrows'] = $this->getVar("gallery/fullscreen/navarrows");
+ $fsOptionItems['navtype'] = $this->escapeHtml($this->getVar("gallery/fullscreen/navtype"));
+ $fsOptionItems['arrows'] = $this->getVar("gallery/fullscreen/arrows");
+ $fsOptionItems['showCaption'] = $this->getVar("gallery/fullscreen/caption");
+
+ if ($this->getVar("gallery/fullscreen/transition/duration")) {
+ $fsOptionItems['transitionduration'] = (int)$this->escapeHtml(
+ $this->getVar("gallery/fullscreen/transition/duration")
+ );
+ }
+
+ $fsOptionItems['transition'] = $this->escapeHtml($this->getVar("gallery/fullscreen/transition/effect"));
+
+ if ($this->getVar("gallery/fullscreen/keyboard")) {
+ $fsOptionItems['keyboard'] = $this->getVar("gallery/fullscreen/keyboard");
+ }
+
+ if ($this->getVar("gallery/fullscreen/thumbmargin")) {
+ $fsOptionItems['thumbmargin'] =
+ (int)$this->escapeHtml($this->getVar("gallery/fullscreen/thumbmargin"));
+ }
+
+ return $this->jsonSerializer->serialize($fsOptionItems);
+ }
+}
diff --git a/app/code/Magento/Catalog/Test/Unit/Block/Product/View/GalleryOptionsTest.php b/app/code/Magento/Catalog/Test/Unit/Block/Product/View/GalleryOptionsTest.php
new file mode 100644
index 0000000000000..7ed8b13fce750
--- /dev/null
+++ b/app/code/Magento/Catalog/Test/Unit/Block/Product/View/GalleryOptionsTest.php
@@ -0,0 +1,223 @@
+escaper = $objectManager->getObject(Escaper::class);
+ $this->configView = $this->createMock(View::class);
+
+ $this->viewConfig = $this->createConfiguredMock(
+ Config::class,
+ [
+ 'getViewConfig' => $this->configView
+ ]
+ );
+
+ $this->context = $this->createConfiguredMock(
+ Context::class,
+ [
+ 'getEscaper' => $this->escaper,
+ 'getViewConfig' => $this->viewConfig
+ ]
+ );
+
+ $this->gallery = $this->createMock(Gallery::class);
+
+ $this->jsonSerializer = $objectManager->getObject(
+ Json::class
+ );
+
+ $this->model = $objectManager->getObject(GalleryOptions::class, [
+ 'context' => $this->context,
+ 'jsonSerializer' => $this->jsonSerializer,
+ 'gallery' => $this->gallery
+ ]);
+ }
+
+ public function testGetOptionsJson()
+ {
+ $configMap = [
+ ['Magento_Catalog', 'gallery/nav', 'thumbs'],
+ ['Magento_Catalog', 'gallery/loop', false],
+ ['Magento_Catalog', 'gallery/keyboard', true],
+ ['Magento_Catalog', 'gallery/arrows', true],
+ ['Magento_Catalog', 'gallery/caption', false],
+ ['Magento_Catalog', 'gallery/allowfullscreen', true],
+ ['Magento_Catalog', 'gallery/navdir', 'horizontal'],
+ ['Magento_Catalog', 'gallery/navarrows', true],
+ ['Magento_Catalog', 'gallery/navtype', 'slides'],
+ ['Magento_Catalog', 'gallery/thumbmargin', '5'],
+ ['Magento_Catalog', 'gallery/transition/effect', 'slide'],
+ ['Magento_Catalog', 'gallery/transition/duration', '500'],
+ ];
+
+ $imageAttributesMap = [
+ ['product_page_image_medium','height',null, 100],
+ ['product_page_image_medium','width',null, 200],
+ ['product_page_image_small','height',null, 300],
+ ['product_page_image_small','width',null, 400]
+ ];
+
+ $this->configView->expects($this->any())
+ ->method('getVarValue')
+ ->will($this->returnValueMap($configMap));
+ $this->gallery->expects($this->any())
+ ->method('getImageAttribute')
+ ->will($this->returnValueMap($imageAttributesMap));
+
+ $json = $this->model->getOptionsJson();
+
+ $decodedJson = $this->jsonSerializer->unserialize($json);
+
+ $this->assertSame('thumbs', $decodedJson['nav']);
+ $this->assertSame(false, $decodedJson['loop']);
+ $this->assertSame(true, $decodedJson['keyboard']);
+ $this->assertSame(true, $decodedJson['arrows']);
+ $this->assertSame(false, $decodedJson['showCaption']);
+ $this->assertSame(true, $decodedJson['allowfullscreen']);
+ $this->assertSame('horizontal', $decodedJson['navdir']);
+ $this->assertSame(true, $decodedJson['navarrows']);
+ $this->assertSame('slides', $decodedJson['navtype']);
+ $this->assertSame(5, $decodedJson['thumbmargin']);
+ $this->assertSame('slide', $decodedJson['transition']);
+ $this->assertSame(500, $decodedJson['transitionduration']);
+ $this->assertSame(100, $decodedJson['height']);
+ $this->assertSame(200, $decodedJson['width']);
+ $this->assertSame(300, $decodedJson['thumbheight']);
+ $this->assertSame(400, $decodedJson['thumbwidth']);
+ }
+
+ public function testGetFSOptionsJson()
+ {
+ $configMap = [
+ ['Magento_Catalog', 'gallery/fullscreen/nav', false],
+ ['Magento_Catalog', 'gallery/fullscreen/loop', true],
+ ['Magento_Catalog', 'gallery/fullscreen/keyboard', true],
+ ['Magento_Catalog', 'gallery/fullscreen/arrows', false],
+ ['Magento_Catalog', 'gallery/fullscreen/caption', true],
+ ['Magento_Catalog', 'gallery/fullscreen/navdir', 'vertical'],
+ ['Magento_Catalog', 'gallery/fullscreen/navarrows', false],
+ ['Magento_Catalog', 'gallery/fullscreen/navtype', 'thumbs'],
+ ['Magento_Catalog', 'gallery/fullscreen/thumbmargin', '10'],
+ ['Magento_Catalog', 'gallery/fullscreen/transition/effect', 'dissolve'],
+ ['Magento_Catalog', 'gallery/fullscreen/transition/duration', '300']
+ ];
+
+ $this->configView->expects($this->any())
+ ->method('getVarValue')
+ ->will($this->returnValueMap($configMap));
+
+ $json = $this->model->getFSOptionsJson();
+
+ $decodedJson = $this->jsonSerializer->unserialize($json);
+
+ //Note, this tests the special case for nav variable set to false. It
+ //Should not be converted to boolean.
+ $this->assertSame('false', $decodedJson['nav']);
+ $this->assertSame(true, $decodedJson['loop']);
+ $this->assertSame(false, $decodedJson['arrows']);
+ $this->assertSame(true, $decodedJson['keyboard']);
+ $this->assertSame(true, $decodedJson['showCaption']);
+ $this->assertSame('vertical', $decodedJson['navdir']);
+ $this->assertSame(false, $decodedJson['navarrows']);
+ $this->assertSame(10, $decodedJson['thumbmargin']);
+ $this->assertSame('thumbs', $decodedJson['navtype']);
+ $this->assertSame('dissolve', $decodedJson['transition']);
+ $this->assertSame(300, $decodedJson['transitionduration']);
+ }
+
+ public function testGetOptionsJsonOptionals()
+ {
+ $configMap = [
+ ['Magento_Catalog', 'gallery/fullscreen/thumbmargin', false],
+ ['Magento_Catalog', 'gallery/fullscreen/transition/duration', false]
+ ];
+
+ $this->configView->expects($this->any())
+ ->method('getVarValue')
+ ->will($this->returnValueMap($configMap));
+
+ $json = $this->model->getOptionsJson();
+
+ $decodedJson = $this->jsonSerializer->unserialize($json);
+
+ $this->assertArrayNotHasKey('thumbmargin', $decodedJson);
+ $this->assertArrayNotHasKey('transitionduration', $decodedJson);
+ }
+
+ public function testGetFSOptionsJsonOptionals()
+ {
+ $configMap = [
+ ['Magento_Catalog', 'gallery/fullscreen/keyboard', false],
+ ['Magento_Catalog', 'gallery/fullscreen/thumbmargin', false],
+ ['Magento_Catalog', 'gallery/fullscreen/transition/duration', false]
+ ];
+
+ $this->configView->expects($this->any())
+ ->method('getVarValue')
+ ->will($this->returnValueMap($configMap));
+
+ $json = $this->model->getFSOptionsJson();
+
+ $decodedJson = $this->jsonSerializer->unserialize($json);
+
+ $this->assertArrayNotHasKey('thumbmargin', $decodedJson);
+ $this->assertArrayNotHasKey('keyboard', $decodedJson);
+ $this->assertArrayNotHasKey('transitionduration', $decodedJson);
+ }
+}
diff --git a/app/code/Magento/Catalog/view/frontend/layout/catalog_product_view.xml b/app/code/Magento/Catalog/view/frontend/layout/catalog_product_view.xml
index 8d3248896b434..4283e3be5a9bf 100644
--- a/app/code/Magento/Catalog/view/frontend/layout/catalog_product_view.xml
+++ b/app/code/Magento/Catalog/view/frontend/layout/catalog_product_view.xml
@@ -121,7 +121,11 @@
-
+
+
+ Magento\Catalog\Block\Product\View\GalleryOptions
+
+
diff --git a/app/code/Magento/Catalog/view/frontend/templates/product/view/gallery.phtml b/app/code/Magento/Catalog/view/frontend/templates/product/view/gallery.phtml
index 1bfa30478df8a..a810dc2916152 100644
--- a/app/code/Magento/Catalog/view/frontend/templates/product/view/gallery.phtml
+++ b/app/code/Magento/Catalog/view/frontend/templates/product/view/gallery.phtml
@@ -45,44 +45,8 @@
"mixins":["magnifier/magnify"],
"magnifierOpts": = /* @escapeNotVerified */ $block->getMagnifier() ?>,
"data": = /* @escapeNotVerified */ $block->getGalleryImagesJson() ?>,
- "options": {
- "nav": "= /* @escapeNotVerified */ $block->getVar("gallery/nav") ?>",
- "loop": = /* @escapeNotVerified */ $block->getVar("gallery/loop") ? 'true' : 'false' ?>,
- "keyboard": = /* @escapeNotVerified */ $block->getVar("gallery/keyboard") ? 'true' : 'false' ?>,
- "arrows": = /* @escapeNotVerified */ $block->getVar("gallery/arrows") ? 'true' : 'false' ?>,
- "allowfullscreen": = /* @escapeNotVerified */ $block->getVar("gallery/allowfullscreen") ? 'true' : 'false' ?>,
- "showCaption": = /* @escapeNotVerified */ $block->getVar("gallery/caption") ? 'true' : 'false' ?>,
- "width": "= /* @escapeNotVerified */ $block->getImageAttribute('product_page_image_medium', 'width') ?>",
- "thumbwidth": "= /* @escapeNotVerified */ $block->getImageAttribute('product_page_image_small', 'width') ?>",
- getImageAttribute('product_page_image_small', 'height') || $block->getImageAttribute('product_page_image_small', 'width')): ?>
- "thumbheight": getImageAttribute('product_page_image_small', 'height')
- ?: $block->getImageAttribute('product_page_image_small', 'width'); ?>,
-
- getImageAttribute('product_page_image_medium', 'height') || $block->getImageAttribute('product_page_image_medium', 'width')): ?>
- "height": getImageAttribute('product_page_image_medium', 'height')
- ?: $block->getImageAttribute('product_page_image_medium', 'width'); ?>,
-
- getVar("gallery/transition/duration")): ?>
- "transitionduration": = /* @escapeNotVerified */ $block->getVar("gallery/transition/duration") ?>,
-
- "transition": "= /* @escapeNotVerified */ $block->getVar("gallery/transition/effect") ?>",
- "navarrows": = /* @escapeNotVerified */ $block->getVar("gallery/navarrows") ? 'true' : 'false' ?>,
- "navtype": "= /* @escapeNotVerified */ $block->getVar("gallery/navtype") ?>",
- "navdir": "= /* @escapeNotVerified */ $block->getVar("gallery/navdir") ?>"
- },
- "fullscreen": {
- "nav": "= /* @escapeNotVerified */ $block->getVar("gallery/fullscreen/nav") ?>",
- "loop": = /* @escapeNotVerified */ $block->getVar("gallery/fullscreen/loop") ? 'true' : 'false' ?>,
- "navdir": "= /* @escapeNotVerified */ $block->getVar("gallery/fullscreen/navdir") ?>",
- "navarrows": = /* @escapeNotVerified */ $block->getVar("gallery/fullscreen/navarrows") ? 'true' : 'false' ?>,
- "navtype": "= /* @escapeNotVerified */ $block->getVar("gallery/fullscreen/navtype") ?>",
- "arrows": = /* @escapeNotVerified */ $block->getVar("gallery/fullscreen/arrows") ? 'true' : 'false' ?>,
- "showCaption": = /* @escapeNotVerified */ $block->getVar("gallery/fullscreen/caption") ? 'true' : 'false' ?>,
- getVar("gallery/fullscreen/transition/duration")): ?>
- "transitionduration": = /* @escapeNotVerified */ $block->getVar("gallery/fullscreen/transition/duration") ?>,
-
- "transition": "= /* @escapeNotVerified */ $block->getVar("gallery/fullscreen/transition/effect") ?>"
- },
+ "options": = /* @noEscape */ $block->getGalleryOptions()->getOptionsJson() ?>,
+ "fullscreen": = /* @noEscape */ $block->getGalleryOptions()->getFSOptionsJson() ?>,
"breakpoints": = /* @escapeNotVerified */ $block->getBreakpoints() ?>
}
}