Skip to content

Commit ec47891

Browse files
🔃 [EngCom] Public Pull Requests - 2.2-develop
Accepted Public Pull Requests: - #13844: Fix issue 13827 (by @julienanquetil) - #13817: Allow changing head and body element through xml layout updates (by @cedricziel) - #13567: Add integration tests for product urls rewrite generation (by @adrien-louis-r) - #13038: Default Welcome message is broken on storefront with enabled translate-inline (by @pareshpansuriya) - #13828: Inconsistent Redirect in Admin Notification Controller (by @chickenland) - #13787: Issue-13768 Fixed error messages on admin user account page after redirect for force password change (by @nuzil) Fixed GitHub Issues: - #13350: Magento 2.2 Encoding Issue -> Google Analytics (reported by @danielpfarmer) has been fixed in #13844 by @julienanquetil in 2.2-develop branch Related commits: 1. 5843e81 2. 0d5197f - #13827: Google Analytics character encoding issue ( \u0020 ) (reported by @Munszu) has been fixed in #13844 by @julienanquetil in 2.2-develop branch Related commits: 1. 5843e81 2. 0d5197f - #4454: CMS Page with <head> in layout update xml (reported by @zhiyicai) has been fixed in #13817 by @cedricziel in 2.2-develop branch Related commits: 1. 341cdaf - #5863: URL Rewrite issues occur very often /catalog/product/view/id/711/s/product-name/category/16/ (reported by @kayintveen) has been fixed in #13567 by @adrien-louis-r in 2.2-develop branch Related commits: 1. 1ef4dcc 2. 864f371 - #8227: After upgrade to 2.1.3 url rewrite problem multi store (reported by @philipvandebriel) has been fixed in #13567 by @adrien-louis-r in 2.2-develop branch Related commits: 1. 1ef4dcc 2. 864f371 - #8957: Permanent Redirect for old URL missing via API (reported by @MarcoGrecoBitbull) has been fixed in #13567 by @adrien-louis-r in 2.2-develop branch Related commits: 1. 1ef4dcc 2. 864f371 - #10073: Magento don't create product redirect if URL key on store view level was changed. (reported by @sergei-sss) has been fixed in #13567 by @adrien-louis-r in 2.2-develop branch Related commits: 1. 1ef4dcc 2. 864f371 - #13240: Permanent 301 redirect is not generated when product url changes on storeview scope (reported by @koenner01) has been fixed in #13567 by @adrien-louis-r in 2.2-develop branch Related commits: 1. 1ef4dcc 2. 864f371 - #12711: Default Welcome message is broken on storefront with enabled translate-inline (reported by @alena-marchenko) has been fixed in #13038 by @pareshpansuriya in 2.2-develop branch Related commits: 1. 6144c4f 2. 7e913f1 3. cbc704d - #13768: Expired backend password - Attention: Something went wrong (reported by @janssensjelle) has been fixed in #13787 by @nuzil in 2.2-develop branch Related commits: 1. 96a8b58
2 parents 30462cd + 7e17a4f commit ec47891

File tree

8 files changed

+294
-8
lines changed

8 files changed

+294
-8
lines changed

app/code/Magento/AdminNotification/Controller/Adminhtml/Notification/MassRemove.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,6 @@ public function execute()
3939
$this->messageManager->addException($e, __("We couldn't remove the messages because of an error."));
4040
}
4141
}
42-
$this->getResponse()->setRedirect($this->_redirect->getRedirectUrl($this->getUrl('*')));
42+
$this->_redirect('adminhtml/*/');
4343
}
4444
}

