Skip to content

Commit 9fa5cdf

Browse files
committed
Merge remote-tracking branch 'mainline/2.2-develop' into MAGETWO-90053
# Conflicts: # dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Catalog/ActionGroup/AddProductToCartActionGroup.xml
2 parents 88a774b + 9cfd602 commit 9fa5cdf

File tree

166 files changed

+3231
-598
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

166 files changed

+3231
-598
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ The members of this team have been recognized for their outstanding commitment t
3535
</a>
3636

3737
<h3>Top Contributors</h3>
38-
Magento team thanks for any contribution that can improve our code base, documentation or increase test coverage. We always recognize our most active members, your contributions are the foundation of the Magento open source platform.
38+
Magento is thankful for any contribution that can improve our code base, documentation or increase test coverage. We always recognize our most active members, as their contributions are the foundation of the Magento Open Source platform.
3939
<a href="https://magento.com/magento-contributors">
4040
<img src="https://raw.githubusercontent.com/wiki/magento/magento2/images/contributors.png"/>
4141
</a>

app/code/Magento/Backend/Block/GlobalSearch.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ public function getWidgetInitOptions()
7373
'filterProperty' => 'name',
7474
'preventClickPropagation' => false,
7575
'minLength' => 2,
76+
'submitInputOnEnter' => false,
7677
]
7778
];
7879
}

