diff --git a/.htaccess b/.htaccess
index 90b9c16a5a8c0..e7a6c2e218cb7 100644
--- a/.htaccess
+++ b/.htaccess
@@ -36,7 +36,7 @@
############################################
## adjust memory limit
- php_value memory_limit 768M
+ php_value memory_limit 756M
php_value max_execution_time 18000
############################################
@@ -59,7 +59,7 @@
############################################
## adjust memory limit
- php_value memory_limit 768M
+ php_value memory_limit 756M
php_value max_execution_time 18000
############################################
diff --git a/.htaccess.sample b/.htaccess.sample
index 3b61bb672ec8a..aa8aaaf9b2818 100644
--- a/.htaccess.sample
+++ b/.htaccess.sample
@@ -35,7 +35,7 @@
############################################
## adjust memory limit
- php_value memory_limit 768M
+ php_value memory_limit 756M
php_value max_execution_time 18000
############################################
diff --git a/.user.ini b/.user.ini
index 8c0b765e0551c..bfc3a86d88e20 100644
--- a/.user.ini
+++ b/.user.ini
@@ -1,4 +1,4 @@
-memory_limit = 768M
+memory_limit = 756M
max_execution_time = 18000
session.auto_start = off
suhosin.session.cryptua = off
\ No newline at end of file
diff --git a/app/code/Magento/Backend/Block/Dashboard/Graph.php b/app/code/Magento/Backend/Block/Dashboard/Graph.php
index cecd7b8050352..301dffbdc4987 100644
--- a/app/code/Magento/Backend/Block/Dashboard/Graph.php
+++ b/app/code/Magento/Backend/Block/Dashboard/Graph.php
@@ -421,6 +421,8 @@ public function getChartUrl($directUrl = true)
$tmpstring = implode('|', $this->_axisLabels[$idx]);
$valueBuffer[] = $indexid . ":|" . $tmpstring;
+ } elseif ($idx == 'y') {
+ $valueBuffer[] = $indexid . ":|" . implode('|', $yLabels);
}
$indexid++;
}
diff --git a/app/code/Magento/Catalog/Model/Product/Attribute/SetRepository.php b/app/code/Magento/Catalog/Model/Product/Attribute/SetRepository.php
index ab6cdb3b464a4..14774103b8cd2 100644
--- a/app/code/Magento/Catalog/Model/Product/Attribute/SetRepository.php
+++ b/app/code/Magento/Catalog/Model/Product/Attribute/SetRepository.php
@@ -62,6 +62,7 @@ public function save(\Magento\Eav\Api\Data\AttributeSetInterface $attributeSet)
*/
public function getList(\Magento\Framework\Api\SearchCriteriaInterface $searchCriteria)
{
+ $this->searchCriteriaBuilder->setFilterGroups((array)$searchCriteria->getFilterGroups());
$this->searchCriteriaBuilder->addFilters(
[
$this->filterBuilder
@@ -71,9 +72,15 @@ public function getList(\Magento\Framework\Api\SearchCriteriaInterface $searchCr
->create(),
]
);
+
+ $this->searchCriteriaBuilder->setSortOrders((array)$searchCriteria->getSortOrders());
$this->searchCriteriaBuilder->setCurrentPage($searchCriteria->getCurrentPage());
$this->searchCriteriaBuilder->setPageSize($searchCriteria->getPageSize());
- return $this->attributeSetRepository->getList($this->searchCriteriaBuilder->create());
+
+ $searchResult = $this->attributeSetRepository->getList($this->searchCriteriaBuilder->create());
+ $searchResult->setSearchCriteria($searchCriteria);
+
+ return $searchResult;
}
/**
diff --git a/app/code/Magento/Catalog/Model/ProductRepository.php b/app/code/Magento/Catalog/Model/ProductRepository.php
index 4a72539e982f2..4927a19146723 100644
--- a/app/code/Magento/Catalog/Model/ProductRepository.php
+++ b/app/code/Magento/Catalog/Model/ProductRepository.php
@@ -312,7 +312,7 @@ private function cacheProduct($cacheKey, \Magento\Catalog\Api\Data\ProductInterf
if ($this->cacheLimit && count($this->instances) > $this->cacheLimit) {
$offset = round($this->cacheLimit / -2);
$this->instancesById = array_slice($this->instancesById, $offset, null, true);
- $this->instances = array_slice($this->instances, $offset);
+ $this->instances = array_slice($this->instances, $offset, null, true);
}
}
diff --git a/app/code/Magento/Catalog/view/frontend/templates/product/list/items.phtml b/app/code/Magento/Catalog/view/frontend/templates/product/list/items.phtml
index 1b9f014b7c27f..fc0967ca60d2d 100644
--- a/app/code/Magento/Catalog/view/frontend/templates/product/list/items.phtml
+++ b/app/code/Magento/Catalog/view/frontend/templates/product/list/items.phtml
@@ -203,7 +203,7 @@ switch ($type = $block->getType()) {
= $block->getReviewsSummaryHtml($_item, $templateType) ?>
- isComposite() && $_item->isSaleable() && $type == 'related'): ?>
+ isComposite() && $_item->isSaleable() && $type == 'related'): ?>
getRequiredOptions()): ?>
diff --git a/app/code/Magento/Checkout/Block/Checkout/AttributeMerger.php b/app/code/Magento/Checkout/Block/Checkout/AttributeMerger.php
index 4ee3d070d5b77..d93475a4744ca 100644
--- a/app/code/Magento/Checkout/Block/Checkout/AttributeMerger.php
+++ b/app/code/Magento/Checkout/Block/Checkout/AttributeMerger.php
@@ -168,20 +168,19 @@ protected function getFieldConfig(
$element = [
'component' => isset($additionalConfig['component']) ? $additionalConfig['component'] : $uiComponent,
- 'config' => [
- // customScope is used to group elements within a single form (e.g. they can be validated separately)
- 'customScope' => $dataScopePrefix,
- 'customEntry' => isset($additionalConfig['config']['customEntry'])
- ? $additionalConfig['config']['customEntry']
- : null,
- 'template' => 'ui/form/field',
- 'elementTmpl' => isset($additionalConfig['config']['elementTmpl'])
- ? $additionalConfig['config']['elementTmpl']
- : $elementTemplate,
- 'tooltip' => isset($additionalConfig['config']['tooltip'])
- ? $additionalConfig['config']['tooltip']
- : null
- ],
+ 'config' => $this->mergeConfigurationNode(
+ 'config',
+ $additionalConfig,
+ [
+ 'config' => [
+ // customScope is used to group elements within a single
+ // form (e.g. they can be validated separately)
+ 'customScope' => $dataScopePrefix,
+ 'template' => 'ui/form/field',
+ 'elementTmpl' => $elementTemplate,
+ ],
+ ]
+ ),
'dataScope' => $dataScopePrefix . '.' . $attributeCode,
'label' => $attributeConfig['label'],
'provider' => $providerName,
diff --git a/app/code/Magento/Checkout/view/frontend/web/js/model/resource-url-manager.js b/app/code/Magento/Checkout/view/frontend/web/js/model/resource-url-manager.js
index 2d27d4a032b24..410f5b4927374 100644
--- a/app/code/Magento/Checkout/view/frontend/web/js/model/resource-url-manager.js
+++ b/app/code/Magento/Checkout/view/frontend/web/js/model/resource-url-manager.js
@@ -75,8 +75,8 @@ define([
quoteId: quoteId
} : {},
urls = {
- 'guest': '/guest-carts/' + quoteId + '/coupons/' + couponCode,
- 'customer': '/carts/mine/coupons/' + couponCode
+ 'guest': '/guest-carts/' + quoteId + '/coupons/' + encodeURIComponent(couponCode),
+ 'customer': '/carts/mine/coupons/' + encodeURIComponent(couponCode)
};
return this.getUrl(urls, params);
diff --git a/app/code/Magento/Customer/Block/Widget/Dob.php b/app/code/Magento/Customer/Block/Widget/Dob.php
index 037d24d065708..0d282042b1d94 100644
--- a/app/code/Magento/Customer/Block/Widget/Dob.php
+++ b/app/code/Magento/Customer/Block/Widget/Dob.php
@@ -186,7 +186,8 @@ public function getFieldHtml()
'max_date' => '-1d',
'change_month' => 'true',
'change_year' => 'true',
- 'show_on' => 'both'
+ 'show_on' => 'both',
+ 'first_day' => $this->getFirstDay()
]);
return $this->dateElement->getHtml();
}
@@ -307,4 +308,17 @@ public function getMaxDateRange()
}
return null;
}
+
+ /**
+ * Return first day of the week
+ *
+ * @return int
+ */
+ public function getFirstDay()
+ {
+ return (int)$this->_scopeConfig->getValue(
+ 'general/locale/firstday',
+ \Magento\Store\Model\ScopeInterface::SCOPE_STORE
+ );
+ }
}
diff --git a/app/code/Magento/Customer/Model/AccountManagement.php b/app/code/Magento/Customer/Model/AccountManagement.php
index b7b099ec45232..59205a4d91838 100644
--- a/app/code/Magento/Customer/Model/AccountManagement.php
+++ b/app/code/Magento/Customer/Model/AccountManagement.php
@@ -12,16 +12,17 @@
use Magento\Customer\Api\Data\AddressInterface;
use Magento\Customer\Api\Data\CustomerInterface;
use Magento\Customer\Api\Data\ValidationResultsInterfaceFactory;
-use Magento\Customer\Model\EmailNotificationInterface;
use Magento\Customer\Helper\View as CustomerViewHelper;
use Magento\Customer\Model\Config\Share as ConfigShare;
use Magento\Customer\Model\Customer as CustomerModel;
+use Magento\Customer\Model\Customer\CredentialsValidator;
use Magento\Customer\Model\Metadata\Validator;
use Magento\Eav\Model\Validator\Attribute\Backend;
use Magento\Framework\Api\ExtensibleDataObjectConverter;
use Magento\Framework\App\Area;
use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Framework\App\ObjectManager;
+use Magento\Framework\DataObjectFactory as ObjectFactory;
use Magento\Framework\Encryption\EncryptorInterface as Encryptor;
use Magento\Framework\Encryption\Helper\Security;
use Magento\Framework\Event\ManagerInterface;
@@ -30,23 +31,22 @@
use Magento\Framework\Exception\InputException;
use Magento\Framework\Exception\InvalidEmailOrPasswordException;
use Magento\Framework\Exception\LocalizedException;
+use Magento\Framework\Exception\MailException;
use Magento\Framework\Exception\NoSuchEntityException;
use Magento\Framework\Exception\State\ExpiredException;
use Magento\Framework\Exception\State\InputMismatchException;
use Magento\Framework\Exception\State\InvalidTransitionException;
-use Magento\Framework\DataObjectFactory as ObjectFactory;
use Magento\Framework\Exception\State\UserLockedException;
-use Magento\Framework\Registry;
-use Magento\Store\Model\ScopeInterface;
-use Psr\Log\LoggerInterface as PsrLogger;
-use Magento\Framework\Exception\MailException;
+use Magento\Framework\Intl\DateTimeFactory;
use Magento\Framework\Mail\Template\TransportBuilder;
use Magento\Framework\Math\Random;
use Magento\Framework\Reflection\DataObjectProcessor;
+use Magento\Framework\Registry;
use Magento\Framework\Stdlib\DateTime;
use Magento\Framework\Stdlib\StringUtils as StringHelper;
+use Magento\Store\Model\ScopeInterface;
use Magento\Store\Model\StoreManagerInterface;
-use Magento\Customer\Model\Customer\CredentialsValidator;
+use Psr\Log\LoggerInterface as PsrLogger;
/**
* Handle various customer account actions
@@ -293,6 +293,11 @@ class AccountManagement implements AccountManagementInterface
*/
private $credentialsValidator;
+ /**
+ * @var DateTimeFactory
+ */
+ private $dateTimeFactory;
+
/**
* @param CustomerFactory $customerFactory
* @param ManagerInterface $eventManager
@@ -318,6 +323,7 @@ class AccountManagement implements AccountManagementInterface
* @param ObjectFactory $objectFactory
* @param ExtensibleDataObjectConverter $extensibleDataObjectConverter
* @param CredentialsValidator|null $credentialsValidator
+ * @param DateTimeFactory $dateTimeFactory
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
*/
public function __construct(
@@ -344,7 +350,8 @@ public function __construct(
CustomerModel $customerModel,
ObjectFactory $objectFactory,
ExtensibleDataObjectConverter $extensibleDataObjectConverter,
- CredentialsValidator $credentialsValidator = null
+ CredentialsValidator $credentialsValidator = null,
+ DateTimeFactory $dateTimeFactory = null
) {
$this->customerFactory = $customerFactory;
$this->eventManager = $eventManager;
@@ -369,8 +376,9 @@ public function __construct(
$this->customerModel = $customerModel;
$this->objectFactory = $objectFactory;
$this->extensibleDataObjectConverter = $extensibleDataObjectConverter;
- $this->credentialsValidator = $credentialsValidator ?: ObjectManager::getInstance()
- ->get(CredentialsValidator::class);
+ $this->credentialsValidator =
+ $credentialsValidator ?: ObjectManager::getInstance()->get(CredentialsValidator::class);
+ $this->dateTimeFactory = $dateTimeFactory ?: ObjectManager::getInstance()->get(DateTimeFactory::class);
}
/**
@@ -380,7 +388,6 @@ public function __construct(
*/
private function getAuthentication()
{
-
if (!($this->authentication instanceof AuthenticationInterface)) {
return \Magento\Framework\App\ObjectManager::getInstance()->get(
\Magento\Customer\Model\AuthenticationInterface::class
@@ -613,16 +620,16 @@ protected function makeRequiredCharactersCheck($password)
$return = 0;
if (preg_match('/[0-9]+/', $password)) {
- $counter ++;
+ $counter++;
}
if (preg_match('/[A-Z]+/', $password)) {
- $counter ++;
+ $counter++;
}
if (preg_match('/[a-z]+/', $password)) {
- $counter ++;
+ $counter++;
}
if (preg_match('/[^a-zA-Z0-9]+/', $password)) {
- $counter ++;
+ $counter++;
}
if ($counter < $requiredNumber) {
@@ -890,16 +897,14 @@ public function validate(CustomerInterface $customer)
$result = $this->getEavValidator()->isValid($customerModel);
if ($result === false && is_array($this->getEavValidator()->getMessages())) {
- return $validationResults->setIsValid(false)
- ->setMessages(
- call_user_func_array(
- 'array_merge',
- $this->getEavValidator()->getMessages()
- )
- );
+ return $validationResults->setIsValid(false)->setMessages(
+ call_user_func_array(
+ 'array_merge',
+ $this->getEavValidator()->getMessages()
+ )
+ );
}
- return $validationResults->setIsValid(true)
- ->setMessages([]);
+ return $validationResults->setIsValid(true)->setMessages([]);
}
/**
@@ -949,10 +954,12 @@ public function isCustomerInStore($customerWebsiteId, $storeId)
private function validateResetPasswordToken($customerId, $resetPasswordLinkToken)
{
if (empty($customerId) || $customerId < 0) {
- throw new InputException(__(
- 'Invalid value of "%value" provided for the %fieldName field.',
- ['value' => $customerId, 'fieldName' => 'customerId']
- ));
+ throw new InputException(
+ __(
+ 'Invalid value of "%value" provided for the %fieldName field.',
+ ['value' => $customerId, 'fieldName' => 'customerId']
+ )
+ );
}
if (!is_string($resetPasswordLinkToken) || empty($resetPasswordLinkToken)) {
$params = ['fieldName' => 'resetPasswordLinkToken'];
@@ -1076,10 +1083,10 @@ protected function getTemplateTypes()
* self::NEW_ACCOUNT_EMAIL_CONFIRMATION email with confirmation link
*/
$types = [
- self::NEW_ACCOUNT_EMAIL_REGISTERED => self::XML_PATH_REGISTER_EMAIL_TEMPLATE,
+ self::NEW_ACCOUNT_EMAIL_REGISTERED => self::XML_PATH_REGISTER_EMAIL_TEMPLATE,
self::NEW_ACCOUNT_EMAIL_REGISTERED_NO_PASSWORD => self::XML_PATH_REGISTER_NO_PASSWORD_EMAIL_TEMPLATE,
- self::NEW_ACCOUNT_EMAIL_CONFIRMED => self::XML_PATH_CONFIRMED_EMAIL_TEMPLATE,
- self::NEW_ACCOUNT_EMAIL_CONFIRMATION => self::XML_PATH_CONFIRM_EMAIL_TEMPLATE,
+ self::NEW_ACCOUNT_EMAIL_CONFIRMED => self::XML_PATH_CONFIRMED_EMAIL_TEMPLATE,
+ self::NEW_ACCOUNT_EMAIL_CONFIRMATION => self::XML_PATH_CONFIRM_EMAIL_TEMPLATE,
];
return $types;
}
@@ -1109,12 +1116,11 @@ protected function sendEmailTemplate(
$email = $customer->getEmail();
}
- $transport = $this->transportBuilder->setTemplateIdentifier($templateId)
- ->setTemplateOptions(['area' => Area::AREA_FRONTEND, 'store' => $storeId])
- ->setTemplateVars($templateParams)
- ->setFrom($this->scopeConfig->getValue($sender, ScopeInterface::SCOPE_STORE, $storeId))
- ->addTo($email, $this->customerViewHelper->getCustomerName($customer))
- ->getTransport();
+ $transport = $this->transportBuilder->setTemplateIdentifier($templateId)->setTemplateOptions(
+ ['area' => Area::AREA_FRONTEND, 'store' => $storeId]
+ )->setTemplateVars($templateParams)->setFrom(
+ $this->scopeConfig->getValue($sender, ScopeInterface::SCOPE_STORE, $storeId)
+ )->addTo($email, $this->customerViewHelper->getCustomerName($customer))->getTransport();
$transport->sendMessage();
@@ -1178,8 +1184,8 @@ public function isResetPasswordLinkTokenExpired($rpToken, $rpTokenCreatedAt)
$expirationPeriod = $this->customerModel->getResetPasswordLinkExpirationPeriod();
- $currentTimestamp = (new \DateTime())->getTimestamp();
- $tokenTimestamp = (new \DateTime($rpTokenCreatedAt))->getTimestamp();
+ $currentTimestamp = $this->dateTimeFactory->create()->getTimestamp();
+ $tokenTimestamp = $this->dateTimeFactory->create($rpTokenCreatedAt)->getTimestamp();
if ($tokenTimestamp > $currentTimestamp) {
return true;
}
@@ -1215,7 +1221,9 @@ public function changeResetPasswordLinkToken($customer, $passwordLinkToken)
if (is_string($passwordLinkToken) && !empty($passwordLinkToken)) {
$customerSecure = $this->customerRegistry->retrieveSecureData($customer->getId());
$customerSecure->setRpToken($passwordLinkToken);
- $customerSecure->setRpTokenCreatedAt((new \DateTime())->format(DateTime::DATETIME_PHP_FORMAT));
+ $customerSecure->setRpTokenCreatedAt(
+ $this->dateTimeFactory->create()->format(DateTime::DATETIME_PHP_FORMAT)
+ );
$this->customerRepository->save($customer);
}
return true;
@@ -1304,8 +1312,8 @@ protected function getFullCustomerObject($customer)
// No need to flatten the custom attributes or nested objects since the only usage is for email templates and
// object passed for events
$mergedCustomerData = $this->customerRegistry->retrieveSecureData($customer->getId());
- $customerData = $this->dataProcessor
- ->buildOutputDataArray($customer, \Magento\Customer\Api\Data\CustomerInterface::class);
+ $customerData =
+ $this->dataProcessor->buildOutputDataArray($customer, \Magento\Customer\Api\Data\CustomerInterface::class);
$mergedCustomerData->addData($customerData);
$mergedCustomerData->setData('name', $this->customerViewHelper->getCustomerName($customer));
return $mergedCustomerData;
diff --git a/app/code/Magento/Customer/Model/ResourceModel/CustomerRepository.php b/app/code/Magento/Customer/Model/ResourceModel/CustomerRepository.php
index a87f32d945070..e66caeeb33707 100644
--- a/app/code/Magento/Customer/Model/ResourceModel/CustomerRepository.php
+++ b/app/code/Magento/Customer/Model/ResourceModel/CustomerRepository.php
@@ -246,7 +246,7 @@ public function save(\Magento\Customer\Api\Data\CustomerInterface $customer, $pa
$savedCustomer = $this->get($customer->getEmail(), $customer->getWebsiteId());
$this->eventManager->dispatch(
'customer_save_after_data_object',
- ['customer_data_object' => $savedCustomer, 'orig_customer_data_object' => $customer]
+ ['customer_data_object' => $savedCustomer, 'orig_customer_data_object' => $prevCustomerData]
);
return $savedCustomer;
}
diff --git a/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php b/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php
index de9c0460ad29e..34662eecc0c1c 100644
--- a/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php
+++ b/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php
@@ -10,6 +10,7 @@
use Magento\Customer\Model\EmailNotificationInterface;
use Magento\Framework\App\Area;
use Magento\Framework\Exception\NoSuchEntityException;
+use Magento\Framework\Intl\DateTimeFactory;
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper;
use Magento\Store\Model\ScopeInterface;
@@ -114,6 +115,11 @@ class AccountManagementTest extends \PHPUnit\Framework\TestCase
*/
protected $emailNotificationMock;
+ /**
+ * @var DateTimeFactory|\PHPUnit_Framework_MockObject_MockObject
+ */
+ private $dateTimeFactory;
+
/**
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
*/
@@ -163,6 +169,8 @@ protected function setUp()
->disableOriginalConstructor()
->getMock();
+ $this->dateTimeFactory = $this->createMock(DateTimeFactory::class);
+
$this->objectManagerHelper = new ObjectManagerHelper($this);
$this->accountManagement = $this->objectManagerHelper->getObject(
\Magento\Customer\Model\AccountManagement::class,
@@ -190,6 +198,7 @@ protected function setUp()
'customerModel' => $this->customer,
'objectFactory' => $this->objectFactory,
'extensibleDataObjectConverter' => $this->extensibleDataObjectConverter,
+ 'dateTimeFactory' => $this->dateTimeFactory,
]
);
$reflection = new \ReflectionClass(get_class($this->accountManagement));
@@ -552,6 +561,8 @@ public function testCreateAccountWithoutPassword()
$customerEmail = 'email@email.com';
$newLinkToken = '2jh43j5h2345jh23lh452h345hfuzasd96ofu';
+ $datetime = $this->prepareDateTimeFactory();
+
$address = $this->getMockBuilder(\Magento\Customer\Api\Data\AddressInterface::class)
->disableOriginalConstructor()
->getMock();
@@ -624,7 +635,9 @@ public function testCreateAccountWithoutPassword()
->method('setRpToken')
->with($newLinkToken);
$customerSecure->expects($this->any())
- ->method('setRpTokenCreatedAt');
+ ->method('setRpTokenCreatedAt')
+ ->with($datetime)
+ ->willReturnSelf();
$customerSecure->expects($this->any())
->method('getPasswordHash')
->willReturn(null);
@@ -756,6 +769,8 @@ public function testCreateAccountWithPassword()
$minPasswordLength = 5;
$minCharacterSetsNum = 2;
+ $datetime = $this->prepareDateTimeFactory();
+
$this->scopeConfig->expects($this->any())
->method('getValue')
->willReturnMap(
@@ -865,7 +880,9 @@ public function testCreateAccountWithPassword()
->method('setRpToken')
->with($newLinkToken);
$customerSecure->expects($this->any())
- ->method('setRpTokenCreatedAt');
+ ->method('setRpTokenCreatedAt')
+ ->with($datetime)
+ ->willReturnSelf();
$customerSecure->expects($this->any())
->method('getPasswordHash')
->willReturn($hash);
@@ -995,7 +1012,7 @@ protected function prepareInitiatePasswordReset($email, $templateIdentifier, $se
{
$websiteId = 1;
- $dateTime = date(\Magento\Framework\Stdlib\DateTime::DATETIME_PHP_FORMAT);
+ $datetime = $this->prepareDateTimeFactory();
$customerData = ['key' => 'value'];
$customerName = 'Customer Name';
@@ -1047,7 +1064,7 @@ protected function prepareInitiatePasswordReset($email, $templateIdentifier, $se
->willReturnSelf();
$this->customerSecure->expects($this->any())
->method('setRpTokenCreatedAt')
- ->with($dateTime)
+ ->with($datetime)
->willReturnSelf();
$this->customerSecure->expects($this->any())
->method('addData')
@@ -1257,18 +1274,20 @@ private function reInitModel()
->method('getRpToken')
->willReturn('newStringToken');
- $date = date('Y-m-d', strtotime('-1 year'));
+ $pastDateTime = '2016-10-25 00:00:00';
$this->customerSecure
->expects($this->any())
->method('getRpTokenCreatedAt')
- ->willReturn($date);
+ ->willReturn($pastDateTime);
$this->customer = $this->getMockBuilder(\Magento\Customer\Model\Customer::class)
->disableOriginalConstructor()
->setMethods(['getResetPasswordLinkExpirationPeriod'])
->getMock();
+ $this->prepareDateTimeFactory();
+
$this->objectManagerHelper = new ObjectManagerHelper($this);
$this->accountManagement = $this->objectManagerHelper->getObject(
\Magento\Customer\Model\AccountManagement::class,
@@ -1277,6 +1296,7 @@ private function reInitModel()
'customerRegistry' => $this->customerRegistry,
'customerRepository' => $this->customerRepository,
'customerModel' => $this->customer,
+ 'dateTimeFactory' => $this->dateTimeFactory,
]
);
$reflection = new \ReflectionClass(get_class($this->accountManagement));
@@ -1320,7 +1340,7 @@ public function testChangePassword()
->with(null);
$customerSecure->expects($this->once())
->method('setRpTokenCreatedAt')
- ->with(null);
+ ->willReturnSelf();
$customerSecure->expects($this->any())
->method('getPasswordHash')
->willReturn($passwordHash);
@@ -1586,6 +1606,8 @@ public function testCreateAccountWithPasswordHashWithCustomerAddresses()
$storeId = 1;
$hash = '4nj54lkj5jfi03j49f8bgujfgsd';
+ $this->prepareDateTimeFactory();
+
//Handle store
$store = $this->getMockBuilder(\Magento\Store\Model\Store::class)->disableOriginalConstructor()->getMock();
$store->expects($this->any())
@@ -1630,7 +1652,7 @@ public function testCreateAccountWithPasswordHashWithCustomerAddresses()
->expects($this->any())
->method("getId")
->willReturn($customerId);
- //Return Customer from customer repositoryå
+ //Return Customer from customer repository
$this->customerRepository
->expects($this->atLeastOnce())
->method('save')
@@ -1673,4 +1695,30 @@ public function testCreateAccountWithPasswordHashWithCustomerAddresses()
$this->assertSame($customer, $this->accountManagement->createAccountWithPasswordHash($customer, $hash));
}
+
+ /**
+ * @return string
+ */
+ private function prepareDateTimeFactory()
+ {
+ $dateTime = '2017-10-25 18:57:08';
+ $timestamp = '1508983028';
+ $dateTimeMock = $this->createMock(\DateTime::class);
+ $dateTimeMock->expects($this->any())
+ ->method('format')
+ ->with(\Magento\Framework\Stdlib\DateTime::DATETIME_PHP_FORMAT)
+ ->willReturn($dateTime);
+
+ $dateTimeMock
+ ->expects($this->any())
+ ->method('getTimestamp')
+ ->willReturn($timestamp);
+
+ $this->dateTimeFactory
+ ->expects($this->any())
+ ->method('create')
+ ->willReturn($dateTimeMock);
+
+ return $dateTime;
+ }
}
diff --git a/app/code/Magento/Customer/Test/Unit/Model/ResourceModel/CustomerRepositoryTest.php b/app/code/Magento/Customer/Test/Unit/Model/ResourceModel/CustomerRepositoryTest.php
index bedd9ff7b842d..61c25641df6cd 100644
--- a/app/code/Magento/Customer/Test/Unit/Model/ResourceModel/CustomerRepositoryTest.php
+++ b/app/code/Magento/Customer/Test/Unit/Model/ResourceModel/CustomerRepositoryTest.php
@@ -241,6 +241,8 @@ public function testSave()
'save',
]);
+ $origCustomer = $this->customer;
+
$this->customer->expects($this->atLeastOnce())
->method('__toArray')
->willReturn(['default_billing', 'default_shipping']);
@@ -417,7 +419,7 @@ public function testSave()
->method('dispatch')
->with(
'customer_save_after_data_object',
- ['customer_data_object' => $this->customer, 'orig_customer_data_object' => $customerAttributesMetaData]
+ ['customer_data_object' => $this->customer, 'orig_customer_data_object' => $origCustomer]
);
$this->model->save($this->customer);
@@ -475,6 +477,8 @@ public function testSaveWithPasswordHash()
]
);
+ $origCustomer = $this->customer;
+
$this->customer->expects($this->atLeastOnce())
->method('__toArray')
->willReturn(['default_billing', 'default_shipping']);
@@ -642,7 +646,7 @@ public function testSaveWithPasswordHash()
->method('dispatch')
->with(
'customer_save_after_data_object',
- ['customer_data_object' => $this->customer, 'orig_customer_data_object' => $customerAttributesMetaData]
+ ['customer_data_object' => $this->customer, 'orig_customer_data_object' => $origCustomer]
);
$this->model->save($this->customer, $passwordHash);
diff --git a/app/code/Magento/Customer/etc/adminhtml/menu.xml b/app/code/Magento/Customer/etc/adminhtml/menu.xml
index ade53e0630988..7a1b62b37d395 100644
--- a/app/code/Magento/Customer/etc/adminhtml/menu.xml
+++ b/app/code/Magento/Customer/etc/adminhtml/menu.xml
@@ -10,6 +10,6 @@
-
+
diff --git a/app/code/Magento/Newsletter/Model/Subscriber.php b/app/code/Magento/Newsletter/Model/Subscriber.php
index 7847098083949..9e021a21d23b3 100644
--- a/app/code/Magento/Newsletter/Model/Subscriber.php
+++ b/app/code/Magento/Newsletter/Model/Subscriber.php
@@ -395,6 +395,10 @@ public function subscribe($email)
{
$this->loadByEmail($email);
+ if ($this->getId() && $this->getStatus() == self::STATUS_SUBSCRIBED) {
+ return $this->getStatus();
+ }
+
if (!$this->getId()) {
$this->setSubscriberConfirmCode($this->randomSequence());
}
diff --git a/app/code/Magento/OfflineShipping/Model/Carrier/Tablerate.php b/app/code/Magento/OfflineShipping/Model/Carrier/Tablerate.php
index b12691ad16245..87d4b984cf933 100644
--- a/app/code/Magento/OfflineShipping/Model/Carrier/Tablerate.php
+++ b/app/code/Magento/OfflineShipping/Model/Carrier/Tablerate.php
@@ -113,8 +113,9 @@ public function collectRates(RateRequest $request)
// Free shipping by qty
$freeQty = 0;
+ $freePackageValue = 0;
+
if ($request->getAllItems()) {
- $freePackageValue = 0;
foreach ($request->getAllItems() as $item) {
if ($item->getProduct()->isVirtual() || $item->getParentItem()) {
continue;
diff --git a/app/code/Magento/Quote/Model/Quote/Address.php b/app/code/Magento/Quote/Model/Quote/Address.php
index 109ca91cb2ae8..87c5feaba8f2e 100644
--- a/app/code/Magento/Quote/Model/Quote/Address.php
+++ b/app/code/Magento/Quote/Model/Quote/Address.php
@@ -1170,7 +1170,8 @@ public function validateMinimumAmount()
*/
public function getAppliedTaxes()
{
- return $this->serializer->unserialize($this->getData('applied_taxes'));
+ $taxes = $this->getData('applied_taxes');
+ return $taxes ? $this->serializer->unserialize($taxes) : [];
}
/**
diff --git a/app/code/Magento/Quote/Test/Unit/Model/Quote/AddressTest.php b/app/code/Magento/Quote/Test/Unit/Model/Quote/AddressTest.php
index 1557fe420be02..d01ae7304bdc6 100644
--- a/app/code/Magento/Quote/Test/Unit/Model/Quote/AddressTest.php
+++ b/app/code/Magento/Quote/Test/Unit/Model/Quote/AddressTest.php
@@ -9,7 +9,7 @@
namespace Magento\Quote\Test\Unit\Model\Quote;
use Magento\Directory\Model\Currency;
-use \Magento\Quote\Model\Quote\Address;
+use Magento\Quote\Model\Quote\Address;
use Magento\Quote\Model\Quote\Address\Rate;
use Magento\Quote\Model\ResourceModel\Quote\Address\Rate\CollectionFactory as RateCollectionFactory;
use Magento\Quote\Model\ResourceModel\Quote\Address\Rate\Collection as RatesCollection;
@@ -28,6 +28,7 @@
use Magento\Store\Api\Data\StoreInterface;
use Magento\Store\Api\Data\WebsiteInterface;
use Magento\Quote\Model\Quote\Address\RateResult\AbstractResult;
+use Magento\Framework\Serialize\Serializer\Json;
/**
* Test class for sales quote address model
@@ -117,7 +118,7 @@ protected function setUp()
$objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this);
$this->scopeConfig = $this->createMock(\Magento\Framework\App\Config::class);
- $this->serializer = $this->createMock(\Magento\Framework\Serialize\Serializer\Json::class);
+ $this->serializer = new Json();
$this->requestFactory = $this->getMockBuilder(RateRequestFactory::class)
->disableOriginalConstructor()
@@ -273,20 +274,17 @@ public function testValidateMiniumumAmountNegative()
public function testSetAndGetAppliedTaxes()
{
$data = ['data'];
- $result = json_encode($data);
-
- $this->serializer->expects($this->once())
- ->method('serialize')
- ->with($data)
- ->willReturn($result);
-
- $this->serializer->expects($this->once())
- ->method('unserialize')
- ->with($result)
- ->willReturn($data);
+ self::assertInstanceOf(Address::class, $this->address->setAppliedTaxes($data));
+ self::assertEquals($data, $this->address->getAppliedTaxes());
+ }
- $this->assertInstanceOf(\Magento\Quote\Model\Quote\Address::class, $this->address->setAppliedTaxes($data));
- $this->assertEquals($data, $this->address->getAppliedTaxes());
+ /**
+ * Checks a case, when applied taxes are not provided.
+ */
+ public function testGetAppliedTaxesWithEmptyValue()
+ {
+ $this->address->setData('applied_taxes', null);
+ self::assertEquals([], $this->address->getAppliedTaxes());
}
/**
diff --git a/app/code/Magento/Reports/Model/ResourceModel/Review/Customer/Collection.php b/app/code/Magento/Reports/Model/ResourceModel/Review/Customer/Collection.php
index a832823967647..02eae4d75d2a7 100644
--- a/app/code/Magento/Reports/Model/ResourceModel/Review/Customer/Collection.php
+++ b/app/code/Magento/Reports/Model/ResourceModel/Review/Customer/Collection.php
@@ -103,6 +103,21 @@ protected function _joinCustomers()
return $this;
}
+ /**
+ * {@inheritdoc}
+ *
+ * Additional processing of 'customer_name' field is required, as it is a concat field, which can not be aliased.
+ * @see _joinCustomers
+ */
+ public function addFieldToFilter($field, $condition = null)
+ {
+ if ($field === 'customer_name') {
+ $field = $this->getConnection()->getConcatSql(['customer.firstname', 'customer.lastname'], ' ');
+ }
+
+ return parent::addFieldToFilter($field, $condition);
+ }
+
/**
* Get select count sql
*
@@ -110,13 +125,14 @@ protected function _joinCustomers()
*/
public function getSelectCountSql()
{
- $countSelect = clone $this->_select;
+ $countSelect = clone $this->getSelect();
$countSelect->reset(\Magento\Framework\DB\Select::ORDER);
$countSelect->reset(\Magento\Framework\DB\Select::GROUP);
$countSelect->reset(\Magento\Framework\DB\Select::HAVING);
$countSelect->reset(\Magento\Framework\DB\Select::LIMIT_COUNT);
$countSelect->reset(\Magento\Framework\DB\Select::LIMIT_OFFSET);
$countSelect->reset(\Magento\Framework\DB\Select::COLUMNS);
+ $countSelect->reset(\Magento\Framework\DB\Select::WHERE);
$countSelect->columns(new \Zend_Db_Expr('COUNT(DISTINCT detail.customer_id)'));
diff --git a/app/code/Magento/Sales/Model/AdminOrder/Create.php b/app/code/Magento/Sales/Model/AdminOrder/Create.php
index ccc5c134514f6..c8afc6d8a292b 100644
--- a/app/code/Magento/Sales/Model/AdminOrder/Create.php
+++ b/app/code/Magento/Sales/Model/AdminOrder/Create.php
@@ -10,6 +10,8 @@
use Magento\Customer\Api\AddressMetadataInterface;
use Magento\Customer\Model\Metadata\Form as CustomerForm;
+use Magento\Framework\App\ObjectManager;
+use Magento\Quote\Model\Quote\Address;
use Magento\Quote\Model\Quote\Item;
/**
@@ -323,7 +325,7 @@ public function __construct(
$this->dataObjectHelper = $dataObjectHelper;
$this->orderManagement = $orderManagement;
$this->quoteFactory = $quoteFactory;
- $this->serializer = $serializer ?: \Magento\Framework\App\ObjectManager::getInstance()
+ $this->serializer = $serializer ?: ObjectManager::getInstance()
->get(\Magento\Framework\Serialize\Serializer\Json::class);
parent::__construct($data);
}
@@ -1449,32 +1451,36 @@ public function getBillingAddress()
*/
public function setBillingAddress($address)
{
- if (is_array($address)) {
- $billingAddress = $this->_objectManager->create(
- \Magento\Quote\Model\Quote\Address::class
- )->setData(
- $address
- )->setAddressType(
- \Magento\Quote\Model\Quote\Address::TYPE_BILLING
- );
- $this->_setQuoteAddress($billingAddress, $address);
- /**
- * save_in_address_book is not a valid attribute and is filtered out by _setQuoteAddress,
- * that is why it should be added after _setQuoteAddress call
- */
- $saveInAddressBook = (int)(!empty($address['save_in_address_book']));
- $billingAddress->setData('save_in_address_book', $saveInAddressBook);
-
- if (!$this->getQuote()->isVirtual() && $this->getShippingAddress()->getSameAsBilling()) {
- $shippingAddress = clone $billingAddress;
- $shippingAddress->setSameAsBilling(true);
- $shippingAddress->setSaveInAddressBook(false);
- $address['save_in_address_book'] = 0;
- $this->setShippingAddress($address);
- }
+ if (!is_array($address)) {
+ return $this;
+ }
+
+ $billingAddress = $this->_objectManager->create(Address::class)
+ ->setData($address)
+ ->setAddressType(Address::TYPE_BILLING);
+
+ $this->_setQuoteAddress($billingAddress, $address);
+
+ /**
+ * save_in_address_book is not a valid attribute and is filtered out by _setQuoteAddress,
+ * that is why it should be added after _setQuoteAddress call
+ */
+ $saveInAddressBook = (int)(!empty($address['save_in_address_book']));
+ $billingAddress->setData('save_in_address_book', $saveInAddressBook);
+
+ $quote = $this->getQuote();
+ if (!$quote->isVirtual() && $this->getShippingAddress()->getSameAsBilling()) {
+ $address['save_in_address_book'] = 0;
+ $this->setShippingAddress($address);
+ }
- $this->getQuote()->setBillingAddress($billingAddress);
+ // not assigned billing address should be saved as new
+ // but if quote already has the billing address it won't be overridden
+ if (empty($billingAddress->getCustomerAddressId())) {
+ $billingAddress->setCustomerAddressId(null);
+ $quote->getBillingAddress()->setCustomerAddressId(null);
}
+ $quote->setBillingAddress($billingAddress);
return $this;
}
@@ -1775,6 +1781,7 @@ public function _prepareCustomer()
$address = $this->getShippingAddress()->setCustomerId($this->getQuote()->getCustomer()->getId());
$this->setShippingAddress($address);
}
+ $this->getBillingAddress()->setCustomerId($customer->getId());
$this->getQuote()->updateCustomerData($this->getQuote()->getCustomer());
$customer = $this->getQuote()->getCustomer();
diff --git a/app/code/Magento/Sales/etc/fieldset.xml b/app/code/Magento/Sales/etc/fieldset.xml
index 3d29575063fef..d680d7373bc35 100644
--- a/app/code/Magento/Sales/etc/fieldset.xml
+++ b/app/code/Magento/Sales/etc/fieldset.xml
@@ -486,6 +486,12 @@
+
+
+
+
+
+
diff --git a/app/code/Magento/Sales/view/adminhtml/web/order/create/scripts.js b/app/code/Magento/Sales/view/adminhtml/web/order/create/scripts.js
index 1c755b4e08a0d..8e25584627d3b 100644
--- a/app/code/Magento/Sales/view/adminhtml/web/order/create/scripts.js
+++ b/app/code/Magento/Sales/view/adminhtml/web/order/create/scripts.js
@@ -157,6 +157,7 @@ define([
}
if(this.addresses[id]){
this.fillAddressFields(container, this.addresses[id]);
+
}
else{
this.fillAddressFields(container, {});
@@ -190,43 +191,53 @@ define([
}
},
- changeAddressField : function(event){
- var field = Event.element(event);
- var re = /[^\[]*\[([^\]]*)_address\]\[([^\]]*)\](\[(\d)\])?/;
- var matchRes = field.name.match(re);
+ /**
+ * Triggers on each form's element changes.
+ *
+ * @param {Object} event
+ */
+ changeAddressField: function (event) {
+ var field = Event.element(event),
+ re = /[^\[]*\[([^\]]*)_address\]\[([^\]]*)\](\[(\d)\])?/,
+ matchRes = field.name.match(re),
+ type,
+ name,
+ data;
if (!matchRes) {
return;
}
- var type = matchRes[1];
- var name = matchRes[2];
- var data;
+ type = matchRes[1];
+ name = matchRes[2];
- if(this.isBillingField(field.id)){
- data = this.serializeData(this.billingAddressContainer)
- }
- else{
- data = this.serializeData(this.shippingAddressContainer)
+ if (this.isBillingField(field.id)) {
+ data = this.serializeData(this.billingAddressContainer);
+ } else {
+ data = this.serializeData(this.shippingAddressContainer);
}
data = data.toObject();
- if( (type == 'billing' && this.shippingAsBilling)
- || (type == 'shipping' && !this.shippingAsBilling) ) {
+ if (type === 'billing' && this.shippingAsBilling || type === 'shipping' && !this.shippingAsBilling) {
data['reset_shipping'] = true;
}
- data['order['+type+'_address][customer_address_id]'] = $('order-'+type+'_address_customer_address_id').value;
+ data['order[' + type + '_address][customer_address_id]'] = null;
+ data['shipping_as_billing'] = jQuery('[name="shipping_same_as_billing"]').is(':checked') ? 1 : 0;
+
+ if (name === 'customer_address_id') {
+ data['order[' + type + '_address][customer_address_id]'] =
+ $('order-' + type + '_address_customer_address_id').value;
+ }
if (data['reset_shipping']) {
this.resetShippingMethod(data);
} else {
this.saveData(data);
- if (name == 'country_id' || name == 'customer_address_id') {
+
+ if (name === 'country_id' || name === 'customer_address_id') {
this.loadArea(['shipping_method', 'billing_method', 'totals', 'items'], true, data);
}
- // added for reloading of default sender and default recipient for giftmessages
- //this.loadArea(['giftmessage'], true, data);
}
},
diff --git a/app/code/Magento/SampleData/Console/Command/SampleDataDeployCommand.php b/app/code/Magento/SampleData/Console/Command/SampleDataDeployCommand.php
index 50ad8bdbb3e33..158c588d11358 100644
--- a/app/code/Magento/SampleData/Console/Command/SampleDataDeployCommand.php
+++ b/app/code/Magento/SampleData/Console/Command/SampleDataDeployCommand.php
@@ -136,8 +136,8 @@ private function updateMemoryLimit()
if (function_exists('ini_set')) {
@ini_set('display_errors', 1);
$memoryLimit = trim(ini_get('memory_limit'));
- if ($memoryLimit != -1 && $this->getMemoryInBytes($memoryLimit) < 768 * 1024 * 1024) {
- @ini_set('memory_limit', '768M');
+ if ($memoryLimit != -1 && $this->getMemoryInBytes($memoryLimit) < 756 * 1024 * 1024) {
+ @ini_set('memory_limit', '756M');
}
}
}
diff --git a/app/code/Magento/Tax/Controller/Adminhtml/Tax/IgnoreTaxNotification.php b/app/code/Magento/Tax/Controller/Adminhtml/Tax/IgnoreTaxNotification.php
index 847f1312e8caf..b623b6c6868e7 100644
--- a/app/code/Magento/Tax/Controller/Adminhtml/Tax/IgnoreTaxNotification.php
+++ b/app/code/Magento/Tax/Controller/Adminhtml/Tax/IgnoreTaxNotification.php
@@ -51,8 +51,8 @@ public function execute()
}
// clear the block html cache
- $this->_cacheTypeList->cleanType('block_html');
- $this->_eventManager->dispatch('adminhtml_cache_refresh_type', ['type' => 'block_html']);
+ $this->_cacheTypeList->cleanType('config');
+ $this->_eventManager->dispatch('adminhtml_cache_refresh_type', ['type' => 'config']);
/** @var \Magento\Backend\Model\View\Result\Redirect $resultRedirect */
$resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT);
diff --git a/app/code/Magento/Tax/Test/Unit/Controller/Adminhtml/Tax/IgnoreTaxNotificationTest.php b/app/code/Magento/Tax/Test/Unit/Controller/Adminhtml/Tax/IgnoreTaxNotificationTest.php
index 0f879a6e162f5..2035885f05e8f 100644
--- a/app/code/Magento/Tax/Test/Unit/Controller/Adminhtml/Tax/IgnoreTaxNotificationTest.php
+++ b/app/code/Magento/Tax/Test/Unit/Controller/Adminhtml/Tax/IgnoreTaxNotificationTest.php
@@ -19,7 +19,7 @@ public function testExecute()
->getMock();
$cacheTypeList->expects($this->once())
->method('cleanType')
- ->with('block_html')
+ ->with('config')
->willReturn(null);
$request = $this->getMockBuilder(\Magento\Framework\App\Request\Http::class)
diff --git a/app/code/Magento/Ui/i18n/en_US.csv b/app/code/Magento/Ui/i18n/en_US.csv
index 1a1b56b379075..225d83387563b 100644
--- a/app/code/Magento/Ui/i18n/en_US.csv
+++ b/app/code/Magento/Ui/i18n/en_US.csv
@@ -179,3 +179,25 @@ settings/addAfter,settings/addAfter
Action,Action
CSV,CSV
"Excel XML","Excel XML"
+"Please select one of the options above.","Please select one of the options above."
+"Please select a file.","Please select a file."
+"Please select one of the options.","Please select one of the options."
+"Please enter a value less than or equal to %s.","Please enter a value less than or equal to %s."
+"Please enter a value greater than or equal to %s.","Please enter a value greater than or equal to %s."
+"Card type does not match credit card number.","Card type does not match credit card number."
+"Credit card number does not match credit card type.","Credit card number does not match credit card type."
+"Incorrect credit card expiration date.","Incorrect credit card expiration date."
+"Please enter less or equal than %1 symbols.","Please enter less or equal than %1 symbols."
+"Please enter more or equal than %1 symbols.","Please enter more or equal than %1 symbols."
+"Please enter a valid value from list","Please enter a valid value from list"
+"Please enter valid SKU key.","Please enter valid SKU key."
+"Please enter a valid number.","Please enter a valid number."
+"Admin is a required field in the each row.","Admin is a required field in the each row."
+"Please fix this field.","Please fix this field."
+"Please enter a valid date (ISO).","Please enter a valid date (ISO)."
+"Please enter only digits.","Please enter only digits."
+"Please enter the same value again.","Please enter the same value again."
+"Please enter no more than {0} characters.","Please enter no more than {0} characters."
+"Please enter at least {0} characters.","Please enter at least {0} characters."
+"Please enter a value between {0} and {1} characters long.","Please enter a value between {0} and {1} characters long."
+"Please enter a value between {0} and {1}.","Please enter a value between {0} and {1}."
diff --git a/app/code/Magento/Ui/view/base/web/js/form/element/abstract.js b/app/code/Magento/Ui/view/base/web/js/form/element/abstract.js
index 6bbcb4416d33a..b6979121a1891 100755
--- a/app/code/Magento/Ui/view/base/web/js/form/element/abstract.js
+++ b/app/code/Magento/Ui/view/base/web/js/form/element/abstract.js
@@ -118,8 +118,8 @@ define([
this._super();
- scope = this.dataScope;
- name = scope.split('.').slice(1);
+ scope = this.dataScope.split('.');
+ name = scope.length > 1 ? scope.slice(1) : scope;
valueUpdate = this.showFallbackReset ? 'afterkeydown' : this.valueUpdate;
diff --git a/app/code/Magento/Ui/view/base/web/js/grid/columns/date.js b/app/code/Magento/Ui/view/base/web/js/grid/columns/date.js
index 396ad3ce307ad..81c0cc1ccdbb7 100644
--- a/app/code/Magento/Ui/view/base/web/js/grid/columns/date.js
+++ b/app/code/Magento/Ui/view/base/web/js/grid/columns/date.js
@@ -39,7 +39,7 @@ define([
getLabel: function (value, format) {
var date = moment(this._super());
- date = date.isValid() ?
+ date = date.isValid() && value[this.index] ?
date.format(format || this.dateFormat) :
'';
diff --git a/app/design/adminhtml/Magento/backend/web/css/styles-old.less b/app/design/adminhtml/Magento/backend/web/css/styles-old.less
index 358250adf0341..b66fed0c0a09a 100644
--- a/app/design/adminhtml/Magento/backend/web/css/styles-old.less
+++ b/app/design/adminhtml/Magento/backend/web/css/styles-old.less
@@ -1383,7 +1383,6 @@
line-height: 1.33;
vertical-align: middle;
white-space: normal;
- word-break: break-all;
&[data-config-scope] {
position: relative;
diff --git a/dev/tests/api-functional/framework/Magento/TestFramework/WebApiApplication.php b/dev/tests/api-functional/framework/Magento/TestFramework/WebApiApplication.php
index 03364acbb8663..992653a3a65d6 100644
--- a/dev/tests/api-functional/framework/Magento/TestFramework/WebApiApplication.php
+++ b/dev/tests/api-functional/framework/Magento/TestFramework/WebApiApplication.php
@@ -26,8 +26,12 @@ public function run()
/**
* {@inheritdoc}
*/
- public function install()
+ public function install($cleanup)
{
+ if ($cleanup) {
+ $this->cleanup();
+ }
+
$installOptions = $this->getInstallConfig();
/* Install application */
diff --git a/dev/tests/api-functional/framework/bootstrap.php b/dev/tests/api-functional/framework/bootstrap.php
index 7a7b061858ac7..942582392e89e 100644
--- a/dev/tests/api-functional/framework/bootstrap.php
+++ b/dev/tests/api-functional/framework/bootstrap.php
@@ -58,10 +58,8 @@
);
if (defined('TESTS_MAGENTO_INSTALLATION') && TESTS_MAGENTO_INSTALLATION === 'enabled') {
- if (defined('TESTS_CLEANUP') && TESTS_CLEANUP === 'enabled') {
- $application->cleanup();
- }
- $application->install();
+ $cleanup = (defined('TESTS_CLEANUP') && TESTS_CLEANUP === 'enabled');
+ $application->install($cleanup);
}
$bootstrap = new \Magento\TestFramework\Bootstrap(
diff --git a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/AttributeSetRepositoryTest.php b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/AttributeSetRepositoryTest.php
index 5e640390c3231..4f917a9c9961a 100644
--- a/dev/tests/api-functional/testsuite/Magento/Catalog/Api/AttributeSetRepositoryTest.php
+++ b/dev/tests/api-functional/testsuite/Magento/Catalog/Api/AttributeSetRepositoryTest.php
@@ -165,19 +165,9 @@ public function testGetList()
{
$searchCriteria = [
'searchCriteria' => [
- 'filter_groups' => [
- [
- 'filters' => [
- [
- 'field' => 'entity_type_code',
- 'value' => 'catalog_product',
- 'condition_type' => 'eq',
- ],
- ],
- ],
- ],
+ 'filter_groups' => [],
'current_page' => 1,
- 'page_size' => 2,
+ 'page_size' => 2
],
];
diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/CreateCustomerGroupEntityTest.php b/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/CreateCustomerGroupEntityTest.php
index 7d99e1a157173..de6717a3bd4af 100644
--- a/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/CreateCustomerGroupEntityTest.php
+++ b/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/CreateCustomerGroupEntityTest.php
@@ -16,7 +16,7 @@
*
* Test Flow:
* 1.Log in to backend as admin user.
- * 2.Navigate to Stores>Other Settings>Customer Groups.
+ * 2.Navigate to Customers > Customer Groups.
* 3.Start to create new Customer Group.
* 4.Fill in all data according to data set.
* 5.Click "Save Customer Group" button.
diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/DeleteCustomerGroupEntityTest.php b/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/DeleteCustomerGroupEntityTest.php
index 390a446ef6d63..7f2b4254dff16 100644
--- a/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/DeleteCustomerGroupEntityTest.php
+++ b/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/DeleteCustomerGroupEntityTest.php
@@ -18,7 +18,7 @@
* 2. Customer is created and assigned to this group.
* Steps:
* 1. Log in to backend as admin user.
- * 2. Navigate to Stores > Other Settings > Customer Groups.
+ * 2. Navigate to Customers > Customer Groups.
* 3. Click on Customer Group from grid.
* 4. Click on Delete "Customer Group".
* 5. Confirm in pop-up.
diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/DeleteSystemCustomerGroupTest.php b/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/DeleteSystemCustomerGroupTest.php
index 0dba9e32b0200..3beaa0915b6e6 100644
--- a/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/DeleteSystemCustomerGroupTest.php
+++ b/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/DeleteSystemCustomerGroupTest.php
@@ -13,7 +13,7 @@
/**
* Steps:
* 1. Login to backend as admin user.
- * 2. Navigate to Stores > Other Settings > Customer Groups.
+ * 2. Navigate to Customers > Customer Groups.
* 3. Select system Customer Group specified in data set from grid.
* 4. Perform all assertions.
*
diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/NavigateMenuTest.xml b/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/NavigateMenuTest.xml
index e26f3a999eb48..404e62dcad648 100644
--- a/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/NavigateMenuTest.xml
+++ b/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/NavigateMenuTest.xml
@@ -18,7 +18,7 @@
- Stores > Customer Groups
+ Customers > Customer Groups
Customer Groups
diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/UpdateCustomerGroupEntityTest.php b/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/UpdateCustomerGroupEntityTest.php
index badebdec63ea6..aa50235cb4a10 100644
--- a/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/UpdateCustomerGroupEntityTest.php
+++ b/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/UpdateCustomerGroupEntityTest.php
@@ -19,7 +19,7 @@
* 1. Customer Group is created
* Steps:
* 1. Log in to backend as admin user
- * 2. Navigate to Stores > Other Settings > Customer Groups
+ * 2. Navigate to Customers > Customer Groups
* 3. Click on Customer Group from grid
* 4. Update data according to data set
* 5. Click "Save Customer Group" button
diff --git a/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/VerifyDisabledCustomerGroupFieldTest.php b/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/VerifyDisabledCustomerGroupFieldTest.php
index 902b4b7f9ae15..bc8392763edd2 100644
--- a/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/VerifyDisabledCustomerGroupFieldTest.php
+++ b/dev/tests/functional/tests/app/Magento/Customer/Test/TestCase/VerifyDisabledCustomerGroupFieldTest.php
@@ -13,7 +13,7 @@
/**
* Steps:
* 1. Login to backend as admin user.
- * 2. Navigate to Stores > Other Settings > Customer Groups.
+ * 2. Navigate to Customers > Customer Groups.
* 3. Select system Customer Group specified in data set from grid.
* 4. Perform all assertions.
*
diff --git a/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/OnePageCheckoutTest.xml b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/OnePageCheckoutTest.xml
index dbca95921f0c5..1e50cdf69197f 100644
--- a/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/OnePageCheckoutTest.xml
+++ b/dev/tests/functional/tests/app/Magento/Paypal/Test/TestCase/OnePageCheckoutTest.xml
@@ -76,7 +76,7 @@
false
payflowpro
- - #Y: Yes. Matched Address and five-didgit ZIP
+ - #Y: Yes. Matched Address and five-digit ZIP
Processing
@@ -113,7 +113,7 @@
payflowpro
visa_default
- - #Y: Yes. Matched Address and five-didgit ZIP
+ - #Y: Yes. Matched Address and five-digit ZIP
payflowpro, payflowpro_use_avs_zip
Processing
diff --git a/dev/tests/integration/framework/Magento/TestFramework/Application.php b/dev/tests/integration/framework/Magento/TestFramework/Application.php
index 2f4395b161a69..e0cd3c52e2ca3 100644
--- a/dev/tests/integration/framework/Magento/TestFramework/Application.php
+++ b/dev/tests/integration/framework/Magento/TestFramework/Application.php
@@ -435,10 +435,11 @@ public function cleanup()
/**
* Install an application
*
+ * @param bool $cleanup
* @return void
* @throws \Magento\Framework\Exception\LocalizedException
*/
- public function install()
+ public function install($cleanup)
{
$dirs = \Magento\Framework\App\Bootstrap::INIT_PARAM_FILESYSTEM_DIR_PATHS;
$this->_ensureDirExists($this->installDir);
@@ -453,8 +454,9 @@ public function install()
$installParams = $this->getInstallCliParams();
// performance optimization: restore DB from last good dump to make installation on top of it (much faster)
+ // do not restore from the database if the cleanup option is set to ensure we have a clean DB to test on
$db = $this->getDbInstance();
- if ($db->isDbDumpExists()) {
+ if ($db->isDbDumpExists() && !$cleanup) {
$db->restoreFromDbDump();
}
diff --git a/dev/tests/integration/framework/bootstrap.php b/dev/tests/integration/framework/bootstrap.php
index 13008938147b5..4e14c8113a708 100644
--- a/dev/tests/integration/framework/bootstrap.php
+++ b/dev/tests/integration/framework/bootstrap.php
@@ -74,7 +74,7 @@
$application->cleanup();
}
if (!$application->isInstalled()) {
- $application->install();
+ $application->install($settings->getAsBoolean('TESTS_CLEANUP'));
}
$application->initialize([]);
diff --git a/dev/tests/integration/testsuite/Magento/Reports/Model/ResourceModel/Review/Customer/CollectionTest.php b/dev/tests/integration/testsuite/Magento/Reports/Model/ResourceModel/Review/Customer/CollectionTest.php
new file mode 100644
index 0000000000000..c14ccbff3a785
--- /dev/null
+++ b/dev/tests/integration/testsuite/Magento/Reports/Model/ResourceModel/Review/Customer/CollectionTest.php
@@ -0,0 +1,36 @@
+collection = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create(
+ \Magento\Reports\Model\ResourceModel\Review\Customer\Collection::class
+ );
+ }
+
+ /**
+ * This tests covers issue described in:
+ * https://github.com/magento/magento2/issues/10301
+ *
+ * @magentoDataFixture Magento/Review/_files/customer_review.php
+ */
+ public function testSelectCountSql()
+ {
+ $this->collection->addFieldToFilter('customer_name', ['like' => '%John%'])->getItems();
+ $this->assertEquals(1, $this->collection->getSize());
+ }
+}
diff --git a/dev/tests/integration/testsuite/Magento/Sales/Controller/Adminhtml/Order/CreateTest.php b/dev/tests/integration/testsuite/Magento/Sales/Controller/Adminhtml/Order/CreateTest.php
index 5f3dbdabc640a..e071dde26a263 100644
--- a/dev/tests/integration/testsuite/Magento/Sales/Controller/Adminhtml/Order/CreateTest.php
+++ b/dev/tests/integration/testsuite/Magento/Sales/Controller/Adminhtml/Order/CreateTest.php
@@ -5,6 +5,10 @@
*/
namespace Magento\Sales\Controller\Adminhtml\Order;
+use Magento\Customer\Api\CustomerRepositoryInterface;
+use Magento\Backend\Model\Session\Quote;
+use Magento\Quote\Api\CartRepositoryInterface;
+
/**
* @magentoAppArea adminhtml
* @magentoDbIsolation enabled
@@ -158,7 +162,7 @@ public function testIndexAction()
*/
public function testGetAclResource($actionName, $reordered, $expectedResult)
{
- $this->_objectManager->get(\Magento\Backend\Model\Session\Quote::class)->setReordered($reordered);
+ $this->_objectManager->get(Quote::class)->setReordered($reordered);
$orderController = $this->_objectManager->get(
\Magento\Sales\Controller\Adminhtml\Order\Stub\OrderCreateStub::class
);
@@ -229,4 +233,57 @@ public function testDeniedSaveAction()
$this->dispatch('backend/sales/order_create/save');
$this->assertEquals('403', $this->getResponse()->getHttpResponseCode());
}
+
+ /**
+ * Checks a case when shipping is the same as billing and billing address details was changed by request.
+ * Both billing and shipping addresses should be updated.
+ *
+ * @magentoAppArea adminhtml
+ * @magentoDataFixture Magento/Sales/_files/quote_with_customer.php
+ */
+ public function testSyncBetweenQuoteAddresses()
+ {
+ /** @var CustomerRepositoryInterface $customerRepository */
+ $customerRepository = $this->_objectManager->get(CustomerRepositoryInterface::class);
+ $customer = $customerRepository->get('customer@example.com');
+
+ /** @var CartRepositoryInterface $quoteRepository */
+ $quoteRepository = $this->_objectManager->get(CartRepositoryInterface::class);
+ $quote = $quoteRepository->getActiveForCustomer($customer->getId());
+
+ $session = $this->_objectManager->get(Quote::class);
+ $session->setQuoteId($quote->getId());
+
+ $data = [
+ 'firstname' => 'John',
+ 'lastname' => 'Doe',
+ 'street' => ['Soborna 23'],
+ 'city' => 'Kyiv',
+ 'country_id' => 'UA',
+ 'region' => 'Kyivska',
+ 'region_id' => 1
+ ];
+ $this->getRequest()->setPostValue(
+ [
+ 'order' => ['billing_address' => $data],
+ 'reset_shipping' => 1,
+ 'customer_id' => $customer->getId(),
+ 'store_id' => 1,
+ 'json' => true
+ ]
+ );
+
+ $this->dispatch('backend/sales/order_create/loadBlock/block/shipping_address');
+ self::assertEquals(200, $this->getResponse()->getHttpResponseCode());
+
+ $updatedQuote = $quoteRepository->get($quote->getId());
+
+ $billingAddress = $updatedQuote->getBillingAddress();
+ self::assertEquals($data['region_id'], $billingAddress->getRegionId());
+ self::assertEquals($data['country_id'], $billingAddress->getCountryId());
+
+ $shippingAddress = $updatedQuote->getShippingAddress();
+ self::assertEquals($data['city'], $shippingAddress->getCity());
+ self::assertEquals($data['street'], $shippingAddress->getStreet());
+ }
}
diff --git a/dev/travis/before_script.sh b/dev/travis/before_script.sh
index 0e8cc26e154df..7cf55ca8083f1 100755
--- a/dev/travis/before_script.sh
+++ b/dev/travis/before_script.sh
@@ -71,7 +71,7 @@ case $TEST_SUITE in
--output-file="$changed_files_ce" \
--base-path="$TRAVIS_BUILD_DIR" \
--repo='https://github.com/magento/magento2.git' \
- --branch='$TRAVIS_BRANCH'
+ --branch="$TRAVIS_BRANCH"
cat "$changed_files_ce" | sed 's/^/ + including /'
cd ../../..
diff --git a/lib/internal/Magento/Framework/App/DeploymentConfig/Writer/PhpFormatter.php b/lib/internal/Magento/Framework/App/DeploymentConfig/Writer/PhpFormatter.php
index 4a40e19c818e7..b419b3827e5ff 100644
--- a/lib/internal/Magento/Framework/App/DeploymentConfig/Writer/PhpFormatter.php
+++ b/lib/internal/Magento/Framework/App/DeploymentConfig/Writer/PhpFormatter.php
@@ -21,21 +21,48 @@ class PhpFormatter implements FormatterInterface
public function format($data, array $comments = [])
{
if (!empty($comments) && is_array($data)) {
- $elements = [];
+ return "formatData($data, $comments) . "\n);\n";
+ }
+ return " $value) {
- $comment = ' ';
if (!empty($comments[$key])) {
- $section = " * For the section: " . $key . "\n";
- $exportedComment = is_string($comments[$key])
- ? $comments[$key]
- : var_export($comments[$key], true);
- $comment = " /**\n" . $section . " * " . str_replace("\n", "\n * ", $exportedComment) . "\n */\n";
+ $elements[] = $prefix . '/**';
+ $elements[] = $prefix . ' * For the section: ' . $key;
+
+ foreach (explode("\n", $comments[$key]) as $commentLine) {
+ $elements[] = $prefix . ' * ' . $commentLine;
+ }
+
+ $elements[] = $prefix . " */";
+ }
+
+ $elements[] = $prefix . var_export($key, true) . ' => ' .
+ (!is_array($value) ? var_export($value, true) . ',' : '');
+
+ if (is_array($value)) {
+ $elements[] = $prefix . 'array (';
+ $elements[] = $this->formatData($value, [], ' ' . $prefix);
+ $elements[] = $prefix . '),';
}
- $space = is_array($value) ? " \n" : ' ';
- $elements[] = $comment . var_export($key, true) . ' =>' . $space . var_export($value, true);
}
- return " 'just text',
- 'ns4' => 'just text'
+ 'ns4' => 'just text',
);
TEXT;
@@ -126,7 +126,7 @@ public function formatWithCommentDataProvider()
* For the section: ns4
* comment for namespace 4
*/
- 'ns4' => 'just text'
+ 'ns4' => 'just text',
);
TEXT;
diff --git a/lib/internal/Magento/Framework/Convert/Excel.php b/lib/internal/Magento/Framework/Convert/Excel.php
index f2a629407c1cf..09acd88b38a7f 100644
--- a/lib/internal/Magento/Framework/Convert/Excel.php
+++ b/lib/internal/Magento/Framework/Convert/Excel.php
@@ -147,6 +147,7 @@ protected function _getXmlRow($row, $useCallback)
}
if (isset($value[0]) && in_array($value[0], ['=', '+', '-'])) {
$value = ' ' . $value;
+ $dataType = 'String';
}
$value = str_replace("\r\n", '
', $value);
diff --git a/lib/internal/Magento/Framework/Shell/CommandRenderer.php b/lib/internal/Magento/Framework/Shell/CommandRenderer.php
index 32e75a7420d1e..6cf91d09479e1 100644
--- a/lib/internal/Magento/Framework/Shell/CommandRenderer.php
+++ b/lib/internal/Magento/Framework/Shell/CommandRenderer.php
@@ -16,8 +16,8 @@ class CommandRenderer implements CommandRendererInterface
*/
public function render($command, array $arguments = [])
{
+ $command = preg_replace('/(\s+2>&1)*(\s*\|)|$/', ' 2>&1$2', $command);
$arguments = array_map('escapeshellarg', $arguments);
- $command = preg_replace('/\s?\||$/', ' 2>&1$0', $command);
if (empty($arguments)) {
return $command;
}
diff --git a/lib/internal/Magento/Framework/Shell/Test/Unit/CommandRendererTest.php b/lib/internal/Magento/Framework/Shell/Test/Unit/CommandRendererTest.php
index dcc091473eeec..213e2afa2c655 100644
--- a/lib/internal/Magento/Framework/Shell/Test/Unit/CommandRendererTest.php
+++ b/lib/internal/Magento/Framework/Shell/Test/Unit/CommandRendererTest.php
@@ -5,27 +5,40 @@
*/
namespace Magento\Framework\Shell\Test\Unit;
-use \Magento\Framework\Shell\CommandRenderer;
+use Magento\Framework\Shell\CommandRenderer;
class CommandRendererTest extends \PHPUnit\Framework\TestCase
{
- public function testRender()
+ /**
+ * @param $expectedCommand
+ * @param $actualCommand
+ * @param $testArguments
+ * @dataProvider commandsDataProvider
+ */
+ public function testRender($expectedCommand, $actualCommand, $testArguments)
{
- $testArgument = 'argument';
- $testArgument2 = 'argument2';
$commandRenderer = new CommandRenderer();
$this->assertEquals(
- "php -r " . escapeshellarg($testArgument) . " 2>&1 | grep " . escapeshellarg($testArgument2) . " 2>&1",
- $commandRenderer->render('php -r %s | grep %s', [$testArgument, $testArgument2])
+ $expectedCommand,
+ $commandRenderer->render($actualCommand, $testArguments)
);
}
- public function testRenderWithoutArguments()
+ public function commandsDataProvider()
{
- $commandRenderer = new CommandRenderer();
- $this->assertEquals(
- "php -r %s 2>&1 | grep %s 2>&1",
- $commandRenderer->render('php -r %s | grep %s', [])
- );
+ $testArgument = 'argument';
+ $testArgument2 = 'argument2';
+
+ $expectedCommand = "php -r %s 2>&1 | grep %s 2>&1";
+ $expectedCommandArgs = "php -r '" . $testArgument . "' 2>&1 | grep '" . $testArgument2 . "' 2>&1";
+
+ return [
+ [$expectedCommand, 'php -r %s | grep %s', []],
+ [$expectedCommand, 'php -r %s 2>&1 | grep %s', []],
+ [$expectedCommand, 'php -r %s 2>&1 2>&1 | grep %s', []],
+ [$expectedCommandArgs, 'php -r %s | grep %s', [$testArgument, $testArgument2]],
+ [$expectedCommandArgs, 'php -r %s 2>&1 | grep %s', [$testArgument, $testArgument2]],
+ [$expectedCommandArgs, 'php -r %s 2>&1 2>&1 | grep %s', [$testArgument, $testArgument2]],
+ ];
}
}
diff --git a/lib/internal/Magento/Framework/View/Element/Html/Date.php b/lib/internal/Magento/Framework/View/Element/Html/Date.php
index 648d9ad6917e4..558e39427cb44 100644
--- a/lib/internal/Magento/Framework/View/Element/Html/Date.php
+++ b/lib/internal/Magento/Framework/View/Element/Html/Date.php
@@ -26,6 +26,7 @@ protected function _toHtml()
$changeYear = $this->getChangeYear();
$maxDate = $this->getMaxDate();
$showOn = $this->getShowOn();
+ $firstDay = $this->getFirstDay();
$html .= '';
diff --git a/lib/internal/Magento/Framework/View/Layout/etc/elements.xsd b/lib/internal/Magento/Framework/View/Layout/etc/elements.xsd
index ea80380865e6a..39cdec05a65ea 100755
--- a/lib/internal/Magento/Framework/View/Layout/etc/elements.xsd
+++ b/lib/internal/Magento/Framework/View/Layout/etc/elements.xsd
@@ -138,7 +138,7 @@
-
+
diff --git a/lib/internal/Magento/Framework/View/Page/Config.php b/lib/internal/Magento/Framework/View/Page/Config.php
index 248841e47499d..6fadc91bd73ee 100644
--- a/lib/internal/Magento/Framework/View/Page/Config.php
+++ b/lib/internal/Magento/Framework/View/Page/Config.php
@@ -173,7 +173,7 @@ public function __construct(
$this->setElementAttribute(
self::ELEMENT_TYPE_HTML,
self::HTML_ATTRIBUTE_LANG,
- str_replace('_', '-', $this->localeResolver->getLocale())
+ strstr($this->localeResolver->getLocale(), '_', true)
);
}
diff --git a/lib/web/mage/backend/suggest.js b/lib/web/mage/backend/suggest.js
index 81bde35f9e12a..412a80804ae0f 100644
--- a/lib/web/mage/backend/suggest.js
+++ b/lib/web/mage/backend/suggest.js
@@ -245,6 +245,7 @@
case keyCode.ENTER:
case keyCode.NUMPAD_ENTER:
+ this._toggleEnter(event);
if (this.isDropdownShown() && this._focused) {
this._proxyEvents(event);
@@ -314,6 +315,30 @@
this._bindDropdown();
},
+ /**
+ * @param {Object} event - event object
+ * @private
+ */
+ _toggleEnter: function (event) {
+ var suggestList,
+ activeItems,
+ selectedItem;
+
+ suggestList = $(event.currentTarget.parentNode).find('ul').first();
+ activeItems = suggestList.find('._active');
+
+ if (activeItems.length >= 0) {
+ selectedItem = activeItems.first();
+
+ if (selectedItem.find('a') && selectedItem.find('a').attr('href') !== undefined) {
+ window.location = selectedItem.find('a').attr('href');
+ event.preventDefault();
+
+ return false;
+ }
+ }
+ },
+
/**
* @param {Object} e - event object
* @private
diff --git a/nginx.conf.sample b/nginx.conf.sample
index d2f10502e03f8..7257c329df24b 100644
--- a/nginx.conf.sample
+++ b/nginx.conf.sample
@@ -41,7 +41,7 @@ location ~* ^/setup($|/) {
fastcgi_pass fastcgi_backend;
fastcgi_param PHP_FLAG "session.auto_start=off \n suhosin.session.cryptua=off";
- fastcgi_param PHP_VALUE "memory_limit=768M \n max_execution_time=600";
+ fastcgi_param PHP_VALUE "memory_limit=756M \n max_execution_time=600";
fastcgi_read_timeout 600s;
fastcgi_connect_timeout 600s;
@@ -162,13 +162,13 @@ location /media/import/ {
}
# PHP entry point for main application
-location ~ (index|get|static|report|404|503)\.php$ {
+location ~ (index|get|static|report|404|503|health_check)\.php$ {
try_files $uri =404;
fastcgi_pass fastcgi_backend;
fastcgi_buffers 1024 4k;
fastcgi_param PHP_FLAG "session.auto_start=off \n suhosin.session.cryptua=off";
- fastcgi_param PHP_VALUE "memory_limit=768M \n max_execution_time=18000";
+ fastcgi_param PHP_VALUE "memory_limit=756M \n max_execution_time=18000";
fastcgi_read_timeout 600s;
fastcgi_connect_timeout 600s;
diff --git a/pub/.htaccess b/pub/.htaccess
index bdae9be342d8d..047ba279f8651 100644
--- a/pub/.htaccess
+++ b/pub/.htaccess
@@ -37,7 +37,7 @@
############################################
## Adjust memory limit
- php_value memory_limit 768M
+ php_value memory_limit 756M
php_value max_execution_time 18000
############################################
@@ -60,7 +60,7 @@
############################################
## Adjust memory limit
- php_value memory_limit 768M
+ php_value memory_limit 756M
php_value max_execution_time 18000
############################################
diff --git a/pub/.user.ini b/pub/.user.ini
index 8c0b765e0551c..bfc3a86d88e20 100644
--- a/pub/.user.ini
+++ b/pub/.user.ini
@@ -1,4 +1,4 @@
-memory_limit = 768M
+memory_limit = 756M
max_execution_time = 18000
session.auto_start = off
suhosin.session.cryptua = off
\ No newline at end of file
diff --git a/setup/src/Magento/Setup/Console/Command/AdminUserCreateCommand.php b/setup/src/Magento/Setup/Console/Command/AdminUserCreateCommand.php
index 940bcbbd6d7f1..4ad8e7c229bfd 100644
--- a/setup/src/Magento/Setup/Console/Command/AdminUserCreateCommand.php
+++ b/setup/src/Magento/Setup/Console/Command/AdminUserCreateCommand.php
@@ -6,13 +6,14 @@
namespace Magento\Setup\Console\Command;
-use Magento\Setup\Model\AdminAccount;
use Magento\Framework\Setup\ConsoleLogger;
+use Magento\Setup\Model\AdminAccount;
use Magento\Setup\Model\InstallerFactory;
use Magento\User\Model\UserValidationRules;
-use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
+use Symfony\Component\Console\Question\Question;
class AdminUserCreateCommand extends AbstractSetupCommand
{
@@ -50,6 +51,98 @@ protected function configure()
parent::configure();
}
+ /**
+ * @param \Symfony\Component\Console\Input\InputInterface $input
+ * @param \Symfony\Component\Console\Output\OutputInterface $output
+ *
+ * @SuppressWarnings(PHPMD.CyclomaticComplexity)
+ */
+ protected function interact(InputInterface $input, OutputInterface $output)
+ {
+ /** @var \Symfony\Component\Console\Helper\QuestionHelper $questionHelper */
+ $questionHelper = $this->getHelper('question');
+
+ if (!$input->getOption(AdminAccount::KEY_USER)) {
+ $question = new Question('Admin user: ', '');
+ $this->addNotEmptyValidator($question);
+
+ $input->setOption(
+ AdminAccount::KEY_USER,
+ $questionHelper->ask($input, $output, $question)
+ );
+ }
+
+ if (!$input->getOption(AdminAccount::KEY_PASSWORD)) {
+ $question = new Question('Admin password: ', '');
+ $question->setHidden(true);
+
+ $question->setValidator(function ($value) use ($output) {
+ $user = new \Magento\Framework\DataObject();
+ $user->setPassword($value);
+
+ $validator = new \Magento\Framework\Validator\DataObject();
+ $this->validationRules->addPasswordRules($validator);
+
+ $validator->isValid($user);
+ foreach ($validator->getMessages() as $message) {
+ throw new \Exception($message);
+ }
+
+ return $value;
+ });
+
+ $input->setOption(
+ AdminAccount::KEY_PASSWORD,
+ $questionHelper->ask($input, $output, $question)
+ );
+ }
+
+ if (!$input->getOption(AdminAccount::KEY_EMAIL)) {
+ $question = new Question('Admin email: ', '');
+ $this->addNotEmptyValidator($question);
+
+ $input->setOption(
+ AdminAccount::KEY_EMAIL,
+ $questionHelper->ask($input, $output, $question)
+ );
+ }
+
+ if (!$input->getOption(AdminAccount::KEY_FIRST_NAME)) {
+ $question = new Question('Admin first name: ', '');
+ $this->addNotEmptyValidator($question);
+
+ $input->setOption(
+ AdminAccount::KEY_FIRST_NAME,
+ $questionHelper->ask($input, $output, $question)
+ );
+ }
+
+ if (!$input->getOption(AdminAccount::KEY_LAST_NAME)) {
+ $question = new Question('Admin last name: ', '');
+ $this->addNotEmptyValidator($question);
+
+ $input->setOption(
+ AdminAccount::KEY_LAST_NAME,
+ $questionHelper->ask($input, $output, $question)
+ );
+ }
+ }
+
+ /**
+ * @param \Symfony\Component\Console\Question\Question $question
+ * @return void
+ */
+ private function addNotEmptyValidator(Question $question)
+ {
+ $question->setValidator(function ($value) {
+ if (trim($value) == '') {
+ throw new \Exception('The value cannot be empty');
+ }
+
+ return $value;
+ });
+ }
+
/**
* {@inheritdoc}
*/
@@ -57,7 +150,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
{
$errors = $this->validate($input);
if ($errors) {
- $output->writeln('' . implode('' . PHP_EOL . '', $errors) . '');
+ $output->writeln('' . implode('' . PHP_EOL . '', $errors) . '');
// we must have an exit code higher than zero to indicate something was wrong
return \Magento\Framework\Console\Cli::RETURN_FAILURE;
}
@@ -113,7 +206,7 @@ public function validate(InputInterface $input)
? '' : $input->getOption(AdminAccount::KEY_PASSWORD)
);
- $validator = new \Magento\Framework\Validator\DataObject;
+ $validator = new \Magento\Framework\Validator\DataObject();
$this->validationRules->addUserInfoRules($validator);
$this->validationRules->addPasswordRules($validator);
diff --git a/setup/src/Magento/Setup/Module/I18n/Parser/Adapter/Xml.php b/setup/src/Magento/Setup/Module/I18n/Parser/Adapter/Xml.php
index a0868d9f08566..dd87fa4b2aea2 100644
--- a/setup/src/Magento/Setup/Module/I18n/Parser/Adapter/Xml.php
+++ b/setup/src/Magento/Setup/Module/I18n/Parser/Adapter/Xml.php
@@ -65,7 +65,7 @@ private function parseTranslatableNodes(\SimpleXMLElement $attributes, \SimpleXM
{
$nodesDelimiter = strpos($attributes['translate'], ' ') === false ? ',' : ' ';
foreach (explode($nodesDelimiter, $attributes['translate']) as $value) {
- $phrase = (string)$element->{$value};
+ $phrase = trim((string)$element->{$value});
if ($phrase) {
$this->_addPhrase($phrase);
}
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 1cfd0c9494a51..d244f48d4e1ea 100644
--- a/setup/src/Magento/Setup/Test/Unit/Console/Command/AdminUserCreateCommandTest.php
+++ b/setup/src/Magento/Setup/Test/Unit/Console/Command/AdminUserCreateCommandTest.php
@@ -5,14 +5,21 @@
*/
namespace Magento\Setup\Test\Unit\Console\Command;
-use Magento\Setup\Model\AdminAccount;
use Magento\Setup\Console\Command\AdminUserCreateCommand;
+use Magento\Setup\Model\AdminAccount;
use Magento\Setup\Mvc\Bootstrap\InitParamListener;
use Magento\User\Model\UserValidationRules;
+use Symfony\Component\Console\Application;
+use Symfony\Component\Console\Helper\QuestionHelper;
use Symfony\Component\Console\Tester\CommandTester;
class AdminUserCreateCommandTest extends \PHPUnit\Framework\TestCase
{
+ /**
+ * @var \PHPUnit_Framework_MockObject_MockObject|\Symfony\Component\Console\Helper\QuestionHelper
+ */
+ private $questionHelperMock;
+
/**
* @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Setup\Model\InstallerFactory
*/
@@ -27,6 +34,10 @@ public function setUp()
{
$this->installerFactoryMock = $this->createMock(\Magento\Setup\Model\InstallerFactory::class);
$this->command = new AdminUserCreateCommand($this->installerFactoryMock, new UserValidationRules());
+
+ $this->questionHelperMock = $this->getMockBuilder(QuestionHelper::class)
+ ->setMethods(['ask'])
+ ->getMock();
}
public function testExecute()
@@ -50,10 +61,70 @@ public function testExecute()
$installerMock = $this->createMock(\Magento\Setup\Model\Installer::class);
$installerMock->expects($this->once())->method('installAdminUser')->with($data);
$this->installerFactoryMock->expects($this->once())->method('create')->willReturn($installerMock);
- $commandTester->execute($options);
+ $commandTester->execute($options, ['interactive' => false]);
$this->assertEquals('Created Magento administrator user named user' . PHP_EOL, $commandTester->getDisplay());
}
+ public function testInteraction()
+ {
+ $application = new Application();
+ $application->add($this->command);
+
+ $this->questionHelperMock->expects($this->at(0))
+ ->method('ask')
+ ->will($this->returnValue('admin'));
+
+ $this->questionHelperMock->expects($this->at(1))
+ ->method('ask')
+ ->will($this->returnValue('Password123'));
+
+ $this->questionHelperMock->expects($this->at(2))
+ ->method('ask')
+ ->will($this->returnValue('john.doe@example.com'));
+
+ $this->questionHelperMock->expects($this->at(3))
+ ->method('ask')
+ ->will($this->returnValue('John'));
+
+ $this->questionHelperMock->expects($this->at(4))
+ ->method('ask')
+ ->will($this->returnValue('Doe'));
+
+ // We override the standard helper with our mock
+ $this->command->getHelperSet()->set($this->questionHelperMock, 'question');
+
+ $installerMock = $this->createMock(\Magento\Setup\Model\Installer::class);
+
+ $expectedData = [
+ 'admin-user' => 'admin',
+ 'admin-password' => 'Password123',
+ 'admin-email' => 'john.doe@example.com',
+ 'admin-firstname' => 'John',
+ 'admin-lastname' => 'Doe',
+ 'magento-init-params' => null,
+ 'help' => false,
+ 'quiet' => false,
+ 'verbose' => false,
+ 'version' => false,
+ 'ansi' => false,
+ 'no-ansi' => false,
+ 'no-interaction' => false,
+ ];
+
+ $installerMock->expects($this->once())->method('installAdminUser')->with($expectedData);
+ $this->installerFactoryMock->expects($this->once())->method('create')->willReturn($installerMock);
+
+ $commandTester = new CommandTester($this->command);
+ $commandTester->execute([
+ 'command' => $this->command->getName(),
+ ]);
+
+ $this->assertEquals(
+ 'Created Magento administrator user named admin' . PHP_EOL,
+ $commandTester->getDisplay()
+ );
+ }
+
public function testGetOptionsList()
{
/* @var $argsList \Symfony\Component\Console\Input\InputArgument[] */
diff --git a/setup/src/Magento/Setup/Test/Unit/Module/I18n/Parser/Adapter/XmlTest.php b/setup/src/Magento/Setup/Test/Unit/Module/I18n/Parser/Adapter/XmlTest.php
index 1a052ba8c3233..842a2a8d8f2cc 100644
--- a/setup/src/Magento/Setup/Test/Unit/Module/I18n/Parser/Adapter/XmlTest.php
+++ b/setup/src/Magento/Setup/Test/Unit/Module/I18n/Parser/Adapter/XmlTest.php
@@ -53,6 +53,7 @@ public function parseDataProvider()
['phrase' => 'Phrase 2', 'file' => $default, 'line' => '', 'quote' => ''],
['phrase' => 'Phrase 3', 'file' => $default, 'line' => '', 'quote' => ''],
['phrase' => 'Phrase 1', 'file' => $default, 'line' => '', 'quote' => ''],
+ ['phrase' => 'Comment from new line.', 'file' => $default, 'line' => '', 'quote' => ''],
],
],
[
diff --git a/setup/src/Magento/Setup/Test/Unit/Module/I18n/Parser/Adapter/_files/default.xml b/setup/src/Magento/Setup/Test/Unit/Module/I18n/Parser/Adapter/_files/default.xml
index 77edb3881e0c5..510ff16abc6ef 100644
--- a/setup/src/Magento/Setup/Test/Unit/Module/I18n/Parser/Adapter/_files/default.xml
+++ b/setup/src/Magento/Setup/Test/Unit/Module/I18n/Parser/Adapter/_files/default.xml
@@ -15,4 +15,9 @@
Phrase 1
+
+
+
+
+