app/code/Magento/GoogleAnalytics/Block/Ga.php

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -130,8 +130,8 @@ public function getOrdersTrackingCode()
130130
'price': '%s',
131131
'quantity': %s
132132
});",
133-
$this->escapeJs($item->getSku()),
134-
$this->escapeJs($item->getName()),
133+
$this->escapeJsQuote($item->getSku()),
134+
$this->escapeJsQuote($item->getName()),
135135
$item->getPrice(),
136136
$item->getQtyOrdered()
137137
);
@@ -146,7 +146,7 @@ public function getOrdersTrackingCode()
146146
'shipping': '%s'
147147
});",
148148
$order->getIncrementId(),
149-
$this->escapeJs($this->_storeManager->getStore()->getFrontendName()),
149+
$this->escapeJsQuote($this->_storeManager->getStore()->getFrontendName()),
150150
$order->getGrandTotal(),
151151
$order->getTaxAmount(),
152152
$order->getShippingAmount()
@@ -236,15 +236,15 @@ public function getOrdersTrackingData()
236236
foreach ($collection as $order) {
237237
foreach ($order->getAllVisibleItems() as $item) {
238238
$result['products'][] = [
239-
'id' => $this->escapeJs($item->getSku()),
240-
'name' => $this->escapeJs($item->getName()),
239+
'id' => $this->escapeJsQuote($item->getSku()),
240+
'name' => $this->escapeJsQuote($item->getName()),
241241
'price' => $item->getPrice(),
242242
'quantity' => $item->getQtyOrdered(),
243243
];
244244
}
245245
$result['orders'][] = [
246246
'id' => $order->getIncrementId(),
247-
'affiliation' => $this->escapeJs($this->_storeManager->getStore()->getFrontendName()),
247+
'affiliation' => $this->escapeJsQuote($this->_storeManager->getStore()->getFrontendName()),
248248
'revenue' => $order->getGrandTotal(),
249249
'tax' => $order->getTaxAmount(),
250250
'shipping' => $order->getShippingAmount(),

app/code/Magento/Theme/view/frontend/templates/html/header.phtml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ $welcomeMessage = $block->getWelcome();
1919
</span>
2020
<!-- /ko -->
2121
<!-- ko ifnot: customer().fullname -->
22-
<span data-bind='html:"<?= $block->escapeHtmlAttr($welcomeMessage) ?>"'></span>
22+
<span data-bind='html:"<?= $block->escapeHtml($welcomeMessage) ?>"'></span>
2323
<?= $block->getBlockHtml('header.additional') ?>
2424
<!-- /ko -->
2525
</li>

app/code/Magento/User/Observer/Backend/ForceAdminPasswordChangeObserver.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ public function execute(EventObserver $observer)
108108
'adminhtml_system_account_index',
109109
'adminhtml_system_account_save',
110110
'adminhtml_auth_logout',
111+
'mui_index_render'
111112
];
112113
/** @var \Magento\Framework\App\Action\Action $controller */
113114
$controller = $observer->getEvent()->getControllerAction();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,230 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
namespace Magento\CatalogUrlRewrite\Observer;
7+
8+
use Magento\Store\Model\StoreManagerInterface;
9+
use Magento\UrlRewrite\Service\V1\Data\UrlRewrite;
10+
use Magento\CatalogUrlRewrite\Model\CategoryUrlRewriteGenerator;
11+
12+
/**
13+
* @magentoAppArea adminhtml
14+
*/
15+
class ProductProcessUrlRewriteSavingObserverTest extends \PHPUnit\Framework\TestCase
16+
{
17+
/** @var \Magento\Framework\ObjectManagerInterface */
18+
protected $objectManager;
19+
20+
protected function setUp()
21+
{
22+
$this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
23+
}
24+
25+
/**
26+
* @param array $filter
27+
* @return array
28+
*/
29+
private function getActualResults(array $filter)
30+
{
31+
/** @var \Magento\UrlRewrite\Model\UrlFinderInterface $urlFinder */
32+
$urlFinder = $this->objectManager->get(\Magento\UrlRewrite\Model\UrlFinderInterface::class);
33+
$actualResults = [];
34+
foreach ($urlFinder->findAllByData($filter) as $url) {
35+
$actualResults[] = [
36+
'request_path' => $url->getRequestPath(),
37+
'target_path' => $url->getTargetPath(),
38+
'is_auto_generated' => (int)$url->getIsAutogenerated(),
39+
'redirect_type' => $url->getRedirectType(),
40+
'store_id' => $url->getStoreId()
41+
];
42+
}
43+
return $actualResults;
44+
}
45+
46+
/**
47+
* @magentoDataFixture Magento/CatalogUrlRewrite/_files/product_rewrite_multistore.php
48+
* @magentoAppIsolation enabled
49+
*/
50+
public function testUrlKeyHasChangedInGlobalContext()
51+
{
52+
/** @var \Magento\Catalog\Api\ProductRepositoryInterface $productRepository*/
53+
$productRepository = $this->objectManager->create(\Magento\Catalog\Api\ProductRepositoryInterface::class);
54+
/** @var \Magento\Catalog\Model\Product $product*/
55+
$product = $productRepository->get('product1');
56+
57+
/** @var StoreManagerInterface $storeManager */
58+
$storeManager = $this->objectManager->get(StoreManagerInterface::class);
59+
$storeManager->setCurrentStore(0);
60+
61+
$testStore = $storeManager->getStore('test');
62+
$productFilter = [
63+
UrlRewrite::ENTITY_TYPE => 'product',
64+
];
65+
66+
$expected = [
67+
[
68+
'request_path' => "product-1.html",
69+
'target_path' => "catalog/product/view/id/" . $product->getId(),
70+
'is_auto_generated' => 1,
71+
'redirect_type' => 0,
72+
'store_id' => 1,
73+
],
74+
[
75+
'request_path' => "product-1.html",
76+
'target_path' => "catalog/product/view/id/" . $product->getId(),
77+
'is_auto_generated' => 1,
78+
'redirect_type' => 0,
79+
'store_id' => $testStore->getId(),
80+
],
81+
];
82+
$actual = $this->getActualResults($productFilter);
83+
foreach ($expected as $row) {
84+
$this->assertContains($row, $actual);
85+
}
86+
87+
$product->setData('save_rewrites_history', true);
88+
$product->setUrlKey('new-url');
89+
$product->save();
90+
91+
$expected = [
92+
[
93+
'request_path' => "new-url.html",
94+
'target_path' => "catalog/product/view/id/" . $product->getId(),
95+
'is_auto_generated' => 1,
96+
'redirect_type' => 0,
97+
'store_id' => 1,
98+
],
99+
[
100+
'request_path' => "new-url.html",
101+
'target_path' => "catalog/product/view/id/" . $product->getId(),
102+
'is_auto_generated' => 1,
103+
'redirect_type' => 0,
104+
'store_id' => $testStore->getId(),
105+
],
106+
[
107+
'request_path' => "product-1.html",
108+
'target_path' => "new-url.html",
109+
'is_auto_generated' => 0,
110+
'redirect_type' => 301,
111+
'store_id' => 1,
112+
],
113+
[
114+
'request_path' => "product-1.html",
115+
'target_path' => "new-url.html",
116+
'is_auto_generated' => 0,
117+
'redirect_type' => 301,
118+
'store_id' => $testStore->getId(),
119+
],
120+
];
121+
122+
$actual = $this->getActualResults($productFilter);
123+
foreach ($expected as $row) {
124+
$this->assertContains($row, $actual);
125+
}
126+
}
127+
128+
/**
129+
* @magentoDataFixture Magento/CatalogUrlRewrite/_files/product_rewrite_multistore.php
130+
* @magentoAppIsolation enabled
131+
*/
132+
public function testUrlKeyHasChangedInStoreviewContextWithPermanentRedirection()
133+
{
134+
/** @var \Magento\Catalog\Api\ProductRepositoryInterface $productRepository*/
135+
$productRepository = $this->objectManager->create(\Magento\Catalog\Api\ProductRepositoryInterface::class);
136+
/** @var \Magento\Catalog\Model\Product $product*/
137+
$product = $productRepository->get('product1');
138+
139+
/** @var StoreManagerInterface $storeManager */
140+
$storeManager = $this->objectManager->get(StoreManagerInterface::class);
141+
$storeManager->setCurrentStore(1);
142+
143+
$testStore = $storeManager->getStore('test');
144+
145+
$productFilter = [
146+
UrlRewrite::ENTITY_TYPE => 'product',
147+
];
148+
149+
$product->setData('save_rewrites_history', true);
150+
$product->setUrlKey('new-url');
151+
$product->save();
152+
153+
$expected = [
154+
[
155+
'request_path' => "new-url.html",
156+
'target_path' => "catalog/product/view/id/" . $product->getId(),
157+
'is_auto_generated' => 1,
158+
'redirect_type' => 0,
159+
'store_id' => 1,
160+
],
161+
[
162+
'request_path' => "product-1.html",
163+
'target_path' => "catalog/product/view/id/" . $product->getId(),
164+
'is_auto_generated' => 1,
165+
'redirect_type' => 0,
166+
'store_id' => $testStore->getId(),
167+
],
168+
[
169+
'request_path' => "product-1.html",
170+
'target_path' => "new-url.html",
171+
'is_auto_generated' => 0,
172+
'redirect_type' => 301,
173+
'store_id' => 1,
174+
],
175+
];
176+
177+
$actual = $this->getActualResults($productFilter);
178+
foreach ($expected as $row) {
179+
$this->assertContains($row, $actual);
180+
}
181+
}
182+
183+
/**
184+
* @magentoDataFixture Magento/CatalogUrlRewrite/_files/product_rewrite_multistore.php
185+
* @magentoAppIsolation enabled
186+
*/
187+
public function testUrlKeyHasChangedInStoreviewContextWithoutPermanentRedirection()
188+
{
189+
/** @var \Magento\Catalog\Api\ProductRepositoryInterface $productRepository*/
190+
$productRepository = $this->objectManager->create(\Magento\Catalog\Api\ProductRepositoryInterface::class);
191+
/** @var \Magento\Catalog\Model\Product $product*/
192+
$product = $productRepository->get('product1');
193+
194+
/** @var StoreManagerInterface $storeManager */
195+
$storeManager = $this->objectManager->get(StoreManagerInterface::class);
196+
$storeManager->setCurrentStore(1);
197+
198+
$testStore = $storeManager->getStore('test');
199+
200+
$productFilter = [
201+
UrlRewrite::ENTITY_TYPE => 'product',
202+
];
203+
204+
$product->setData('save_rewrites_history', false);
205+
$product->setUrlKey('new-url');
206+
$product->save();
207+
208+
$expected = [
209+
[
210+
'request_path' => "new-url.html",
211+
'target_path' => "catalog/product/view/id/" . $product->getId(),
212+
'is_auto_generated' => 1,
213+
'redirect_type' => 0,
214+
'store_id' => 1,
215+
],
216+
[
217+
'request_path' => "product-1.html",
218+
'target_path' => "catalog/product/view/id/" . $product->getId(),
219+
'is_auto_generated' => 1,
220+
'redirect_type' => 0,
221+
'store_id' => $testStore->getId(),
222+
],
223+
];
224+
225+
$actual = $this->getActualResults($productFilter);
226+
foreach ($expected as $row) {
227+
$this->assertContains($row, $actual);
228+
}
229+
}
230+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
use Magento\Catalog\Api\ProductRepositoryInterface;
7+
use Magento\Catalog\Setup\CategorySetup;
8+
use Magento\Store\Model\StoreManagerInterface;
9+
use Magento\TestFramework\Helper\Bootstrap;
10+
11+
\Magento\TestFramework\Helper\Bootstrap::getInstance()
12+
->loadArea(\Magento\Backend\App\Area\FrontNameResolver::AREA_CODE);
13+
14+
require __DIR__ . '/../../Store/_files/store.php';
15+
16+
/** @var $installer CategorySetup */
17+
$objectManager = Bootstrap::getObjectManager();
18+
$installer = $objectManager->create(CategorySetup::class);
19+
$storeManager = $objectManager->get(StoreManagerInterface::class);
20+
$storeManager->setCurrentStore(0);
21+
22+
/** @var $product \Magento\Catalog\Model\Product */
23+
$product = $objectManager->create(\Magento\Catalog\Model\Product::class);
24+
$product->setTypeId(\Magento\Catalog\Model\Product\Type::TYPE_SIMPLE)
25+
->setAttributeSetId($installer->getAttributeSetId('catalog_product', 'Default'))
26+
->setStoreId(0)
27+
->setWebsiteIds([1])
28+
->setName('Product1')
29+
->setSku('product1')
30+
->setPrice(10)
31+
->setWeight(18)
32+
->setStockData(['use_config_manage_stock' => 0])
33+
->setUrlKey('product-1')
34+
->setVisibility(\Magento\Catalog\Model\Product\Visibility::VISIBILITY_BOTH)
35+
->setStatus(\Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED);
36+
37+
/** @var ProductRepositoryInterface $productRepository */
38+
$productRepository = $objectManager->get(ProductRepositoryInterface::class);
39+
$productRepository->save($product);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
use Magento\Catalog\Api\ProductRepositoryInterface;
7+
use Magento\TestFramework\Helper\Bootstrap;
8+
9+
$objectManager = Bootstrap::getObjectManager();
10+
11+
require __DIR__ . '/../../Store/_files/store_rollback.php';
12+
require __DIR__ . '/../../Store/_files/second_store_rollback.php';

lib/internal/Magento/Framework/View/Layout/etc/page_layout.xsd

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,17 @@
77
-->
88
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
99
<xs:include schemaLocation="urn:magento:framework:View/Layout/etc/elements.xsd"/>
10+
<xs:include schemaLocation="urn:magento:framework:View/Layout/etc/head.xsd"/>
11+
<xs:include schemaLocation="urn:magento:framework:View/Layout/etc/body.xsd"/>
1012

1113
<xs:complexType name="pageLayoutType">
1214
<xs:sequence minOccurs="0" maxOccurs="unbounded">
1315
<xs:element ref="referenceContainer" minOccurs="0" maxOccurs="unbounded"/>
1416
<xs:element name="container" type="containerType" minOccurs="0" maxOccurs="unbounded"/>
1517
<xs:element ref="update" minOccurs="0" maxOccurs="unbounded"/>
1618
<xs:element ref="move" minOccurs="0" maxOccurs="unbounded"/>
19+
<xs:element name="head" type="headType" minOccurs="0" maxOccurs="unbounded"/>
20+
<xs:element name="body" type="bodyType" minOccurs="0" maxOccurs="unbounded"/>
1721
</xs:sequence>
1822
</xs:complexType>
1923

0 commit comments

Comments
 (0)