Skip to content

Commit 6fa1080

Browse files
committed
Merge remote-tracking branch 'origin/2.4-develop' into MCP-946
2 parents 6ada698 + bbaa528 commit 6fa1080

File tree

9 files changed

+328
-35
lines changed

9 files changed

+328
-35
lines changed

app/code/Magento/ProductVideo/view/frontend/web/js/load-player.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,14 @@ define([
241241

242242
return;
243243
}
244+
245+
// if script already loaded by other library
246+
if (window.YT) {
247+
videoRegister.register('youtube', true);
248+
$(window).trigger('youtubeapiready');
249+
250+
return;
251+
}
244252
videoRegister.register('youtube');
245253

246254
element = document.createElement('script');
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
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\Search\ViewModel;
9+
10+
use Magento\Framework\View\Element\Block\ArgumentInterface;
11+
12+
/**
13+
* View model for search additional form params
14+
*/
15+
class AdditionalSearchFormData implements ArgumentInterface
16+
{
17+
/**
18+
* Return search query params
19+
*
20+
* @return array
21+
*/
22+
public function getFormData(): array
23+
{
24+
return [];
25+
}
26+
}

app/code/Magento/Search/view/frontend/layout/default.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
<block class="Magento\Framework\View\Element\Template" name="top.search" as="topSearch" template="Magento_Search::form.mini.phtml">
1212
<arguments>
1313
<argument name="configProvider" xsi:type="object">Magento\Search\ViewModel\ConfigProvider</argument>
14+
<argument name="additionalSearchFormData" xsi:type="object">Magento\Search\ViewModel\AdditionalSearchFormData</argument>
1415
</arguments>
1516
</block>
1617
</referenceContainer>

app/code/Magento/Search/view/frontend/templates/form.mini.phtml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
/** @var $escaper \Magento\Framework\Escaper */
1111
/** @var $configProvider \Magento\Search\ViewModel\ConfigProvider */
1212
$configProvider = $block->getData('configProvider');
13+
/** @var $versionManager \Magento\Search\ViewModel\AdditionalSearchFormData */
14+
$additionalSearchFormData = $block->getData('additionalSearchFormData');
1315
/** @var $helper \Magento\Search\Helper\Data */
1416
$helper = $configProvider->getSearchHelperData();
1517
$allowedSuggestion = $configProvider->isSuggestionsAllowed();
@@ -20,6 +22,12 @@ $quickSearchUrl = $allowedSuggestion ? $escaper->escapeUrl($helper->getSuggestUr
2022
<div class="block block-content">
2123
<form class="form minisearch" id="search_mini_form"
2224
action="<?= $escaper->escapeUrl($helper->getResultUrl()) ?>" method="get">
25+
<?php if (!empty($queryParams = $additionalSearchFormData->getFormData())): ?>
26+
<?php foreach ($queryParams as $param): ?>
27+
<input type="hidden" name="<?= $escaper->escapeHtmlAttr($param['name']) ?>"
28+
value="<?= $escaper->escapeHtmlAttr($param['value']) ?>"/>
29+
<?php endforeach; ?>
30+
<?php endif; ?>
2331
<div class="field search">
2432
<label class="label" for="search" data-role="minisearch-label">
2533
<span><?= $escaper->escapeHtml(__('Search')) ?></span>

app/code/Magento/Wishlist/Pricing/ConfiguredPrice/ConfigurableProduct.php

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ class ConfigurableProduct extends AbstractPrice
1717
/**
1818
* Price type final.
1919
*/
20-
const PRICE_CODE = 'final_price';
20+
public const PRICE_CODE = 'final_price';
2121

2222
/**
2323
* @var ItemInterface
@@ -58,7 +58,28 @@ public function getConfiguredRegularAmount(): \Magento\Framework\Pricing\Amount\
5858
public function getValue()
5959
{
6060
$price = $this->getProduct()->getPriceInfo()->getPrice(self::PRICE_CODE)->getValue();
61-
61+
/** @var \Magento\Catalog\Model\Product $product */
62+
$product = parent::getProduct();
63+
/** @var \Magento\Wishlist\Model\Item\Option $configurableCustomOption */
64+
$configurableCustomOption = $product->getCustomOption('option_ids');
65+
$customPrice = 0;
66+
if ($configurableCustomOption && $configurableCustomOption->getValue()) {
67+
$item = $this->item;
68+
$configurableProduct = $configurableCustomOption->getProduct();
69+
foreach (explode(',', $configurableCustomOption->getValue()) as $optionId) {
70+
$option = $configurableProduct->getOptionById($optionId);
71+
if ($option) {
72+
$itemOption = $item->getOptionByCode('option_' . $option->getId());
73+
/** @var $group \Magento\Catalog\Model\Product\Option\Type\DefaultType */
74+
$group = $option->groupFactory($option->getType())
75+
->setOption($option);
76+
$customPrice += $group->getOptionPrice($itemOption->getValue(), $price);
77+
}
78+
}
79+
}
80+
if ($customPrice) {
81+
$price = $price + $customPrice;
82+
}
6283
return max(0, $price);
6384
}
6485

@@ -78,6 +99,7 @@ public function getProduct()
7899
{
79100
/** @var \Magento\Catalog\Model\Product $product */
80101
$product = parent::getProduct();
102+
81103
/** @var \Magento\Wishlist\Model\Item\Option $customOption */
82104
$customOption = $product->getCustomOption('simple_product');
83105

app/code/Magento/Wishlist/Test/Unit/Pricing/ConfiguredPrice/ConfigurableProductTest.php

Lines changed: 108 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@
88
namespace Magento\Wishlist\Test\Unit\Pricing\ConfiguredPrice;
99

1010
use Magento\Catalog\Model\Product;
11+
use Magento\Catalog\Model\Product\Configuration\Item\ItemInterface;
12+
use Magento\Catalog\Model\Product\Configuration\Item\Option\OptionInterface;
13+
use Magento\Catalog\Model\Product\Option\Type\DefaultType;
14+
use Magento\Catalog\Model\Product\Option as ProductOption;
1115
use Magento\Framework\Pricing\Adjustment\CalculatorInterface;
1216
use Magento\Framework\Pricing\Price\PriceInterface;
1317
use Magento\Framework\Pricing\PriceCurrencyInterface;
@@ -19,6 +23,9 @@
1923
use PHPUnit\Framework\MockObject\MockObject;
2024
use PHPUnit\Framework\TestCase;
2125

26+
/**
27+
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
28+
*/
2229
class ConfigurableProductTest extends TestCase
2330
{
2431
/**
@@ -72,9 +79,16 @@ protected function setUp(): void
7279
);
7380
}
7481

75-
public function testGetValue()
82+
/**
83+
* @param array $options
84+
*
85+
* @dataProvider setOptionsDataProvider
86+
* @throws \Magento\Framework\Exception\LocalizedException
87+
*/
88+
public function testGetValue(array $options, $optionIds)
7689
{
7790
$priceValue = 10;
91+
$customPrice = 100;
7892

7993
$priceMock = $this->getMockBuilder(PriceInterface::class)
8094
->getMockForAbstractClass();
@@ -100,14 +114,66 @@ public function testGetValue()
100114
$wishlistItemOptionMock = $this->getMockBuilder(Option::class)
101115
->disableOriginalConstructor()
102116
->getMock();
103-
$wishlistItemOptionMock->expects($this->once())
104-
->method('getProduct')
105-
->willReturn($productMock);
117+
$wishlistItemOptionMock->expects($this->exactly(2))
118+
->method('getProduct')->willReturn($productMock);
106119

107-
$this->saleableItem->expects($this->once())
120+
$this->saleableItem->expects($this->any())
108121
->method('getCustomOption')
109-
->with('simple_product')
110-
->willReturn($wishlistItemOptionMock);
122+
->withConsecutive(['simple_product'], ['option_ids'])
123+
->willReturnOnConsecutiveCalls($wishlistItemOptionMock, $wishlistItemOptionMock);
124+
125+
$wishlistItemOptionMock->expects($this->any())
126+
->method('getValue')->willReturn($optionIds);
127+
128+
$wishlistItemOptionMock->expects($this->exactly(2))
129+
->method('getProduct')->willReturn($productMock);
130+
131+
$productOptionMock = $this->getMockBuilder(ProductOption::class)
132+
->disableOriginalConstructor()
133+
->getMock();
134+
135+
$defaultTypeMock = $this->getMockBuilder(DefaultType::class)
136+
->disableOriginalConstructor()
137+
->getMock();
138+
139+
$productOptionMock->expects($this->any())
140+
->method('getId')
141+
->willReturn($options['option_id']);
142+
$productOptionMock->expects($this->any())
143+
->method('getType')
144+
->willReturn($options['type']);
145+
146+
$productOptionMock->expects($this->any())
147+
->method('groupFactory')
148+
->with($options['type'])
149+
->willReturn($defaultTypeMock);
150+
$productMock->expects($this->any())
151+
->method('getOptionById')
152+
->with($options['option_id'])->willReturn($productOptionMock);
153+
$defaultTypeMock->expects($this->any())
154+
->method('setOption')
155+
->with($productOptionMock)
156+
->willReturnSelf();
157+
158+
$itemMock = $this->getMockForAbstractClass(ItemInterface::class);
159+
$this->model->setItem($itemMock);
160+
161+
$optionInterfaceMock = $this->getMockForAbstractClass(OptionInterface::class);
162+
163+
$itemMock->expects($this->any())
164+
->method('getOptionByCode')
165+
->with('option_'.$options['option_id'])
166+
->willReturn($optionInterfaceMock);
167+
168+
$optionInterfaceMock->expects($this->any())
169+
->method('getValue')
170+
->willReturn($productOptionMock);
171+
172+
$defaultTypeMock->expects($this->any())
173+
->method('getOptionPrice')
174+
->with($productOptionMock, $priceValue)
175+
->willReturn($customPrice);
176+
$priceValue += $customPrice;
111177

112178
$this->assertEquals($priceValue, $this->model->getValue());
113179
}
@@ -122,10 +188,10 @@ public function testGetValueWithNoCustomOption()
122188
->method('getValue')
123189
->willReturn($priceValue);
124190

125-
$this->saleableItem->expects($this->once())
191+
$this->saleableItem->expects($this->any())
126192
->method('getCustomOption')
127-
->with('simple_product')
128-
->willReturn(null);
193+
->withConsecutive(['simple_product'], ['option_ids'])
194+
->willReturnOnConsecutiveCalls(null, null);
129195

130196
$this->saleableItem->expects($this->once())
131197
->method('getPriceInfo')
@@ -138,4 +204,36 @@ public function testGetValueWithNoCustomOption()
138204

139205
$this->assertEquals(100, $this->model->getValue());
140206
}
207+
208+
public function setOptionsDataProvider(): array
209+
{
210+
return ['options' =>
211+
[
212+
[
213+
'option_id' => '1',
214+
'product_id' => '2091',
215+
'type' => 'checkbox',
216+
'is_require' => '1',
217+
'default_title' => 'check',
218+
'title' => 'check',
219+
'default_price' => null,
220+
'default_price_type' => null,
221+
'price' => null,
222+
'price_type' => null
223+
], '1',
224+
[
225+
'option_id' => '2',
226+
'product_id' => '2091',
227+
'type' => 'field',
228+
'is_require' => '1',
229+
'default_title' => 'field',
230+
'title' => 'field',
231+
'default_price' => '100.000000',
232+
'default_price_type' => 'fixed',
233+
'price' => '100.000000',
234+
'price_type' => 'fixed'
235+
], '2'
236+
],
237+
];
238+
}
141239
}

dev/tests/integration/testsuite/Magento/CatalogSearch/Block/ResultTest.php

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,18 @@ public function testEscapeSearchText(string $searchValue, string $expectedOutput
7373
/** @var Result $searchResultBlock */
7474
$searchResultBlock = $this->layout->createBlock(Result::class);
7575
/** @var Template $searchBlock */
76+
$searchQueryParams = $this->getMockBuilder(\Magento\Search\ViewModel\AdditionalSearchFormData::class)
77+
->disableOriginalConstructor()
78+
->setMethods(['getFormData'])
79+
->getMock();
80+
$searchQueryParams->expects($this->any())
81+
->method('getFormData')
82+
->willReturn([]);
7683
$searchBlock = $this->layout->createBlock(Template::class);
77-
$searchBlock->setData(['configProvider' => $this->configProvider]);
84+
$searchBlock->setData([
85+
'configProvider' => $this->configProvider,
86+
'additionalSearchFormData' => $searchQueryParams,
87+
]);
7888
$searchBlock->setTemplate('Magento_Search::form.mini.phtml');
7989
/** @var RequestInterface $request */
8090
$request = $this->objectManager->get(RequestInterface::class);

lib/internal/Magento/Framework/View/Element/UiComponent/Context.php

Lines changed: 38 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -349,13 +349,16 @@ protected function setAcceptType()
349349
{
350350
$this->acceptType = 'html';
351351

352-
$rawAcceptType = $this->request->getHeader('Accept');
353-
if (strpos($rawAcceptType, 'json') !== false) {
354-
$this->acceptType = 'json';
355-
} elseif (strpos($rawAcceptType, 'html') !== false) {
356-
$this->acceptType = 'html';
357-
} elseif (strpos($rawAcceptType, 'xml') !== false) {
358-
$this->acceptType = 'xml';
352+
$acceptTypes = $this->getSortedAcceptHeader();
353+
foreach ($acceptTypes as $acceptType) {
354+
if (strpos($acceptType, 'json') !== false) {
355+
$this->acceptType = 'json';
356+
} elseif (strpos($acceptType, 'html') !== false) {
357+
$this->acceptType = 'html';
358+
} elseif (strpos($acceptType, 'xml') !== false) {
359+
$this->acceptType = 'xml';
360+
}
361+
break;
359362
}
360363
}
361364

@@ -408,4 +411,32 @@ public function getUiComponentFactory()
408411
{
409412
return $this->uiComponentFactory;
410413
}
414+
415+
/**
416+
* Returns sorted accept header based on q value
417+
*
418+
* @return array
419+
*/
420+
private function getSortedAcceptHeader()
421+
{
422+
$acceptTypes = [];
423+
$acceptHeader = $this->request->getHeader('Accept');
424+
$contentTypes = explode(',', $acceptHeader);
425+
foreach ($contentTypes as $contentType) {
426+
// the default quality is 1.
427+
$q = 1;
428+
// check if there is a different quality
429+
if (strpos($contentType, ';q=') !== false) {
430+
list($contentType, $q) = explode(';q=', $contentType);
431+
}
432+
433+
if (array_key_exists($q, $acceptTypes)) {
434+
$acceptTypes[$q] = $acceptTypes[$q] . ',' . $contentType;
435+
} else {
436+
$acceptTypes[$q] = $contentType;
437+
}
438+
}
439+
krsort($acceptTypes);
440+
return array_values($acceptTypes);
441+
}
411442
}

0 commit comments

Comments
 (0)