diff --git a/app/code/Magento/Backend/view/adminhtml/templates/system/search.phtml b/app/code/Magento/Backend/view/adminhtml/templates/system/search.phtml
index b50183ced29b4..af369800287c1 100644
--- a/app/code/Magento/Backend/view/adminhtml/templates/system/search.phtml
+++ b/app/code/Magento/Backend/view/adminhtml/templates/system/search.phtml
@@ -42,7 +42,7 @@
<% if (data.items.length) { %>
<% _.each(data.items, function(value){ %>
+ <%= data.optionData(value) %>
>
<%- value.name %>
<%- value.type %>
diff --git a/app/code/Magento/Catalog/Model/Indexer/Product/Flat/Action/Indexer.php b/app/code/Magento/Catalog/Model/Indexer/Product/Flat/Action/Indexer.php
index 3a1611299288c..466ba746fa108 100644
--- a/app/code/Magento/Catalog/Model/Indexer/Product/Flat/Action/Indexer.php
+++ b/app/code/Magento/Catalog/Model/Indexer/Product/Flat/Action/Indexer.php
@@ -56,39 +56,36 @@ public function __construct(
* @return \Magento\Catalog\Model\Indexer\Product\Flat
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
+ * @SuppressWarnings(PHPMD.NPathComplexity)
*/
public function write($storeId, $productId, $valueFieldSuffix = '')
{
$flatTable = $this->_productIndexerHelper->getFlatTableName($storeId);
+ $entityTableName = $this->_productIndexerHelper->getTable('catalog_product_entity');
$attributes = $this->_productIndexerHelper->getAttributes();
$eavAttributes = $this->_productIndexerHelper->getTablesStructure($attributes);
$updateData = [];
$describe = $this->_connection->describeTable($flatTable);
+ $metadata = $this->getMetadataPool()->getMetadata(ProductInterface::class);
+ $linkField = $metadata->getLinkField();
foreach ($eavAttributes as $tableName => $tableColumns) {
$columnsChunks = array_chunk($tableColumns, self::ATTRIBUTES_CHUNK_SIZE, true);
foreach ($columnsChunks as $columns) {
$select = $this->_connection->select();
- $selectValue = $this->_connection->select();
- $keyColumns = [
- 'entity_id' => 'e.entity_id',
- 'attribute_id' => 't.attribute_id',
- 'value' => $this->_connection->getIfNullSql('`t2`.`value`', '`t`.`value`'),
- ];
-
- if ($tableName != $this->_productIndexerHelper->getTable('catalog_product_entity')) {
+
+ if ($tableName != $entityTableName) {
$valueColumns = [];
$ids = [];
$select->from(
- ['e' => $this->_productIndexerHelper->getTable('catalog_product_entity')],
- $keyColumns
- );
-
- $selectValue->from(
- ['e' => $this->_productIndexerHelper->getTable('catalog_product_entity')],
- $keyColumns
+ ['e' => $entityTableName],
+ [
+ 'entity_id' => 'e.entity_id',
+ 'attribute_id' => 't.attribute_id',
+ 'value' => $this->_connection->getIfNullSql('`t2`.`value`', '`t`.`value`'),
+ ]
);
/** @var $attribute \Magento\Catalog\Model\ResourceModel\Eav\Attribute */
@@ -97,8 +94,7 @@ public function write($storeId, $productId, $valueFieldSuffix = '')
$ids[$attribute->getId()] = $columnName;
}
}
- $linkField = $this->getMetadataPool()->getMetadata(ProductInterface::class)->getLinkField();
- $select->joinLeft(
+ $select->joinInner(
['t' => $tableName],
sprintf('e.%s = t.%s ', $linkField, $linkField) . $this->_connection->quoteInto(
' AND t.attribute_id IN (?)',
@@ -116,8 +112,6 @@ public function write($storeId, $productId, $valueFieldSuffix = '')
[]
)->where(
'e.entity_id = ' . $productId
- )->where(
- 't.attribute_id IS NOT NULL'
);
$cursor = $this->_connection->query($select);
while ($row = $cursor->fetch(\Zend_Db::FETCH_ASSOC)) {
@@ -157,7 +151,7 @@ public function write($storeId, $productId, $valueFieldSuffix = '')
$columnNames[] = 'attribute_set_id';
$columnNames[] = 'type_id';
$select->from(
- ['e' => $this->_productIndexerHelper->getTable('catalog_product_entity')],
+ ['e' => $entityTableName],
$columnNames
)->where(
'e.entity_id = ' . $productId
@@ -175,7 +169,9 @@ public function write($storeId, $productId, $valueFieldSuffix = '')
if (!empty($updateData)) {
$updateData += ['entity_id' => $productId];
- $updateData += ['row_id' => $productId];
+ if ($linkField !== $metadata->getIdentifierField()) {
+ $updateData += [$linkField => $productId];
+ }
$updateFields = [];
foreach ($updateData as $key => $value) {
$updateFields[$key] = $key;
@@ -187,6 +183,8 @@ public function write($storeId, $productId, $valueFieldSuffix = '')
}
/**
+ * Get MetadataPool instance
+ *
* @return \Magento\Framework\EntityManager\MetadataPool
*/
private function getMetadataPool()
diff --git a/app/code/Magento/Catalog/Model/Indexer/Product/Flat/Action/Row.php b/app/code/Magento/Catalog/Model/Indexer/Product/Flat/Action/Row.php
index 709f27d031ebe..6d0727259d9db 100644
--- a/app/code/Magento/Catalog/Model/Indexer/Product/Flat/Action/Row.php
+++ b/app/code/Magento/Catalog/Model/Indexer/Product/Flat/Action/Row.php
@@ -5,16 +5,20 @@
*/
namespace Magento\Catalog\Model\Indexer\Product\Flat\Action;
+use Magento\Catalog\Api\Data\ProductInterface;
use Magento\Catalog\Model\Indexer\Product\Flat\FlatTableBuilder;
use Magento\Catalog\Model\Indexer\Product\Flat\TableBuilder;
+use Magento\Framework\EntityManager\MetadataPool;
/**
- * Class Row reindex action
+ * Class Row reindex action.
+ *
+ * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
*/
class Row extends \Magento\Catalog\Model\Indexer\Product\Flat\AbstractAction
{
/**
- * @var \Magento\Catalog\Model\Indexer\Product\Flat\Action\Indexer
+ * @var Indexer
*/
protected $flatItemWriter;
@@ -23,6 +27,11 @@ class Row extends \Magento\Catalog\Model\Indexer\Product\Flat\AbstractAction
*/
protected $flatItemEraser;
+ /**
+ * @var MetadataPool
+ */
+ private $metadataPool;
+
/**
* @param \Magento\Framework\App\ResourceConnection $resource
* @param \Magento\Store\Model\StoreManagerInterface $storeManager
@@ -32,6 +41,7 @@ class Row extends \Magento\Catalog\Model\Indexer\Product\Flat\AbstractAction
* @param FlatTableBuilder $flatTableBuilder
* @param Indexer $flatItemWriter
* @param Eraser $flatItemEraser
+ * @param MetadataPool|null $metadataPool
*/
public function __construct(
\Magento\Framework\App\ResourceConnection $resource,
@@ -41,7 +51,8 @@ public function __construct(
TableBuilder $tableBuilder,
FlatTableBuilder $flatTableBuilder,
Indexer $flatItemWriter,
- Eraser $flatItemEraser
+ Eraser $flatItemEraser,
+ MetadataPool $metadataPool = null
) {
parent::__construct(
$resource,
@@ -53,6 +64,8 @@ public function __construct(
);
$this->flatItemWriter = $flatItemWriter;
$this->flatItemEraser = $flatItemEraser;
+ $this->metadataPool = $metadataPool ?:
+ \Magento\Framework\App\ObjectManager::getInstance()->get(MetadataPool::class);
}
/**
@@ -61,7 +74,6 @@ public function __construct(
* @param int|null $id
* @return \Magento\Catalog\Model\Indexer\Product\Flat\Action\Row
* @throws \Magento\Framework\Exception\LocalizedException
- * @throws \Zend_Db_Statement_Exception
*/
public function execute($id = null)
{
@@ -71,50 +83,47 @@ public function execute($id = null)
);
}
$ids = [$id];
- foreach ($this->_storeManager->getStores() as $store) {
+ $linkField = $this->metadataPool->getMetadata(ProductInterface::class)->getLinkField();
+
+ $stores = $this->_storeManager->getStores();
+ foreach ($stores as $store) {
$tableExists = $this->_isFlatTableExists($store->getId());
if ($tableExists) {
$this->flatItemEraser->removeDeletedProducts($ids, $store->getId());
}
/* @var $status \Magento\Eav\Model\Entity\Attribute */
- $status = $this->_productIndexerHelper->getAttribute('status');
+ $status = $this->_productIndexerHelper->getAttribute(ProductInterface::STATUS);
$statusTable = $status->getBackend()->getTable();
$statusConditions = [
'store_id IN(0,' . (int)$store->getId() . ')',
'attribute_id = ' . (int)$status->getId(),
- 'entity_id = ' . (int)$id
+ $linkField . ' = ' . (int)$id,
];
$select = $this->_connection->select();
- $select->from(
- $statusTable,
- ['value']
- )->where(
- implode(' AND ', $statusConditions)
- )->order(
- 'store_id DESC'
- );
+ $select->from($statusTable, ['value'])
+ ->where(implode(' AND ', $statusConditions))
+ ->order('store_id DESC')
+ ->limit(1);
$result = $this->_connection->query($select);
- $status = $result->fetch(1);
+ $status = $result->fetchColumn(0);
- if ($status['value'] == \Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED) {
- if (isset($ids[0])) {
- if (!$tableExists) {
- $this->_flatTableBuilder->build(
- $store->getId(),
- [$ids[0]],
- $this->_valueFieldSuffix,
- $this->_tableDropSuffix,
- false
- );
- }
- $this->flatItemWriter->write($store->getId(), $ids[0], $this->_valueFieldSuffix);
+ if ($status == \Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_ENABLED) {
+ if (!$tableExists) {
+ $this->_flatTableBuilder->build(
+ $store->getId(),
+ $ids,
+ $this->_valueFieldSuffix,
+ $this->_tableDropSuffix,
+ false
+ );
}
- }
- if ($status['value'] == \Magento\Catalog\Model\Product\Attribute\Source\Status::STATUS_DISABLED) {
+ $this->flatItemWriter->write($store->getId(), $id, $this->_valueFieldSuffix);
+ } else {
$this->flatItemEraser->deleteProductsFromStore($id, $store->getId());
}
}
+
return $this;
}
}
diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Product/Flat/Action/RowTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Product/Flat/Action/RowTest.php
index a49fa9a15e341..85d8dd8a14917 100644
--- a/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Product/Flat/Action/RowTest.php
+++ b/app/code/Magento/Catalog/Test/Unit/Model/Indexer/Product/Flat/Action/RowTest.php
@@ -6,7 +6,9 @@
namespace Magento\Catalog\Test\Unit\Model\Indexer\Product\Flat\Action;
+use Magento\Catalog\Api\Data\ProductInterface;
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
+use PHPUnit_Framework_MockObject_MockObject as MockObject;
/**
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
@@ -19,45 +21,48 @@ class RowTest extends \PHPUnit\Framework\TestCase
protected $model;
/**
- * @var \PHPUnit_Framework_MockObject_MockObject
+ * @var MockObject
*/
protected $storeManager;
/**
- * @var \PHPUnit_Framework_MockObject_MockObject
+ * @var MockObject
*/
protected $store;
/**
- * @var \PHPUnit_Framework_MockObject_MockObject
+ * @var MockObject
*/
protected $productIndexerHelper;
/**
- * @var \PHPUnit_Framework_MockObject_MockObject
+ * @var MockObject
*/
protected $resource;
/**
- * @var \PHPUnit_Framework_MockObject_MockObject
+ * @var MockObject
*/
protected $connection;
/**
- * @var \PHPUnit_Framework_MockObject_MockObject
+ * @var MockObject
*/
protected $flatItemWriter;
/**
- * @var \PHPUnit_Framework_MockObject_MockObject
+ * @var MockObject
*/
protected $flatItemEraser;
/**
- * @var \PHPUnit_Framework_MockObject_MockObject
+ * @var MockObject
*/
protected $flatTableBuilder;
+ /**
+ * @inheritdoc
+ */
protected function setUp()
{
$objectManager = new ObjectManager($this);
@@ -68,11 +73,11 @@ protected function setUp()
$this->resource = $this->createMock(\Magento\Framework\App\ResourceConnection::class);
$this->resource->expects($this->any())->method('getConnection')
->with('default')
- ->will($this->returnValue($this->connection));
+ ->willReturn($this->connection);
$this->storeManager = $this->createMock(\Magento\Store\Model\StoreManagerInterface::class);
$this->store = $this->createMock(\Magento\Store\Model\Store::class);
- $this->store->expects($this->any())->method('getId')->will($this->returnValue('store_id_1'));
- $this->storeManager->expects($this->any())->method('getStores')->will($this->returnValue([$this->store]));
+ $this->store->expects($this->any())->method('getId')->willReturn('store_id_1');
+ $this->storeManager->expects($this->any())->method('getStores')->willReturn([$this->store]);
$this->flatItemEraser = $this->createMock(\Magento\Catalog\Model\Indexer\Product\Flat\Action\Eraser::class);
$this->flatItemWriter = $this->createMock(\Magento\Catalog\Model\Indexer\Product\Flat\Action\Indexer::class);
$this->flatTableBuilder = $this->createMock(
@@ -89,9 +94,7 @@ protected function setUp()
->disableOriginalConstructor()
->getMock();
$backendMock->expects($this->any())->method('getTable')->willReturn($attributeTable);
- $statusAttributeMock->expects($this->any())->method('getBackend')->willReturn(
- $backendMock
- );
+ $statusAttributeMock->expects($this->any())->method('getBackend')->willReturn($backendMock);
$statusAttributeMock->expects($this->any())->method('getId')->willReturn($statusId);
$selectMock = $this->getMockBuilder(\Magento\Framework\DB\Select::class)
->disableOriginalConstructor()
@@ -102,24 +105,32 @@ protected function setUp()
['value']
)->willReturnSelf();
$selectMock->expects($this->any())->method('where')->willReturnSelf();
+ $selectMock->expects($this->any())->method('order')->willReturnSelf();
+ $selectMock->expects($this->any())->method('limit')->willReturnSelf();
$pdoMock = $this->createMock(\Zend_Db_Statement_Pdo::class);
- $this->connection->expects($this->any())
- ->method('query')
- ->with($selectMock)
- ->will($this->returnValue($pdoMock));
- $pdoMock->expects($this->any())->method('fetch')->will($this->returnValue(['value' => 1]));
+ $this->connection->expects($this->any())->method('query')->with($selectMock)->willReturn($pdoMock);
+ $pdoMock->expects($this->any())->method('fetchColumn')->willReturn('1');
+
+ $metadataPool = $this->createMock(\Magento\Framework\EntityManager\MetadataPool::class);
+ $productMetadata = $this->getMockBuilder(\Magento\Framework\EntityManager\EntityMetadataInterface::class)
+ ->getMockForAbstractClass();
+ $metadataPool->expects($this->any())->method('getMetadata')->with(ProductInterface::class)
+ ->willReturn($productMetadata);
+ $productMetadata->expects($this->any())->method('getLinkField')->willReturn('entity_id');
$this->model = $objectManager->getObject(
\Magento\Catalog\Model\Indexer\Product\Flat\Action\Row::class,
[
- 'resource' => $this->resource,
- 'storeManager' => $this->storeManager,
- 'productHelper' => $this->productIndexerHelper,
- 'flatItemEraser' => $this->flatItemEraser,
- 'flatItemWriter' => $this->flatItemWriter,
- 'flatTableBuilder' => $this->flatTableBuilder
+ 'resource' => $this->resource,
+ 'storeManager' => $this->storeManager,
+ 'productHelper' => $this->productIndexerHelper,
+ 'flatItemEraser' => $this->flatItemEraser,
+ 'flatItemWriter' => $this->flatItemWriter,
+ 'flatTableBuilder' => $this->flatTableBuilder,
]
);
+
+ $objectManager->setBackwardCompatibleProperty($this->model, 'metadataPool', $metadataPool);
}
/**
@@ -134,9 +145,9 @@ public function testExecuteWithEmptyId()
public function testExecuteWithNonExistingFlatTablesCreatesTables()
{
$this->productIndexerHelper->expects($this->any())->method('getFlatTableName')
- ->will($this->returnValue('store_flat_table'));
+ ->willReturn('store_flat_table');
$this->connection->expects($this->any())->method('isTableExists')->with('store_flat_table')
- ->will($this->returnValue(false));
+ ->willReturn(false);
$this->flatItemEraser->expects($this->never())->method('removeDeletedProducts');
$this->flatTableBuilder->expects($this->once())->method('build')->with('store_id_1', ['product_id_1']);
$this->flatItemWriter->expects($this->once())->method('write')->with('store_id_1', 'product_id_1');
@@ -146,9 +157,9 @@ public function testExecuteWithNonExistingFlatTablesCreatesTables()
public function testExecuteWithExistingFlatTablesCreatesTables()
{
$this->productIndexerHelper->expects($this->any())->method('getFlatTableName')
- ->will($this->returnValue('store_flat_table'));
+ ->willReturn('store_flat_table');
$this->connection->expects($this->any())->method('isTableExists')->with('store_flat_table')
- ->will($this->returnValue(true));
+ ->willReturn(true);
$this->flatItemEraser->expects($this->once())->method('removeDeletedProducts');
$this->flatTableBuilder->expects($this->never())->method('build')->with('store_id_1', ['product_id_1']);
$this->model->execute('product_id_1');
diff --git a/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/edit/attribute_set.phtml b/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/edit/attribute_set.phtml
index 6a5f6c4648494..a7e8564e7a1d8 100644
--- a/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/edit/attribute_set.phtml
+++ b/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/edit/attribute_set.phtml
@@ -14,7 +14,7 @@
<% } %>
<% if (!data.term && data.items.length && !data.allShown()) { %>
diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminApplyCatalogRuleByCategoryTest.xml b/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminApplyCatalogRuleByCategoryTest.xml
index 716a363ec5d78..741da96179b8c 100644
--- a/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminApplyCatalogRuleByCategoryTest.xml
+++ b/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminApplyCatalogRuleByCategoryTest.xml
@@ -16,9 +16,6 @@
-
-
-
diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminCreateCatalogPriceRuleTest.xml b/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminCreateCatalogPriceRuleTest.xml
index 072385c46645a..befe0b0ce7f98 100644
--- a/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminCreateCatalogPriceRuleTest.xml
+++ b/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminCreateCatalogPriceRuleTest.xml
@@ -17,9 +17,6 @@
-
-
-
@@ -77,9 +74,6 @@
-
-
-
@@ -103,9 +97,6 @@
-
-
-
@@ -129,9 +120,6 @@
-
-
-
@@ -155,9 +143,6 @@
-
-
-
diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminDeleteCatalogPriceRuleTest.xml b/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminDeleteCatalogPriceRuleTest.xml
index 83770ffff5eab..d3546d06492be 100644
--- a/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminDeleteCatalogPriceRuleTest.xml
+++ b/app/code/Magento/CatalogRule/Test/Mftf/Test/AdminDeleteCatalogPriceRuleTest.xml
@@ -17,9 +17,6 @@
-
-
-
diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Test/StorefrontInactiveCatalogRuleTest.xml b/app/code/Magento/CatalogRule/Test/Mftf/Test/StorefrontInactiveCatalogRuleTest.xml
index 55f775e40feaa..e7be6e8443a36 100644
--- a/app/code/Magento/CatalogRule/Test/Mftf/Test/StorefrontInactiveCatalogRuleTest.xml
+++ b/app/code/Magento/CatalogRule/Test/Mftf/Test/StorefrontInactiveCatalogRuleTest.xml
@@ -17,9 +17,6 @@
-
-
-
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/cart/shipping-estimation.js b/app/code/Magento/Checkout/view/frontend/web/js/view/cart/shipping-estimation.js
index 39b5ea0299ab8..a857d89a72b14 100644
--- a/app/code/Magento/Checkout/view/frontend/web/js/view/cart/shipping-estimation.js
+++ b/app/code/Magento/Checkout/view/frontend/web/js/view/cart/shipping-estimation.js
@@ -55,6 +55,12 @@ define(
checkoutDataResolver.resolveEstimationAddress();
address = quote.isVirtual() ? quote.billingAddress() : quote.shippingAddress();
+ if (!address && quote.isVirtual()) {
+ address = addressConverter.formAddressDataToQuoteAddress(
+ checkoutData.getSelectedBillingAddress()
+ );
+ }
+
if (address) {
estimatedAddress = address.isEditable() ?
addressConverter.quoteAddressToFormAddressData(address) :
diff --git a/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerOrderSection.xml b/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerOrderSection.xml
index 253a6a83c9438..e8b11b27ddc70 100644
--- a/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerOrderSection.xml
+++ b/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerOrderSection.xml
@@ -9,6 +9,7 @@
+
diff --git a/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerOrderViewSection.xml b/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerOrderViewSection.xml
index 53b07b2b6a51c..81612d1c64334 100644
--- a/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerOrderViewSection.xml
+++ b/app/code/Magento/Customer/Test/Mftf/Section/StorefrontCustomerOrderViewSection.xml
@@ -13,5 +13,6 @@
+
diff --git a/app/code/Magento/Email/view/frontend/web/logo_email.png b/app/code/Magento/Email/view/frontend/web/logo_email.png
index 0cca183e08da2..215e9d06edcdc 100644
Binary files a/app/code/Magento/Email/view/frontend/web/logo_email.png and b/app/code/Magento/Email/view/frontend/web/logo_email.png differ
diff --git a/app/code/Magento/Sales/Test/Mftf/ActionGroup/CreateOrderToPrintPageActionGroup.xml b/app/code/Magento/Sales/Test/Mftf/ActionGroup/CreateOrderToPrintPageActionGroup.xml
new file mode 100644
index 0000000000000..fe2fc49f1d015
--- /dev/null
+++ b/app/code/Magento/Sales/Test/Mftf/ActionGroup/CreateOrderToPrintPageActionGroup.xml
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/code/Magento/Sales/Test/Mftf/Page/StorefrontCustomerSignOutPage.xml b/app/code/Magento/Sales/Test/Mftf/Page/StorefrontCustomerSignOutPage.xml
new file mode 100644
index 0000000000000..4e89e5476c3bc
--- /dev/null
+++ b/app/code/Magento/Sales/Test/Mftf/Page/StorefrontCustomerSignOutPage.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
diff --git a/app/code/Magento/Sales/Test/Mftf/Page/StorefrontSalesOrderPrintPage.xml b/app/code/Magento/Sales/Test/Mftf/Page/StorefrontSalesOrderPrintPage.xml
new file mode 100644
index 0000000000000..874e6889ec58c
--- /dev/null
+++ b/app/code/Magento/Sales/Test/Mftf/Page/StorefrontSalesOrderPrintPage.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
diff --git a/app/code/Magento/Sales/Test/Mftf/Section/SalesOrderPrintSection.xml b/app/code/Magento/Sales/Test/Mftf/Section/SalesOrderPrintSection.xml
new file mode 100644
index 0000000000000..b08a66140fabf
--- /dev/null
+++ b/app/code/Magento/Sales/Test/Mftf/Section/SalesOrderPrintSection.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
diff --git a/app/code/Magento/Sales/Test/Mftf/Test/StorefrontRedirectToOrderHistory.xml b/app/code/Magento/Sales/Test/Mftf/Test/StorefrontRedirectToOrderHistory.xml
new file mode 100644
index 0000000000000..ec725ad5fe4c5
--- /dev/null
+++ b/app/code/Magento/Sales/Test/Mftf/Test/StorefrontRedirectToOrderHistory.xml
@@ -0,0 +1,78 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/code/Magento/Sales/view/frontend/layout/sales_guest_print.xml b/app/code/Magento/Sales/view/frontend/layout/sales_guest_print.xml
index 0e2689e3e2191..99af16ce629d0 100644
--- a/app/code/Magento/Sales/view/frontend/layout/sales_guest_print.xml
+++ b/app/code/Magento/Sales/view/frontend/layout/sales_guest_print.xml
@@ -12,11 +12,20 @@
-
-
+
+
-
+
diff --git a/app/code/Magento/Sales/view/frontend/layout/sales_order_print.xml b/app/code/Magento/Sales/view/frontend/layout/sales_order_print.xml
index f8d2e373e8af8..4410a6fc4a9a2 100644
--- a/app/code/Magento/Sales/view/frontend/layout/sales_order_print.xml
+++ b/app/code/Magento/Sales/view/frontend/layout/sales_order_print.xml
@@ -12,11 +12,20 @@
-
-
+
+
-
+
diff --git a/app/code/Magento/Tax/Test/Mftf/Test/StorefrontTaxInformationInShoppingCartForGuestVirtualQuoteTest.xml b/app/code/Magento/Tax/Test/Mftf/Test/StorefrontTaxInformationInShoppingCartForGuestVirtualQuoteTest.xml
index a0eac56e4db09..06f6abb2973e7 100644
--- a/app/code/Magento/Tax/Test/Mftf/Test/StorefrontTaxInformationInShoppingCartForGuestVirtualQuoteTest.xml
+++ b/app/code/Magento/Tax/Test/Mftf/Test/StorefrontTaxInformationInShoppingCartForGuestVirtualQuoteTest.xml
@@ -18,9 +18,6 @@
-
-
-
diff --git a/app/code/Magento/User/Controller/Adminhtml/Auth/Forgotpassword.php b/app/code/Magento/User/Controller/Adminhtml/Auth/Forgotpassword.php
index c0e78fae2c2c6..565b312325ddc 100644
--- a/app/code/Magento/User/Controller/Adminhtml/Auth/Forgotpassword.php
+++ b/app/code/Magento/User/Controller/Adminhtml/Auth/Forgotpassword.php
@@ -6,8 +6,10 @@
*/
namespace Magento\User\Controller\Adminhtml\Auth;
-use Magento\Security\Model\SecurityManager;
+use Magento\Framework\App\Action\HttpGetActionInterface;
+use Magento\Framework\App\Action\HttpPostActionInterface;
use Magento\Framework\App\ObjectManager;
+use Magento\Security\Model\SecurityManager;
use Magento\Backend\App\Action\Context;
use Magento\User\Model\UserFactory;
use Magento\User\Model\ResourceModel\User\CollectionFactory;
@@ -16,14 +18,25 @@
use Magento\Framework\Exception\SecurityViolationException;
use Magento\User\Controller\Adminhtml\Auth;
use Magento\Backend\Helper\Data;
+use Magento\User\Model\Spi\NotificatorInterface;
-class Forgotpassword extends Auth
+/**
+ * Initiate forgot-password process.
+ *
+ * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
+ */
+class Forgotpassword extends Auth implements HttpGetActionInterface, HttpPostActionInterface
{
/**
* @var SecurityManager
*/
protected $securityManager;
+ /**
+ * @var NotificatorInterface
+ */
+ private $notificator;
+
/**
* User model factory
*
@@ -41,13 +54,16 @@ class Forgotpassword extends Auth
* @param UserFactory $userFactory
* @param SecurityManager $securityManager
* @param CollectionFactory $userCollectionFactory
+ * @param Data $backendDataHelper
+ * @param NotificatorInterface|null $notificator
*/
public function __construct(
Context $context,
UserFactory $userFactory,
SecurityManager $securityManager,
CollectionFactory $userCollectionFactory = null,
- Data $backendDataHelper = null
+ Data $backendDataHelper = null,
+ ?NotificatorInterface $notificator = null
) {
parent::__construct($context, $userFactory);
$this->securityManager = $securityManager;
@@ -55,6 +71,8 @@ public function __construct(
ObjectManager::getInstance()->get(CollectionFactory::class);
$this->backendDataHelper = $backendDataHelper ?:
ObjectManager::getInstance()->get(Data::class);
+ $this->notificator = $notificator
+ ?? ObjectManager::getInstance()->get(NotificatorInterface::class);
}
/**
@@ -96,7 +114,7 @@ public function execute()
$newPassResetToken = $this->backendDataHelper->generateResetPasswordLinkToken();
$user->changeResetPasswordLinkToken($newPassResetToken);
$user->save();
- $user->sendPasswordResetConfirmationEmail();
+ $this->notificator->sendForgotPassword($user);
}
break;
}
diff --git a/app/code/Magento/User/Controller/Adminhtml/User/Save.php b/app/code/Magento/User/Controller/Adminhtml/User/Save.php
index 09061384a8e61..521c09f7b7707 100644
--- a/app/code/Magento/User/Controller/Adminhtml/User/Save.php
+++ b/app/code/Magento/User/Controller/Adminhtml/User/Save.php
@@ -10,8 +10,11 @@
use Magento\Framework\Exception\AuthenticationException;
use Magento\Framework\Exception\State\UserLockedException;
use Magento\Security\Model\SecurityCookie;
+use Magento\User\Model\Spi\NotificationExceptionInterface;
/**
+ * Save admin user.
+ *
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
*/
class Save extends \Magento\User\Controller\Adminhtml\User implements HttpPostActionInterface
@@ -37,7 +40,7 @@ private function getSecurityCookie()
}
/**
- * @return void
+ * @inheritDoc
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
* @SuppressWarnings(PHPMD.NPathComplexity)
*/
@@ -92,17 +95,19 @@ public function execute()
$currentUser->performIdentityCheck($data[$currentUserPasswordField]);
$model->save();
- $model->sendNotificationEmailsIfRequired();
-
$this->messageManager->addSuccess(__('You saved the user.'));
$this->_getSession()->setUserData(false);
$this->_redirect('adminhtml/*/');
+
+ $model->sendNotificationEmailsIfRequired();
} catch (UserLockedException $e) {
$this->_auth->logout();
$this->getSecurityCookie()->setLogoutReasonCookie(
\Magento\Security\Model\AdminSessionsManager::LOGOUT_REASON_USER_LOCKED
);
$this->_redirect('adminhtml/*/');
+ } catch (NotificationExceptionInterface $exception) {
+ $this->messageManager->addErrorMessage($exception->getMessage());
} catch (\Magento\Framework\Exception\AuthenticationException $e) {
$this->messageManager->addError(
__('The password entered for the current user is invalid. Verify the password and try again.')
@@ -121,6 +126,8 @@ public function execute()
}
/**
+ * Redirect to Edit form.
+ *
* @param \Magento\User\Model\User $model
* @param array $data
* @return void
diff --git a/app/code/Magento/User/Model/Notificator.php b/app/code/Magento/User/Model/Notificator.php
new file mode 100644
index 0000000000000..3a5522db4c533
--- /dev/null
+++ b/app/code/Magento/User/Model/Notificator.php
@@ -0,0 +1,194 @@
+transportBuilder = $transportBuilder;
+ $this->config = $config;
+ $this->deployConfig = $deployConfig;
+ $this->storeManager = $storeManager;
+ }
+
+ /**
+ * Send a notification.
+ *
+ * @param string $templateConfigId
+ * @param array $templateVars
+ * @param string $toEmail
+ * @param string $toName
+ * @throws MailException
+ *
+ * @return void
+ */
+ private function sendNotification(
+ string $templateConfigId,
+ array $templateVars,
+ string $toEmail,
+ string $toName
+ ): void {
+ $transport = $this->transportBuilder
+ ->setTemplateIdentifier($this->config->getValue($templateConfigId))
+ ->setTemplateModel(BackendTemplate::class)
+ ->setTemplateOptions([
+ 'area' => FrontNameResolver::AREA_CODE,
+ 'store' => Store::DEFAULT_STORE_ID
+ ])
+ ->setTemplateVars($templateVars)
+ ->setFrom(
+ $this->config->getValue('admin/emails/forgot_email_identity')
+ )
+ ->addTo($toEmail, $toName)
+ ->getTransport();
+ $transport->sendMessage();
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function sendForgotPassword(UserInterface $user): void
+ {
+ try {
+ $this->sendNotification(
+ 'admin/emails/forgot_email_template',
+ [
+ 'user' => $user,
+ 'store' => $this->storeManager->getStore(
+ Store::DEFAULT_STORE_ID
+ )
+ ],
+ $user->getEmail(),
+ $user->getFirstName().' '.$user->getLastName()
+ );
+ } catch (LocalizedException $exception) {
+ throw new NotificatorException(
+ __($exception->getMessage()),
+ $exception
+ );
+ }
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function sendCreated(UserInterface $user): void
+ {
+ $toEmails = [];
+ $generalEmail = $this->config->getValue(
+ 'trans_email/ident_general/email'
+ );
+ if ($generalEmail) {
+ $toEmails[] = $generalEmail;
+ }
+ if ($adminEmail = $this->deployConfig->get('user_admin_email')) {
+ $toEmails[] = $adminEmail;
+ }
+
+ try {
+ foreach ($toEmails as $toEmail) {
+ $this->sendNotification(
+ 'admin/emails/new_user_notification_template',
+ [
+ 'user' => $user,
+ 'store' => $this->storeManager->getStore(
+ Store::DEFAULT_STORE_ID
+ )
+ ],
+ $toEmail,
+ __('Administrator')->getText()
+ );
+ }
+ } catch (LocalizedException $exception) {
+ throw new NotificatorException(
+ __($exception->getMessage()),
+ $exception
+ );
+ }
+ }
+
+ /**
+ * @inheritDoc
+ */
+ public function sendUpdated(UserInterface $user, array $changed): void
+ {
+ $email = $user->getEmail();
+ if ($user instanceof User) {
+ $email = $user->getOrigData('email');
+ }
+
+ try {
+ $this->sendNotification(
+ 'admin/emails/user_notification_template',
+ [
+ 'user' => $user,
+ 'store' => $this->storeManager->getStore(
+ Store::DEFAULT_STORE_ID
+ ),
+ 'changes' => implode(', ', $changed)
+ ],
+ $email,
+ $user->getFirstName().' '.$user->getLastName()
+ );
+ } catch (LocalizedException $exception) {
+ throw new NotificatorException(
+ __($exception->getMessage()),
+ $exception
+ );
+ }
+ }
+}
diff --git a/app/code/Magento/User/Model/NotificatorException.php b/app/code/Magento/User/Model/NotificatorException.php
new file mode 100644
index 0000000000000..5b581879814ab
--- /dev/null
+++ b/app/code/Magento/User/Model/NotificatorException.php
@@ -0,0 +1,20 @@
+_encryptor = $encryptor;
parent::__construct($context, $registry, $resource, $resourceCollection, $data);
@@ -166,7 +190,12 @@ public function __construct(
$this->_transportBuilder = $transportBuilder;
$this->_storeManager = $storeManager;
$this->validationRules = $validationRules;
- $this->serializer = $serializer ?: ObjectManager::getInstance()->get(Json::class);
+ $this->serializer = $serializer
+ ?: ObjectManager::getInstance()->get(Json::class);
+ $this->deploymentConfig = $deploymentConfig
+ ?: ObjectManager::getInstance()->get(DeploymentConfig::class);
+ $this->notificator = $notificator
+ ?: ObjectManager::getInstance()->get(NotificatorInterface::class);
}
/**
@@ -180,6 +209,8 @@ protected function _construct()
}
/**
+ * Removing dependencies and leaving only entity's properties.
+ *
* @return string[]
*/
public function __sleep()
@@ -196,12 +227,18 @@ public function __sleep()
'_encryptor',
'_transportBuilder',
'_storeManager',
- '_validatorBeforeSave'
+ '_validatorBeforeSave',
+ 'validationRules',
+ 'serializer',
+ 'deploymentConfig',
+ 'notificator'
]
);
}
/**
+ * Restoring required objects after serialization.
+ *
* @return void
*/
public function __wakeup()
@@ -218,6 +255,9 @@ public function __wakeup()
$this->_encryptor = $objectManager->get(\Magento\Framework\Encryption\EncryptorInterface::class);
$this->_transportBuilder = $objectManager->get(\Magento\Framework\Mail\Template\TransportBuilder::class);
$this->_storeManager = $objectManager->get(\Magento\Store\Model\StoreManagerInterface::class);
+ $this->validationRules = $objectManager->get(UserValidationRules::class);
+ $this->deploymentConfig = $objectManager->get(DeploymentConfig::class);
+ $this->notificator = $objectManager->get(NotificatorInterface::class);
}
/**
@@ -388,7 +428,7 @@ public function deleteFromRole()
}
/**
- * Check if such combination role/user exists
+ * Check if such combination role/user exists.
*
* @return bool
*/
@@ -399,28 +439,24 @@ public function roleUserExists()
}
/**
- * Send email with reset password confirmation link
+ * Send email with reset password confirmation link.
+ *
+ * @deprecated
+ * @see NotificatorInterface::sendForgotPassword()
*
* @return $this
*/
public function sendPasswordResetConfirmationEmail()
{
- $templateId = $this->_config->getValue(self::XML_PATH_FORGOT_EMAIL_TEMPLATE);
- $transport = $this->_transportBuilder->setTemplateIdentifier($templateId)
- ->setTemplateModel(\Magento\Email\Model\BackendTemplate::class)
- ->setTemplateOptions(['area' => FrontNameResolver::AREA_CODE, 'store' => Store::DEFAULT_STORE_ID])
- ->setTemplateVars(['user' => $this, 'store' => $this->_storeManager->getStore(Store::DEFAULT_STORE_ID)])
- ->setFrom($this->_config->getValue(self::XML_PATH_FORGOT_EMAIL_IDENTITY))
- ->addTo($this->getEmail(), $this->getName())
- ->getTransport();
+ $this->notificator->sendForgotPassword($this);
- $transport->sendMessage();
return $this;
}
/**
* Send email to when password is resetting
*
+ * @throws NotificationExceptionInterface
* @return $this
* @deprecated 100.1.0
*/
@@ -431,20 +467,20 @@ public function sendPasswordResetNotificationEmail()
}
/**
- * Check changes and send notification emails
+ * Check changes and send notification emails.
*
+ * @throws NotificationExceptionInterface
* @return $this
* @since 100.1.0
*/
public function sendNotificationEmailsIfRequired()
{
- $changes = $this->createChangesDescriptionString();
-
- if ($changes) {
- if ($this->getEmail() != $this->getOrigData('email') && $this->getOrigData('email')) {
- $this->sendUserNotificationEmail($changes, $this->getOrigData('email'));
- }
- $this->sendUserNotificationEmail($changes);
+ if ($this->isObjectNew()) {
+ //Notification about a new user.
+ $this->notificator->sendCreated($this);
+ } elseif ($changes = $this->createChangesDescriptionString()) {
+ //User changed.
+ $this->notificator->sendUpdated($this, explode(', ', $changes));
}
return $this;
@@ -478,35 +514,21 @@ protected function createChangesDescriptionString()
}
/**
- * Send user notification email
+ * Send user notification email.
*
* @param string $changes
* @param string $email
+ * @throws NotificationExceptionInterface
* @return $this
* @since 100.1.0
+ * @deprecated
+ * @see NotificatorInterface::sendUpdated()
+ * @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
protected function sendUserNotificationEmail($changes, $email = null)
{
- if ($email === null) {
- $email = $this->getEmail();
- }
+ $this->notificator->sendUpdated($this, explode(', ', $changes));
- $transport = $this->_transportBuilder
- ->setTemplateIdentifier($this->_config->getValue(self::XML_PATH_USER_NOTIFICATION_TEMPLATE))
- ->setTemplateModel(\Magento\Email\Model\BackendTemplate::class)
- ->setTemplateOptions(['area' => FrontNameResolver::AREA_CODE, 'store' => Store::DEFAULT_STORE_ID])
- ->setTemplateVars(
- [
- 'user' => $this,
- 'store' => $this->_storeManager->getStore(Store::DEFAULT_STORE_ID),
- 'changes' => $changes
- ]
- )
- ->setFrom($this->_config->getValue(self::XML_PATH_FORGOT_EMAIL_IDENTITY))
- ->addTo($email, $this->getName())
- ->getTransport();
-
- $transport->sendMessage();
return $this;
}
@@ -738,7 +760,7 @@ public function setHasAvailableResources($hasResources)
}
/**
- * {@inheritdoc}
+ * @inheritDoc
*/
public function getFirstName()
{
@@ -746,7 +768,7 @@ public function getFirstName()
}
/**
- * {@inheritdoc}
+ * @inheritDoc
*/
public function setFirstName($firstName)
{
@@ -754,7 +776,7 @@ public function setFirstName($firstName)
}
/**
- * {@inheritdoc}
+ * @inheritDoc
*/
public function getLastName()
{
@@ -762,7 +784,7 @@ public function getLastName()
}
/**
- * {@inheritdoc}
+ * @inheritDoc
*/
public function setLastName($lastName)
{
@@ -770,7 +792,7 @@ public function setLastName($lastName)
}
/**
- * {@inheritdoc}
+ * @inheritDoc
*/
public function getEmail()
{
@@ -778,7 +800,7 @@ public function getEmail()
}
/**
- * {@inheritdoc}
+ * @inheritDoc
*/
public function setEmail($email)
{
@@ -786,7 +808,7 @@ public function setEmail($email)
}
/**
- * {@inheritdoc}
+ * @inheritDoc
*/
public function getUserName()
{
@@ -794,7 +816,7 @@ public function getUserName()
}
/**
- * {@inheritdoc}
+ * @inheritDoc
*/
public function setUserName($userName)
{
@@ -802,7 +824,7 @@ public function setUserName($userName)
}
/**
- * {@inheritdoc}
+ * @inheritDoc
*/
public function getPassword()
{
@@ -810,7 +832,7 @@ public function getPassword()
}
/**
- * {@inheritdoc}
+ * @inheritDoc
*/
public function setPassword($password)
{
@@ -818,7 +840,7 @@ public function setPassword($password)
}
/**
- * {@inheritdoc}
+ * @inheritDoc
*/
public function getCreated()
{
@@ -826,7 +848,7 @@ public function getCreated()
}
/**
- * {@inheritdoc}
+ * @inheritDoc
*/
public function setCreated($created)
{
@@ -834,7 +856,7 @@ public function setCreated($created)
}
/**
- * {@inheritdoc}
+ * @inheritDoc
*/
public function getModified()
{
@@ -842,7 +864,7 @@ public function getModified()
}
/**
- * {@inheritdoc}
+ * @inheritDoc
*/
public function setModified($modified)
{
@@ -850,7 +872,7 @@ public function setModified($modified)
}
/**
- * {@inheritdoc}
+ * @inheritDoc
*/
public function getIsActive()
{
@@ -858,7 +880,7 @@ public function getIsActive()
}
/**
- * {@inheritdoc}
+ * @inheritDoc
*/
public function setIsActive($isActive)
{
@@ -866,7 +888,7 @@ public function setIsActive($isActive)
}
/**
- * {@inheritdoc}
+ * @inheritDoc
*/
public function getInterfaceLocale()
{
@@ -874,7 +896,7 @@ public function getInterfaceLocale()
}
/**
- * {@inheritdoc}
+ * @inheritDoc
*/
public function setInterfaceLocale($interfaceLocale)
{
diff --git a/app/code/Magento/User/Test/Unit/Model/UserTest.php b/app/code/Magento/User/Test/Unit/Model/UserTest.php
index 4bc5db138c7ba..670316c2500fc 100644
--- a/app/code/Magento/User/Test/Unit/Model/UserTest.php
+++ b/app/code/Magento/User/Test/Unit/Model/UserTest.php
@@ -6,7 +6,9 @@
namespace Magento\User\Test\Unit\Model;
-use Magento\Framework\Serialize\Serializer\Json;
+use Magento\User\Helper\Data as UserHelper;
+use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
+use Magento\User\Model\User;
/**
* Test class for \Magento\User\Model\User testing
@@ -16,55 +18,11 @@
*/
class UserTest extends \PHPUnit\Framework\TestCase
{
- /** @var \Magento\User\Model\User */
- protected $model;
+ /** @var User */
+ private $model;
- /** @var \Magento\User\Helper\Data|\PHPUnit_Framework_MockObject_MockObject */
- protected $userDataMock;
-
- /** @var \Magento\Framework\Mail\Template\TransportBuilder|\PHPUnit_Framework_MockObject_MockObject */
- protected $transportBuilderMock;
-
- /** @var \Magento\Framework\Model\Context|\PHPUnit_Framework_MockObject_MockObject */
- protected $contextMock;
-
- /** @var \Magento\User\Model\ResourceModel\User|\PHPUnit_Framework_MockObject_MockObject */
- protected $resourceMock;
-
- /** @var \Magento\Framework\Data\Collection\AbstractDb|\PHPUnit_Framework_MockObject_MockObject */
- protected $collectionMock;
-
- /** @var \Magento\Framework\Mail\TransportInterface|\PHPUnit_Framework_MockObject_MockObject */
- protected $transportMock;
-
- /** @var \Magento\Store\Model\StoreManagerInterface|\PHPUnit_Framework_MockObject_MockObject */
- protected $storeManagerMock;
-
- /** @var \Magento\Store\Model\Store|\PHPUnit_Framework_MockObject_MockObject */
- protected $storeMock;
-
- /** @var \Magento\Backend\App\ConfigInterface|\PHPUnit_Framework_MockObject_MockObject */
- protected $configMock;
-
- /** @var \Magento\Framework\Encryption\EncryptorInterface|\PHPUnit_Framework_MockObject_MockObject */
- protected $encryptorMock;
-
- /** @var \Magento\Framework\Event\ManagerInterface|\PHPUnit_Framework_MockObject_MockObject */
- protected $eventManagerMock;
-
- /** @var \Magento\Framework\Validator\DataObjectFactory|\PHPUnit_Framework_MockObject_MockObject */
- protected $validatorObjectFactoryMock;
-
- /** @var \Magento\User\Model\UserValidationRules|\PHPUnit_Framework_MockObject_MockObject */
- protected $validationRulesMock;
-
- /** @var \Magento\Authorization\Model\RoleFactory|\PHPUnit_Framework_MockObject_MockObject */
- protected $roleFactoryMock;
-
- /**
- * @var Json|\PHPUnit_Framework_MockObject_MockObject
- */
- private $serializer;
+ /** @var UserHelper|\PHPUnit_Framework_MockObject_MockObject */
+ private $userDataMock;
/**
* Set required values
@@ -72,308 +30,20 @@ class UserTest extends \PHPUnit\Framework\TestCase
*/
protected function setUp()
{
- $this->userDataMock = $this->getMockBuilder(\Magento\User\Helper\Data::class)
+ $this->userDataMock = $this->getMockBuilder(UserHelper::class)
->disableOriginalConstructor()
->setMethods([])
->getMock();
- $this->contextMock = $this->getMockBuilder(\Magento\Framework\Model\Context::class)
- ->disableOriginalConstructor()
- ->setMethods([])
- ->getMock();
- $this->resourceMock = $this->getMockBuilder(\Magento\User\Model\ResourceModel\User::class)
- ->disableOriginalConstructor()
- ->setMethods([])
- ->getMock();
- $this->collectionMock = $this->getMockBuilder(\Magento\Framework\Data\Collection\AbstractDb::class)
- ->disableOriginalConstructor()
- ->setMethods([])
- ->getMockForAbstractClass();
- $coreRegistry = $this->getMockBuilder(\Magento\Framework\Registry::class)
- ->disableOriginalConstructor()
- ->setMethods([])
- ->getMock();
- $this->eventManagerMock = $this->getMockBuilder(\Magento\Framework\Event\ManagerInterface::class)
- ->disableOriginalConstructor()
- ->setMethods(['dispatch'])
- ->getMockForAbstractClass();
- $this->validatorObjectFactoryMock = $this->getMockBuilder(\Magento\Framework\Validator\DataObjectFactory::class)
- ->disableOriginalConstructor()->setMethods(['create'])
- ->getMock();
- $this->roleFactoryMock = $this->getMockBuilder(\Magento\Authorization\Model\RoleFactory::class)
- ->disableOriginalConstructor()
- ->setMethods(['create'])
- ->getMock();
- $this->transportMock = $this->getMockBuilder(\Magento\Framework\Mail\TransportInterface::class)
- ->disableOriginalConstructor()
- ->setMethods([])
- ->getMock();
- $this->transportBuilderMock = $this->getMockBuilder(\Magento\Framework\Mail\Template\TransportBuilder::class)
- ->disableOriginalConstructor()
- ->setMethods([])
- ->getMock();
- $this->storeMock = $this->getMockBuilder(\Magento\Store\Model\Store::class)
- ->disableOriginalConstructor()
- ->setMethods([])
- ->getMock();
- $this->storeManagerMock = $this->getMockBuilder(\Magento\Store\Model\StoreManagerInterface::class)
- ->disableOriginalConstructor()
- ->setMethods([])
- ->getMock();
-
- $this->configMock = $this->getMockBuilder(\Magento\Backend\App\ConfigInterface::class)
- ->disableOriginalConstructor()
- ->setMethods([])
- ->getMock();
-
- $this->validationRulesMock = $this->getMockBuilder(\Magento\User\Model\UserValidationRules::class)
- ->disableOriginalConstructor()
- ->setMethods([])
- ->getMock();
-
- $this->encryptorMock = $this->getMockBuilder(\Magento\Framework\Encryption\EncryptorInterface::class)
- ->setMethods(['validateHash'])
- ->getMockForAbstractClass();
-
- $this->serializer = $this->createPartialMock(Json::class, ['serialize', 'unserialize']);
- $objectManagerHelper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this);
+ $objectManagerHelper = new ObjectManager($this);
$this->model = $objectManagerHelper->getObject(
- \Magento\User\Model\User::class,
+ User::class,
[
- 'eventManager' => $this->eventManagerMock,
'userData' => $this->userDataMock,
- 'registry' => $coreRegistry,
- 'resource' => $this->resourceMock,
- 'resourceCollection' => $this->collectionMock,
- 'validatorObjectFactory' => $this->validatorObjectFactoryMock,
- 'roleFactory' => $this->roleFactoryMock,
- 'transportBuilder' => $this->transportBuilderMock,
- 'storeManager' => $this->storeManagerMock,
- 'validationRules' => $this->validationRulesMock,
- 'config' => $this->configMock,
- 'encryptor' => $this->encryptorMock,
- 'serializer' => $this->serializer
]
);
}
- /**
- * @return void
- */
- public function testSendNotificationEmailsIfRequired()
- {
- $storeId = 0;
- $email = 'test1@example.com';
- $origEmail = 'test2@example.com';
-
- $password = '1234567';
- $origPassword = '123456789';
-
- $username = 'admin1';
- $origUsername = 'admin2';
-
- $firstName = 'Foo';
- $lastName = 'Bar';
-
- $changes = __('email') . ', ' . __('password') . ', ' . __('username');
-
- $this->model->setEmail($email);
- $this->model->setOrigData('email', $origEmail);
-
- $this->model->setPassword($password);
- $this->model->setOrigData('password', $origPassword);
-
- $this->model->setUserName($username);
- $this->model->setOrigData('username', $origUsername);
-
- $this->model->setFirstName($firstName);
- $this->model->setLastName($lastName);
-
- $this->configMock->expects($this->exactly(4))
- ->method('getValue')
- ->withConsecutive(
- [\Magento\User\Model\User::XML_PATH_USER_NOTIFICATION_TEMPLATE],
- [\Magento\User\Model\User::XML_PATH_FORGOT_EMAIL_IDENTITY],
- [\Magento\User\Model\User::XML_PATH_USER_NOTIFICATION_TEMPLATE],
- [\Magento\User\Model\User::XML_PATH_FORGOT_EMAIL_IDENTITY]
- )->willReturnOnConsecutiveCalls(
- 'templateId',
- 'sender',
- 'templateId',
- 'sender'
- );
-
- $this->transportBuilderMock->expects($this->exactly(2))
- ->method('setTemplateModel')
- ->with($this->equalTo(\Magento\Email\Model\BackendTemplate::class))
- ->willReturnSelf();
- $this->transportBuilderMock->expects($this->exactly(2))
- ->method('setTemplateOptions')
- ->willReturnSelf();
- $this->transportBuilderMock->expects($this->exactly(2))
- ->method('setTemplateVars')
- ->with(['user' => $this->model, 'store' => $this->storeMock, 'changes' => $changes])
- ->willReturnSelf();
- $this->transportBuilderMock->expects($this->exactly(2))
- ->method('addTo')
- ->withConsecutive(
- $this->equalTo($email),
- $this->equalTo($firstName . ' ' . $lastName),
- $this->equalTo($origEmail),
- $this->equalTo($firstName . ' ' . $lastName)
- )
- ->willReturnSelf();
- $this->transportBuilderMock->expects($this->exactly(2))
- ->method('setFrom')
- ->with('sender')
- ->willReturnSelf();
- $this->transportBuilderMock->expects($this->exactly(2))
- ->method('setTemplateIdentifier')
- ->with('templateId')
- ->willReturnSelf();
- $this->transportBuilderMock->expects($this->exactly(2))
- ->method('getTransport')
- ->willReturn($this->transportMock);
- $this->transportMock->expects($this->exactly(2))->method('sendMessage');
-
- $this->storeManagerMock->expects($this->exactly(2))
- ->method('getStore')
- ->with($storeId)
- ->willReturn($this->storeMock);
-
- $this->assertInstanceOf(\Magento\User\Model\User::class, $this->model->sendNotificationEmailsIfRequired());
- }
-
- /**
- * @return void
- */
- public function testSendPasswordResetConfirmationEmail()
- {
- $storeId = 0;
- $email = 'test@example.com';
- $firstName = 'Foo';
- $lastName = 'Bar';
-
- $this->model->setEmail($email);
- $this->model->setFirstName($firstName);
- $this->model->setLastName($lastName);
-
- $this->configMock->expects($this->at(0))
- ->method('getValue')
- ->with(\Magento\User\Model\User::XML_PATH_FORGOT_EMAIL_TEMPLATE)
- ->willReturn('templateId');
- $this->configMock->expects($this->at(1))
- ->method('getValue')
- ->with(\Magento\User\Model\User::XML_PATH_FORGOT_EMAIL_IDENTITY)
- ->willReturn('sender');
- $this->transportBuilderMock->expects($this->once())
- ->method('setTemplateModel')
- ->with($this->equalTo(\Magento\Email\Model\BackendTemplate::class))
- ->willReturnSelf();
- $this->transportBuilderMock->expects($this->once())
- ->method('setTemplateOptions')
- ->willReturnSelf();
- $this->transportBuilderMock->expects($this->once())
- ->method('setTemplateVars')
- ->with(['user' => $this->model, 'store' => $this->storeMock])
- ->willReturnSelf();
- $this->transportBuilderMock->expects($this->once())
- ->method('addTo')
- ->with($this->equalTo($email), $this->equalTo($firstName . ' ' . $lastName))
- ->willReturnSelf();
- $this->transportBuilderMock->expects($this->once())
- ->method('setFrom')
- ->with('sender')
- ->willReturnSelf();
- $this->transportBuilderMock->expects($this->once())
- ->method('setTemplateIdentifier')
- ->with('templateId')
- ->willReturnSelf();
- $this->transportBuilderMock->expects($this->once())
- ->method('getTransport')
- ->willReturn($this->transportMock);
- $this->transportMock->expects($this->once())->method('sendMessage');
-
- $this->storeManagerMock->expects($this->once())
- ->method('getStore')
- ->with($storeId)
- ->willReturn($this->storeMock);
-
- $this->assertInstanceOf(\Magento\User\Model\User::class, $this->model->sendPasswordResetConfirmationEmail());
- }
-
- /**
- * @return void
- */
- public function testVerifyIdentity()
- {
- $password = 'password';
- $this->encryptorMock
- ->expects($this->once())
- ->method('validateHash')
- ->with($password, $this->model->getPassword())
- ->willReturn(true);
- $this->model->setIsActive(true);
- $this->resourceMock->expects($this->once())->method('hasAssigned2Role')->willReturn(true);
- $this->assertTrue(
- $this->model->verifyIdentity($password),
- 'Identity verification failed while should have passed.'
- );
- }
-
- /**
- * @return void
- */
- public function testVerifyIdentityFailure()
- {
- $password = 'password';
- $this->encryptorMock
- ->expects($this->once())
- ->method('validateHash')
- ->with($password, $this->model->getPassword())
- ->willReturn(false);
- $this->assertFalse(
- $this->model->verifyIdentity($password),
- 'Identity verification passed while should have failed.'
- );
- }
-
- /**
- * @return void
- */
- public function testVerifyIdentityInactiveRecord()
- {
- $password = 'password';
- $this->encryptorMock
- ->expects($this->once())
- ->method('validateHash')
- ->with($password, $this->model->getPassword())
- ->willReturn(true);
- $this->model->setIsActive(false);
- $this->expectException(\Magento\Framework\Exception\AuthenticationException::class);
- $this->expectExceptionMessage('The account sign-in was incorrect or your account is disabled temporarily. '
- . 'Please wait and try again later.');
- $this->model->verifyIdentity($password);
- }
-
- /**
- * @return void
- */
- public function testVerifyIdentityNoAssignedRoles()
- {
- $password = 'password';
- $this->encryptorMock
- ->expects($this->once())
- ->method('validateHash')
- ->with($password, $this->model->getPassword())
- ->willReturn(true);
- $this->model->setIsActive(true);
- $this->resourceMock->expects($this->once())->method('hasAssigned2Role')->willReturn(false);
- $this->expectException(\Magento\Framework\Exception\AuthenticationException::class);
- $this->expectExceptionMessage('More permissions are needed to access this.');
- $this->model->verifyIdentity($password);
- }
-
/**
* @return void
*/
@@ -399,225 +69,21 @@ public function testSleep()
$this->assertEmpty($expectedResult);
}
- /**
- * @return void
- */
- public function testBeforeSave()
- {
- $this->eventManagerMock->expects($this->any())->method('dispatch');
- $this->model->setIsActive(1);
- $actualData = $this->model->beforeSave()->getData();
- $this->assertArrayHasKey('extra', $actualData);
- $this->assertArrayHasKey('password', $actualData);
- $this->assertArrayHasKey('is_active', $actualData);
- }
-
- /**
- * @return void
- */
- public function testValidateOk()
- {
- /** @var $validatorMock \Magento\Framework\Validator\DataObject|\PHPUnit_Framework_MockObject_MockObject */
- $validatorMock = $this->getMockBuilder(\Magento\Framework\Validator\DataObject::class)
- ->disableOriginalConstructor()
- ->setMethods([])
- ->getMock();
- $this->validatorObjectFactoryMock->expects($this->once())->method('create')->willReturn($validatorMock);
- $this->validationRulesMock->expects($this->once())
- ->method('addUserInfoRules')
- ->with($validatorMock);
- $validatorMock->expects($this->once())->method('isValid')->willReturn(true);
- $this->assertTrue($this->model->validate());
- }
-
- /**
- * @return void
- */
- public function testValidateInvalid()
- {
- $messages = ['Invalid username'];
- /** @var $validatorMock \Magento\Framework\Validator\DataObject|\PHPUnit_Framework_MockObject_MockObject */
- $validatorMock = $this->getMockBuilder(\Magento\Framework\Validator\DataObject::class)
- ->disableOriginalConstructor()
- ->setMethods([])
- ->getMock();
- $this->validatorObjectFactoryMock->expects($this->once())->method('create')->willReturn($validatorMock);
- $this->validationRulesMock->expects($this->once())
- ->method('addUserInfoRules')
- ->with($validatorMock);
- $validatorMock->expects($this->once())->method('isValid')->willReturn(false);
- $validatorMock->expects($this->once())->method('getMessages')->willReturn($messages);
- $this->assertEquals($messages, $this->model->validate());
- }
-
- /**
- * @return void
- */
- public function testSaveExtra()
- {
- $data = [1, 2, 3];
- $this->resourceMock->expects($this->once())
- ->method('saveExtra')
- ->with($this->model, json_encode($data));
-
- $this->serializer->expects($this->once())
- ->method('serialize')
- ->with($data)
- ->will($this->returnValue(json_encode($data)));
-
- $this->assertInstanceOf(\Magento\User\Model\User::class, $this->model->saveExtra($data));
- }
-
- /**
- * @return void
- */
- public function testGetRoles()
- {
- $this->resourceMock->expects($this->once())->method('getRoles')->with($this->model)->willReturn([]);
- $this->assertInternalType('array', $this->model->getRoles());
- }
-
- /**
- * @return void
- */
- public function testGetRole()
- {
- $roles = ['role'];
- $roleMock = $this->getMockBuilder(\Magento\Authorization\Model\Role::class)
- ->disableOriginalConstructor()
- ->setMethods([])
- ->getMock();
- $this->roleFactoryMock->expects($this->once())->method('create')->willReturn($roleMock);
- $this->resourceMock->expects($this->once())->method('getRoles')->with($this->model)->willReturn($roles);
- $roleMock->expects($this->once())->method('load')->with($roles[0]);
- $this->assertInstanceOf(\Magento\Authorization\Model\Role::class, $this->model->getRole());
- }
-
- /**
- * @return void
- */
- public function testDeleteFromRole()
- {
- $this->resourceMock->expects($this->once())->method('deleteFromRole')->with($this->model);
- $this->assertInstanceOf(\Magento\User\Model\User::class, $this->model->deleteFromRole());
- }
-
- /**
- * @return void
- */
- public function testRoleUserExistsTrue()
- {
- $result = ['role'];
- $this->resourceMock->expects($this->once())->method('roleUserExists')->with($this->model)->willReturn($result);
- $this->assertTrue($this->model->roleUserExists());
- }
-
- /**
- * @return void
- */
- public function testRoleUserExistsFalse()
- {
- $result = [];
- $this->resourceMock->expects($this->once())->method('roleUserExists')->with($this->model)->willReturn($result);
- $this->assertFalse($this->model->roleUserExists());
- }
-
- /**
- * @return void
- */
- public function testGetAclRole()
- {
- $roles = ['role'];
- $result = 1;
- $roleMock = $this->getMockBuilder(\Magento\Authorization\Model\Role::class)
- ->disableOriginalConstructor()
- ->setMethods([])
- ->getMock();
- $this->roleFactoryMock->expects($this->once())->method('create')->willReturn($roleMock);
- $this->resourceMock->expects($this->once())->method('getRoles')->with($this->model)->willReturn($roles);
- $roleMock->expects($this->once())->method('load')->with($roles[0]);
- $roleMock->expects($this->once())->method('getId')->willReturn($result);
- $this->assertEquals($result, $this->model->getAclRole());
- }
-
- /**
- * @dataProvider authenticateDataProvider
- * @param string $usernameIn
- * @param string $usernameOut
- * @param bool $expectedResult
- * @return void
- */
- public function testAuthenticate($usernameIn, $usernameOut, $expectedResult)
- {
- $password = 'password';
- $config = 'config';
-
- $data = ['id' => 1, 'is_active' => 1, 'username' => $usernameOut];
-
- $this->configMock->expects($this->once())
- ->method('isSetFlag')
- ->with('admin/security/use_case_sensitive_login')
- ->willReturn($config);
- $this->eventManagerMock->expects($this->any())->method('dispatch');
-
- $this->resourceMock->expects($this->any())->method('loadByUsername')->willReturn($data);
- $this->model->setIdFieldName('id');
-
- $this->encryptorMock->expects($this->any())->method('validateHash')->willReturn(true);
- $this->resourceMock->expects($this->any())->method('hasAssigned2Role')->willReturn(true);
- $this->assertEquals($expectedResult, $this->model->authenticate($usernameIn, $password));
- }
-
- /**
- * @return array
- */
- public function authenticateDataProvider()
- {
- return [
- 'success' => [
- 'usernameIn' => 'username',
- 'usernameOut' => 'username',
- 'expectedResult' => true
- ],
- 'failedUsername' => [
- 'usernameIn' => 'username1',
- 'usernameOut' => 'username2',
- 'expectedResult' => false
- ]
- ];
- }
-
- /**
- * @expectedException \Magento\Framework\Exception\LocalizedException
- * @return void
- */
- public function testAuthenticateException()
- {
- $username = 'username';
- $password = 'password';
- $config = 'config';
-
- $this->configMock->expects($this->once())
- ->method('isSetFlag')
- ->with('admin/security/use_case_sensitive_login')
- ->willReturn($config);
-
- $this->eventManagerMock->expects($this->any())->method('dispatch');
- $this->resourceMock->expects($this->once())
- ->method('loadByUsername')
- ->willThrowException(new \Magento\Framework\Exception\LocalizedException(__()));
- $this->model->authenticate($username, $password);
- }
-
/**
* @return void
*/
public function testChangeResetPasswordLinkToken()
{
$token = '1';
- $this->assertInstanceOf(\Magento\User\Model\User::class, $this->model->changeResetPasswordLinkToken($token));
+ $this->assertInstanceOf(
+ User::class,
+ $this->model->changeResetPasswordLinkToken($token)
+ );
$this->assertEquals($token, $this->model->getRpToken());
- $this->assertInternalType('string', $this->model->getRpTokenCreatedAt());
+ $this->assertInternalType(
+ 'string',
+ $this->model->getRpTokenCreatedAt()
+ );
}
/**
@@ -640,168 +106,4 @@ public function testIsResetPasswordLinkTokenExpiredIsExpiredToken()
$this->userDataMock->expects($this->once())->method('getResetPasswordLinkExpirationPeriod')->willReturn(0);
$this->assertTrue($this->model->isResetPasswordLinkTokenExpired());
}
-
- /**
- * @return void
- */
- public function testIsResetPasswordLinkTokenExpiredIsNotExpiredToken()
- {
- $this->model->setRpToken('1');
- $this->model->setRpTokenCreatedAt(
- (new \DateTime())->format(\Magento\Framework\Stdlib\DateTime::DATETIME_PHP_FORMAT)
- );
- $this->userDataMock->expects($this->once())->method('getResetPasswordLinkExpirationPeriod')->willReturn(1);
- $this->assertFalse($this->model->isResetPasswordLinkTokenExpired());
- }
-
- public function testCheckPasswordChangeEqualToCurrent()
- {
- /** @var $validatorMock \Magento\Framework\Validator\DataObject|\PHPUnit_Framework_MockObject_MockObject */
- $validatorMock = $this->getMockBuilder(\Magento\Framework\Validator\DataObject::class)
- ->disableOriginalConstructor()
- ->setMethods([])
- ->getMock();
- $this->validatorObjectFactoryMock->expects($this->once())->method('create')->willReturn($validatorMock);
- $this->validationRulesMock->expects($this->once())
- ->method('addUserInfoRules')
- ->with($validatorMock);
- $validatorMock->expects($this->once())->method('isValid')->willReturn(true);
-
- $newPassword = "NEWmYn3wpassw0rd";
- $oldPassword = "OLDmYn3wpassw0rd";
- $this->model->setPassword($newPassword)
- ->setId(1)
- ->setOrigData('password', $oldPassword);
- $this->encryptorMock->expects($this->once())
- ->method('isValidHash')
- ->with($newPassword, $oldPassword)
- ->willReturn(true);
- $result = $this->model->validate();
- $this->assertInternalType('array', $result);
- $this->assertCount(1, $result);
- $this->assertContains("Sorry, but this password has already been used.", (string)$result[0]);
- }
-
- public function testCheckPasswordChangeEqualToPrevious()
- {
- /** @var $validatorMock \Magento\Framework\Validator\DataObject|\PHPUnit_Framework_MockObject_MockObject */
- $validatorMock = $this->getMockBuilder(\Magento\Framework\Validator\DataObject::class)
- ->disableOriginalConstructor()
- ->setMethods([])
- ->getMock();
- $this->validatorObjectFactoryMock->expects($this->once())->method('create')->willReturn($validatorMock);
- $this->validationRulesMock->expects($this->once())
- ->method('addUserInfoRules')
- ->with($validatorMock);
- $validatorMock->expects($this->once())->method('isValid')->willReturn(true);
-
- $newPassword = "NEWmYn3wpassw0rd";
- $newPasswordHash = "new password hash";
- $oldPassword = "OLDmYn3wpassw0rd";
- $this->model->setPassword($newPassword)
- ->setId(1)
- ->setOrigData('password', $oldPassword);
- $this->encryptorMock->expects($this->atLeastOnce())
- ->method('isValidHash')
- ->will($this->onConsecutiveCalls(false, true));
-
- $this->resourceMock->expects($this->once())->method('getOldPasswords')->willReturn(['hash1', $newPasswordHash]);
-
- $result = $this->model->validate();
- $this->assertInternalType('array', $result);
- $this->assertCount(1, $result);
- $this->assertContains("Sorry, but this password has already been used.", (string)$result[0]);
- }
-
- public function testCheckPasswordChangeValid()
- {
- /** @var $validatorMock \Magento\Framework\Validator\DataObject|\PHPUnit_Framework_MockObject_MockObject */
- $validatorMock = $this->getMockBuilder(\Magento\Framework\Validator\DataObject::class)
- ->disableOriginalConstructor()
- ->setMethods([])
- ->getMock();
- $this->validatorObjectFactoryMock->expects($this->once())->method('create')->willReturn($validatorMock);
- $this->validationRulesMock->expects($this->once())
- ->method('addUserInfoRules')
- ->with($validatorMock);
- $validatorMock->expects($this->once())->method('isValid')->willReturn(true);
-
- $newPassword = "NEWmYn3wpassw0rd";
- $oldPassword = "OLDmYn3wpassw0rd";
- $this->model->setPassword($newPassword)
- ->setId(1)
- ->setOrigData('password', $oldPassword);
- $this->encryptorMock->expects($this->atLeastOnce())
- ->method('isValidHash')
- ->will($this->onConsecutiveCalls(false, false, false));
-
- $this->resourceMock->expects($this->once())->method('getOldPasswords')->willReturn(['hash1', 'hash2']);
-
- $result = $this->model->validate();
- $this->assertTrue($result);
- }
-
- /**
- * Test for performIdentityCheck method
- *
- * @param bool $verifyIdentityResult
- * @param bool $lockExpires
- * @dataProvider dataProviderPerformIdentityCheck
- */
- public function testPerformIdentityCheck($verifyIdentityResult, $lockExpires)
- {
- $password = 'qwerty1';
- $userName = 'John Doe';
-
- $this->encryptorMock
- ->expects($this->once())
- ->method('validateHash')
- ->with($password, $this->model->getPassword())
- ->willReturn($verifyIdentityResult);
- $this->model->setIsActive(true);
- $this->resourceMock->expects($this->any())->method('hasAssigned2Role')->willReturn(true);
-
- $this->model->setUserName($userName);
- $this->model->setLockExpires($lockExpires);
-
- $this->eventManagerMock->expects($this->any())
- ->method('dispatch')
- ->with(
- 'admin_user_authenticate_after',
- [
- 'username' => $userName,
- 'password' => $password,
- 'user' => $this->model,
- 'result' => $verifyIdentityResult
- ]
- )
- ->willReturnSelf();
-
- if ($lockExpires) {
- $this->expectException(\Magento\Framework\Exception\State\UserLockedException::class);
- $this->expectExceptionMessage((string)__('Your account is temporarily disabled. Please try again later.'));
- }
-
- if (!$lockExpires && !$verifyIdentityResult) {
- $this->expectException(\Magento\Framework\Exception\AuthenticationException::class);
- $this->expectExceptionMessage(
- (string)__('The password entered for the current user is invalid. Verify the password and try again.')
- );
- }
-
- $this->model->performIdentityCheck($password);
- }
-
- /**
- * @return array
- */
- public function dataProviderPerformIdentityCheck()
- {
- return [
- ['verifyIdentityResult' => true, 'lockExpires' => false],
- ['verifyIdentityResult' => false, 'lockExpires' => false],
- ['verifyIdentityResult' => true, 'lockExpires' => true],
- ['verifyIdentityResult' => false, 'lockExpires' => true]
- ];
- }
}
diff --git a/app/code/Magento/User/etc/config.xml b/app/code/Magento/User/etc/config.xml
index f6a3924b5a27d..c1f51bcbecef4 100644
--- a/app/code/Magento/User/etc/config.xml
+++ b/app/code/Magento/User/etc/config.xml
@@ -10,6 +10,7 @@
admin_emails_forgot_email_template
+ admin_emails_new_user_notification_template
general
admin_emails_user_notification_template
diff --git a/app/code/Magento/User/etc/di.xml b/app/code/Magento/User/etc/di.xml
index b92549b54dac4..8fc85bc19e59a 100644
--- a/app/code/Magento/User/etc/di.xml
+++ b/app/code/Magento/User/etc/di.xml
@@ -17,4 +17,5 @@
+
diff --git a/app/code/Magento/User/etc/email_templates.xml b/app/code/Magento/User/etc/email_templates.xml
index b998f304c249b..637c2b799f37a 100644
--- a/app/code/Magento/User/etc/email_templates.xml
+++ b/app/code/Magento/User/etc/email_templates.xml
@@ -8,4 +8,10 @@
+
diff --git a/app/code/Magento/User/view/adminhtml/email/new_user_notification.html b/app/code/Magento/User/view/adminhtml/email/new_user_notification.html
new file mode 100644
index 0000000000000..891faf5fb8c2b
--- /dev/null
+++ b/app/code/Magento/User/view/adminhtml/email/new_user_notification.html
@@ -0,0 +1,18 @@
+
+
+
+
+{{trans "Hello,"}}
+
+{{trans "A new admin account was created for %first_name, %last_name using %email." first_name=$user.first_name last_name=$user.last_name email=$user.email}}
+{{trans "If you have not authorized this action, please contact us immediately at %store_email" store_email=$store_email |escape}}{{depend store_phone}} {{trans "or call us at %store_phone" store_phone=$store_phone |escape}}{{/depend}}.
+
+{{trans "Thanks,"}}
+{{var store.getFrontendName()}}
diff --git a/app/code/Magento/Widget/Block/Adminhtml/Widget/Chooser.php b/app/code/Magento/Widget/Block/Adminhtml/Widget/Chooser.php
index d813e94437326..45b3056eac68d 100644
--- a/app/code/Magento/Widget/Block/Adminhtml/Widget/Chooser.php
+++ b/app/code/Magento/Widget/Block/Adminhtml/Widget/Chooser.php
@@ -11,6 +11,9 @@
*/
namespace Magento\Widget\Block\Adminhtml\Widget;
+/**
+ * Chooser widget block.
+ */
class Chooser extends \Magento\Backend\Block\Template
{
/**
@@ -180,7 +183,7 @@ protected function _toHtml()
diff --git a/app/design/frontend/Magento/blank/web/images/logo.svg b/app/design/frontend/Magento/blank/web/images/logo.svg
index e4f627809b627..0f29d4e3eef21 100644
--- a/app/design/frontend/Magento/blank/web/images/logo.svg
+++ b/app/design/frontend/Magento/blank/web/images/logo.svg
@@ -1 +1 @@
-
+
diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/OnePageCheckoutOfflinePaymentMethodsTest.xml b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/OnePageCheckoutOfflinePaymentMethodsTest.xml
index 387e6418ee572..2cb0e2874040b 100644
--- a/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/OnePageCheckoutOfflinePaymentMethodsTest.xml
+++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestCase/OnePageCheckoutOfflinePaymentMethodsTest.xml
@@ -125,7 +125,6 @@
- MAGETWO-66737: Magento\Checkout\Test\TestCase\OnePageCheckoutTest with OnePageCheckoutTestVariation3 and 4 is not stable
test_type:acceptance_test, test_type:extended_acceptance_test, severity:S0
diff --git a/dev/tests/functional/utils/log.php b/dev/tests/functional/utils/log.php
index b6c19458b10b9..68a68d4bad648 100644
--- a/dev/tests/functional/utils/log.php
+++ b/dev/tests/functional/utils/log.php
@@ -4,11 +4,16 @@
* See COPYING.txt for license details.
*/
+declare(strict_types=1);
+
if (!isset($_GET['name'])) {
- throw new \InvalidArgumentException('The name of log file is required for getting logs.');
+ throw new \InvalidArgumentException(
+ 'The name of log file is required for getting logs.'
+ );
}
-
$name = urldecode($_GET['name']);
-$file = file_get_contents('../../../../var/log/' . $name);
+if (preg_match('/\.\.(\\\|\/)/', $name)) {
+ throw new \InvalidArgumentException('Invalid log file name');
+}
-echo serialize($file);
+echo serialize(file_get_contents('../../../../var/log' .'/' .$name));
diff --git a/dev/tests/integration/testsuite/Magento/User/Controller/Adminhtml/AuthTest.php b/dev/tests/integration/testsuite/Magento/User/Controller/Adminhtml/AuthTest.php
index 1a726c4e2c174..5f4964d042da4 100644
--- a/dev/tests/integration/testsuite/Magento/User/Controller/Adminhtml/AuthTest.php
+++ b/dev/tests/integration/testsuite/Magento/User/Controller/Adminhtml/AuthTest.php
@@ -5,6 +5,9 @@
*/
namespace Magento\User\Controller\Adminhtml;
+use Magento\TestFramework\Mail\Template\TransportBuilderMock;
+use Magento\TestFramework\Helper\Bootstrap;
+
/**
* Test class for \Magento\User\Controller\Adminhtml\Auth
*
@@ -35,7 +38,7 @@ public function testForgotpasswordAction()
$this->dispatch('backend/admin/auth/forgotpassword');
$this->assertRedirect(
$this->equalTo(
- \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get(
+ Bootstrap::getObjectManager()->get(
\Magento\Backend\Helper\Data::class
)->getHomePageUrl()
)
@@ -51,22 +54,25 @@ public function testForgotpasswordAction()
*/
public function testEmailSendForgotPasswordAction()
{
- $transportBuilderMock = $this->prepareEmailMock(
- 1,
- 'admin_emails_forgot_email_template',
- 'general'
+ /** @var TransportBuilderMock $transportMock */
+ $transportMock = Bootstrap::getObjectManager()->get(
+ TransportBuilderMock::class
);
- $this->addMockToClass($transportBuilderMock, \Magento\User\Model\User::class);
-
$this->getRequest()->setPostValue('email', 'adminUser@example.com');
$this->dispatch('backend/admin/auth/forgotpassword');
$this->assertRedirect(
$this->equalTo(
- \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get(
+ Bootstrap::getObjectManager()->get(
\Magento\Backend\Helper\Data::class
)->getHomePageUrl()
)
);
+ $message = $transportMock->getSentMessage();
+ $this->assertNotEmpty($message);
+ $this->assertEquals(
+ __('Password Reset Confirmation for %1', ['John Doe'])->render(),
+ $message->getSubject()
+ );
}
/**
@@ -79,13 +85,13 @@ public function testEmailSendForgotPasswordAction()
public function testResetPasswordAction()
{
/** @var $user \Magento\User\Model\User */
- $user = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(
+ $user = Bootstrap::getObjectManager()->create(
\Magento\User\Model\User::class
)->loadByUsername(
'dummy_username'
);
$this->assertNotEmpty($user->getId(), 'Broken fixture');
- $resetPasswordToken = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->get(
+ $resetPasswordToken = Bootstrap::getObjectManager()->get(
\Magento\User\Helper\Data::class
)->generateResetPasswordLinkToken();
$user->changeResetPasswordLinkToken($resetPasswordToken);
@@ -123,7 +129,7 @@ public function testResetPasswordActionWithDummyToken()
*/
public function testResetPasswordPostAction($password, $passwordConfirmation, $isPasswordChanged)
{
- $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+ $objectManager = Bootstrap::getObjectManager();
/** @var $user \Magento\User\Model\User */
$user = $objectManager->create(\Magento\User\Model\User::class);
@@ -203,7 +209,7 @@ public function testResetPasswordPostActionWithDummyToken()
\Magento\Framework\Message\MessageInterface::TYPE_ERROR
);
- $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+ $objectManager = Bootstrap::getObjectManager();
/** @var \Magento\Backend\Helper\Data $backendHelper */
$backendHelper = $objectManager->get(\Magento\Backend\Helper\Data::class);
@@ -218,7 +224,7 @@ public function testResetPasswordPostActionWithDummyToken()
*/
public function testResetPasswordPostActionWithInvalidPassword()
{
- $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
+ $objectManager = Bootstrap::getObjectManager();
$user = $objectManager->create(\Magento\User\Model\User::class);
$user->loadByUsername('dummy_username');
diff --git a/lib/web/images/logo.svg b/lib/web/images/logo.svg
index e4f627809b627..0f29d4e3eef21 100644
--- a/lib/web/images/logo.svg
+++ b/lib/web/images/logo.svg
@@ -1 +1 @@
-
+
diff --git a/lib/web/images/magento-logo.svg b/lib/web/images/magento-logo.svg
index e4f627809b627..0f29d4e3eef21 100644
--- a/lib/web/images/magento-logo.svg
+++ b/lib/web/images/magento-logo.svg
@@ -1 +1 @@
-
+
diff --git a/setup/src/Magento/Setup/Console/Command/AdminUserCreateCommand.php b/setup/src/Magento/Setup/Console/Command/AdminUserCreateCommand.php
index 00fa272e74962..173ea9e49a8a4 100644
--- a/setup/src/Magento/Setup/Console/Command/AdminUserCreateCommand.php
+++ b/setup/src/Magento/Setup/Console/Command/AdminUserCreateCommand.php
@@ -15,6 +15,9 @@
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Question\Question;
+/**
+ * Command to create an admin user.
+ */
class AdminUserCreateCommand extends AbstractSetupCommand
{
/**
@@ -52,6 +55,8 @@ protected function configure()
}
/**
+ * Creation admin user in interaction mode.
+ *
* @param \Symfony\Component\Console\Input\InputInterface $input
* @param \Symfony\Component\Console\Output\OutputInterface $output
*
@@ -129,6 +134,8 @@ protected function interact(InputInterface $input, OutputInterface $output)
}
/**
+ * Add not empty validator.
+ *
* @param \Symfony\Component\Console\Question\Question $question
* @return void
*/
@@ -144,7 +151,7 @@ private function addNotEmptyValidator(Question $question)
}
/**
- * {@inheritdoc}
+ * @inheritdoc
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
@@ -165,25 +172,43 @@ protected function execute(InputInterface $input, OutputInterface $output)
/**
* Get list of arguments for the command
*
+ * @param int $mode The mode of options.
* @return InputOption[]
*/
- public function getOptionsList()
+ public function getOptionsList($mode = InputOption::VALUE_REQUIRED)
{
+ $requiredStr = ($mode === InputOption::VALUE_REQUIRED ? '(Required) ' : '');
+
return [
- new InputOption(AdminAccount::KEY_USER, null, InputOption::VALUE_REQUIRED, '(Required) Admin user'),
- new InputOption(AdminAccount::KEY_PASSWORD, null, InputOption::VALUE_REQUIRED, '(Required) Admin password'),
- new InputOption(AdminAccount::KEY_EMAIL, null, InputOption::VALUE_REQUIRED, '(Required) Admin email'),
+ new InputOption(
+ AdminAccount::KEY_USER,
+ null,
+ $mode,
+ $requiredStr . 'Admin user'
+ ),
+ new InputOption(
+ AdminAccount::KEY_PASSWORD,
+ null,
+ $mode,
+ $requiredStr . 'Admin password'
+ ),
+ new InputOption(
+ AdminAccount::KEY_EMAIL,
+ null,
+ $mode,
+ $requiredStr . 'Admin email'
+ ),
new InputOption(
AdminAccount::KEY_FIRST_NAME,
null,
- InputOption::VALUE_REQUIRED,
- '(Required) Admin first name'
+ $mode,
+ $requiredStr . 'Admin first name'
),
new InputOption(
AdminAccount::KEY_LAST_NAME,
null,
- InputOption::VALUE_REQUIRED,
- '(Required) Admin last name'
+ $mode,
+ $requiredStr . 'Admin last name'
),
];
}
diff --git a/setup/src/Magento/Setup/Console/Command/InstallCommand.php b/setup/src/Magento/Setup/Console/Command/InstallCommand.php
index 7e767292b36e8..74c2e3b24234c 100644
--- a/setup/src/Magento/Setup/Console/Command/InstallCommand.php
+++ b/setup/src/Magento/Setup/Console/Command/InstallCommand.php
@@ -10,6 +10,8 @@
use Magento\Deploy\Console\Command\App\ConfigImportCommand;
use Magento\Framework\Setup\Declaration\Schema\DryRunLogger;
use Magento\Framework\Setup\Declaration\Schema\OperationsExecutor;
+use Magento\Framework\Setup\Declaration\Schema\Request;
+use Magento\Setup\Model\AdminAccount;
use Magento\Setup\Model\ConfigModel;
use Magento\Setup\Model\InstallerFactory;
use Magento\Framework\Setup\ConsoleLogger;
@@ -136,7 +138,7 @@ protected function configure()
{
$inputOptions = $this->configModel->getAvailableOptions();
$inputOptions = array_merge($inputOptions, $this->userConfig->getOptionsList());
- $inputOptions = array_merge($inputOptions, $this->adminUser->getOptionsList());
+ $inputOptions = array_merge($inputOptions, $this->adminUser->getOptionsList(InputOption::VALUE_OPTIONAL));
$inputOptions = array_merge($inputOptions, [
new InputOption(
self::INPUT_KEY_CLEANUP_DB,
@@ -251,7 +253,7 @@ protected function initialize(InputInterface $input, OutputInterface $output)
}
$errors = $this->configModel->validate($configOptionsToValidate);
- $errors = array_merge($errors, $this->adminUser->validate($input));
+ $errors = array_merge($errors, $this->validateAdmin($input));
$errors = array_merge($errors, $this->validate($input));
$errors = array_merge($errors, $this->userConfig->validate($input));
@@ -320,7 +322,7 @@ private function interactiveQuestions(InputInterface $input, OutputInterface $ou
$output->writeln("");
- foreach ($this->adminUser->getOptionsList() as $option) {
+ foreach ($this->adminUser->getOptionsList(InputOption::VALUE_OPTIONAL) as $option) {
$configOptionsToValidate[$option->getName()] = $this->askQuestion(
$input,
$output,
@@ -411,4 +413,24 @@ private function askQuestion(
return $value;
}
+
+ /**
+ * Performs validation of admin options if at least one of them was set.
+ *
+ * @param InputInterface $input
+ * @return array
+ */
+ private function validateAdmin(InputInterface $input): array
+ {
+ if ($input->getOption(AdminAccount::KEY_FIRST_NAME)
+ || $input->getOption(AdminAccount::KEY_LAST_NAME)
+ || $input->getOption(AdminAccount::KEY_EMAIL)
+ || $input->getOption(AdminAccount::KEY_USER)
+ || $input->getOption(AdminAccount::KEY_PASSWORD)
+ ) {
+ return $this->adminUser->validate($input);
+ }
+
+ return [];
+ }
}
diff --git a/setup/src/Magento/Setup/Model/Installer.php b/setup/src/Magento/Setup/Model/Installer.php
index c7a84b0cf022e..ad24307ac18b9 100644
--- a/setup/src/Magento/Setup/Model/Installer.php
+++ b/setup/src/Magento/Setup/Model/Installer.php
@@ -267,7 +267,7 @@ class Installer
* @param \Magento\Framework\Setup\SampleData\State $sampleDataState
* @param ComponentRegistrar $componentRegistrar
* @param PhpReadinessCheck $phpReadinessCheck
- *
+ * @throws \Magento\Setup\Exception
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
*/
public function __construct(
@@ -345,7 +345,9 @@ public function install($request)
[$request[InstallCommand::INPUT_KEY_SALES_ORDER_INCREMENT_PREFIX]],
];
}
- $script[] = ['Installing admin user...', 'installAdminUser', [$request]];
+ if ($this->isAdminDataSet($request)) {
+ $script[] = ['Installing admin user...', 'installAdminUser', [$request]];
+ }
if (!$this->isDryRun($request)) {
$script[] = ['Caches clearing:', 'cleanCaches', [$request]];
@@ -909,6 +911,7 @@ private function throwExceptionForNotWritablePaths(array $paths)
* @param string $type
* @param array $request
* @return void
+ * @throws \Magento\Framework\Setup\Exception
* @throws \Magento\Setup\Exception
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
* @SuppressWarnings(PHPMD.NPathComplexity)
@@ -1473,4 +1476,28 @@ private function cleanupGeneratedFiles()
$this->log->log($message);
}
}
+
+ /**
+ * Checks that admin data is not empty in request array
+ *
+ * @param \ArrayObject|array $request
+ * @return bool
+ */
+ private function isAdminDataSet($request)
+ {
+ $adminData = array_filter($request, function ($value, $key) {
+ return in_array(
+ $key,
+ [
+ AdminAccount::KEY_EMAIL,
+ AdminAccount::KEY_FIRST_NAME,
+ AdminAccount::KEY_LAST_NAME,
+ AdminAccount::KEY_USER,
+ AdminAccount::KEY_PASSWORD,
+ ]
+ ) && $value !== null;
+ }, ARRAY_FILTER_USE_BOTH);
+
+ return !empty($adminData);
+ }
}
diff --git a/setup/src/Magento/Setup/Test/Unit/Console/Command/AdminUserCreateCommandTest.php b/setup/src/Magento/Setup/Test/Unit/Console/Command/AdminUserCreateCommandTest.php
index a80302b40a617..b90fa66b3d450 100644
--- a/setup/src/Magento/Setup/Test/Unit/Console/Command/AdminUserCreateCommandTest.php
+++ b/setup/src/Magento/Setup/Test/Unit/Console/Command/AdminUserCreateCommandTest.php
@@ -11,8 +11,12 @@
use Magento\User\Model\UserValidationRules;
use Symfony\Component\Console\Application;
use Symfony\Component\Console\Helper\QuestionHelper;
+use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Tester\CommandTester;
+/**
+ * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
+ */
class AdminUserCreateCommandTest extends \PHPUnit\Framework\TestCase
{
/**
@@ -125,11 +129,34 @@ public function testInteraction()
);
}
- public function testGetOptionsList()
+ /**
+ * @param int $mode
+ * @param string $description
+ * @dataProvider getOptionListDataProvider
+ */
+ public function testGetOptionsList($mode, $description)
{
/* @var $argsList \Symfony\Component\Console\Input\InputArgument[] */
- $argsList = $this->command->getOptionsList();
+ $argsList = $this->command->getOptionsList($mode);
$this->assertEquals(AdminAccount::KEY_EMAIL, $argsList[2]->getName());
+ $this->assertEquals($description, $argsList[2]->getDescription());
+ }
+
+ /**
+ * @return array
+ */
+ public function getOptionListDataProvider()
+ {
+ return [
+ [
+ 'mode' => InputOption::VALUE_REQUIRED,
+ 'description' => '(Required) Admin email',
+ ],
+ [
+ 'mode' => InputOption::VALUE_OPTIONAL,
+ 'description' => 'Admin email',
+ ],
+ ];
}
/**
diff --git a/setup/src/Magento/Setup/Test/Unit/Console/Command/InstallCommandTest.php b/setup/src/Magento/Setup/Test/Unit/Console/Command/InstallCommandTest.php
index 5b7b6c1626911..3c3a875a278e8 100644
--- a/setup/src/Magento/Setup/Test/Unit/Console/Command/InstallCommandTest.php
+++ b/setup/src/Magento/Setup/Test/Unit/Console/Command/InstallCommandTest.php
@@ -16,6 +16,7 @@
use Magento\Backend\Setup\ConfigOptionsList as BackendConfigOptionsList;
use Magento\Framework\Config\ConfigOptionsListConstants as SetupConfigOptionsList;
use Magento\Setup\Model\StoreConfigurationDataMapper;
+use Magento\Setup\Console\Command\AdminUserCreateCommand;
/**
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
@@ -62,6 +63,11 @@ class InstallCommandTest extends \PHPUnit\Framework\TestCase
*/
private $configImportMock;
+ /**
+ * @var AdminUserCreateCommand|\PHPUnit_Framework_MockObject_MockObject
+ */
+ private $adminUserMock;
+
public function setUp()
{
$this->input = [
@@ -73,11 +79,6 @@ public function setUp()
'--' . StoreConfigurationDataMapper::KEY_LANGUAGE => 'en_US',
'--' . StoreConfigurationDataMapper::KEY_TIMEZONE => 'America/Chicago',
'--' . StoreConfigurationDataMapper::KEY_CURRENCY => 'USD',
- '--' . AdminAccount::KEY_USER => 'user',
- '--' . AdminAccount::KEY_PASSWORD => '123123q',
- '--' . AdminAccount::KEY_EMAIL => 'test@test.com',
- '--' . AdminAccount::KEY_FIRST_NAME => 'John',
- '--' . AdminAccount::KEY_LAST_NAME => 'Doe',
];
$configModel = $this->createMock(\Magento\Setup\Model\ConfigModel::class);
@@ -100,15 +101,11 @@ public function setUp()
->method('validate')
->will($this->returnValue([]));
- $adminUser = $this->createMock(\Magento\Setup\Console\Command\AdminUserCreateCommand::class);
- $adminUser
+ $this->adminUserMock = $this->createMock(AdminUserCreateCommand::class);
+ $this->adminUserMock
->expects($this->once())
->method('getOptionsList')
->will($this->returnValue($this->getOptionsListAdminUser()));
- $adminUser
- ->expects($this->once())
- ->method('validate')
- ->will($this->returnValue([]));
$this->installerFactory = $this->createMock(\Magento\Setup\Model\InstallerFactory::class);
$this->installer = $this->createMock(\Magento\Setup\Model\Installer::class);
@@ -143,7 +140,7 @@ public function setUp()
$this->installerFactory,
$configModel,
$userConfig,
- $adminUser
+ $this->adminUserMock
);
$this->command->setApplication(
$this->applicationMock
@@ -152,6 +149,16 @@ public function setUp()
public function testExecute()
{
+ $this->input['--' . AdminAccount::KEY_USER] = 'user';
+ $this->input['--' . AdminAccount::KEY_PASSWORD] = '123123q';
+ $this->input['--' . AdminAccount::KEY_EMAIL] = 'test@test.com';
+ $this->input['--' . AdminAccount::KEY_FIRST_NAME] = 'John';
+ $this->input['--' . AdminAccount::KEY_LAST_NAME] = 'Doe';
+
+ $this->adminUserMock
+ ->expects($this->once())
+ ->method('validate')
+ ->willReturn([]);
$this->installerFactory->expects($this->once())
->method('create')
->will($this->returnValue($this->installer));
@@ -269,6 +276,9 @@ private function getOptionsListAdminUser()
*/
public function testValidate($prefixValue)
{
+ $this->adminUserMock
+ ->expects($this->never())
+ ->method('validate');
$this->installerFactory->expects($this->once())
->method('create')
->will($this->returnValue($this->installer));
@@ -288,6 +298,9 @@ public function testValidate($prefixValue)
*/
public function testValidateWithException($prefixValue)
{
+ $this->adminUserMock
+ ->expects($this->never())
+ ->method('validate');
$this->installerFactory->expects($this->never())
->method('create')
->will($this->returnValue($this->installer));
diff --git a/setup/src/Magento/Setup/Test/Unit/Model/InstallerTest.php b/setup/src/Magento/Setup/Test/Unit/Model/InstallerTest.php
index 8a4263be18ecf..e600002d53560 100644
--- a/setup/src/Magento/Setup/Test/Unit/Model/InstallerTest.php
+++ b/setup/src/Magento/Setup/Test/Unit/Model/InstallerTest.php
@@ -9,6 +9,7 @@
use Magento\Backend\Setup\ConfigOptionsList;
use Magento\Framework\Config\ConfigOptionsListConstants;
use Magento\Framework\Setup\SchemaListener;
+ use Magento\Setup\Model\AdminAccount;
use Magento\Setup\Model\DeclarationInstaller;
use Magento\Setup\Model\Installer;
use Magento\Framework\App\Filesystem\DirectoryList;
@@ -268,17 +269,13 @@ private function createObject($connectionFactory = false, $objectManagerProvider
}
/**
+ * @param array $request
+ * @param array $logMessages
+ * @dataProvider installDataProvider
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
*/
- public function testInstall()
+ public function testInstall(array $request, array $logMessages)
{
- $request = [
- ConfigOptionsListConstants::INPUT_KEY_DB_HOST => '127.0.0.1',
- ConfigOptionsListConstants::INPUT_KEY_DB_NAME => 'magento',
- ConfigOptionsListConstants::INPUT_KEY_DB_USER => 'magento',
- ConfigOptionsListConstants::INPUT_KEY_ENCRYPTION_KEY => 'encryption_key',
- ConfigOptionsList::INPUT_KEY_BACKEND_FRONTNAME => 'backend',
- ];
$this->config->expects($this->atLeastOnce())
->method('get')
->willReturnMap(
@@ -353,7 +350,7 @@ public function testInstall()
[\Magento\Setup\Model\DeclarationInstaller::class, $this->declarationInstallerMock],
[\Magento\Framework\Registry::class, $registry]
]));
- $this->adminFactory->expects($this->once())->method('create')->willReturn(
+ $this->adminFactory->expects($this->any())->method('create')->willReturn(
$this->createMock(\Magento\Setup\Model\AdminAccount::class)
);
$this->sampleDataState->expects($this->once())->method('hasError')->willReturn(true);
@@ -366,11 +363,119 @@ public function testInstall()
$this->filePermissions->expects($this->once())
->method('getMissingWritableDirectoriesForDbUpgrade')
->willReturn([]);
- $this->setupLoggerExpectsForInstall();
+ call_user_func_array(
+ [
+ $this->logger->expects($this->exactly(count($logMessages)))->method('log'),
+ 'withConsecutive'
+ ],
+ $logMessages
+ );
+ $this->logger->expects($this->exactly(2))
+ ->method('logSuccess')
+ ->withConsecutive(
+ ['Magento installation complete.'],
+ ['Magento Admin URI: /']
+ );
$this->object->install($request);
}
+ /**
+ * @return array
+ */
+ public function installDataProvider()
+ {
+ return [
+ [
+ 'request' => [
+ ConfigOptionsListConstants::INPUT_KEY_DB_HOST => '127.0.0.1',
+ ConfigOptionsListConstants::INPUT_KEY_DB_NAME => 'magento',
+ ConfigOptionsListConstants::INPUT_KEY_DB_USER => 'magento',
+ ConfigOptionsListConstants::INPUT_KEY_ENCRYPTION_KEY => 'encryption_key',
+ ConfigOptionsList::INPUT_KEY_BACKEND_FRONTNAME => 'backend',
+ ],
+ 'logMessages' => [
+ ['Starting Magento installation:'],
+ ['File permissions check...'],
+ ['Required extensions check...'],
+ ['Enabling Maintenance Mode...'],
+ ['Installing deployment configuration...'],
+ ['Installing database schema:'],
+ ['Schema creation/updates:'],
+ ['Module \'Foo_One\':'],
+ ['Module \'Bar_Two\':'],
+ ['Schema post-updates:'],
+ ['Module \'Foo_One\':'],
+ ['Module \'Bar_Two\':'],
+ ['Installing user configuration...'],
+ ['Enabling caches:'],
+ ['Current status:'],
+ [''],
+ ['Installing data...'],
+ ['Data install/update:'],
+ ['Module \'Foo_One\':'],
+ ['Module \'Bar_Two\':'],
+ ['Data post-updates:'],
+ ['Module \'Foo_One\':'],
+ ['Module \'Bar_Two\':'],
+ //['Installing admin user...'],
+ ['Caches clearing:'],
+ ['Cache cleared successfully'],
+ ['Disabling Maintenance Mode:'],
+ ['Post installation file permissions check...'],
+ ['Write installation date...'],
+ ['Sample Data is installed with errors. See log file for details']
+ ],
+ ],
+ [
+ 'request' => [
+ ConfigOptionsListConstants::INPUT_KEY_DB_HOST => '127.0.0.1',
+ ConfigOptionsListConstants::INPUT_KEY_DB_NAME => 'magento',
+ ConfigOptionsListConstants::INPUT_KEY_DB_USER => 'magento',
+ ConfigOptionsListConstants::INPUT_KEY_ENCRYPTION_KEY => 'encryption_key',
+ ConfigOptionsList::INPUT_KEY_BACKEND_FRONTNAME => 'backend',
+ AdminAccount::KEY_USER => 'admin',
+ AdminAccount::KEY_PASSWORD => '123',
+ AdminAccount::KEY_EMAIL => 'admin@example.com',
+ AdminAccount::KEY_FIRST_NAME => 'John',
+ AdminAccount::KEY_LAST_NAME => 'Doe',
+ ],
+ 'logMessages' => [
+ ['Starting Magento installation:'],
+ ['File permissions check...'],
+ ['Required extensions check...'],
+ ['Enabling Maintenance Mode...'],
+ ['Installing deployment configuration...'],
+ ['Installing database schema:'],
+ ['Schema creation/updates:'],
+ ['Module \'Foo_One\':'],
+ ['Module \'Bar_Two\':'],
+ ['Schema post-updates:'],
+ ['Module \'Foo_One\':'],
+ ['Module \'Bar_Two\':'],
+ ['Installing user configuration...'],
+ ['Enabling caches:'],
+ ['Current status:'],
+ [''],
+ ['Installing data...'],
+ ['Data install/update:'],
+ ['Module \'Foo_One\':'],
+ ['Module \'Bar_Two\':'],
+ ['Data post-updates:'],
+ ['Module \'Foo_One\':'],
+ ['Module \'Bar_Two\':'],
+ ['Installing admin user...'],
+ ['Caches clearing:'],
+ ['Cache cleared successfully'],
+ ['Disabling Maintenance Mode:'],
+ ['Post installation file permissions check...'],
+ ['Write installation date...'],
+ ['Sample Data is installed with errors. See log file for details']
+ ],
+ ],
+ ];
+ }
+
public function testCheckInstallationFilePermissions()
{
$this->filePermissions
@@ -590,44 +695,6 @@ private function prepareForUpdateModulesTests()
return $newObject;
}
-
- /**
- * Set up logger expectations for install method
- * @return void
- */
- private function setupLoggerExpectsForInstall()
- {
- $this->logger->expects($this->at(0))->method('log')->with('Starting Magento installation:');
- $this->logger->expects($this->at(1))->method('log')->with('File permissions check...');
- $this->logger->expects($this->at(3))->method('log')->with('Required extensions check...');
- // at(2) invokes logMeta()
- $this->logger->expects($this->at(5))->method('log')->with('Enabling Maintenance Mode...');
- // at(4) - logMeta and so on...
- $this->logger->expects($this->at(7))->method('log')->with('Installing deployment configuration...');
- $this->logger->expects($this->at(9))->method('log')->with('Installing database schema:');
- $this->logger->expects($this->at(11))->method('log')->with("Module 'Foo_One':");
- $this->logger->expects($this->at(13))->method('log')->with("Module 'Bar_Two':");
- $this->logger->expects($this->at(15))->method('log')->with('Schema post-updates:');
- $this->logger->expects($this->at(16))->method('log')->with("Module 'Foo_One':");
- $this->logger->expects($this->at(18))->method('log')->with("Module 'Bar_Two':");
- $this->logger->expects($this->at(21))->method('log')->with('Installing user configuration...');
- $this->logger->expects($this->at(23))->method('log')->with('Enabling caches:');
- $this->logger->expects($this->at(27))->method('log')->with('Installing data...');
- $this->logger->expects($this->at(28))->method('log')->with('Data install/update:');
- $this->logger->expects($this->at(29))->method('log')->with("Module 'Foo_One':");
- $this->logger->expects($this->at(31))->method('log')->with("Module 'Bar_Two':");
- $this->logger->expects($this->at(33))->method('log')->with('Data post-updates:');
- $this->logger->expects($this->at(34))->method('log')->with("Module 'Foo_One':");
- $this->logger->expects($this->at(36))->method('log')->with("Module 'Bar_Two':");
- $this->logger->expects($this->at(39))->method('log')->with('Installing admin user...');
- $this->logger->expects($this->at(41))->method('log')->with('Caches clearing:');
- $this->logger->expects($this->at(44))->method('log')->with('Disabling Maintenance Mode:');
- $this->logger->expects($this->at(46))->method('log')->with('Post installation file permissions check...');
- $this->logger->expects($this->at(48))->method('log')->with('Write installation date...');
- $this->logger->expects($this->at(50))->method('logSuccess')->with('Magento installation complete.');
- $this->logger->expects($this->at(52))->method('log')
- ->with('Sample Data is installed with errors. See log file for details');
- }
}
}
diff --git a/setup/view/magento/setup/marketplace-credentials.phtml b/setup/view/magento/setup/marketplace-credentials.phtml
index 32ae512313610..8bd0bb0438d61 100644
--- a/setup/view/magento/setup/marketplace-credentials.phtml
+++ b/setup/view/magento/setup/marketplace-credentials.phtml
@@ -7,7 +7,7 @@
diff --git a/setup/view/magento/setup/popupauth.phtml b/setup/view/magento/setup/popupauth.phtml
index 8b074abaa5f12..3ffca7ba49bab 100644
--- a/setup/view/magento/setup/popupauth.phtml
+++ b/setup/view/magento/setup/popupauth.phtml
@@ -17,7 +17,9 @@