Skip to content

Commit c1eb14b

Browse files
authored
Merge pull request #2752 from magento-mpi/mpi-PR-2506
Fixed issues: - MAGETWO-86658: Admin global search preview works inconsistently. - MAGETWO-92820: Once Payflow Pro payment is Declined, customer cannot continue checkout - MAGETWO-92280: [B2B] Unable to add to cart grouped product by SKU with enabled Shared Catalog - MAGETWO-92502: Extra XHR POST request made on every page
2 parents aa4b734 + 15c4c85 commit c1eb14b

File tree

14 files changed

+665
-133
lines changed

14 files changed

+665
-133
lines changed

app/code/Magento/Catalog/view/frontend/web/js/product/storage/storage-service.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ define([
4747
* @param {*} data
4848
*/
4949
add: function (data) {
50-
if (!utils.compare(data, this.data()).equal) {
50+
if (!_.isEmpty(data) && !utils.compare(data, this.data()).equal) {
5151
this.data(_.extend(utils.copy(this.data()), data));
5252
}
5353
},
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\Cms\Ui\Component;
9+
10+
use Magento\Framework\Api\Filter;
11+
use Magento\Framework\Api\Search\SearchCriteriaBuilder;
12+
13+
/**
14+
* Provides extension point to add additional filters to search criteria.
15+
*/
16+
interface AddFilterInterface
17+
{
18+
/**
19+
* Adds custom filter to search criteria builder based on received filter.
20+
*
21+
* @param SearchCriteriaBuilder $searchCriteriaBuilder
22+
* @param Filter $filter
23+
* @return void
24+
*/
25+
public function addFilter(SearchCriteriaBuilder $searchCriteriaBuilder, Filter $filter);
26+
}

app/code/Magento/Cms/Ui/Component/DataProvider.php

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
*/
66
namespace Magento\Cms\Ui\Component;
77

8+
use Magento\Framework\Api\Filter;
89
use Magento\Framework\Api\FilterBuilder;
910
use Magento\Framework\Api\Search\SearchCriteriaBuilder;
1011
use Magento\Framework\App\ObjectManager;
@@ -19,6 +20,11 @@ class DataProvider extends \Magento\Framework\View\Element\UiComponent\DataProvi
1920
*/
2021
private $authorization;
2122

23+
/**
24+
* @var AddFilterInterface[]
25+
*/
26+
private $additionalFilterPool;
27+
2228
/**
2329
* @param string $name
2430
* @param string $primaryFieldName
@@ -29,6 +35,8 @@ class DataProvider extends \Magento\Framework\View\Element\UiComponent\DataProvi
2935
* @param FilterBuilder $filterBuilder
3036
* @param array $meta
3137
* @param array $data
38+
* @param array $additionalFilterPool
39+
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
3240
*/
3341
public function __construct(
3442
$name,
@@ -39,7 +47,8 @@ public function __construct(
3947
RequestInterface $request,
4048
FilterBuilder $filterBuilder,
4149
array $meta = [],
42-
array $data = []
50+
array $data = [],
51+
array $additionalFilterPool = []
4352
) {
4453
parent::__construct(
4554
$name,
@@ -54,6 +63,7 @@ public function __construct(
5463
);
5564

5665
$this->meta = array_replace_recursive($meta, $this->prepareMetadata());
66+
$this->additionalFilterPool = $additionalFilterPool;
5767
}
5868

5969
/**
@@ -95,4 +105,16 @@ public function prepareMetadata()
95105

96106
return $metadata;
97107
}
108+
109+
/**
110+
* @inheritdoc
111+
*/
112+
public function addFilter(Filter $filter)
113+
{
114+
if (!empty($this->additionalFilterPool[$filter->getField()])) {
115+
$this->additionalFilterPool[$filter->getField()]->addFilter($this->searchCriteriaBuilder, $filter);
116+
} else {
117+
parent::addFilter($filter);
118+
}
119+
}
98120
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
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\Cms\Ui\Component\Page;
9+
10+
use Magento\Cms\Ui\Component\AddFilterInterface;
11+
use Magento\Framework\Api\Filter;
12+
use Magento\Framework\Api\FilterBuilder;
13+
use Magento\Framework\Api\Search\SearchCriteriaBuilder;
14+
15+
/**
16+
* Adds fulltext filter for CMS Page title attribute.
17+
*/
18+
class FulltextFilter implements AddFilterInterface
19+
{
20+
/**
21+
* @var FilterBuilder
22+
*/
23+
private $filterBuilder;
24+
25+
/**
26+
* @param FilterBuilder $filterBuilder
27+
*/
28+
public function __construct(FilterBuilder $filterBuilder)
29+
{
30+
$this->filterBuilder = $filterBuilder;
31+
}
32+
33+
/**
34+
* @inheritdoc
35+
*/
36+
public function addFilter(SearchCriteriaBuilder $searchCriteriaBuilder, Filter $filter)
37+
{
38+
$titleFilter = $this->filterBuilder->setField('title')
39+
->setValue(sprintf('%%%s%%', $filter->getValue()))
40+
->setConditionType('like')
41+
->create();
42+
$searchCriteriaBuilder->addFilter($titleFilter);
43+
}
44+
}

app/code/Magento/Cms/etc/di.xml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,4 +189,12 @@
189189
<argument name="collectionProcessor" xsi:type="object">Magento\Cms\Model\Api\SearchCriteria\BlockCollectionProcessor</argument>
190190
</arguments>
191191
</type>
192+
193+
<type name="Magento\Cms\Ui\Component\DataProvider">
194+
<arguments>
195+
<argument name="additionalFilterPool" xsi:type="array">
196+
<item name="fulltext" xsi:type="object">Magento\Cms\Ui\Component\Page\FulltextFilter</item>
197+
</argument>
198+
</arguments>
199+
</type>
192200
</config>

app/code/Magento/Payment/view/frontend/templates/transparent/iframe.phtml

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,10 @@ $params = $block->getParams();
6565
'jquery',
6666
'Magento_Checkout/js/model/quote',
6767
'Magento_Checkout/js/action/place-order',
68-
'Magento_Checkout/js/action/redirect-on-success'
68+
'Magento_Checkout/js/action/redirect-on-success',
69+
'Magento_Checkout/js/model/full-screen-loader'
6970
],
70-
function($, quote, placeOrderAction, redirectOnSuccessAction) {
71+
function($, quote, placeOrderAction, redirectOnSuccessAction, fullScreenLoader) {
7172
var parent = window.top;
7273

7374
$(parent).trigger('clearTimeout');
@@ -77,6 +78,12 @@ $params = $block->getParams();
7778
function () {
7879
redirectOnSuccessAction.execute();
7980
}
81+
).fail(
82+
function () {
83+
var parent = window.top;
84+
$(parent).trigger('clearTimeout');
85+
fullScreenLoader.stopLoader();
86+
}
8087
);
8188
}
8289
);

app/code/Magento/Sales/Block/Adminhtml/Order/Create/Form.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,7 @@ public function getOrderDataJson()
189189
$data['shipping_method_reseted'] = !(bool)$this->getQuote()->getShippingAddress()->getShippingMethod();
190190
$data['payment_method'] = $this->getQuote()->getPayment()->getMethod();
191191
}
192+
$data['quote_id'] = $this->_sessionQuote->getQuoteId();
192193

193194
return $this->_jsonEncoder->encode($data);
194195
}
Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
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\Sales\Test\Unit\Block\Adminhtml\Order\Create;
9+
10+
use Magento\Backend\Block\Template\Context;
11+
use Magento\Backend\Model\Session\Quote as QuoteSession;
12+
use Magento\Customer\Api\CustomerRepositoryInterface;
13+
use Magento\Customer\Api\Data\CustomerInterface;
14+
use Magento\Customer\Model\Address\Mapper;
15+
use Magento\Customer\Model\Metadata\FormFactory;
16+
use Magento\Framework\Currency;
17+
use Magento\Framework\Json\EncoderInterface;
18+
use Magento\Framework\Locale\CurrencyInterface;
19+
use Magento\Framework\Pricing\PriceCurrencyInterface;
20+
use Magento\Quote\Model\Quote;
21+
use Magento\Quote\Model\Quote\Address;
22+
use Magento\Quote\Model\Quote\Payment;
23+
use Magento\Sales\Block\Adminhtml\Order\Create\Form;
24+
use Magento\Sales\Model\AdminOrder\Create;
25+
use Magento\Store\Model\Store;
26+
use PHPUnit\Framework\TestCase;
27+
use PHPUnit_Framework_MockObject_MockObject as MockObject;
28+
29+
/**
30+
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
31+
*/
32+
class FormTest extends TestCase
33+
{
34+
/**
35+
* @var QuoteSession|MockObject
36+
*/
37+
private $quoteSession;
38+
39+
/**
40+
* @var CustomerRepositoryInterface|MockObject
41+
*/
42+
private $customerRepository;
43+
44+
/**
45+
* @var CurrencyInterface|MockObject
46+
*/
47+
private $localeCurrency;
48+
49+
/**
50+
* @var Form
51+
*/
52+
private $block;
53+
54+
/**
55+
* @inheritdoc
56+
*/
57+
protected function setUp()
58+
{
59+
/** @var Context|MockObject $context */
60+
$context = $this->getMockBuilder(Context::class)
61+
->disableOriginalConstructor()
62+
->getMock();
63+
$this->quoteSession = $this->getMockBuilder(QuoteSession::class)
64+
->disableOriginalConstructor()
65+
->setMethods(['getCustomerId', 'getQuoteId', 'getStoreId', 'getStore', 'getQuote'])
66+
->getMock();
67+
/** @var Create|MockObject $create */
68+
$create = $this->getMockBuilder(Create::class)
69+
->disableOriginalConstructor()
70+
->getMock();
71+
/** @var PriceCurrencyInterface|MockObject $priceCurrency */
72+
$priceCurrency = $this->getMockForAbstractClass(PriceCurrencyInterface::class);
73+
/** @var EncoderInterface|MockObject $encoder */
74+
$encoder = $this->getMockForAbstractClass(EncoderInterface::class);
75+
$encoder->method('encode')
76+
->willReturnCallback(function ($param) {
77+
return json_encode($param);
78+
});
79+
/** @var FormFactory|MockObject $formFactory */
80+
$formFactory = $this->getMockBuilder(FormFactory::class)
81+
->disableOriginalConstructor()
82+
->getMock();
83+
$this->customerRepository = $this->getMockForAbstractClass(CustomerRepositoryInterface::class);
84+
85+
$this->localeCurrency = $this->getMockForAbstractClass(CurrencyInterface::class);
86+
/** @var Mapper|MockObject $addressMapper */
87+
$addressMapper = $this->getMockBuilder(Mapper::class)
88+
->disableOriginalConstructor()
89+
->getMock();
90+
91+
$this->block = new Form(
92+
$context,
93+
$this->quoteSession,
94+
$create,
95+
$priceCurrency,
96+
$encoder,
97+
$formFactory,
98+
$this->customerRepository,
99+
$this->localeCurrency,
100+
$addressMapper
101+
);
102+
}
103+
104+
/**
105+
* Checks if order contains all needed data.
106+
*/
107+
public function testGetOrderDataJson()
108+
{
109+
$customerId = 1;
110+
$storeId = 1;
111+
$quoteId = 2;
112+
$expected = [
113+
'customer_id' => $customerId,
114+
'addresses' => [],
115+
'store_id' => $storeId,
116+
'currency_symbol' => '$',
117+
'shipping_method_reseted' => false,
118+
'payment_method' => 'free',
119+
'quote_id' => $quoteId
120+
];
121+
122+
$this->quoteSession->method('getCustomerId')
123+
->willReturn($customerId);
124+
$this->quoteSession->method('getStoreId')
125+
->willReturn($storeId);
126+
$this->quoteSession->method('getQuoteId')
127+
->willReturn($quoteId);
128+
129+
$customer = $this->getMockBuilder(CustomerInterface::class)
130+
->disableOriginalConstructor()
131+
->getMock();
132+
$customer->method('getAddresses')
133+
->willReturn([]);
134+
$this->customerRepository->method('getById')
135+
->with($customerId)
136+
->willReturn($customer);
137+
138+
$this->withCurrencySymbol('$');
139+
140+
$this->withQuote();
141+
142+
self::assertEquals($expected, json_decode($this->block->getOrderDataJson(), true));
143+
}
144+
145+
/**
146+
* Configures mock object for currency.
147+
*
148+
* @param string $symbol
149+
*/
150+
private function withCurrencySymbol(string $symbol)
151+
{
152+
$store = $this->getMockBuilder(Store::class)
153+
->disableOriginalConstructor()
154+
->getMock();
155+
$store->method('getCurrentCurrencyCode')
156+
->willReturn('USD');
157+
$this->quoteSession->method('getStore')
158+
->willReturn($store);
159+
160+
$currency = $this->getMockBuilder(Currency::class)
161+
->disableOriginalConstructor()
162+
->getMock();
163+
$currency->method('getSymbol')
164+
->willReturn($symbol);
165+
$this->localeCurrency->method('getCurrency')
166+
->with('USD')
167+
->willReturn($currency);
168+
}
169+
170+
/**
171+
* Configures shipping and payment mock objects.
172+
*/
173+
private function withQuote()
174+
{
175+
$quote = $this->getMockBuilder(Quote::class)
176+
->disableOriginalConstructor()
177+
->getMock();
178+
$this->quoteSession->method('getQuote')
179+
->willReturn($quote);
180+
181+
$address = $this->getMockBuilder(Address::class)
182+
->disableOriginalConstructor()
183+
->getMock();
184+
$address->method('getShippingMethod')
185+
->willReturn('free');
186+
$quote->method('getShippingAddress')
187+
->willReturn($address);
188+
189+
$payment = $this->getMockBuilder(Payment::class)
190+
->disableOriginalConstructor()
191+
->getMock();
192+
$payment->method('getMethod')
193+
->willReturn('free');
194+
$quote->method('getPayment')
195+
->willReturn($payment);
196+
}
197+
}

app/code/Magento/Sales/view/adminhtml/web/order/create/scripts.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ define([
2121
this.loadBaseUrl = false;
2222
this.customerId = data.customer_id ? data.customer_id : false;
2323
this.storeId = data.store_id ? data.store_id : false;
24+
this.quoteId = data['quote_id'] ? data['quote_id'] : false;
2425
this.currencyId = false;
2526
this.currencySymbol = data.currency_symbol ? data.currency_symbol : '';
2627
this.addresses = data.addresses ? data.addresses : $H({});

0 commit comments

Comments
 (0)