Skip to content

Commit ac363e4

Browse files
author
Palamar, Mykola
committed
MAGETWO-47017: [Github] Add Configurable Product To Cart from Category Page #2574 #5850 #5882 #6572 #5558
1 parent 492f0ca commit ac363e4

File tree

28 files changed

+839
-5
lines changed

28 files changed

+839
-5
lines changed

app/code/Magento/Catalog/Block/Product/AbstractProduct.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ public function __construct(\Magento\Catalog\Block\Product\Context $context, arr
124124
*/
125125
public function getAddToCartUrl($product, $additional = [])
126126
{
127-
if ($product->getTypeInstance()->hasRequiredOptions($product)) {
127+
if (!$product->getTypeInstance()->isPossibleBuyFromList($product)) {
128128
if (!isset($additional['_escape'])) {
129129
$additional['_escape'] = true;
130130
}

app/code/Magento/Catalog/Model/Product/Type/AbstractType.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1092,4 +1092,15 @@ public function getAssociatedProducts($product)
10921092
{
10931093
return [];
10941094
}
1095+
1096+
/**
1097+
* Check if product can be potentially buyed from the category page or some other list
1098+
*
1099+
* @param \Magento\Catalog\Model\Product $product
1100+
* @return bool
1101+
*/
1102+
public function isPossibleBuyFromList($product)
1103+
{
1104+
return !$this->hasRequiredOptions($product);
1105+
}
10951106
}

app/code/Magento/Catalog/view/frontend/web/js/catalog-add-to-cart.js

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,10 +64,30 @@ define([
6464
},
6565

6666
ajaxSubmit: function(form) {
67-
var self = this;
67+
var self = this,
68+
swatchAttributesValue = [],
69+
urlHashParams = '';
6870
$(self.options.minicartSelector).trigger('contentLoading');
6971
self.disableAddToCartButton(form);
7072

73+
$(form.prop("elements")).each(function(index, item){
74+
item = $(item);
75+
if (item.attr('name') && item.attr('name').search('super') != -1) {
76+
var r = /\[(\d+)\]/;
77+
var matches = r.exec(item.attr('name'));
78+
79+
if (matches) {
80+
swatchAttributesValue.push(item.attr('data-attr-name') + '=' + item.val());
81+
}
82+
}
83+
});
84+
85+
console.log(form.serialize());
86+
if (swatchAttributesValue.length > 0) {
87+
urlHashParams = '#' + swatchAttributesValue.join('&');
88+
}
89+
90+
7191
$.ajax({
7292
url: form.attr('action'),
7393
data: form.serialize(),
@@ -84,7 +104,7 @@ define([
84104
}
85105

86106
if (res.backUrl) {
87-
window.location = res.backUrl;
107+
window.location = res.backUrl + urlHashParams;
88108
return;
89109
}
90110
if (res.messages) {

app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable.php

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1287,4 +1287,19 @@ private function getCatalogConfig()
12871287
}
12881288
return $this->catalogConfig;
12891289
}
1290+
1291+
/**
1292+
* @inheritdoc
1293+
*/
1294+
public function isPossibleBuyFromList($product)
1295+
{
1296+
$isAllCustomOptionsDisplayed = true;
1297+
foreach ($this->getConfigurableAttributes($product) as $attribute) {
1298+
$eavAttribute = $attribute->getProductAttribute();
1299+
1300+
$isAllCustomOptionsDisplayed = ($isAllCustomOptionsDisplayed && $eavAttribute->getUsedInProductListing());
1301+
}
1302+
1303+
return $isAllCustomOptionsDisplayed;
1304+
}
12901305
}

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

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,8 @@ define([
264264
*/
265265
_init: function () {
266266
if (this.options.jsonConfig !== '' && this.options.jsonSwatchConfig !== '') {
267+
// store unsorted attributes
268+
this.options.jsonConfig.mappedAttributes = _.clone(this.options.jsonConfig.attributes);
267269
this._sortAttributes();
268270
this._RenderControls();
269271
$(this.element).trigger('swatch.initialized');
@@ -617,6 +619,7 @@ define([
617619
$parent.attr('option-selected', $this.attr('option-id')).find('.selected').removeClass('selected');
618620
$label.text($this.attr('option-label'));
619621
$input.val($this.attr('option-id'));
622+
$input.attr('data-attr-name', this._getAttributeCodeById(attributeId));
620623
$this.addClass('selected');
621624
$widget._toggleCheckedAttributes($this, $wrapper);
622625
}
@@ -633,6 +636,11 @@ define([
633636
$input.trigger('change');
634637
},
635638

639+
_getAttributeCodeById: function (attributeId) {
640+
var attribute = this.options.jsonConfig.mappedAttributes[attributeId];
641+
return attribute ? attribute.code : attributeId;
642+
},
643+
636644
/**
637645
* Toggle accessibility attributes
638646
*
@@ -1104,7 +1112,7 @@ define([
11041112
params = $.parseQuery(window.location.href.substr(hashIndex + 1));
11051113

11061114
selectedAttributes = _.invert(_.mapObject(_.invert(params), function (attributeId) {
1107-
var attribute = this.options.jsonConfig.attributes[attributeId];
1115+
var attribute = this.options.jsonConfig.mappedAttributes[attributeId];
11081116

11091117
return attribute ? attribute.code : attributeId;
11101118
}.bind(this)));

dev/tests/functional/tests/app/Magento/Catalog/Test/Handler/CatalogProductAttribute/Curl.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,14 @@ class Curl extends AbstractCurl implements CatalogProductAttributeInterface
4747
'No' => 0,
4848
'Yes' => 1,
4949
],
50+
'is_global' => [
51+
'Store View' => '0',
52+
'Global' => '1',
53+
],
54+
'used_in_product_listing' => [
55+
'No' => '0',
56+
'Yes' => '1',
57+
],
5058
];
5159

5260
/**
@@ -76,6 +84,7 @@ public function persist(FixtureInterface $fixture = null)
7684
unset($data['options']);
7785
}
7886

87+
$data = $this->changeStructureOfTheData($data);
7988
$url = $_ENV['app_backend_url'] . 'catalog/product_attribute/save/back/edit';
8089
$curl = new BackendDecorator(new CurlTransport(), $this->_configuration);
8190
$curl->write($url, $data);
@@ -104,4 +113,12 @@ public function persist(FixtureInterface $fixture = null)
104113

105114
return $resultData;
106115
}
116+
117+
/**
118+
* @param array $data
119+
* @return array
120+
*/
121+
protected function changeStructureOfTheData(array $data) {
122+
return $data;
123+
}
107124
}

dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Handler/ConfigurableProduct/Curl.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ protected function prepareConfigurableMatrix(FixtureInterface $product)
172172
$keyIds[] = $attribute['options'][$optionKey]['id'];
173173
$configurableAttribute[] = sprintf(
174174
'"%s":"%s"',
175-
$attribute['attribute_code'],
175+
isset($attribute['attribute_code']) ? $attribute['attribute_code'] : $attribute['frontend_label'] ,
176176
$attribute['options'][$optionKey]['id']
177177
);
178178
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?php
2+
/**
3+
* Copyright © 2016 Magento. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
namespace Magento\Swatches\Test\Block\Product;
8+
9+
use Magento\Mtf\Client\Locator;
10+
use Magento\Mtf\Fixture\FixtureInterface;
11+
use Magento\Catalog\Test\Block\Product\ListProduct as CatalogListProduct;
12+
13+
/**
14+
* Product list block.
15+
*/
16+
class ListProduct extends CatalogListProduct
17+
{
18+
/**
19+
* @inheritdoc
20+
*/
21+
public function getProductItem(FixtureInterface $product)
22+
{
23+
$locator = sprintf($this->productItem, $product->getName());
24+
25+
return $this->blockFactory->create(
26+
\Magento\Swatches\Test\Block\Product\ProductList\ProductItem::class,
27+
['element' => $this->_rootElement->find($locator, Locator::SELECTOR_XPATH)]
28+
);
29+
}
30+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
<?php
2+
/**
3+
* Copyright © 2016 Magento. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
namespace Magento\Swatches\Test\Block\Product\ProductList;
8+
9+
use Magento\Mtf\Client\Locator;
10+
use Magento\Catalog\Test\Block\Product\ProductList\ProductItem as CatalogProductItem;
11+
12+
/**
13+
* Product item block on frontend category view.
14+
*/
15+
class ProductItem extends CatalogProductItem
16+
{
17+
/**
18+
* @var string
19+
*/
20+
protected $swatchSelector = 'div[option-id="%s"]';
21+
22+
/**
23+
* Fill product options on category page
24+
*
25+
* @param $product
26+
*/
27+
public function fillData($product) {
28+
$checkoutData = $product->getCheckoutData();
29+
$options = $checkoutData['options']['configurable_options'];
30+
$confAttrData = $product->getDataFieldConfig('configurable_attributes_data');
31+
$attributes = ($confAttrData['source'])->getAttributes();
32+
33+
foreach ($options as $option) {
34+
$availableOptions = $attributes[$option['title']]->getOptions();
35+
$optionForSelect = $availableOptions[str_replace('option_key_', '', $option['value'])];
36+
$this->clickOnSwatch($optionForSelect['id']);
37+
}
38+
}
39+
40+
/**
41+
* Click on swatch
42+
*
43+
* @param $optionId
44+
*/
45+
private function clickOnSwatch($optionId) {
46+
$selector = sprintf($this->swatchSelector, $optionId);
47+
$this->_rootElement->find($selector, Locator::SELECTOR_CSS)->click();
48+
}
49+
50+
/**
51+
* @inheritdoc
52+
*/
53+
public function clickAddToCart()
54+
{
55+
$this->_rootElement->hover();
56+
parent::clickAddToCart();
57+
}
58+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?php
2+
/**
3+
* Copyright © 2016 Magento. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
namespace Magento\Swatches\Test\Fixture\Cart;
8+
9+
use Magento\ConfigurableProduct\Test\Fixture\Cart\Item as ConfigurableCart;
10+
11+
/**
12+
* @inheritdoc
13+
*/
14+
class Item extends ConfigurableCart
15+
{
16+
17+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<!--
3+
/**
4+
* Copyright © 2016 Magento. All rights reserved.
5+
* See COPYING.txt for license details.
6+
*/
7+
-->
8+
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/fixture.xsd">
9+
<fixture
10+
name="configurableProductSwatch"
11+
module="Magento_Swatches"
12+
class="Magento\Swatches\Test\Fixture\ConfigurableProduct"
13+
extends="\Magento\ConfigurableProduct\Test\Fixture\ConfigurableProduct"
14+
>
15+
<!-- <field name="configurable_attributes_data" is_required="0" group="variations" source="Magento\Swatches\Test\Fixture\ConfigurableProduct\ConfigurableAttributesData" repository="Magento\ConfigurableProduct\Test\Repository\ConfigurableProduct\ConfigurableAttributesData" />-->
16+
</fixture>
17+
</config>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?php
2+
/**
3+
* Copyright © 2016 Magento. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
namespace Magento\Swatches\Test\Fixture\ConfigurableProduct;
8+
9+
use Magento\ConfigurableProduct\Test\Fixture\ConfigurableProduct\ConfigurableAttributesData as
10+
ConfigurableProductAttributesData;
11+
12+
/**
13+
* Source configurable attributes data of the configurable products.
14+
*/
15+
class ConfigurableAttributesData extends ConfigurableProductAttributesData
16+
{
17+
18+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<!--
3+
/**
4+
* Copyright © 2016 Magento. All rights reserved.
5+
* See COPYING.txt for license details.
6+
*/
7+
-->
8+
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/fixture.xsd">
9+
<fixture name="swatchesProductAttribute"
10+
module="Magento_Swatches"
11+
handler_interface="Magento\Swatches\Test\Handler\SwatchProductAttribute\SwatchProductAttributeInterface"
12+
repository_class="Magento\Swatches\Test\Repository\SwatchProductAttribute"
13+
class="Magento\Swatches\Test\Fixture\CatalogProductAttribute"
14+
extends="\Magento\Catalog\Test\Fixture\CatalogProductAttribute">
15+
</fixture>
16+
</config>
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<?php
2+
/**
3+
* Copyright © 2016 Magento. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
namespace Magento\Swatches\Test\Handler\SwatchProductAttribute;
8+
9+
use Magento\Catalog\Test\Handler\CatalogProductAttribute\Curl as CatalogProductAttributeCurl;
10+
use Magento\Mtf\Config\DataInterface;
11+
use Magento\Mtf\System\Event\EventManagerInterface;
12+
13+
/**
14+
* Class Curl
15+
* Curl handler for creating Swatch Attribute
16+
*/
17+
class Curl extends CatalogProductAttributeCurl implements SwatchProductAttributeInterface
18+
{
19+
/**
20+
* Add mapping data related to swatches
21+
*
22+
* @param DataInterface $configuration
23+
* @param EventManagerInterface $eventManager
24+
*/
25+
public function __construct(DataInterface $configuration, EventManagerInterface $eventManager)
26+
{
27+
$this->mappingData['frontend_input'] = [
28+
'Text Swatch' => 'swatch_text',
29+
];
30+
31+
parent::__construct($configuration, $eventManager);
32+
}
33+
34+
/**
35+
* Re-map options from default options structure to swatches structure
36+
*
37+
* @param array $data
38+
* @return array
39+
*/
40+
protected function changeStructureOfTheData(array $data) {
41+
$data['optiontext'] = $data['option'];
42+
$data['swatchtext'] = [
43+
'value' => $data['option']['value']
44+
];
45+
unset($data['option']);
46+
return $data;
47+
}
48+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<?php
2+
/**
3+
* Copyright © 2016 Magento. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
namespace Magento\Swatches\Test\Handler\SwatchProductAttribute;
8+
9+
use Magento\Mtf\Handler\HandlerInterface;
10+
11+
/**
12+
* Interface for swatch specific Curl calls
13+
*/
14+
interface SwatchProductAttributeInterface extends HandlerInterface
15+
{
16+
}

0 commit comments

Comments
 (0)