Skip to content

Commit 0a8d6e0

Browse files
committed
Merge branch '2.4-develop' of https://github.com/magento-commerce/magento2ce into ACP2E-4058
2 parents 3dffdfe + fab20b0 commit 0a8d6e0

File tree

65 files changed

+1501
-323
lines changed

Some content is hidden

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

65 files changed

+1501
-323
lines changed

app/code/Magento/AwsS3/Driver/AwsS3.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,9 @@ private function createDirectoryRecursively(string $path): bool
188188
$parentDir = dirname($path);
189189

190190
while (!$this->isDirectory($parentDir)) {
191-
$this->createDirectoryRecursively($parentDir);
191+
if (!$this->createDirectoryRecursively($parentDir)) {
192+
return false;
193+
}
192194
}
193195

194196
if (!$this->isDirectory($path)) {

app/code/Magento/AwsS3/Test/Unit/Driver/AwsS3Test.php

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
/**
2020
* @see AwsS3
21+
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
2122
*/
2223
class AwsS3Test extends TestCase
2324
{
@@ -497,6 +498,23 @@ public function testCreateDirectory(): void
497498
self::assertTrue($this->driver->createDirectory(self::URL . 'test/test2/'));
498499
}
499500

501+
/**
502+
* This test ensures that the method does not loop infinitely in case of an exception
503+
*
504+
* @return void
505+
* @throws FileSystemException
506+
* @throws \PHPUnit\Framework\MockObject\Exception
507+
*/
508+
public function testShouldFailSafelyIfUnableToCreateDirectory(): void
509+
{
510+
$this->adapterMock->expects(self::once())
511+
->method('createDirectory')
512+
->willThrowException($this->createMock(\League\Flysystem\FilesystemException::class))
513+
->with('test');
514+
515+
self::assertFalse($this->driver->createDirectory(self::URL . 'test/test2/'));
516+
}
517+
500518
public function testRename(): void
501519
{
502520
$this->adapterMock->expects(self::once())

app/code/Magento/Backend/Block/Store/Switcher.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -457,6 +457,15 @@ public function getCurrentSelectionName()
457457
if ($this->getCurrentWebsiteName() !== '') {
458458
return $this->getCurrentWebsiteName();
459459
}
460+
461+
if (!$this->hasDefaultOption()) {
462+
$websites = $this->getWebsites();
463+
if (!empty($websites)) {
464+
$websiteArray = array_values($websites);
465+
return $websiteArray[0]->getName();
466+
}
467+
}
468+
460469
return $this->getDefaultSelectionName();
461470
}
462471

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

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,14 @@
88
use Magento\Bundle\Api\Data\OptionInterfaceFactory as OptionFactory;
99
use Magento\Bundle\Api\Data\LinkInterfaceFactory as LinkFactory;
1010
use Magento\Catalog\Api\Data\ProductCustomOptionInterfaceFactory;
11+
use Magento\Catalog\Api\Data\ProductInterface;
1112
use Magento\Catalog\Api\ProductRepositoryInterface as ProductRepository;
1213
use Magento\Store\Model\StoreManagerInterface as StoreManager;
1314
use Magento\Framework\App\RequestInterface;
1415

1516
/**
16-
* Class Bundle
17+
* Plugin class to initialize Bundle product
18+
*
1719
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
1820
*/
1921
class Bundle
@@ -106,12 +108,14 @@ public function afterInitialize(
106108
$product->setBundleOptionsData($result['bundle_options']);
107109
}
108110

111+
if (!$result['bundle_selections']) {
112+
$this->resetBundleProductOptions($product);
113+
}
114+
109115
$this->processBundleOptionsData($product);
110116
$this->processDynamicOptionsData($product);
111117
} elseif (!$compositeReadonly) {
112-
$extension = $product->getExtensionAttributes();
113-
$extension->setBundleProductOptions([]);
114-
$product->setExtensionAttributes($extension);
118+
$this->resetBundleProductOptions($product);
115119
}
116120

117121
$affectProductSelections = (bool)$this->request->getPost('affect_bundle_product_selections');
@@ -120,6 +124,8 @@ public function afterInitialize(
120124
}
121125

122126
/**
127+
* Process Bundle Options Data
128+
*
123129
* @param \Magento\Catalog\Model\Product $product
124130
* @return void
125131
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
@@ -161,10 +167,11 @@ protected function processBundleOptionsData(\Magento\Catalog\Model\Product $prod
161167
$extension = $product->getExtensionAttributes();
162168
$extension->setBundleProductOptions($options);
163169
$product->setExtensionAttributes($extension);
164-
return;
165170
}
166171

167172
/**
173+
* Process Dynamic Options Data
174+
*
168175
* @param \Magento\Catalog\Model\Product $product
169176
* @return void
170177
*/
@@ -198,9 +205,10 @@ protected function processDynamicOptionsData(\Magento\Catalog\Model\Product $pro
198205
}
199206