app/code/Magento/Braintree/Model/Adminhtml/System/Config/CountryCreditCard.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,13 @@ public function __construct(
6666
public function beforeSave()
6767
{
6868
$value = $this->getValue();
69+
if (!is_array($value)) {
70+
try {
71+
$value = $this->serializer->unserialize($value);
72+
} catch (\InvalidArgumentException $e) {
73+
$value = [];
74+
}
75+
}
6976
$result = [];
7077
foreach ($value as $data) {
7178
if (empty($data['country_id']) || empty($data['cc_types'])) {

app/code/Magento/Braintree/Model/AvsEmsCodeMapper.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ class AvsEmsCodeMapper implements PaymentVerificationInterface
2424
*
2525
* @var string
2626
*/
27-
private static $unavailableCode = 'U';
27+
private static $unavailableCode = '';
2828

2929
/**
3030
* List of mapping AVS codes

app/code/Magento/Braintree/Test/Unit/Model/AvsEmsCodeMapperTest.php

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -84,11 +84,11 @@ public function testGetCodeWithException()
8484
public function getCodeDataProvider()
8585
{
8686
return [
87-
['avsZip' => null, 'avsStreet' => null, 'expected' => 'U'],
88-
['avsZip' => null, 'avsStreet' => 'M', 'expected' => 'U'],
89-
['avsZip' => 'M', 'avsStreet' => null, 'expected' => 'U'],
90-
['avsZip' => 'M', 'avsStreet' => 'Unknown', 'expected' => 'U'],
91-
['avsZip' => 'I', 'avsStreet' => 'A', 'expected' => 'U'],
87+
['avsZip' => null, 'avsStreet' => null, 'expected' => ''],
88+
['avsZip' => null, 'avsStreet' => 'M', 'expected' => ''],
89+
['avsZip' => 'M', 'avsStreet' => null, 'expected' => ''],
90+
['avsZip' => 'M', 'avsStreet' => 'Unknown', 'expected' => ''],
91+
['avsZip' => 'I', 'avsStreet' => 'A', 'expected' => ''],
9292
['avsZip' => 'M', 'avsStreet' => 'M', 'expected' => 'Y'],
9393
['avsZip' => 'N', 'avsStreet' => 'M', 'expected' => 'A'],
9494
['avsZip' => 'M', 'avsStreet' => 'N', 'expected' => 'Z'],

app/code/Magento/Bundle/Controller/Adminhtml/Product/Initialization/Helper/Plugin/Bundle.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,8 +105,13 @@ public function afterInitialize(
105105
if ($result['bundle_options'] && !$compositeReadonly) {
106106
$product->setBundleOptionsData($result['bundle_options']);
107107
}
108+
108109
$this->processBundleOptionsData($product);
109110
$this->processDynamicOptionsData($product);
111+
} elseif (!$compositeReadonly) {
112+
$extension = $product->getExtensionAttributes();
113+
$extension->setBundleProductOptions([]);
114+
$product->setExtensionAttributes($extension);
110115
}
111116

112117
$affectProductSelections = (bool)$this->request->getPost('affect_bundle_product_selections');

app/code/Magento/Bundle/Model/OptionRepository.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -277,10 +277,11 @@ protected function updateOptionSelection(
277277
* @param string $sku
278278
* @return \Magento\Catalog\Api\Data\ProductInterface
279279
* @throws \Magento\Framework\Exception\InputException
280+
* @throws \Magento\Framework\Exception\NoSuchEntityException
280281
*/
281282
private function getProduct($sku)
282283
{
283-
$product = $this->productRepository->get($sku, true);
284+
$product = $this->productRepository->get($sku, true, null, true);
284285
if ($product->getTypeId() != \Magento\Catalog\Model\Product\Type::TYPE_BUNDLE) {
285286
throw new InputException(__('Only implemented for bundle product'));
286287
}

app/code/Magento/Bundle/Model/Product/SaveHandler.php

Lines changed: 87 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
*/
66
namespace Magento\Bundle\Model\Product;
77

8-
use Magento\Catalog\Api\Data\ProductInterface;
98
use Magento\Bundle\Api\ProductOptionRepositoryInterface as OptionRepository;
109
use Magento\Bundle\Api\ProductLinkManagementInterface;
1110
use Magento\Framework\App\ObjectManager;
@@ -53,50 +52,50 @@ public function __construct(
5352
* @param object $entity
5453
* @param array $arguments
5554
* @return \Magento\Catalog\Api\Data\ProductInterface|object
55+
* @throws \Magento\Framework\Exception\NoSuchEntityException
56+
* @throws \Magento\Framework\Exception\InputException
57+
* @throws \Magento\Framework\Exception\CouldNotSaveException
5658
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
5759
*/
5860
public function execute($entity, $arguments = [])
5961
{
6062
/** @var \Magento\Bundle\Api\Data\OptionInterface[] $options */
61-
$options = $entity->getExtensionAttributes()->getBundleProductOptions() ?: [];
63+
$bundleProductOptions = $entity->getExtensionAttributes()->getBundleProductOptions() ?: [];
6264

63-
if ($entity->getTypeId() !== 'bundle' || empty($options)) {
65+
if ($entity->getTypeId() !== Type::TYPE_CODE || empty($bundleProductOptions)) {
6466
return $entity;
6567
}
6668

67-
if (!$entity->getCopyFromView()) {
68-
$updatedOptions = [];
69-
$oldOptions = $this->optionRepository->getList($entity->getSku());
70-
71-
$metadata = $this->metadataPool->getMetadata(ProductInterface::class);
69+
$existingBundleProductOptions = $this->optionRepository->getList($entity->getSku());
7270

73-
$productId = $entity->getData($metadata->getLinkField());
71+
$existingOptionsIds = !empty($existingBundleProductOptions)
72+
? $this->getOptionIds($existingBundleProductOptions)
73+
: [];
74+
$optionIds = !empty($bundleProductOptions)
75+
? $this->getOptionIds($bundleProductOptions)
76+
: [];
7477

75-
foreach ($options as $option) {
76-
$updatedOptions[$option->getOptionId()][$productId] = (bool)$option->getOptionId();
77-
}
78-
79-
foreach ($oldOptions as $option) {
80-
if (!isset($updatedOptions[$option->getOptionId()][$productId])) {
81-
$option->setParentId($productId);
82-
$this->removeOptionLinks($entity->getSku(), $option);
83-
$this->optionRepository->delete($option);
84-
}
85-
}
86-
}
78+
$options = $bundleProductOptions ?: [];
8779

88-
foreach ($options as $option) {
89-
$this->optionRepository->save($entity, $option);
80+
if (!$entity->getCopyFromView()) {
81+
$this->processRemovedOptions($entity->getSku(), $existingOptionsIds, $optionIds);
82+
83+
$newOptionsIds = array_diff($optionIds, $existingOptionsIds);
84+
$this->saveOptions($entity, $options, $newOptionsIds);
85+
} else {
86+
//save only labels and not selections + product links
87+
$this->saveOptions($entity, $options);
88+
$entity->setCopyFromView(false);
9089
}
9190

92-
$entity->setCopyFromView(false);
93-
9491
return $entity;
9592
}
9693

9794
/**
9895
* @param string $entitySku
9996
* @param \Magento\Bundle\Api\Data\OptionInterface $option
97+
* @throws \Magento\Framework\Exception\NoSuchEntityException
98+
* @throws \Magento\Framework\Exception\InputException
10099
* @return void
101100
*/
102101
protected function removeOptionLinks($entitySku, $option)
@@ -108,4 +107,67 @@ protected function removeOptionLinks($entitySku, $option)
108107
}
109108
}
110109
}
110+
111+
/**
112+
* Perform save for all options entities
113+
*
114+
* @param object $entity
115+
* @param array $options
116+
* @param array $newOptionsIds
117+
* @throws \Magento\Framework\Exception\CouldNotSaveException
118+
* @throws \Magento\Framework\Exception\InputException
119+
* @return void
120+
*/
121+
private function saveOptions($entity, array $options, array $newOptionsIds = [])
122+
{
123+
foreach ($options as $option) {
124+
if (in_array($option->getOptionId(), $newOptionsIds, true)) {
125+
$option->setOptionId(null);
126+
}
127+
$this->optionRepository->save($entity, $option);
128+
}
129+
}
130+
131+
/**
132+
* Get options ids from array of the options entities
133+
*
134+
* @param array $options
135+
* @return array
136+
*/
137+
private function getOptionIds(array $options)
138+
{
139+
$optionIds = [];
140+
141+
if (empty($options)) {
142+
return $optionIds;
143+
}
144+
145+
/** @var \Magento\Bundle\Api\Data\OptionInterface $option */
146+
foreach ($options as $option) {
147+
if ($option->getOptionId()) {
148+
$optionIds[] = $option->getOptionId();
149+
}
150+
}
151+
return $optionIds;
152+
}
153+
154+
/**
155+
* Removes old options that no longer exists
156+
*
157+
* @param string $entitySku
158+
* @param array $existingOptionsIds
159+
* @param array $optionIds
160+
* @throws \Magento\Framework\Exception\NoSuchEntityException
161+
* @throws \Magento\Framework\Exception\InputException
162+
* @throws \Magento\Framework\Exception\CouldNotSaveException
163+
* @return void
164+
*/
165+
private function processRemovedOptions($entitySku, array $existingOptionsIds, array $optionIds)
166+
{
167+
foreach (array_diff($existingOptionsIds, $optionIds) as $optionId) {
168+
$option = $this->optionRepository->get($entitySku, $optionId);
169+
$this->removeOptionLinks($entitySku, $option);
170+
$this->optionRepository->delete($option);
171+
}
172+
}
111173
}

app/code/Magento/Bundle/Model/ResourceModel/Option.php

Lines changed: 14 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -81,39 +81,28 @@ protected function _afterSave(\Magento\Framework\Model\AbstractModel $object)
8181
{
8282
parent::_afterSave($object);
8383

84-
$conditions = [
84+
$condition = [
8585
'option_id = ?' => $object->getId(),
8686
'store_id = ? OR store_id = 0' => $object->getStoreId(),
8787
'parent_product_id = ?' => $object->getParentId()
8888
];
89-
9089
$connection = $this->getConnection();
90+
$connection->delete($this->getTable('catalog_product_bundle_option_value'), $condition);
9191

92-
if ($this->isOptionPresent($conditions)) {
93-
$connection->update(
94-
$this->getTable('catalog_product_bundle_option_value'),
95-
[
96-
'title' => $object->getTitle()
97-
],
98-
$conditions
99-
);
100-
} else {
101-
$data = new \Magento\Framework\DataObject();
102-
$data->setOptionId($object->getId())
103-
->setStoreId($object->getStoreId())
104-
->setParentProductId($object->getParentId())
105-
->setTitle($object->getTitle());
92+
$data = new \Magento\Framework\DataObject();
93+
$data->setOptionId($object->getId())
94+
->setStoreId($object->getStoreId())
95+
->setParentProductId($object->getParentId())
96+
->setTitle($object->getTitle());
10697

107-
$connection->insert($this->getTable('catalog_product_bundle_option_value'), $data->getData());
98+
$connection->insert($this->getTable('catalog_product_bundle_option_value'), $data->getData());
10899

109-
/**
110-
* also saving default value if this store view scope
111-
*/
112-
if ($object->getStoreId()) {
113-
$data->setStoreId(0);
114-
$data->setTitle($object->getDefaultTitle());
115-
$connection->insert($this->getTable('catalog_product_bundle_option_value'), $data->getData());
116-
}
100+
/**
101+
* also saving default fallback value
102+
*/
103+
if (0 !== (int)$object->getStoreId()) {
104+
$data->setStoreId(0)->setTitle($object->getDefaultTitle());
105+
$connection->insert($this->getTable('catalog_product_bundle_option_value'), $data->getData());
117106
}
118107

119108
return $this;
@@ -218,26 +207,4 @@ public function save(\Magento\Framework\Model\AbstractModel $object)
218207

219208
return $this;
220209
}
221-
222-
/**
223-
* Is Bundle option present in the database
224-
*
225-
* @param array $conditions
226-
*
227-
* @return bool
228-
*/
229-
private function isOptionPresent($conditions)
230-
{
231-
$connection = $this->getConnection();
232-
233-
$select = $connection->select()->from($this->getTable('catalog_product_bundle_option_value'));
234-
foreach ($conditions as $condition => $conditionValue) {
235-
$select->where($condition, $conditionValue);
236-
}
237-
$select->limit(1);
238-
239-
$rowSelect = $connection->fetchRow($select);
240-
241-
return (is_array($rowSelect) && !empty($rowSelect));
242-
}
243210
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -356,7 +356,7 @@ public function getIdentities()
356356
* Get post parameters
357357
*
358358
* @param Product $product
359-
* @return string
359+
* @return array
360360
*/
361361
public function getAddToCartPostParams(Product $product)
362362
{

0 commit comments

Comments
 (0)