diff --git a/app/code/Magento/Bundle/Test/Mftf/Test/AdminCreateAndEditBundleProductOptionsNegativeTest.xml b/app/code/Magento/Bundle/Test/Mftf/Test/AdminCreateAndEditBundleProductOptionsNegativeTest.xml
new file mode 100644
index 0000000000000..8a8e9dd275ee4
--- /dev/null
+++ b/app/code/Magento/Bundle/Test/Mftf/Test/AdminCreateAndEditBundleProductOptionsNegativeTest.xml
@@ -0,0 +1,122 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/code/Magento/Bundle/Test/Mftf/Test/AdminCreateAndEditBundleProductSettingsTest.xml b/app/code/Magento/Bundle/Test/Mftf/Test/AdminCreateAndEditBundleProductSettingsTest.xml
index 1d2d566ffd447..1a7117fbf4485 100644
--- a/app/code/Magento/Bundle/Test/Mftf/Test/AdminCreateAndEditBundleProductSettingsTest.xml
+++ b/app/code/Magento/Bundle/Test/Mftf/Test/AdminCreateAndEditBundleProductSettingsTest.xml
@@ -136,117 +136,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/app/code/Magento/Bundle/Test/Mftf/Test/AdvanceCatalogSearchBundleByDescriptionMysqlTest.xml b/app/code/Magento/Bundle/Test/Mftf/Test/AdvanceCatalogSearchBundleByDescriptionMysqlTest.xml
new file mode 100644
index 0000000000000..e9525e2a144fb
--- /dev/null
+++ b/app/code/Magento/Bundle/Test/Mftf/Test/AdvanceCatalogSearchBundleByDescriptionMysqlTest.xml
@@ -0,0 +1,47 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/code/Magento/Bundle/Test/Mftf/Test/AdvanceCatalogSearchBundleByDescriptionTest.xml b/app/code/Magento/Bundle/Test/Mftf/Test/AdvanceCatalogSearchBundleByDescriptionTest.xml
new file mode 100644
index 0000000000000..95b4e06678af2
--- /dev/null
+++ b/app/code/Magento/Bundle/Test/Mftf/Test/AdvanceCatalogSearchBundleByDescriptionTest.xml
@@ -0,0 +1,51 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/code/Magento/Bundle/Test/Mftf/Test/AdvanceCatalogSearchBundleByNameMysqlTest.xml b/app/code/Magento/Bundle/Test/Mftf/Test/AdvanceCatalogSearchBundleByNameMysqlTest.xml
new file mode 100644
index 0000000000000..05fe8dd7de27e
--- /dev/null
+++ b/app/code/Magento/Bundle/Test/Mftf/Test/AdvanceCatalogSearchBundleByNameMysqlTest.xml
@@ -0,0 +1,47 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/code/Magento/Bundle/Test/Mftf/Test/AdvanceCatalogSearchBundleByPriceMysqlTest.xml b/app/code/Magento/Bundle/Test/Mftf/Test/AdvanceCatalogSearchBundleByPriceMysqlTest.xml
new file mode 100644
index 0000000000000..c70e9a95ab532
--- /dev/null
+++ b/app/code/Magento/Bundle/Test/Mftf/Test/AdvanceCatalogSearchBundleByPriceMysqlTest.xml
@@ -0,0 +1,56 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/code/Magento/Bundle/Test/Mftf/Test/AdvanceCatalogSearchBundleByPriceTest.xml b/app/code/Magento/Bundle/Test/Mftf/Test/AdvanceCatalogSearchBundleByPriceTest.xml
new file mode 100644
index 0000000000000..f45c9ceba635f
--- /dev/null
+++ b/app/code/Magento/Bundle/Test/Mftf/Test/AdvanceCatalogSearchBundleByPriceTest.xml
@@ -0,0 +1,60 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/code/Magento/Bundle/Test/Mftf/Test/AdvanceCatalogSearchBundleByShortDescriptionMysqlTest.xml b/app/code/Magento/Bundle/Test/Mftf/Test/AdvanceCatalogSearchBundleByShortDescriptionMysqlTest.xml
new file mode 100644
index 0000000000000..2bb2974b78555
--- /dev/null
+++ b/app/code/Magento/Bundle/Test/Mftf/Test/AdvanceCatalogSearchBundleByShortDescriptionMysqlTest.xml
@@ -0,0 +1,47 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/code/Magento/Bundle/Test/Mftf/Test/AdvanceCatalogSearchBundleByShortDescriptionTest.xml b/app/code/Magento/Bundle/Test/Mftf/Test/AdvanceCatalogSearchBundleByShortDescriptionTest.xml
new file mode 100644
index 0000000000000..05e14174d14a5
--- /dev/null
+++ b/app/code/Magento/Bundle/Test/Mftf/Test/AdvanceCatalogSearchBundleByShortDescriptionTest.xml
@@ -0,0 +1,51 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/code/Magento/Bundle/Test/Mftf/Test/AdvanceCatalogSearchBundleBySkuTest.xml b/app/code/Magento/Bundle/Test/Mftf/Test/AdvanceCatalogSearchBundleBySkuTest.xml
new file mode 100644
index 0000000000000..eadf7667b010b
--- /dev/null
+++ b/app/code/Magento/Bundle/Test/Mftf/Test/AdvanceCatalogSearchBundleBySkuTest.xml
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/code/Magento/Bundle/Test/Mftf/Test/AdvanceCatalogSearchBundleProductTest.xml b/app/code/Magento/Bundle/Test/Mftf/Test/AdvanceCatalogSearchBundleProductTest.xml
index c6aab0ea54ea2..e6af89181e558 100644
--- a/app/code/Magento/Bundle/Test/Mftf/Test/AdvanceCatalogSearchBundleProductTest.xml
+++ b/app/code/Magento/Bundle/Test/Mftf/Test/AdvanceCatalogSearchBundleProductTest.xml
@@ -36,280 +36,8 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
@@ -320,49 +48,4 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/app/code/Magento/Bundle/Test/Mftf/Test/MassEnableDisableBundleProductsTest.xml b/app/code/Magento/Bundle/Test/Mftf/Test/MassEnableDisableBundleProductsTest.xml
index 97e509db39fa7..4760570adfa2e 100644
--- a/app/code/Magento/Bundle/Test/Mftf/Test/MassEnableDisableBundleProductsTest.xml
+++ b/app/code/Magento/Bundle/Test/Mftf/Test/MassEnableDisableBundleProductsTest.xml
@@ -120,9 +120,7 @@
-
-
-
+
diff --git a/app/code/Magento/Bundle/Test/Mftf/Test/StorefrontAdvanceCatalogSearchBundleBySkuWithHyphenTest.xml b/app/code/Magento/Bundle/Test/Mftf/Test/StorefrontAdvanceCatalogSearchBundleBySkuWithHyphenTest.xml
index d8d6034cd1a21..07be59b998dec 100644
--- a/app/code/Magento/Bundle/Test/Mftf/Test/StorefrontAdvanceCatalogSearchBundleBySkuWithHyphenTest.xml
+++ b/app/code/Magento/Bundle/Test/Mftf/Test/StorefrontAdvanceCatalogSearchBundleBySkuWithHyphenTest.xml
@@ -36,8 +36,7 @@
-
-
+
diff --git a/app/code/Magento/Bundle/Test/Mftf/Test/StorefrontBundleAddToCartSuccessTest.xml b/app/code/Magento/Bundle/Test/Mftf/Test/StorefrontBundleAddToCartSuccessTest.xml
new file mode 100644
index 0000000000000..9fc19f5c5750f
--- /dev/null
+++ b/app/code/Magento/Bundle/Test/Mftf/Test/StorefrontBundleAddToCartSuccessTest.xml
@@ -0,0 +1,114 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/code/Magento/Bundle/Test/Mftf/Test/StorefrontBundleCartTest.xml b/app/code/Magento/Bundle/Test/Mftf/Test/StorefrontBundleCartTest.xml
index d617ced82074e..ed4a592b0d71e 100644
--- a/app/code/Magento/Bundle/Test/Mftf/Test/StorefrontBundleCartTest.xml
+++ b/app/code/Magento/Bundle/Test/Mftf/Test/StorefrontBundleCartTest.xml
@@ -124,108 +124,4 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/app/code/Magento/Bundle/Test/Mftf/Test/StorefrontBundleProductShownInCategoryListAndGridTest.xml b/app/code/Magento/Bundle/Test/Mftf/Test/StorefrontBundleProductShownInCategoryListAndGridTest.xml
index 62a66b7d092ef..b29a9cda7e519 100644
--- a/app/code/Magento/Bundle/Test/Mftf/Test/StorefrontBundleProductShownInCategoryListAndGridTest.xml
+++ b/app/code/Magento/Bundle/Test/Mftf/Test/StorefrontBundleProductShownInCategoryListAndGridTest.xml
@@ -76,9 +76,7 @@
-
-
-
+
diff --git a/app/code/Magento/Catalog/Block/Product/ListProduct.php b/app/code/Magento/Catalog/Block/Product/ListProduct.php
index 144cb682e2d22..59f5cc1b53b26 100644
--- a/app/code/Magento/Catalog/Block/Product/ListProduct.php
+++ b/app/code/Magento/Catalog/Block/Product/ListProduct.php
@@ -355,6 +355,7 @@ public function getIdentities()
}
foreach ($this->_getProductCollection() as $item) {
+ // phpcs:ignore Magento2.Performance.ForeachArrayMerge
$identities = array_merge($identities, $item->getIdentities());
}
@@ -475,8 +476,6 @@ private function initializeProductCollection()
$layer->setCurrentCategory($origCategory);
}
- $this->addToolbarBlock($collection);
-
$this->_eventManager->dispatch(
'catalog_block_product_list_collection',
['collection' => $collection]
diff --git a/app/code/Magento/Catalog/Model/CategoryRepository.php b/app/code/Magento/Catalog/Model/CategoryRepository.php
index a8636306f5e5b..0ce52b966c32c 100644
--- a/app/code/Magento/Catalog/Model/CategoryRepository.php
+++ b/app/code/Magento/Catalog/Model/CategoryRepository.php
@@ -108,6 +108,7 @@ public function save(\Magento\Catalog\Api\Data\CategoryInterface $category)
$parentCategory = $this->get($parentId, $storeId);
$existingData['path'] = $parentCategory->getPath();
$existingData['parent_id'] = $parentId;
+ $existingData['level'] = null;
}
$category->addData($existingData);
try {
diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminAssertParentChildCategoryTreeElementsActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminAssertParentChildCategoryTreeElementsActionGroup.xml
new file mode 100644
index 0000000000000..b1ed08db05b9a
--- /dev/null
+++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminAssertParentChildCategoryTreeElementsActionGroup.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+ Checks category tree, parent category has child category element.
+
+
+
+
+
+
+
+
+
diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminExpandCategoryTreeActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminExpandCategoryTreeActionGroup.xml
new file mode 100644
index 0000000000000..f2cce9b9a42fe
--- /dev/null
+++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminExpandCategoryTreeActionGroup.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+ Expands category tree.
+
+
+
+
+
+
diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminOpenCategoryPageActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminOpenCategoryPageActionGroup.xml
new file mode 100644
index 0000000000000..14c4f5234ba67
--- /dev/null
+++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminOpenCategoryPageActionGroup.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+ Navigates to category page.
+
+
+
+
+
+
diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertAdminCategoryLevelByParentCategoryLevelActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertAdminCategoryLevelByParentCategoryLevelActionGroup.xml
new file mode 100644
index 0000000000000..1830a6abc992e
--- /dev/null
+++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AssertAdminCategoryLevelByParentCategoryLevelActionGroup.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+ Checks category level by parent category level.
+
+
+
+
+
+
+
+
+
diff --git a/app/code/Magento/Catalog/Test/Mftf/Data/CategoryData.xml b/app/code/Magento/Catalog/Test/Mftf/Data/CategoryData.xml
index e252931a0363f..daf4809a4781a 100644
--- a/app/code/Magento/Catalog/Test/Mftf/Data/CategoryData.xml
+++ b/app/code/Magento/Catalog/Test/Mftf/Data/CategoryData.xml
@@ -259,4 +259,10 @@
true
+
+ cat with level 1
+ true
+ 0
+
+
diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/AdminCategorySidebarTreeSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/AdminCategorySidebarTreeSection.xml
index 304c34b404ea5..c35e775152ac9 100644
--- a/app/code/Magento/Catalog/Test/Mftf/Section/AdminCategorySidebarTreeSection.xml
+++ b/app/code/Magento/Catalog/Test/Mftf/Section/AdminCategorySidebarTreeSection.xml
@@ -16,6 +16,7 @@
+
diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminCheckNewCategoryLevelAddedViaApiTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCheckNewCategoryLevelAddedViaApiTest.xml
new file mode 100644
index 0000000000000..427ef6551ce9b
--- /dev/null
+++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminCheckNewCategoryLevelAddedViaApiTest.xml
@@ -0,0 +1,44 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/code/Magento/Catalog/Test/Unit/Block/Product/ListProductTest.php b/app/code/Magento/Catalog/Test/Unit/Block/Product/ListProductTest.php
index fe07f69e8046f..4653934311938 100644
--- a/app/code/Magento/Catalog/Test/Unit/Block/Product/ListProductTest.php
+++ b/app/code/Magento/Catalog/Test/Unit/Block/Product/ListProductTest.php
@@ -187,10 +187,6 @@ public function testGetIdentities()
->method('getProductCollection')
->will($this->returnValue($this->prodCollectionMock));
- $this->layoutMock->expects($this->once())
- ->method('getBlock')
- ->will($this->returnValue($this->toolbarMock));
-
$this->assertEquals(
[$categoryTag, $productTag],
$this->block->getIdentities()
diff --git a/app/code/Magento/Catalog/Test/Unit/Model/CategoryRepositoryTest.php b/app/code/Magento/Catalog/Test/Unit/Model/CategoryRepositoryTest.php
index 864b91b20d017..3799e6e5fa4aa 100644
--- a/app/code/Magento/Catalog/Test/Unit/Model/CategoryRepositoryTest.php
+++ b/app/code/Magento/Catalog/Test/Unit/Model/CategoryRepositoryTest.php
@@ -204,7 +204,7 @@ public function testCreateNewCategory()
$parentCategoryId = 15;
$newCategoryId = 25;
$categoryData = ['level' => '1', 'path' => '1/2', 'parent_id' => 1, 'name' => 'category'];
- $dataForSave = ['store_id' => 1, 'name' => 'category', 'path' => 'path', 'parent_id' => 15];
+ $dataForSave = ['store_id' => 1, 'name' => 'category', 'path' => 'path', 'parent_id' => 15, 'level' => null];
$this->extensibleDataObjectConverterMock
->expects($this->once())
->method('toNestedArray')
diff --git a/app/code/Magento/Cms/Controller/Page/View.php b/app/code/Magento/Cms/Controller/Page/View.php
index 9d5785450ec71..da35e7a9ea9e4 100644
--- a/app/code/Magento/Cms/Controller/Page/View.php
+++ b/app/code/Magento/Cms/Controller/Page/View.php
@@ -1,50 +1,78 @@
request = $request;
+ $this->pageHelper = $pageHelper;
$this->resultForwardFactory = $resultForwardFactory;
- parent::__construct($context);
}
/**
* View CMS page action
*
- * @return \Magento\Framework\Controller\ResultInterface
+ * @return ResultInterface
*/
public function execute()
{
- $pageId = $this->getRequest()->getParam('page_id', $this->getRequest()->getParam('id', false));
- $resultPage = $this->_objectManager->get(\Magento\Cms\Helper\Page::class)->prepareResultPage($this, $pageId);
+ $resultPage = $this->pageHelper->prepareResultPage($this, $this->getPageId());
if (!$resultPage) {
$resultForward = $this->resultForwardFactory->create();
return $resultForward->forward('noroute');
}
return $resultPage;
}
+
+ /**
+ * Returns Page ID if provided or null
+ *
+ * @return int|null
+ */
+ private function getPageId(): ?int
+ {
+ $id = $this->request->getParam('page_id') ?? $this->request->getParam('id');
+
+ return $id ? (int)$id : null;
+ }
}
diff --git a/app/code/Magento/Cms/Helper/Page.php b/app/code/Magento/Cms/Helper/Page.php
index 39b292bf07239..d899a5cea985a 100644
--- a/app/code/Magento/Cms/Helper/Page.php
+++ b/app/code/Magento/Cms/Helper/Page.php
@@ -8,17 +8,20 @@
use Magento\Cms\Model\Page\CustomLayoutManagerInterface;
use Magento\Cms\Model\Page\CustomLayoutRepositoryInterface;
use Magento\Cms\Model\Page\IdentityMap;
-use Magento\Framework\App\Action\Action;
+use Magento\Framework\App\ActionInterface;
+use Magento\Framework\App\Helper\AbstractHelper;
use Magento\Framework\App\ObjectManager;
use Magento\Framework\Exception\NoSuchEntityException;
+use Magento\Framework\View\Result\Page as ResultPage;
/**
* CMS Page Helper
+ *
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
* @SuppressWarnings(PHPMD.NPathComplexity)
*/
-class Page extends \Magento\Framework\App\Helper\AbstractHelper
+class Page extends AbstractHelper
{
/**
* CMS no-route config path
@@ -146,14 +149,14 @@ public function __construct(
/**
* Return result CMS page
*
- * @param Action $action
+ * @param ActionInterface $action
* @param int $pageId
- * @return \Magento\Framework\View\Result\Page|bool
+ * @return ResultPage|bool
*/
- public function prepareResultPage(Action $action, $pageId = null)
+ public function prepareResultPage(ActionInterface $action, $pageId = null)
{
if ($pageId !== null && $pageId !== $this->_page->getId()) {
- $delimiterPosition = strrpos($pageId, '|');
+ $delimiterPosition = strrpos((string)$pageId, '|');
if ($delimiterPosition) {
$pageId = substr($pageId, 0, $delimiterPosition);
}
@@ -180,7 +183,7 @@ public function prepareResultPage(Action $action, $pageId = null)
$this->_design->setDesignTheme($this->_page->getCustomTheme());
}
}
- /** @var \Magento\Framework\View\Result\Page $resultPage */
+ /** @var ResultPage $resultPage */
$resultPage = $this->resultPageFactory->create();
$this->setLayoutType($inRange, $resultPage);
$resultPage->addHandle('cms_page_view');
@@ -247,8 +250,8 @@ public function getPageUrl($pageId = null)
* Set layout type
*
* @param bool $inRange
- * @param \Magento\Framework\View\Result\Page $resultPage
- * @return \Magento\Framework\View\Result\Page
+ * @param ResultPage $resultPage
+ * @return ResultPage
*/
protected function setLayoutType($inRange, $resultPage)
{
diff --git a/app/code/Magento/Cms/Test/Unit/Controller/Page/ViewTest.php b/app/code/Magento/Cms/Test/Unit/Controller/Page/ViewTest.php
index f15e6ff3e3bf2..e4c2beaa75aa7 100644
--- a/app/code/Magento/Cms/Test/Unit/Controller/Page/ViewTest.php
+++ b/app/code/Magento/Cms/Test/Unit/Controller/Page/ViewTest.php
@@ -3,73 +3,80 @@
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
+declare(strict_types=1);
+
namespace Magento\Cms\Test\Unit\Controller\Page;
-class ViewTest extends \PHPUnit\Framework\TestCase
+use Magento\Cms\Controller\Page\View;
+use Magento\Cms\Helper\Page as PageHelper;
+use Magento\Framework\App\RequestInterface;
+use Magento\Framework\Controller\Result\Forward;
+use Magento\Framework\Controller\Result\ForwardFactory;
+use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper;
+use Magento\Framework\View\Result\Page;
+use PHPUnit\Framework\MockObject\MockObject;
+use PHPUnit\Framework\TestCase;
+
+class ViewTest extends TestCase
{
+ private const STUB_PAGE_ID = 2;
+
/**
- * @var \Magento\Cms\Controller\Page\View
+ * @var View
*/
protected $controller;
/**
- * @var \PHPUnit_Framework_MockObject_MockObject
+ * @var MockObject
*/
- protected $cmsHelperMock;
+ protected $pageHelperMock;
/**
- * @var \PHPUnit_Framework_MockObject_MockObject
+ * @var MockObject|RequestInterface
*/
protected $requestMock;
/**
- * @var \Magento\Framework\Controller\Result\ForwardFactory|\PHPUnit_Framework_MockObject_MockObject
+ * @var MockObject|ForwardFactory
*/
protected $forwardFactoryMock;
/**
- * @var \Magento\Framework\Controller\Result\Forward|\PHPUnit_Framework_MockObject_MockObject
+ * @var MockObject|Forward
*/
protected $forwardMock;
/**
- * @var \Magento\Framework\View\Result\Page|\PHPUnit_Framework_MockObject_MockObject
+ * @var MockObject|Page
*/
protected $resultPageMock;
- /**
- * @var string
- */
- protected $pageId = '2';
-
protected function setUp()
{
- $helper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this);
- $objectManagerMock = $this->createMock(\Magento\Framework\ObjectManagerInterface::class);
- $responseMock = $this->createMock(\Magento\Framework\App\Response\Http::class);
- $this->resultPageMock = $this->getMockBuilder(\Magento\Framework\View\Result\Page::class)
+ $objectManager = new ObjectManagerHelper($this);
+
+ $this->resultPageMock = $this->getMockBuilder(Page::class)
->disableOriginalConstructor()
->getMock();
- $this->forwardFactoryMock = $this->getMockBuilder(\Magento\Framework\Controller\Result\ForwardFactory::class)
+ $this->forwardFactoryMock = $this->getMockBuilder(ForwardFactory::class)
->setMethods(['create'])
->disableOriginalConstructor()
->getMock();
- $this->forwardMock = $this->getMockBuilder(\Magento\Framework\Controller\Result\Forward::class)
+ $this->forwardMock = $this->getMockBuilder(Forward::class)
->disableOriginalConstructor()
->getMock();
$this->forwardFactoryMock->expects($this->any())
->method('create')
->willReturn($this->forwardMock);
- $this->requestMock = $this->createMock(\Magento\Framework\App\Request\Http::class);
- $this->cmsHelperMock = $this->createMock(\Magento\Cms\Helper\Page::class);
- $objectManagerMock->expects($this->once())->method('get')->willReturn($this->cmsHelperMock);
- $this->controller = $helper->getObject(
- \Magento\Cms\Controller\Page\View::class,
+ $this->requestMock = $this->createMock(RequestInterface::class);
+ $this->pageHelperMock = $this->createMock(PageHelper::class);
+
+ $this->controller = $objectManager->getObject(
+ View::class,
[
- 'response' => $responseMock,
- 'objectManager' => $objectManagerMock,
'request' => $this->requestMock,
+ 'pageHelper' => $this->pageHelperMock,
'resultForwardFactory' => $this->forwardFactoryMock
]
);
@@ -81,13 +88,13 @@ public function testExecuteResultPage()
->method('getParam')
->willReturnMap(
[
- ['page_id', $this->pageId, $this->pageId],
- ['id', false, $this->pageId]
+ ['page_id', null, self::STUB_PAGE_ID],
+ ['id', null, self::STUB_PAGE_ID]
]
);
- $this->cmsHelperMock->expects($this->once())
+ $this->pageHelperMock->expects($this->once())
->method('prepareResultPage')
- ->with($this->controller, $this->pageId)
+ ->with($this->controller, self::STUB_PAGE_ID)
->willReturn($this->resultPageMock);
$this->assertSame($this->resultPageMock, $this->controller->execute());
}
@@ -98,8 +105,8 @@ public function testExecuteResultForward()
->method('getParam')
->willReturnMap(
[
- ['page_id', $this->pageId, $this->pageId],
- ['id', false, $this->pageId]
+ ['page_id', null, self::STUB_PAGE_ID],
+ ['id', null, self::STUB_PAGE_ID]
]
);
$this->forwardMock->expects($this->once())
diff --git a/app/code/Magento/Customer/Controller/AbstractAccount.php b/app/code/Magento/Customer/Controller/AbstractAccount.php
index 21611329ed9bc..4f2c80711d292 100644
--- a/app/code/Magento/Customer/Controller/AbstractAccount.php
+++ b/app/code/Magento/Customer/Controller/AbstractAccount.php
@@ -9,9 +9,11 @@
use Magento\Framework\App\Action\Action;
/**
- * Class AbstractAccount
- * @package Magento\Customer\Controller
+ * AbstractAccount class is deprecated, in favour of Composition approach to build Controllers
+ *
* @SuppressWarnings(PHPMD.NumberOfChildren)
+ * @deprecated
+ * @see \Magento\Customer\Controller\AccountInterface
*/
abstract class AbstractAccount extends Action implements AccountInterface
{
diff --git a/app/code/Magento/Customer/Controller/Plugin/Account.php b/app/code/Magento/Customer/Controller/Plugin/Account.php
index 179da148e7f78..bbdb58d626108 100644
--- a/app/code/Magento/Customer/Controller/Plugin/Account.php
+++ b/app/code/Magento/Customer/Controller/Plugin/Account.php
@@ -3,21 +3,31 @@
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
+declare(strict_types=1);
+
namespace Magento\Customer\Controller\Plugin;
+use Closure;
+use Magento\Customer\Controller\AccountInterface;
use Magento\Customer\Model\Session;
-use Magento\Framework\App\ActionInterface;
use Magento\Framework\App\RequestInterface;
use Magento\Framework\App\ResponseInterface;
-use Magento\Framework\App\Action\AbstractAction;
use Magento\Framework\Controller\ResultInterface;
+/**
+ * Plugin verifies permissions using Action Name against injected (`fontend/di.xml`) rules
+ */
class Account
{
/**
* @var Session
*/
- protected $session;
+ private $session;
+
+ /**
+ * @var RequestInterface
+ */
+ private $request;
/**
* @var array
@@ -25,50 +35,46 @@ class Account
private $allowedActions = [];
/**
+ * @param RequestInterface $request
* @param Session $customerSession
* @param array $allowedActions List of actions that are allowed for not authorized users
*/
public function __construct(
+ RequestInterface $request,
Session $customerSession,
array $allowedActions = []
) {
+ $this->request = $request;
$this->session = $customerSession;
$this->allowedActions = $allowedActions;
}
/**
- * Dispatch actions allowed for not authorized users
+ * Executes original method if allowed, otherwise - redirects to log in
*
- * @param AbstractAction $subject
- * @param RequestInterface $request
- * @return void
+ * @param AccountInterface $controllerAction
+ * @param Closure $proceed
+ * @return ResultInterface|ResponseInterface|void
+ * @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
- public function beforeDispatch(AbstractAction $subject, RequestInterface $request)
+ public function aroundExecute(AccountInterface $controllerAction, Closure $proceed)
{
- $action = strtolower($request->getActionName());
- $pattern = '/^(' . implode('|', $this->allowedActions) . ')$/i';
-
- if (!preg_match($pattern, $action)) {
- if (!$this->session->authenticate()) {
- $subject->getActionFlag()->set('', ActionInterface::FLAG_NO_DISPATCH, true);
- }
- } else {
- $this->session->setNoReferer(true);
+ /** @FIXME Move Authentication and redirect out of Session model */
+ if ($this->isActionAllowed() || $this->session->authenticate()) {
+ return $proceed();
}
}
/**
- * Remove No-referer flag from customer session
+ * Validates whether currently requested action is one of the allowed
*
- * @param AbstractAction $subject
- * @param ResponseInterface|ResultInterface $result
- * @param RequestInterface $request
- * @return ResponseInterface|ResultInterface
- * @SuppressWarnings(PHPMD.UnusedFormalParameter)
+ * @return bool
*/
- public function afterDispatch(AbstractAction $subject, $result, RequestInterface $request)
+ private function isActionAllowed(): bool
{
- $this->session->unsNoReferer(false);
- return $result;
+ $action = strtolower($this->request->getActionName());
+ $pattern = '/^(' . implode('|', $this->allowedActions) . ')$/i';
+
+ return (bool)preg_match($pattern, $action);
}
}
diff --git a/app/code/Magento/Customer/Test/Unit/Controller/Plugin/AccountTest.php b/app/code/Magento/Customer/Test/Unit/Controller/Plugin/AccountTest.php
index 2c70a8bda28fe..01ff1ced05ff9 100644
--- a/app/code/Magento/Customer/Test/Unit/Controller/Plugin/AccountTest.php
+++ b/app/code/Magento/Customer/Test/Unit/Controller/Plugin/AccountTest.php
@@ -3,18 +3,23 @@
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
+
namespace Magento\Customer\Test\Unit\Controller\Plugin;
+use Closure;
+use Magento\Customer\Controller\AccountInterface;
use Magento\Customer\Controller\Plugin\Account;
use Magento\Customer\Model\Session;
use Magento\Framework\App\ActionFlag;
use Magento\Framework\App\ActionInterface;
-use Magento\Framework\App\Action\AbstractAction;
use Magento\Framework\App\Request\Http;
+use Magento\Framework\App\Request\Http as HttpRequest;
use Magento\Framework\Controller\ResultInterface;
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
+use PHPUnit\Framework\MockObject\MockObject;
+use PHPUnit\Framework\TestCase;
-class AccountTest extends \PHPUnit\Framework\TestCase
+class AccountTest extends TestCase
{
/**
* @var string
@@ -27,59 +32,51 @@ class AccountTest extends \PHPUnit\Framework\TestCase
protected $plugin;
/**
- * @var Session | \PHPUnit_Framework_MockObject_MockObject
+ * @var Session|MockObject
*/
- protected $session;
+ protected $sessionMock;
/**
- * @var AbstractAction | \PHPUnit_Framework_MockObject_MockObject
+ * @var AccountInterface|MockObject
*/
- protected $subject;
+ protected $actionMock;
/**
- * @var Http | \PHPUnit_Framework_MockObject_MockObject
+ * @var Http|MockObject
*/
- protected $request;
+ protected $requestMock;
/**
- * @var ActionFlag | \PHPUnit_Framework_MockObject_MockObject
+ * @var ActionFlag|MockObject
*/
- protected $actionFlag;
+ protected $actionFlagMock;
/**
- * @var ResultInterface|\PHPUnit_Framework_MockObject_MockObject
+ * @var ResultInterface|MockObject
*/
- private $resultInterface;
+ private $resultMock;
protected function setUp()
{
- $this->session = $this->getMockBuilder(\Magento\Customer\Model\Session::class)
+ $this->sessionMock = $this->getMockBuilder(Session::class)
->disableOriginalConstructor()
- ->setMethods([
- 'setNoReferer',
- 'unsNoReferer',
- 'authenticate',
- ])
+ ->setMethods(['setNoReferer', 'unsNoReferer', 'authenticate'])
->getMock();
- $this->subject = $this->getMockBuilder(AbstractAction::class)
- ->setMethods([
- 'getActionFlag',
- ])
+ $this->actionMock = $this->getMockBuilder(AccountInterface::class)
+ ->setMethods(['getActionFlag'])
->disableOriginalConstructor()
->getMockForAbstractClass();
- $this->request = $this->getMockBuilder(\Magento\Framework\App\Request\Http::class)
+ $this->requestMock = $this->getMockBuilder(HttpRequest::class)
->disableOriginalConstructor()
- ->setMethods([
- 'getActionName',
- ])
+ ->setMethods(['getActionName'])
->getMock();
- $this->resultInterface = $this->getMockBuilder(ResultInterface::class)
+ $this->resultMock = $this->getMockBuilder(ResultInterface::class)
->getMockForAbstractClass();
- $this->actionFlag = $this->getMockBuilder(\Magento\Framework\App\ActionFlag::class)
+ $this->actionFlagMock = $this->getMockBuilder(ActionFlag::class)
->disableOriginalConstructor()
->getMock();
}
@@ -87,50 +84,46 @@ protected function setUp()
/**
* @param string $action
* @param array $allowedActions
- * @param boolean $isActionAllowed
- * @param boolean $isAuthenticated
+ * @param boolean $isAllowed
*
- * @dataProvider beforeDispatchDataProvider
+ * @dataProvider beforeExecuteDataProvider
*/
- public function testBeforeDispatch(
- $action,
- $allowedActions,
- $isActionAllowed,
- $isAuthenticated
+ public function testAroundExecuteInterruptsOriginalCallWhenNotAllowed(
+ string $action,
+ array $allowedActions,
+ bool $isAllowed
) {
- $this->request->expects($this->once())
+ /** @var callable|MockObject $proceedMock */
+ $proceedMock = $this->getMockBuilder(\stdClass::class)
+ ->setMethods(['__invoke'])
+ ->getMock();
+
+ $closureMock = Closure::fromCallable($proceedMock);
+
+ $this->requestMock->expects($this->once())
->method('getActionName')
->willReturn($action);
- if ($isActionAllowed) {
- $this->session->expects($this->once())
- ->method('setNoReferer')
- ->with(true)
- ->willReturnSelf();
+ if ($isAllowed) {
+ $proceedMock->expects($this->once())->method('__invoke')->willReturn($this->resultMock);
} else {
- $this->session->expects($this->once())
- ->method('authenticate')
- ->willReturn($isAuthenticated);
- if (!$isAuthenticated) {
- $this->subject->expects($this->once())
- ->method('getActionFlag')
- ->willReturn($this->actionFlag);
-
- $this->actionFlag->expects($this->once())
- ->method('set')
- ->with('', ActionInterface::FLAG_NO_DISPATCH, true)
- ->willReturnSelf();
- }
+ $proceedMock->expects($this->never())->method('__invoke');
}
- $plugin = new Account($this->session, $allowedActions);
- $plugin->beforeDispatch($this->subject, $this->request);
+ $plugin = new Account($this->requestMock, $this->sessionMock, $allowedActions);
+ $result = $plugin->aroundExecute($this->actionMock, $closureMock);
+
+ if ($isAllowed) {
+ $this->assertSame($this->resultMock, $result);
+ } else {
+ $this->assertNull($result);
+ }
}
/**
* @return array
*/
- public function beforeDispatchDataProvider()
+ public function beforeExecuteDataProvider()
{
return [
[
@@ -165,24 +158,4 @@ public function beforeDispatchDataProvider()
],
];
}
-
- public function testAfterDispatch()
- {
- $this->session->expects($this->once())
- ->method('unsNoReferer')
- ->with(false)
- ->willReturnSelf();
-
- $plugin = (new ObjectManager($this))->getObject(
- Account::class,
- [
- 'session' => $this->session,
- 'allowedActions' => ['testaction']
- ]
- );
- $this->assertSame(
- $this->resultInterface,
- $plugin->afterDispatch($this->subject, $this->resultInterface, $this->request)
- );
- }
}
diff --git a/app/code/Magento/Customer/etc/frontend/di.xml b/app/code/Magento/Customer/etc/frontend/di.xml
index a479d0d2af328..8867042cc6dc9 100644
--- a/app/code/Magento/Customer/etc/frontend/di.xml
+++ b/app/code/Magento/Customer/etc/frontend/di.xml
@@ -51,7 +51,7 @@
-
+
diff --git a/app/code/Magento/Directory/Setup/Patch/Data/AddDataForItaly.php b/app/code/Magento/Directory/Setup/Patch/Data/AddDataForItaly.php
new file mode 100644
index 0000000000000..a5d4bcdc0b8be
--- /dev/null
+++ b/app/code/Magento/Directory/Setup/Patch/Data/AddDataForItaly.php
@@ -0,0 +1,196 @@
+moduleDataSetup = $moduleDataSetup;
+ $this->dataInstallerFactory = $dataInstallerFactory;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function apply()
+ {
+ /** @var DataInstaller $dataInstaller */
+ $dataInstaller = $this->dataInstallerFactory->create();
+ $dataInstaller->addCountryRegions(
+ $this->moduleDataSetup->getConnection(),
+ $this->getDataForItaly()
+ );
+
+ return $this;
+ }
+
+ /**
+ * Italy states data.
+ *
+ * @return array
+ * @SuppressWarnings(PHPMD.ExcessiveMethodLength)
+ */
+ private function getDataForItaly()
+ {
+ return [
+ ['IT', 'AG', 'Agrigento'],
+ ['IT', 'AL', 'Alessandria'],
+ ['IT', 'AN', 'Ancona'],
+ ['IT', 'AO', 'Aosta'],
+ ['IT', 'AQ', 'L\'Aquila'],
+ ['IT', 'AR', 'Arezzo'],
+ ['IT', 'AP', 'Ascoli-Piceno'],
+ ['IT', 'AT', 'Asti'],
+ ['IT', 'AV', 'Avellino'],
+ ['IT', 'BA', 'Bari'],
+ ['IT', 'BT', 'Barletta-Andria-Trani'],
+ ['IT', 'BL', 'Belluno'],
+ ['IT', 'BN', 'Benevento'],
+ ['IT', 'BG', 'Bergamo'],
+ ['IT', 'BI', 'Biella'],
+ ['IT', 'BO', 'Bologna'],
+ ['IT', 'BZ', 'Bolzano'],
+ ['IT', 'BS', 'Brescia'],
+ ['IT', 'BR', 'Brindisi'],
+ ['IT', 'CA', 'Cagliari'],
+ ['IT', 'CL', 'Caltanissetta'],
+ ['IT', 'CB', 'Campobasso'],
+ ['IT', 'CI', 'Carbonia Iglesias'],
+ ['IT', 'CE', 'Caserta'],
+ ['IT', 'CT', 'Catania'],
+ ['IT', 'CZ', 'Catanzaro'],
+ ['IT', 'CH', 'Chieti'],
+ ['IT', 'CO', 'Como'],
+ ['IT', 'CS', 'Cosenza'],
+ ['IT', 'CR', 'Cremona'],
+ ['IT', 'KR', 'Crotone'],
+ ['IT', 'CN', 'Cuneo'],
+ ['IT', 'EN', 'Enna'],
+ ['IT', 'FM', 'Fermo'],
+ ['IT', 'FE', 'Ferrara'],
+ ['IT', 'FI', 'Firenze'],
+ ['IT', 'FG', 'Foggia'],
+ ['IT', 'FC', 'Forli-Cesena'],
+ ['IT', 'FR', 'Frosinone'],
+ ['IT', 'GE', 'Genova'],
+ ['IT', 'GO', 'Gorizia'],
+ ['IT', 'GR', 'Grosseto'],
+ ['IT', 'IM', 'Imperia'],
+ ['IT', 'IS', 'Isernia'],
+ ['IT', 'SP', 'La-Spezia'],
+ ['IT', 'LT', 'Latina'],
+ ['IT', 'LE', 'Lecce'],
+ ['IT', 'LC', 'Lecco'],
+ ['IT', 'LI', 'Livorno'],
+ ['IT', 'LO', 'Lodi'],
+ ['IT', 'LU', 'Lucca'],
+ ['IT', 'MC', 'Macerata'],
+ ['IT', 'MN', 'Mantova'],
+ ['IT', 'MS', 'Massa-Carrara'],
+ ['IT', 'MT', 'Matera'],
+ ['IT', 'VS', 'Medio Campidano'],
+ ['IT', 'ME', 'Messina'],
+ ['IT', 'MI', 'Milano'],
+ ['IT', 'MO', 'Modena'],
+ ['IT', 'MB', 'Monza-Brianza'],
+ ['IT', 'NA', 'Napoli'],
+ ['IT', 'NO', 'Novara'],
+ ['IT', 'NU', 'Nuoro'],
+ ['IT', 'OG', 'Ogliastra'],
+ ['IT', 'OT', 'Olbia Tempio'],
+ ['IT', 'OR', 'Oristano'],
+ ['IT', 'PD', 'Padova'],
+ ['IT', 'PA', 'Palermo'],
+ ['IT', 'PR', 'Parma'],
+ ['IT', 'PV', 'Pavia'],
+ ['IT', 'PG', 'Perugia'],
+ ['IT', 'PU', 'Pesaro-Urbino'],
+ ['IT', 'PE', 'Pescara'],
+ ['IT', 'PC', 'Piacenza'],
+ ['IT', 'PI', 'Pisa'],
+ ['IT', 'PT', 'Pistoia'],
+ ['IT', 'PN', 'Pordenone'],
+ ['IT', 'PZ', 'Potenza'],
+ ['IT', 'PO', 'Prato'],
+ ['IT', 'RG', 'Ragusa'],
+ ['IT', 'RA', 'Ravenna'],
+ ['IT', 'RC', 'Reggio-Calabria'],
+ ['IT', 'RE', 'Reggio-Emilia'],
+ ['IT', 'RI', 'Rieti'],
+ ['IT', 'RN', 'Rimini'],
+ ['IT', 'RM', 'Roma'],
+ ['IT', 'RO', 'Rovigo'],
+ ['IT', 'SA', 'Salerno'],
+ ['IT', 'SS', 'Sassari'],
+ ['IT', 'SV', 'Savona'],
+ ['IT', 'SI', 'Siena'],
+ ['IT', 'SR', 'Siracusa'],
+ ['IT', 'SO', 'Sondrio'],
+ ['IT', 'TA', 'Taranto'],
+ ['IT', 'TE', 'Teramo'],
+ ['IT', 'TR', 'Terni'],
+ ['IT', 'TO', 'Torino'],
+ ['IT', 'TP', 'Trapani'],
+ ['IT', 'TN', 'Trento'],
+ ['IT', 'TV', 'Treviso'],
+ ['IT', 'TS', 'Trieste'],
+ ['IT', 'UD', 'Udine'],
+ ['IT', 'VA', 'Varese'],
+ ['IT', 'VE', 'Venezia'],
+ ['IT', 'VB', 'Verbania'],
+ ['IT', 'VC', 'Vercelli'],
+ ['IT', 'VR', 'Verona'],
+ ['IT', 'VV', 'Vibo-Valentia'],
+ ['IT', 'VI', 'Vicenza'],
+ ['IT', 'VT', 'Viterbo'],
+ ];
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public static function getDependencies()
+ {
+ return [
+ InitializeDirectoryData::class,
+ ];
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public function getAliases()
+ {
+ return [];
+ }
+}
diff --git a/app/code/Magento/Sales/Api/Data/OrderPaymentInterface.php b/app/code/Magento/Sales/Api/Data/OrderPaymentInterface.php
index ea0cf5d7b32be..ac400206b8a2f 100644
--- a/app/code/Magento/Sales/Api/Data/OrderPaymentInterface.php
+++ b/app/code/Magento/Sales/Api/Data/OrderPaymentInterface.php
@@ -1042,6 +1042,14 @@ public function setCcNumberEnc($ccNumberEnc);
*/
public function setCcTransId($id);
+ /**
+ * Set the additional information for the order payment.
+ *
+ * @param string[] $additionalInformation
+ * @return $this
+ */
+ public function setAdditionalInformation($additionalInformation);
+
/**
* Sets the address status for the order payment.
*
diff --git a/app/design/frontend/Magento/luma/Magento_Customer/web/css/source/_module.less b/app/design/frontend/Magento/luma/Magento_Customer/web/css/source/_module.less
index 34a2dbfeca472..a0a36f55574fe 100644
--- a/app/design/frontend/Magento/luma/Magento_Customer/web/css/source/_module.less
+++ b/app/design/frontend/Magento/luma/Magento_Customer/web/css/source/_module.less
@@ -348,6 +348,12 @@
position: relative;
}
}
+
+ .additional-addresses {
+ table > thead > tr > th {
+ white-space: nowrap;
+ }
+ }
}
//
diff --git a/dev/tests/integration/testsuite/Magento/Customer/Controller/AuthenticationTest.php b/dev/tests/integration/testsuite/Magento/Customer/Controller/AuthenticationTest.php
new file mode 100644
index 0000000000000..822b3ab8f35d1
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/Customer/Controller/AuthenticationTest.php
@@ -0,0 +1,70 @@
+resetAllowedActions();
+ parent::tearDown();
+ }
+
+ /**
+ * After changes to `di.xml` and overriding list of allowed actions, unallowed ones should cause redirect.
+ */
+ public function testExpectRedirectResponseWhenDispatchNotAllowedAction()
+ {
+ $this->overrideAllowedActions(['notExistingRoute']);
+
+ $this->dispatch('customer/account/create');
+ $this->assertRedirect($this->stringContains('customer/account/login'));
+ }
+
+ /**
+ * Allowed actions should be rendered normally
+ */
+ public function testExpectPageResponseWhenAllowedAction()
+ {
+ $this->overrideAllowedActions(['create']);
+
+ $this->dispatch('customer/account/create');
+ $this->assertEquals(200, $this->getResponse()->getStatusCode());
+ }
+
+ /**
+ * Overrides list of `allowedActions` for Authorization Plugin
+ *
+ * @param string[] $allowedActions
+ * @see \Magento\Customer\Controller\Plugin\Account
+ */
+ private function overrideAllowedActions(array $allowedActions): void
+ {
+ $allowedActions = array_combine($allowedActions, $allowedActions);
+ $pluginFake = $this->_objectManager->create(AccountPlugin::class, ['allowedActions' => $allowedActions]);
+ $this->_objectManager->addSharedInstance($pluginFake, AccountPlugin::class);
+ }
+
+ /**
+ * Removes all the customizations applied to `allowedActions`
+ * @see \Magento\Customer\Controller\Plugin\Account
+ */
+ private function resetAllowedActions()
+ {
+ $this->_objectManager->removeSharedInstance(AccountPlugin::class);
+ }
+}
diff --git a/dev/tests/integration/testsuite/Magento/Directory/Model/RegionTest.php b/dev/tests/integration/testsuite/Magento/Directory/Model/RegionTest.php
new file mode 100644
index 0000000000000..e0e790b265572
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/Directory/Model/RegionTest.php
@@ -0,0 +1,62 @@
+country = Bootstrap::getObjectManager()->create(Country::class);
+ }
+
+ /**
+ * Verify country has regions.
+ *
+ * @var string $countryId
+ * @dataProvider getCountryIdDataProvider
+ */
+ public function testCountryHasRegions($countryId)
+ {
+ $country = $this->country->loadByCode($countryId);
+ $region = $country->getRegions()->getItems();
+
+ $this->assertTrue(!empty($region), 'Country ' . $countryId . ' not have regions');
+ }
+
+ /**
+ * Data provider for testCountryHasRegions
+ *
+ * @return array
+ */
+ public function getCountryIdDataProvider():array
+ {
+ return [
+ ['countryId' => 'US'],
+ ['countryId' => 'CA'],
+ ['countryId' => 'CN'],
+ ['countryId' => 'IN'],
+ ['countryId' => 'AU'],
+ ['countryId' => 'BE'],
+ ['countryId' => 'CO'],
+ ['countryId' => 'MX'],
+ ['countryId' => 'PL'],
+ ['countryId' => 'IT']
+ ];
+ }
+}