200207
/**
208+
* Build product link
209+
*
201210
* @param \Magento\Catalog\Model\Product $product
202211
* @param array $linkData
203-
*
204212
* @return \Magento\Bundle\Api\Data\LinkInterface
205213
*/
206214
private function buildLink(
@@ -228,4 +236,18 @@ private function buildLink(
228236

229237
return $link;
230238
}
239+
240+
/**
241+
* Resets bundle product options inside product extension attributes
242+
*
243+
* @param ProductInterface $product
244+
* @return void
245+
*/
246+
private function resetBundleProductOptions(ProductInterface $product) : void
247+
{
248+
$extension = $product->getExtensionAttributes();
249+
$extension->setBundleProductOptions([]);
250+
$product->setExtensionAttributes($extension);
251+
$product->setDropOptions(true);
252+
}
231253
}

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,9 @@ public function execute($entity, $arguments = [])
9696
/** @var OptionInterface[] $bundleProductOptions */
9797
$bundleProductOptions = $entity->getExtensionAttributes()->getBundleProductOptions() ?: [];
9898
//Only processing bundle products.
99-
if ($entity->getTypeId() !== Type::TYPE_CODE || empty($bundleProductOptions)) {
99+
if ($entity->getTypeId() !== Type::TYPE_CODE
100+
|| (empty($bundleProductOptions) && !$entity->getDropOptions())
101+
) {
100102
return $entity;
101103
}
102104

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

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,13 @@ public function testAfterInitializeIfBundleSelectionsAndCustomOptionsExist()
173173
->method('setBundleOptionsData')
174174
->with($this->bundleOptionsCleaned);
175175
$this->productMock->expects($this->never())->method('setBundleSelectionsData');
176+
$extensionAttribute = $this->getMockBuilder(ProductExtensionInterface::class)
177+
->disableOriginalConstructor()
178+
->addMethods(['setBundleProductOptions'])
179+
->getMockForAbstractClass();
180+
$extensionAttribute->expects($this->once())->method('setBundleProductOptions')->with([]);
181+
$this->productMock->expects($this->once())->method('getExtensionAttributes')->willReturn($extensionAttribute);
182+
$this->productMock->expects($this->once())->method('setExtensionAttributes')->with($extensionAttribute);
176183
$this->productMock->expects($this->once())->method('getPriceType')->willReturn(2);
177184
$this->productMock->expects($this->any())->method('getOptionsReadonly')->willReturn(true);
178185
$this->productMock->expects($this->once())->method('setCanSaveBundleSelections')->with(false);

app/code/Magento/Catalog/Controller/Adminhtml/Product/Action/Attribute/Save.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ public function execute()
143143
$this->validateProductAttributes($attributesData);
144144
$this->publish($attributesData, $websiteRemoveData, $websiteAddData, $storeId, $websiteId, $productIds);
145145
$this->messageManager->addSuccessMessage(__('Message is added to queue'));
146+
$this->attributeHelper->setProductIds([]);
146147
} catch (LocalizedException $e) {
147148
$this->messageManager->addErrorMessage($e->getMessage());
148149
} catch (\Exception $e) {

app/code/Magento/Catalog/Model/ResourceModel/Product/Image.php

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,4 +184,22 @@ private function getUsedImagesSelect(): Select
184184

185185
return $select;
186186
}
187+
188+
/**
189+
* Get related website IDs for a given image file path.
190+
*
191+
* @param string $filepath
192+
* @return array
193+
*/
194+
public function getRelatedWebsiteIds(string $filepath): array
195+
{
196+
$select = $this->getUsedImagesSelect();
197+
$select->where('images.value = ?', $filepath);
198+
$result = array_map(
199+
fn ($ids) => array_map('intval', explode(',', $ids)),
200+
$this->connection->fetchPairs($select)
201+
);
202+
203+
return $result[$filepath] ?? [];
204+
}
187205
}

app/code/Magento/Catalog/Test/Mftf/Data/ProductAttributeData.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -486,5 +486,11 @@
486486
<data key="is_used_for_promo_rules">true</data>
487487
<requiredEntity type="FrontendLabel">ProductAttributeFrontendLabel</requiredEntity>
488488
</entity>
489+
<entity name="multiSelectAttributeWithThreeOptions" extends="productDropDownAttribute" type="ProductAttribute">
490+
<data key="frontend_input">multiselect</data>
491+
<data key="option1">1</data>
492+
<data key="option2">2</data>
493+
<data key="option3">3</data>
494+
</entity>
489495
</entities>
490496

app/code/Magento/Catalog/Test/Mftf/Section/AdminProductFormSection/AdminProductFormSection.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,5 +92,6 @@
9292
<element name="customSelectAttribute" type="select" selector="//select[@name='product[{{attribute_code}}]']" parameterized="true"/>
9393
<element name="customSwitcherAttribute" type="checkbox" selector="//input[@name='product[{{attribute_code}}]' and @value='{{checked_value}}']/parent::div[@data-role='switcher']" parameterized="true"/>
9494
<element name="attributeOptionUncheckDefaultValue" type="checkbox" selector="input[name='use_default[{{attribute_code}}]']" parameterized="true"/>
95+
<element name="customAttributeUnderMassUpdate" type="select" selector="//select[@name='attributes[{{attribute_code}}][]']" parameterized="true"/>
9596
</section>
9697
</sections>

0 commit comments

Comments
 (0)