Skip to content

Commit 0d97464

Browse files
authored
Merge branch '2.4-develop' into fix-26976
2 parents 818a7fa + e1c5c1d commit 0d97464

File tree

240 files changed

+4752
-1671
lines changed

Some content is hidden

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

240 files changed

+4752
-1671
lines changed
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
/**
4+
* Copyright © Magento, Inc. All rights reserved.
5+
* See COPYING.txt for license details.
6+
*/
7+
-->
8+
9+
<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
10+
xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd">
11+
<test name="AdminCheckAnalyticsTrackingTest">
12+
<annotations>
13+
<stories value="AdminAnalytics Check Tracking."/>
14+
<title value="AdminAnalytics Check Tracking."/>
15+
<description value="AdminAnalytics Check Tracking."/>
16+
<severity value="MINOR"/>
17+
<testCaseId value="MC-36869"/>
18+
</annotations>
19+
<before>
20+
<actionGroup ref="AdminLoginActionGroup" stepKey="LoginAsAdmin"/>
21+
<magentoCLI command="config:set admin/usage/enabled 1" stepKey="enableAdminUsageTracking"/>
22+
<actionGroup ref="CliCacheCleanActionGroup" stepKey="cleanInvalidatedCaches">
23+
<argument name="tags" value="config full_page"/>
24+
</actionGroup>
25+
<reloadPage stepKey="pageReload"/>
26+
</before>
27+
<after>
28+
<magentoCLI command="config:set admin/usage/enabled 0" stepKey="disableAdminUsageTracking"/>
29+
<actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/>
30+
</after>
31+
32+
<waitForPageLoad stepKey="waitForPageReloaded"/>
33+
<seeInPageSource html="var adminAnalyticsMetadata =" stepKey="seeInPageSource"/>
34+
</test>
35+
</tests>
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
/**
4+
* Copyright © Magento, Inc. All rights reserved.
5+
* See COPYING.txt for license details.
6+
*/
7+
-->
8+
9+
<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
10+
xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd">
11+
<actionGroup name="AdminNavigateToEmailToFriendSettingsActionGroup">
12+
<amOnPage url="{{AdminConfigurationEmailToFriendPage.url}}" stepKey="navigateToPersistencePage"/>
13+
<conditionalClick selector="{{AdminEmailToFriendSection.DefaultLayoutsTab}}" dependentSelector="{{AdminEmailToFriendSection.CheckIfTabExpand}}" visible="true" stepKey="clickTab"/>
14+
</actionGroup>
15+
</actionGroups>
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
/**
4+
* Copyright © Magento, Inc. All rights reserved.
5+
* See COPYING.txt for license details.
6+
*/
7+
-->
8+
9+
<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
10+
xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd">
11+
<actionGroup name="AssertAdminEmailToFriendOptionsAvailableActionGroup">
12+
<seeElement stepKey="seeEmailTemplateInput" selector="{{AdminEmailToFriendSection.emailTemplate}}"/>
13+
<seeElement stepKey="seeAllowForGuestsInput" selector="{{AdminEmailToFriendSection.allowForGuests}}"/>
14+
<seeElement stepKey="seeMaxRecipientsInput" selector="{{AdminEmailToFriendSection.maxRecipients}}"/>
15+
<seeElement stepKey="seeMaxPerHourInput" selector="{{AdminEmailToFriendSection.maxPerHour}}"/>
16+
<seeElement stepKey="seeLimitSendingBy" selector="{{AdminEmailToFriendSection.limitSendingBy}}"/>
17+
</actionGroup>
18+
</actionGroups>
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
/**
4+
* Copyright © Magento, Inc. All rights reserved.
5+
* See COPYING.txt for license details.
6+
*/
7+
-->
8+
9+
<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
10+
xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd">
11+
<actionGroup name="AssertAdminPageIs404ActionGroup">
12+
<annotations>
13+
<description>Validates that the '404 Error' message is present in the current Admin Page Header.</description>
14+
</annotations>
15+
16+
<see userInput="404 Error" selector="{{AdminHeaderSection.pageHeading}}" stepKey="see404PageHeading"/>
17+
</actionGroup>
18+
</actionGroups>
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
/**
4+
* Copyright © Magento, Inc. All rights reserved.
5+
* See COPYING.txt for license details.
6+
*/
7+
-->
8+
9+
<pages xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
10+
xsi:noNamespaceSchemaLocation="urn:magento:mftf:Page/etc/PageObject.xsd">
11+
<page name="AdminConfigurationEmailToFriendPage" url="admin/system_config/edit/section/sendfriend/" module="Catalog" area="admin">
12+
<section name="AdminEmailToFriendSection"/>
13+
</page>
14+
</pages>
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
/**
4+
* Copyright © Magento, Inc. All rights reserved.
5+
* See COPYING.txt for license details.
6+
*/
7+
-->
8+
9+
<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
10+
xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd">
11+
<test name="AdminCatalogEmailToFriendSettingsTest">
12+
<annotations>
13+
<features value="Backend"/>
14+
<stories value="Enable Email To A Friend Functionality"/>
15+
<title value="Admin should be able to manage settings of Email To A Friend Functionality"/>
16+
<description value="Admin should be able to enable Email To A Friend functionality in Magento Admin backend and see additional options"/>
17+
<group value="backend"/>
18+
<severity value="MINOR"></severity>
19+
<testCaseId value="MC-35895"/>
20+
</annotations>
21+
22+
<before>
23+
<actionGroup ref="AdminLoginActionGroup" stepKey="loginAsAdmin"/>
24+
<magentoCLI stepKey="enableSendFriend" command="config:set sendfriend/email/enabled 1"/>
25+
<magentoCLI stepKey="cacheClean" command="cache:clean config"/>
26+
</before>
27+
<after>
28+
<magentoCLI stepKey="disableSendFriend" command="config:set sendfriend/email/enabled 0"/>
29+
<magentoCLI stepKey="cacheClean" command="cache:clean config"/>
30+
<actionGroup ref="AdminLogoutActionGroup" stepKey="logout"/>
31+
</after>
32+
33+
<actionGroup ref="AdminNavigateToEmailToFriendSettingsActionGroup" stepKey="navigateToSendFriendSettings"/>
34+
<actionGroup ref="AssertAdminEmailToFriendOptionsAvailableActionGroup" stepKey="assertOptions"/>
35+
</test>
36+
</tests>
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\Bundle\Model\Product;
9+
10+
use Magento\Bundle\Helper\Catalog\Product\Configuration;
11+
use Magento\Bundle\Model\Option;
12+
use Magento\Catalog\Model\Product;
13+
use Magento\Catalog\Model\Product\Configuration\Item\ItemInterface;
14+
use Magento\Framework\Pricing\Helper\Data;
15+
use Magento\Framework\Serialize\SerializerInterface;
16+
17+
/**
18+
* Data provider for bundled product options
19+
*/
20+
class BundleOptionDataProvider
21+
{
22+
/**
23+
* @var Data
24+
*/
25+
private $pricingHelper;
26+
27+
/**
28+
* @var SerializerInterface
29+
*/
30+
private $serializer;
31+
32+
/**
33+
* @var Configuration
34+
*/
35+
private $configuration;
36+
37+
/**
38+
* @param Data $pricingHelper
39+
* @param SerializerInterface $serializer
40+
* @param Configuration $configuration
41+
*/
42+
public function __construct(
43+
Data $pricingHelper,
44+
SerializerInterface $serializer,
45+
Configuration $configuration
46+
) {
47+
$this->pricingHelper = $pricingHelper;
48+
$this->serializer = $serializer;
49+
$this->configuration = $configuration;
50+
}
51+
52+
/**
53+
* Extract data for a bundled item
54+
*
55+
* @param ItemInterface $item
56+
*
57+
* @return array
58+
*/
59+
public function getData(ItemInterface $item): array
60+
{
61+
$options = [];
62+
$product = $item->getProduct();
63+
$optionsQuoteItemOption = $item->getOptionByCode('bundle_option_ids');
64+
$bundleOptionsIds = $optionsQuoteItemOption
65+
? $this->serializer->unserialize($optionsQuoteItemOption->getValue())
66+
: [];
67+
68+
/** @var Type $typeInstance */
69+
$typeInstance = $product->getTypeInstance();
70+
71+
if ($bundleOptionsIds) {
72+
$selectionsQuoteItemOption = $item->getOptionByCode('bundle_selection_ids');
73+
$optionsCollection = $typeInstance->getOptionsByIds($bundleOptionsIds, $product);
74+
$bundleSelectionIds = $this->serializer->unserialize($selectionsQuoteItemOption->getValue());
75+
76+
if (!empty($bundleSelectionIds)) {
77+
$selectionsCollection = $typeInstance->getSelectionsByIds($bundleSelectionIds, $product);
78+
$bundleOptions = $optionsCollection->appendSelections($selectionsCollection, true);
79+
80+
$options = $this->buildBundleOptions($bundleOptions, $item);
81+
}
82+
}
83+
84+
return $options;
85+
}
86+
87+
/**
88+
* Build bundle product options based on current selection
89+
*
90+
* @param Option[] $bundleOptions
91+
* @param ItemInterface $item
92+
*
93+
* @return array
94+
*/
95+
private function buildBundleOptions(array $bundleOptions, ItemInterface $item): array
96+
{
97+
$options = [];
98+
foreach ($bundleOptions as $bundleOption) {
99+
if (!$bundleOption->getSelections()) {
100+
continue;
101+
}
102+
103+
$options[] = [
104+
'id' => $bundleOption->getId(),
105+
'label' => $bundleOption->getTitle(),
106+
'type' => $bundleOption->getType(),
107+
'values' => $this->buildBundleOptionValues($bundleOption->getSelections(), $item),
108+
];
109+
}
110+
111+
return $options;
112+
}
113+
114+
/**
115+
* Build bundle product option values based on current selection
116+
*
117+
* @param Product[] $selections
118+
* @param ItemInterface $item
119+
*
120+
* @return array
121+
*/
122+
private function buildBundleOptionValues(array $selections, ItemInterface $item): array
123+
{
124+
$product = $item->getProduct();
125+
$values = [];
126+
127+
foreach ($selections as $selection) {
128+
$qty = (float) $this->configuration->getSelectionQty($product, $selection->getSelectionId());
129+
if (!$qty) {
130+
continue;
131+
}
132+
133+
$selectionPrice = $this->configuration->getSelectionFinalPrice($item, $selection);
134+
$values[] = [
135+
'label' => $selection->getName(),
136+
'id' => $selection->getSelectionId(),
137+
'quantity' => $qty,
138+
'price' => $this->pricingHelper->currency($selectionPrice, false, false),
139+
];
140+
}
141+
142+
return $values;
143+
}
144+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\BundleGraphQl\Model\Wishlist;
9+
10+
use Magento\Bundle\Model\Product\BundleOptionDataProvider;
11+
use Magento\Catalog\Model\Product\Configuration\Item\ItemInterface;
12+
use Magento\Framework\Exception\LocalizedException;
13+
use Magento\Framework\GraphQl\Config\Element\Field;
14+
use Magento\Framework\GraphQl\Query\ResolverInterface;
15+
use Magento\Framework\GraphQl\Schema\Type\ResolveInfo;
16+
17+
/**
18+
* Fetches the selected bundle options
19+
*/
20+
class BundleOptions implements ResolverInterface
21+
{
22+
/**
23+
* @var BundleOptionDataProvider
24+
*/
25+
private $bundleOptionDataProvider;
26+
27+
/**
28+
* @param BundleOptionDataProvider $bundleOptionDataProvider
29+
*/
30+
public function __construct(
31+
BundleOptionDataProvider $bundleOptionDataProvider
32+
) {
33+
$this->bundleOptionDataProvider = $bundleOptionDataProvider;
34+
}
35+
36+
/**
37+
* @inheritdoc
38+
*/
39+
public function resolve(
40+
Field $field,
41+
$context,
42+
ResolveInfo $info,
43+
array $value = null,
44+
array $args = null
45+
) {
46+
if (!$value['itemModel'] instanceof ItemInterface) {
47+
throw new LocalizedException(__('"itemModel" should be a "%instance" instance', [
48+
'instance' => ItemInterface::class
49+
]));
50+
}
51+
52+
return $this->bundleOptionDataProvider->getData($value['itemModel']);
53+
}
54+
}

app/code/Magento/BundleGraphQl/etc/graphql/di.xml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,4 +100,11 @@
100100
</argument>
101101
</arguments>
102102
</type>
103+
<type name="Magento\WishlistGraphQl\Model\Resolver\Type\WishlistItemType">
104+
<arguments>
105+
<argument name="supportedTypes" xsi:type="array">
106+
<item name="bundle" xsi:type="string">BundleWishlistItem</item>
107+
</argument>
108+
</arguments>
109+
</type>
103110
</config>

app/code/Magento/BundleGraphQl/etc/schema.graphqls

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,3 +117,7 @@ type ItemSelectedBundleOptionValue @doc(description: "A list of values for the s
117117
quantity: Float! @doc(description: "Indicates how many of this bundle product were ordered")
118118
price: Money! @doc(description: "The price of the child bundle product")
119119
}
120+
121+
type BundleWishlistItem implements WishlistItemInterface {
122+
bundle_options: [SelectedBundleOption!] @doc(description: "An array containing information about the selected bundle items") @resolver(class: "\\Magento\\BundleGraphQl\\Model\\Wishlist\\BundleOptions")
123+
}

app/code/Magento/Captcha/CustomerData/Captcha.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ public function __construct(
5858
/**
5959
* @inheritdoc
6060
*/
61-
public function getSectionData() :array
61+
public function getSectionData(): array
6262
{
6363
$data = [];
6464

0 commit comments

Comments
 (0)