Skip to content

Commit 57440a7

Browse files
committed
Merge remote-tracking branch 'mainline/2.2-develop' into MPI-BUGFIXES
2 parents 2b9631a + a9a51f6 commit 57440a7

File tree

33 files changed

+774
-151
lines changed

33 files changed

+774
-151
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/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/Checkout/view/frontend/web/js/model/step-navigator.js

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,15 @@ define([
182182
});
183183
},
184184

185+
/**
186+
* Sets window location hash.
187+
*
188+
* @param {String} hash
189+
*/
190+
setHash: function (hash) {
191+
window.location.hash = hash;
192+
},
193+
185194
/**
186195
* Next step.
187196
*/
@@ -199,7 +208,7 @@ define([
199208
if (steps().length > activeIndex + 1) {
200209
code = steps()[activeIndex + 1].code;
201210
steps()[activeIndex + 1].isVisible(true);
202-
window.location = window.checkoutConfig.checkoutUrl + '#' + code;
211+
this.setHash(code);
203212
document.body.scrollTop = document.documentElement.scrollTop = 0;
204213
}
205214
}

app/code/Magento/Checkout/view/frontend/web/js/view/progress-bar.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,11 @@ define([
2626
initialize: function () {
2727
this._super();
2828
$(window).hashchange(_.bind(stepNavigator.handleHash, stepNavigator));
29+
30+
if (!window.location.hash) {
31+
stepNavigator.setHash(stepNavigator.steps().sort(stepNavigator.sortItems)[0].code);
32+
}
33+
2934
stepNavigator.handleHash();
3035
},
3136

app/code/Magento/CheckoutAgreements/Block/Adminhtml/Agreement/Grid.php

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,27 +5,42 @@
55
*/
66
namespace Magento\CheckoutAgreements\Block\Adminhtml\Agreement;
77

8+
use Magento\Framework\App\ObjectManager;
9+
use Magento\CheckoutAgreements\Model\ResourceModel\Agreement\Grid\CollectionFactory as GridCollectionFactory;
10+
811
class Grid extends \Magento\Backend\Block\Widget\Grid\Extended
912
{
1013
/**
1114
* @var \Magento\CheckoutAgreements\Model\ResourceModel\Agreement\CollectionFactory
15+
* @deprecated
1216
*/
1317
protected $_collectionFactory;
1418

19+
/**
20+
* @param GridCollectionFactory
21+
*/
22+
private $gridCollectionFactory;
23+
1524
/**
1625
* @param \Magento\Backend\Block\Template\Context $context
1726
* @param \Magento\Backend\Helper\Data $backendHelper
1827
* @param \Magento\CheckoutAgreements\Model\ResourceModel\Agreement\CollectionFactory $collectionFactory
1928
* @param array $data
29+
* @param GridCollectionFactory $gridColFactory
2030
* @codeCoverageIgnore
2131
*/
2232
public function __construct(
2333
\Magento\Backend\Block\Template\Context $context,
2434
\Magento\Backend\Helper\Data $backendHelper,
2535
\Magento\CheckoutAgreements\Model\ResourceModel\Agreement\CollectionFactory $collectionFactory,
26-
array $data = []
36+
array $data = [],
37+
GridCollectionFactory $gridColFactory = null
2738
) {
39+
2840
$this->_collectionFactory = $collectionFactory;
41+
$this->gridCollectionFactory = $gridColFactory
42+
? : ObjectManager::getInstance()->get(GridCollectionFactory::class);
43+
2944
parent::__construct($context, $backendHelper, $data);
3045
}
3146

@@ -47,7 +62,7 @@ protected function _construct()
4762
*/
4863
protected function _prepareCollection()
4964
{
50-
$this->setCollection($this->_collectionFactory->create());
65+
$this->setCollection($this->gridCollectionFactory->create());
5166
return parent::_prepareCollection();
5267
}
5368

0 commit comments

Comments
 (0)