Skip to content

Commit 4e3a399

Browse files
Merge branch '2.4-develop' into cron-log
2 parents 15075d7 + 488c103 commit 4e3a399

File tree

236 files changed

+6588
-1192
lines changed

Some content is hidden

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

236 files changed

+6588
-1192
lines changed

app/code/Magento/Backend/Test/Mftf/ActionGroup/SecondaryGridActionGroup.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
</arguments>
2121

2222
<!-- search for the name -->
23+
<waitForElementClickable selector="{{AdminSecondaryGridSection.resetFilters}}" stepKey="waitForFiltersReset"/>
2324
<click stepKey="resetFilters" selector="{{AdminSecondaryGridSection.resetFilters}}"/>
2425
<fillField stepKey="fillIdentifier" selector="{{searchInput}}" userInput="{{name}}"/>
2526
<click stepKey="searchForName" selector="{{AdminSecondaryGridSection.searchButton}}"/>

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

Lines changed: 77 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -84,19 +84,29 @@ public function __construct(
8484
* Bulk options save
8585
*
8686
* @param ProductInterface $bundleProduct
87-
* @param OptionInterface[] $options
87+
* @param array $options
88+
* @param array $existingBundleProductOptions
8889
* @return void
8990
* @throws CouldNotSaveException
90-
* @throws NoSuchEntityException
9191
* @throws InputException
92+
* @throws NoSuchEntityException
9293
*/
93-
public function saveBulk(ProductInterface $bundleProduct, array $options): void
94-
{
94+
public function saveBulk(
95+
ProductInterface $bundleProduct,
96+
array $options,
97+
array $existingBundleProductOptions = []
98+
): void {
9599
$metadata = $this->metadataPool->getMetadata(ProductInterface::class);
96100
$optionCollection = $this->type->getOptionsCollection($bundleProduct);
97101

98102
foreach ($options as $option) {
99-
$this->saveOptionItem($bundleProduct, $option, $optionCollection, $metadata);
103+
$this->saveOptionItem(
104+
$bundleProduct,
105+
$option,
106+
$optionCollection,
107+
$metadata,
108+
$existingBundleProductOptions
109+
);
100110
}
101111

102112
$bundleProduct->setIsRelationsChanged(true);
@@ -109,42 +119,42 @@ public function saveBulk(ProductInterface $bundleProduct, array $options): void
109119
* @param OptionInterface $option
110120
* @param Collection $optionCollection
111121
* @param EntityMetadataInterface $metadata
122+
* @param array $existingBundleProductOptions
112123
* @return void
113124
* @throws CouldNotSaveException
114-
* @throws NoSuchEntityException
115125
* @throws InputException
126+
* @throws NoSuchEntityException
116127
*/
117128
private function saveOptionItem(
118129
ProductInterface $bundleProduct,
119130
OptionInterface $option,
120131
Collection $optionCollection,
121-
EntityMetadataInterface $metadata
132+
EntityMetadataInterface $metadata,
133+
array $existingBundleProductOptions = []
122134
) : void {
123135
$linksToAdd = [];
124136

125137
$option->setStoreId($bundleProduct->getStoreId());
126138
$parentId = $bundleProduct->getData($metadata->getLinkField());
127139
$option->setParentId($parentId);
128140
$optionId = $option->getOptionId();
141+
$existingOption = $this->retrieveExistingOption($optionCollection, $option, $existingBundleProductOptions);
129142

130-
/** @var \Magento\Bundle\Model\Option $existingOption */
131-
$existingOption = $optionCollection->getItemById($option->getOptionId())
132-
?? $optionCollection->getNewEmptyItem();
133143
if (!$optionId || $existingOption->getParentId() != $parentId) {
134144
$option->setOptionId(null);
135145
$option->setDefaultTitle($option->getTitle());
136146
if (is_array($option->getProductLinks())) {
137147
$linksToAdd = $option->getProductLinks();
138148
}
139149
} else {
140-
if (!$existingOption->getOptionId()) {
150+
if (!$existingOption || !$existingOption->getOptionId()) {
141151
throw new NoSuchEntityException(
142152
__("The option that was requested doesn't exist. Verify the entity and try again.")
143153
);
144154
}
145155

146156
$option->setData(array_merge($existingOption->getData(), $option->getData()));
147-
$this->updateOptionSelection($bundleProduct, $option);
157+
$this->updateOptionSelection($bundleProduct, $option, $existingOption);
148158
}
149159

150160
try {
@@ -183,15 +193,21 @@ public function save(ProductInterface $bundleProduct, OptionInterface $option)
183193
*
184194
* @param ProductInterface $product
185195
* @param OptionInterface $option
196+
* @param OptionInterface|null $existingOption
186197
* @return void
198+
* @throws CouldNotSaveException
199+
* @throws InputException
200+
* @throws NoSuchEntityException
187201
*/
188-
private function updateOptionSelection(ProductInterface $product, OptionInterface $option)
189-
{
190-
$optionId = $option->getOptionId();
191-
$existingLinks = $this->linkManagement->getChildren($product->getSku(), $optionId);
202+
private function updateOptionSelection(
203+
ProductInterface $product,
204+
OptionInterface $option,
205+
?OptionInterface $existingOption = null
206+
):void {
192207
$linksToAdd = [];
193208
$linksToUpdate = [];
194209
$linksToDelete = [];
210+
195211
if (is_array($option->getProductLinks())) {
196212
$productLinks = $option->getProductLinks();
197213
foreach ($productLinks as $productLink) {
@@ -201,20 +217,24 @@ private function updateOptionSelection(ProductInterface $product, OptionInterfac
201217
$linksToUpdate[] = $productLink;
202218
}
203219
}
204-
/** @var LinkInterface[] $linksToDelete */
205-
$linksToDelete = $this->compareLinks($existingLinks, $linksToUpdate);
206-
$linksToUpdate = $this->verifyLinksToUpdate($existingLinks, $linksToUpdate);
220+
if (!empty($existingOption) && !empty($existingOption->getProductLinks())) {
221+
$linksToDelete = $this->compareLinks($existingOption->getProductLinks(), $linksToUpdate);
222+
$linksToUpdate = $this->verifyLinksToUpdate($existingOption->getProductLinks(), $linksToUpdate);
223+
}
207224
}
225+
208226
foreach ($linksToUpdate as $linkedProduct) {
209227
$this->linkManagement->saveChild($product->getSku(), $linkedProduct);
210228
}
229+
211230
foreach ($linksToDelete as $linkedProduct) {
212231
$this->linkManagement->removeChild(
213232
$product->getSku(),
214233
$option->getOptionId(),
215234
$linkedProduct->getSku()
216235
);
217236
}
237+
218238
$this->addChildren->addChildren($product, (int)$option->getOptionId(), $linksToAdd);
219239
}
220240

@@ -300,4 +320,42 @@ private function compareLinks(array $firstArray, array $secondArray)
300320

301321
return $result;
302322
}
323+
324+
/**
325+
* Retrieve option from list.
326+
*
327+
* @param Collection $optionCollection
328+
* @param OptionInterface $option
329+
* @param array $existingBundleProductOptions
330+
* @return OptionInterface
331+
*/
332+
private function retrieveExistingOption(
333+
Collection $optionCollection,
334+
OptionInterface $option,
335+
array $existingBundleProductOptions
336+
): OptionInterface {
337+
$existingOption = $optionCollection->getItemById($option->getOptionId());
338+
339+
$incomingOption = current(
340+
array_filter($existingBundleProductOptions, function ($obj) use ($option) {
341+
return $obj->getData()['option_id'] == $option->getId();
342+
})
343+
);
344+
345+
if (!empty($incomingOption)) {
346+
$existingOption->setData(
347+
array_merge(
348+
$existingOption->getData(),
349+
$incomingOption->getData()
350+
)
351+
);
352+
}
353+
354+
// @phpstan-ignore-next-line
355+
if (empty($existingOption)) {
356+
$existingOption = $optionCollection->getNewEmptyItem();
357+
}
358+
359+
return $existingOption;
360+
}
303361
}

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

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
/**
2323
* Bundle product save handler
24+
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
2425
*/
2526
class SaveHandler implements ExtensionInterface
2627
{
@@ -107,8 +108,7 @@ public function execute($entity, $arguments = [])
107108

108109
if (!$entity->getCopyFromView()) {
109110
$this->processRemovedOptions($entity, $existingOptionsIds, $optionIds);
110-
$newOptionsIds = array_diff($optionIds, $existingOptionsIds);
111-
$this->saveOptions($entity, $bundleProductOptions, $newOptionsIds);
111+
$this->saveOptions($entity, $bundleProductOptions, $existingBundleProductOptions);
112112
} else {
113113
//save only labels and not selections + product links
114114
$this->saveOptions($entity, $bundleProductOptions);
@@ -150,20 +150,20 @@ protected function removeOptionLinks($entitySku, $option)
150150
/**
151151
* Perform save for all options entities.
152152
*
153-
* @param object $entity
153+
* @param ProductInterface $entity
154154
* @param array $options
155-
* @param array $newOptionsIds
156-
*
155+
* @param array $existingBundleProductOptions
157156
* @return void
157+
* @throws InputException
158+
* @throws NoSuchEntityException
159+
* @throws \Magento\Framework\Exception\CouldNotSaveException
158160
*/
159-
private function saveOptions($entity, array $options, array $newOptionsIds = []): void
160-
{
161-
foreach ($options as $option) {
162-
if (in_array($option->getOptionId(), $newOptionsIds)) {
163-
$option->setOptionId(null);
164-
}
165-
}
166-
$this->optionSave->saveBulk($entity, $options);
161+
private function saveOptions(
162+
ProductInterface $entity,
163+
array $options,
164+
array $existingBundleProductOptions = []
165+
): void {
166+
$this->optionSave->saveBulk($entity, $options, $existingBundleProductOptions);
167167
}
168168

169169
/**

0 commit comments

Comments
 (0)