Skip to content

Commit

Permalink
MAGETWO-47017: [Github] Add Configurable Product To Cart from Categor…
Browse files Browse the repository at this point in the history
  • Loading branch information
Palamar, Mykola committed Oct 17, 2016
1 parent 492f0ca commit ac363e4
Show file tree
Hide file tree
Showing 28 changed files with 839 additions and 5 deletions.
2 changes: 1 addition & 1 deletion app/code/Magento/Catalog/Block/Product/AbstractProduct.php
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ public function __construct(\Magento\Catalog\Block\Product\Context $context, arr
*/
public function getAddToCartUrl($product, $additional = [])
{
if ($product->getTypeInstance()->hasRequiredOptions($product)) {
if (!$product->getTypeInstance()->isPossibleBuyFromList($product)) {
if (!isset($additional['_escape'])) {
$additional['_escape'] = true;
}
Expand Down
11 changes: 11 additions & 0 deletions app/code/Magento/Catalog/Model/Product/Type/AbstractType.php
Original file line number Diff line number Diff line change
Expand Up @@ -1092,4 +1092,15 @@ public function getAssociatedProducts($product)
{
return [];
}

/**
* Check if product can be potentially buyed from the category page or some other list
*
* @param \Magento\Catalog\Model\Product $product
* @return bool
*/
public function isPossibleBuyFromList($product)
{
return !$this->hasRequiredOptions($product);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,30 @@ define([
},

ajaxSubmit: function(form) {
var self = this;
var self = this,
swatchAttributesValue = [],
urlHashParams = '';
$(self.options.minicartSelector).trigger('contentLoading');
self.disableAddToCartButton(form);

$(form.prop("elements")).each(function(index, item){
item = $(item);
if (item.attr('name') && item.attr('name').search('super') != -1) {
var r = /\[(\d+)\]/;
var matches = r.exec(item.attr('name'));

if (matches) {
swatchAttributesValue.push(item.attr('data-attr-name') + '=' + item.val());
}
}
});

console.log(form.serialize());
if (swatchAttributesValue.length > 0) {
urlHashParams = '#' + swatchAttributesValue.join('&');
}


$.ajax({
url: form.attr('action'),
data: form.serialize(),
Expand All @@ -84,7 +104,7 @@ define([
}

if (res.backUrl) {
window.location = res.backUrl;
window.location = res.backUrl + urlHashParams;
return;
}
if (res.messages) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1287,4 +1287,19 @@ private function getCatalogConfig()
}
return $this->catalogConfig;
}

/**
* @inheritdoc
*/
public function isPossibleBuyFromList($product)
{
$isAllCustomOptionsDisplayed = true;
foreach ($this->getConfigurableAttributes($product) as $attribute) {
$eavAttribute = $attribute->getProductAttribute();

$isAllCustomOptionsDisplayed = ($isAllCustomOptionsDisplayed && $eavAttribute->getUsedInProductListing());
}

return $isAllCustomOptionsDisplayed;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,8 @@ define([
*/
_init: function () {
if (this.options.jsonConfig !== '' && this.options.jsonSwatchConfig !== '') {
// store unsorted attributes
this.options.jsonConfig.mappedAttributes = _.clone(this.options.jsonConfig.attributes);
this._sortAttributes();
this._RenderControls();
$(this.element).trigger('swatch.initialized');
Expand Down Expand Up @@ -617,6 +619,7 @@ define([
$parent.attr('option-selected', $this.attr('option-id')).find('.selected').removeClass('selected');
$label.text($this.attr('option-label'));
$input.val($this.attr('option-id'));
$input.attr('data-attr-name', this._getAttributeCodeById(attributeId));
$this.addClass('selected');
$widget._toggleCheckedAttributes($this, $wrapper);
}
Expand All @@ -633,6 +636,11 @@ define([
$input.trigger('change');
},

_getAttributeCodeById: function (attributeId) {
var attribute = this.options.jsonConfig.mappedAttributes[attributeId];
return attribute ? attribute.code : attributeId;
},

/**
* Toggle accessibility attributes
*
Expand Down Expand Up @@ -1104,7 +1112,7 @@ define([
params = $.parseQuery(window.location.href.substr(hashIndex + 1));

selectedAttributes = _.invert(_.mapObject(_.invert(params), function (attributeId) {
var attribute = this.options.jsonConfig.attributes[attributeId];
var attribute = this.options.jsonConfig.mappedAttributes[attributeId];

return attribute ? attribute.code : attributeId;
}.bind(this)));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,14 @@ class Curl extends AbstractCurl implements CatalogProductAttributeInterface
'No' => 0,
'Yes' => 1,
],
'is_global' => [
'Store View' => '0',
'Global' => '1',
],
'used_in_product_listing' => [
'No' => '0',
'Yes' => '1',
],
];

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

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

return $resultData;
}

/**
* @param array $data
* @return array
*/
protected function changeStructureOfTheData(array $data) {
return $data;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ protected function prepareConfigurableMatrix(FixtureInterface $product)
$keyIds[] = $attribute['options'][$optionKey]['id'];
$configurableAttribute[] = sprintf(
'"%s":"%s"',
$attribute['attribute_code'],
isset($attribute['attribute_code']) ? $attribute['attribute_code'] : $attribute['frontend_label'] ,
$attribute['options'][$optionKey]['id']
);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php
/**
* Copyright © 2016 Magento. All rights reserved.
* See COPYING.txt for license details.
*/

namespace Magento\Swatches\Test\Block\Product;

use Magento\Mtf\Client\Locator;
use Magento\Mtf\Fixture\FixtureInterface;
use Magento\Catalog\Test\Block\Product\ListProduct as CatalogListProduct;

/**
* Product list block.
*/
class ListProduct extends CatalogListProduct
{
/**
* @inheritdoc
*/
public function getProductItem(FixtureInterface $product)
{
$locator = sprintf($this->productItem, $product->getName());

return $this->blockFactory->create(
\Magento\Swatches\Test\Block\Product\ProductList\ProductItem::class,
['element' => $this->_rootElement->find($locator, Locator::SELECTOR_XPATH)]
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<?php
/**
* Copyright © 2016 Magento. All rights reserved.
* See COPYING.txt for license details.
*/

namespace Magento\Swatches\Test\Block\Product\ProductList;

use Magento\Mtf\Client\Locator;
use Magento\Catalog\Test\Block\Product\ProductList\ProductItem as CatalogProductItem;

/**
* Product item block on frontend category view.
*/
class ProductItem extends CatalogProductItem
{
/**
* @var string
*/
protected $swatchSelector = 'div[option-id="%s"]';

/**
* Fill product options on category page
*
* @param $product
*/
public function fillData($product) {
$checkoutData = $product->getCheckoutData();
$options = $checkoutData['options']['configurable_options'];
$confAttrData = $product->getDataFieldConfig('configurable_attributes_data');
$attributes = ($confAttrData['source'])->getAttributes();

foreach ($options as $option) {
$availableOptions = $attributes[$option['title']]->getOptions();
$optionForSelect = $availableOptions[str_replace('option_key_', '', $option['value'])];
$this->clickOnSwatch($optionForSelect['id']);
}
}

/**
* Click on swatch
*
* @param $optionId
*/
private function clickOnSwatch($optionId) {
$selector = sprintf($this->swatchSelector, $optionId);
$this->_rootElement->find($selector, Locator::SELECTOR_CSS)->click();
}

/**
* @inheritdoc
*/
public function clickAddToCart()
{
$this->_rootElement->hover();
parent::clickAddToCart();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php
/**
* Copyright © 2016 Magento. All rights reserved.
* See COPYING.txt for license details.
*/

namespace Magento\Swatches\Test\Fixture\Cart;

use Magento\ConfigurableProduct\Test\Fixture\Cart\Item as ConfigurableCart;

/**
* @inheritdoc
*/
class Item extends ConfigurableCart
{

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/**
* Copyright © 2016 Magento. All rights reserved.
* See COPYING.txt for license details.
*/
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/fixture.xsd">
<fixture
name="configurableProductSwatch"
module="Magento_Swatches"
class="Magento\Swatches\Test\Fixture\ConfigurableProduct"
extends="\Magento\ConfigurableProduct\Test\Fixture\ConfigurableProduct"
>
<!-- <field name="configurable_attributes_data" is_required="0" group="variations" source="Magento\Swatches\Test\Fixture\ConfigurableProduct\ConfigurableAttributesData" repository="Magento\ConfigurableProduct\Test\Repository\ConfigurableProduct\ConfigurableAttributesData" />-->
</fixture>
</config>
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php
/**
* Copyright © 2016 Magento. All rights reserved.
* See COPYING.txt for license details.
*/

namespace Magento\Swatches\Test\Fixture\ConfigurableProduct;

use Magento\ConfigurableProduct\Test\Fixture\ConfigurableProduct\ConfigurableAttributesData as
ConfigurableProductAttributesData;

/**
* Source configurable attributes data of the configurable products.
*/
class ConfigurableAttributesData extends ConfigurableProductAttributesData
{

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
/**
* Copyright © 2016 Magento. All rights reserved.
* See COPYING.txt for license details.
*/
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/etc/fixture.xsd">
<fixture name="swatchesProductAttribute"
module="Magento_Swatches"
handler_interface="Magento\Swatches\Test\Handler\SwatchProductAttribute\SwatchProductAttributeInterface"
repository_class="Magento\Swatches\Test\Repository\SwatchProductAttribute"
class="Magento\Swatches\Test\Fixture\CatalogProductAttribute"
extends="\Magento\Catalog\Test\Fixture\CatalogProductAttribute">
</fixture>
</config>
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<?php
/**
* Copyright © 2016 Magento. All rights reserved.
* See COPYING.txt for license details.
*/

namespace Magento\Swatches\Test\Handler\SwatchProductAttribute;

use Magento\Catalog\Test\Handler\CatalogProductAttribute\Curl as CatalogProductAttributeCurl;
use Magento\Mtf\Config\DataInterface;
use Magento\Mtf\System\Event\EventManagerInterface;

/**
* Class Curl
* Curl handler for creating Swatch Attribute
*/
class Curl extends CatalogProductAttributeCurl implements SwatchProductAttributeInterface
{
/**
* Add mapping data related to swatches
*
* @param DataInterface $configuration
* @param EventManagerInterface $eventManager
*/
public function __construct(DataInterface $configuration, EventManagerInterface $eventManager)
{
$this->mappingData['frontend_input'] = [
'Text Swatch' => 'swatch_text',
];

parent::__construct($configuration, $eventManager);
}

/**
* Re-map options from default options structure to swatches structure
*
* @param array $data
* @return array
*/
protected function changeStructureOfTheData(array $data) {
$data['optiontext'] = $data['option'];
$data['swatchtext'] = [
'value' => $data['option']['value']
];
unset($data['option']);
return $data;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<?php
/**
* Copyright © 2016 Magento. All rights reserved.
* See COPYING.txt for license details.
*/

namespace Magento\Swatches\Test\Handler\SwatchProductAttribute;

use Magento\Mtf\Handler\HandlerInterface;

/**
* Interface for swatch specific Curl calls
*/
interface SwatchProductAttributeInterface extends HandlerInterface
{
}
Loading

1 comment on commit ac363e4

@marcosdsdba
Copy link

@marcosdsdba marcosdsdba commented on ac363e4 Feb 24, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @palamar ,

Could help me please !!!

I thing take these files to use in my Magento, but , in moment to running magento setup:upgrade , returns error: Autoload error: Module 'Magento_Catalog' from '/var/www/html/app/code/Magento/Catalog' has been already defined in '/var/www/html/vendor/magento/module-catalog'.

What i need is send bundle direct to cart on grid or list page .

I observe than methods references to cited in #2434 , Methods setTypeHasRequiredOptions (false) and setRequiredOptions(false) do not exist !!!

Sorry, I send a message over here !!!

Thanks !!!

Please sign in to comment.