diff --git a/app/code/Magento/Cms/Model/Block.php b/app/code/Magento/Cms/Model/Block.php index fc369971054d7281b2bccf72d48cf477d8b2090c..3795409a95d2b49f2ae0efc64f30abf050f14062 100644 --- a/app/code/Magento/Cms/Model/Block.php +++ b/app/code/Magento/Cms/Model/Block.php @@ -6,7 +6,6 @@ namespace Magento\Cms\Model; use Magento\Cms\Api\Data\BlockInterface; -use Magento\Cms\Model\ResourceModel\Block as ResourceCmsBlock; use Magento\Framework\DataObject\IdentityInterface; use Magento\Framework\Model\AbstractModel; @@ -58,6 +57,11 @@ class Block extends AbstractModel implements BlockInterface, IdentityInterface public function beforeSave() { $needle = 'block_id="' . $this->getId() . '"'; + + if ($this->hasDataChanges()) { + $this->setUpdateTime(null); + } + if (false == strstr($this->getContent(), $needle)) { return parent::beforeSave(); } diff --git a/app/code/Magento/Cms/Model/Page.php b/app/code/Magento/Cms/Model/Page.php index 591f8d93fcdc6cee0a2e9f5bbc82fe871701ae18..d950f484cd1d99c27d3d1d2f796c094e96906672 100644 --- a/app/code/Magento/Cms/Model/Page.php +++ b/app/code/Magento/Cms/Model/Page.php @@ -6,12 +6,11 @@ namespace Magento\Cms\Model; use Magento\Cms\Api\Data\PageInterface; -use Magento\Cms\Model\ResourceModel\Page as ResourceCmsPage; +use Magento\Cms\Helper\Page as PageHelper; use Magento\Framework\App\Config\ScopeConfigInterface; use Magento\Framework\DataObject\IdentityInterface; use Magento\Framework\Exception\LocalizedException; use Magento\Framework\Model\AbstractModel; -use Magento\Cms\Helper\Page as PageHelper; /** * Cms Page Model @@ -547,6 +546,10 @@ class Page extends AbstractModel implements PageInterface, IdentityInterface $originalIdentifier = $this->getOrigData('identifier'); $currentIdentifier = $this->getIdentifier(); + if ($this->hasDataChanges()) { + $this->setUpdateTime(null); + } + if (!$this->getId() || $originalIdentifier === $currentIdentifier) { return parent::beforeSave(); } diff --git a/app/code/Magento/Cms/Model/ResourceModel/Block.php b/app/code/Magento/Cms/Model/ResourceModel/Block.php index d5bae7359fe356892b2ff5a6288538c8dee6a683..9aab54b02bc14fcae402b5e30570e1b2c28b5699 100644 --- a/app/code/Magento/Cms/Model/ResourceModel/Block.php +++ b/app/code/Magento/Cms/Model/ResourceModel/Block.php @@ -7,10 +7,10 @@ namespace Magento\Cms\Model\ResourceModel; use Magento\Cms\Api\Data\BlockInterface; use Magento\Framework\DB\Select; +use Magento\Framework\EntityManager\EntityManager; +use Magento\Framework\EntityManager\MetadataPool; use Magento\Framework\Exception\LocalizedException; use Magento\Framework\Model\AbstractModel; -use Magento\Framework\EntityManager\MetadataPool; -use Magento\Framework\EntityManager\EntityManager; use Magento\Framework\Model\ResourceModel\Db\AbstractDb; use Magento\Framework\Model\ResourceModel\Db\Context; use Magento\Store\Model\Store; diff --git a/app/code/Magento/Cms/Model/ResourceModel/Page.php b/app/code/Magento/Cms/Model/ResourceModel/Page.php index 8e26c8b67fa4b58cace3e3bbfb62f6d95796bef4..b836cf199632d34e345c732cfd06f645da566e3e 100644 --- a/app/code/Magento/Cms/Model/ResourceModel/Page.php +++ b/app/code/Magento/Cms/Model/ResourceModel/Page.php @@ -6,18 +6,18 @@ namespace Magento\Cms\Model\ResourceModel; +use Magento\Cms\Api\Data\PageInterface; use Magento\Cms\Model\Page as CmsPage; use Magento\Framework\DB\Select; +use Magento\Framework\EntityManager\EntityManager; +use Magento\Framework\EntityManager\MetadataPool; use Magento\Framework\Exception\LocalizedException; use Magento\Framework\Model\AbstractModel; -use Magento\Framework\EntityManager\MetadataPool; use Magento\Framework\Model\ResourceModel\Db\AbstractDb; use Magento\Framework\Model\ResourceModel\Db\Context; use Magento\Framework\Stdlib\DateTime; use Magento\Store\Model\Store; use Magento\Store\Model\StoreManagerInterface; -use Magento\Framework\EntityManager\EntityManager; -use Magento\Cms\Api\Data\PageInterface; /** * Cms page mysql resource diff --git a/app/code/Magento/Config/Model/Config/Source/Nooptreq.php b/app/code/Magento/Config/Model/Config/Source/Nooptreq.php index 03fe5ca2abcccfe62721f747e3f7d3d4f314599f..1c9eb801dfec78962b71b9f9358ad6a462087dab 100644 --- a/app/code/Magento/Config/Model/Config/Source/Nooptreq.php +++ b/app/code/Magento/Config/Model/Config/Source/Nooptreq.php @@ -11,15 +11,19 @@ namespace Magento\Config\Model\Config\Source; */ class Nooptreq implements \Magento\Framework\Option\ArrayInterface { + const VALUE_NO = ''; + const VALUE_OPTIONAL = 'opt'; + const VALUE_REQUIRED = 'req'; + /** * @return array */ public function toOptionArray() { return [ - ['value' => '', 'label' => __('No')], - ['value' => 'opt', 'label' => __('Optional')], - ['value' => 'req', 'label' => __('Required')] + ['value' => self::VALUE_NO, 'label' => __('No')], + ['value' => self::VALUE_OPTIONAL, 'label' => __('Optional')], + ['value' => self::VALUE_REQUIRED, 'label' => __('Required')] ]; } } diff --git a/app/code/Magento/ConfigurableProduct/Ui/DataProvider/Product/Form/Modifier/ConfigurablePanel.php b/app/code/Magento/ConfigurableProduct/Ui/DataProvider/Product/Form/Modifier/ConfigurablePanel.php index 0e03dfe3cde51e27d00e58a057971a0d5de04a51..9fd225e8acaab0ad561e8d2d80817082f68d0d58 100644 --- a/app/code/Magento/ConfigurableProduct/Ui/DataProvider/Product/Form/Modifier/ConfigurablePanel.php +++ b/app/code/Magento/ConfigurableProduct/Ui/DataProvider/Product/Form/Modifier/ConfigurablePanel.php @@ -5,6 +5,7 @@ */ namespace Magento\ConfigurableProduct\Ui\DataProvider\Product\Form\Modifier; +use Magento\Catalog\Model\Product\Attribute\Backend\Sku; use Magento\Catalog\Ui\DataProvider\Product\Form\Modifier\AbstractModifier; use Magento\Ui\Component\Container; use Magento\Ui\Component\Form; @@ -466,7 +467,17 @@ class ConfigurablePanel extends AbstractModifier [], ['dataScope' => 'product_link'] ), - 'sku_container' => $this->getColumn('sku', __('SKU')), + 'sku_container' => $this->getColumn( + 'sku', + __('SKU'), + [ + 'validation' => + [ + 'required-entry' => true, + 'max_text_length' => Sku::SKU_MAX_LENGTH, + ] + ] + ), 'price_container' => $this->getColumn( 'price', __('Price'), diff --git a/app/code/Magento/Customer/Block/Widget/Name.php b/app/code/Magento/Customer/Block/Widget/Name.php index ecd09319cd85ec47fd3ef0f2ac81ee683fe9491a..35f3bbefb8f00ee9a3d2cb2b7b6e3fb82bbe12ee 100644 --- a/app/code/Magento/Customer/Block/Widget/Name.php +++ b/app/code/Magento/Customer/Block/Widget/Name.php @@ -106,8 +106,11 @@ class Name extends AbstractWidget $prefixOptions = $this->options->getNamePrefixOptions(); if ($this->getObject() && !empty($prefixOptions)) { - $oldPrefix = $this->escapeHtml(trim($this->getObject()->getPrefix())); - $prefixOptions[$oldPrefix] = $oldPrefix; + $prefixOption = $this->getObject()->getPrefix(); + $oldPrefix = $this->escapeHtml(trim($prefixOption)); + if ($prefixOption !== null && !isset($prefixOptions[$oldPrefix]) && !isset($prefixOptions[$prefixOption])) { + $prefixOptions[$oldPrefix] = $oldPrefix; + } } return $prefixOptions; } @@ -161,8 +164,11 @@ class Name extends AbstractWidget { $suffixOptions = $this->options->getNameSuffixOptions(); if ($this->getObject() && !empty($suffixOptions)) { - $oldSuffix = $this->escapeHtml(trim($this->getObject()->getSuffix())); - $suffixOptions[$oldSuffix] = $oldSuffix; + $suffixOption = $this->getObject()->getSuffix(); + $oldSuffix = $this->escapeHtml(trim($suffixOption)); + if ($suffixOption !== null && !isset($suffixOptions[$oldSuffix]) && !isset($suffixOptions[$suffixOption])) { + $suffixOptions[$oldSuffix] = $oldSuffix; + } } return $suffixOptions; } diff --git a/app/code/Magento/Customer/Model/AccountConfirmation.php b/app/code/Magento/Customer/Model/AccountConfirmation.php new file mode 100644 index 0000000000000000000000000000000000000000..7d01ff0efc4117aa26d71b85c1f8226d7178d8f2 --- /dev/null +++ b/app/code/Magento/Customer/Model/AccountConfirmation.php @@ -0,0 +1,89 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Customer\Model; + +use Magento\Store\Model\ScopeInterface; +use Magento\Framework\App\Config\ScopeConfigInterface; +use Magento\Framework\Registry; + +/** + * Class AccountConfirmation. + * Checks if email confirmation required for customer. + */ +class AccountConfirmation +{ + /** + * Configuration path for email confirmation. + */ + const XML_PATH_IS_CONFIRM = 'customer/create_account/confirm'; + + /** + * @var ScopeConfigInterface + */ + private $scopeConfig; + + /** + * @var Registry + */ + private $registry; + + /** + * @param ScopeConfigInterface $scopeConfig + * @param Registry $registry + */ + public function __construct( + ScopeConfigInterface $scopeConfig, + Registry $registry + ) { + $this->scopeConfig = $scopeConfig; + $this->registry = $registry; + } + + /** + * Check if accounts confirmation is required. + * + * @param int|null $websiteId + * @param int|null $customerId + * @param string $customerEmail + * @return bool + */ + public function isConfirmationRequired($websiteId, $customerId, $customerEmail): bool + { + if ($this->canSkipConfirmation($customerId, $customerEmail)) { + return false; + } + + return (bool)$this->scopeConfig->getValue( + self::XML_PATH_IS_CONFIRM, + ScopeInterface::SCOPE_WEBSITES, + $websiteId + ); + } + + /** + * Check whether confirmation may be skipped when registering using certain email address. + * + * @param int|null $customerId + * @param string $customerEmail + * @return bool + */ + private function canSkipConfirmation($customerId, $customerEmail): bool + { + if (!$customerId) { + return false; + } + + /* If an email was used to start the registration process and it is the same email as the one + used to register, then this can skip confirmation. + */ + $skipConfirmationIfEmail = $this->registry->registry("skip_confirmation_if_email"); + if (!$skipConfirmationIfEmail) { + return false; + } + + return strtolower($skipConfirmationIfEmail) === strtolower($customerEmail); + } +} diff --git a/app/code/Magento/Customer/Model/AccountManagement.php b/app/code/Magento/Customer/Model/AccountManagement.php index 894dd5931a63c6be9e8590cc422aa2d0de92b666..8ba44f86f5a0ee68f6c9d26339a4af1dcd24a5a1 100644 --- a/app/code/Magento/Customer/Model/AccountManagement.php +++ b/app/code/Magento/Customer/Model/AccountManagement.php @@ -89,6 +89,10 @@ class AccountManagement implements AccountManagementInterface */ const XML_PATH_FORGOT_EMAIL_IDENTITY = 'customer/password/forgot_email_identity'; + /** + * @deprecated + * @see AccountConfirmation::XML_PATH_IS_CONFIRM + */ const XML_PATH_IS_CONFIRM = 'customer/create_account/confirm'; /** @@ -298,6 +302,11 @@ class AccountManagement implements AccountManagementInterface */ private $dateTimeFactory; + /** + * @var AccountConfirmation + */ + private $accountConfirmation; + /** * @param CustomerFactory $customerFactory * @param ManagerInterface $eventManager @@ -323,7 +332,8 @@ class AccountManagement implements AccountManagementInterface * @param ObjectFactory $objectFactory * @param ExtensibleDataObjectConverter $extensibleDataObjectConverter * @param CredentialsValidator|null $credentialsValidator - * @param DateTimeFactory $dateTimeFactory + * @param DateTimeFactory|null $dateTimeFactory + * @param AccountConfirmation|null $accountConfirmation * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( @@ -351,7 +361,8 @@ class AccountManagement implements AccountManagementInterface ObjectFactory $objectFactory, ExtensibleDataObjectConverter $extensibleDataObjectConverter, CredentialsValidator $credentialsValidator = null, - DateTimeFactory $dateTimeFactory = null + DateTimeFactory $dateTimeFactory = null, + AccountConfirmation $accountConfirmation = null ) { $this->customerFactory = $customerFactory; $this->eventManager = $eventManager; @@ -379,6 +390,8 @@ class AccountManagement implements AccountManagementInterface $this->credentialsValidator = $credentialsValidator ?: ObjectManager::getInstance()->get(CredentialsValidator::class); $this->dateTimeFactory = $dateTimeFactory ?: ObjectManager::getInstance()->get(DateTimeFactory::class); + $this->accountConfirmation = $accountConfirmation ?: ObjectManager::getInstance() + ->get(AccountConfirmation::class); } /** @@ -1149,17 +1162,15 @@ class AccountManagement implements AccountManagementInterface * * @param CustomerInterface $customer * @return bool + * @deprecated + * @see AccountConfirmation::isConfirmationRequired */ protected function isConfirmationRequired($customer) { - if ($this->canSkipConfirmation($customer)) { - return false; - } - - return (bool)$this->scopeConfig->getValue( - self::XML_PATH_IS_CONFIRM, - ScopeInterface::SCOPE_WEBSITES, - $customer->getWebsiteId() + return $this->accountConfirmation->isConfirmationRequired( + $customer->getWebsiteId(), + $customer->getId(), + $customer->getEmail() ); } @@ -1168,6 +1179,8 @@ class AccountManagement implements AccountManagementInterface * * @param CustomerInterface $customer * @return bool + * @deprecated + * @see AccountConfirmation::isConfirmationRequired */ protected function canSkipConfirmation($customer) { diff --git a/app/code/Magento/Customer/Model/Customer.php b/app/code/Magento/Customer/Model/Customer.php index 2e2260f16ff919bc08121ba8b89ffd6439a5270c..e0a7281776de929a9f394e7b5035724ee68071c2 100644 --- a/app/code/Magento/Customer/Model/Customer.php +++ b/app/code/Magento/Customer/Model/Customer.php @@ -18,6 +18,7 @@ use Magento\Framework\Exception\InvalidEmailOrPasswordException; use Magento\Framework\Indexer\StateInterface; use Magento\Framework\Reflection\DataObjectProcessor; use Magento\Store\Model\ScopeInterface; +use Magento\Framework\App\ObjectManager; /** * Customer model @@ -58,6 +59,10 @@ class Customer extends \Magento\Framework\Model\AbstractModel const XML_PATH_RESET_PASSWORD_TEMPLATE = 'customer/password/reset_password_template'; + /** + * @deprecated + * @see AccountConfirmation::XML_PATH_IS_CONFIRM + */ const XML_PATH_IS_CONFIRM = 'customer/create_account/confirm'; const XML_PATH_CONFIRM_EMAIL_TEMPLATE = 'customer/create_account/email_confirmation_template'; @@ -208,6 +213,11 @@ class Customer extends \Magento\Framework\Model\AbstractModel */ protected $indexerRegistry; + /** + * @var AccountConfirmation + */ + private $accountConfirmation; + /** * @param \Magento\Framework\Model\Context $context * @param \Magento\Framework\Registry $registry @@ -229,6 +239,7 @@ class Customer extends \Magento\Framework\Model\AbstractModel * @param \Magento\Framework\Indexer\IndexerRegistry $indexerRegistry * @param \Magento\Framework\Data\Collection\AbstractDb|null $resourceCollection * @param array $data + * @param AccountConfirmation|null $accountConfirmation * * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ @@ -252,7 +263,8 @@ class Customer extends \Magento\Framework\Model\AbstractModel \Magento\Customer\Api\CustomerMetadataInterface $metadataService, \Magento\Framework\Indexer\IndexerRegistry $indexerRegistry, \Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null, - array $data = [] + array $data = [], + AccountConfirmation $accountConfirmation = null ) { $this->metadataService = $metadataService; $this->_scopeConfig = $scopeConfig; @@ -269,6 +281,8 @@ class Customer extends \Magento\Framework\Model\AbstractModel $this->dataObjectProcessor = $dataObjectProcessor; $this->dataObjectHelper = $dataObjectHelper; $this->indexerRegistry = $indexerRegistry; + $this->accountConfirmation = $accountConfirmation ?: ObjectManager::getInstance() + ->get(AccountConfirmation::class); parent::__construct( $context, $registry, @@ -770,20 +784,14 @@ class Customer extends \Magento\Framework\Model\AbstractModel * Check if accounts confirmation is required in config * * @return bool + * @deprecated + * @see AccountConfirmation::isConfirmationRequired */ public function isConfirmationRequired() { - if ($this->canSkipConfirmation()) { - return false; - } - $websiteId = $this->getWebsiteId() ? $this->getWebsiteId() : null; - return (bool)$this->_scopeConfig->getValue( - self::XML_PATH_IS_CONFIRM, - ScopeInterface::SCOPE_WEBSITES, - $websiteId - ); + return $this->accountConfirmation->isConfirmationRequired($websiteId, $this->getId(), $this->getEmail()); } /** @@ -1156,6 +1164,8 @@ class Customer extends \Magento\Framework\Model\AbstractModel * Check whether confirmation may be skipped when registering using certain email address * * @return bool + * @deprecated + * @see AccountConfirmation::isConfirmationRequired */ protected function canSkipConfirmation() { diff --git a/app/code/Magento/Customer/Model/Options.php b/app/code/Magento/Customer/Model/Options.php index ee109dac08104ec9612843d50d5baab357dbb156..7747e309d82a60ca383c8fab7734ed6f4c649e4f 100644 --- a/app/code/Magento/Customer/Model/Options.php +++ b/app/code/Magento/Customer/Model/Options.php @@ -5,6 +5,7 @@ */ namespace Magento\Customer\Model; +use Magento\Config\Model\Config\Source\Nooptreq as NooptreqSource; use Magento\Customer\Helper\Address as AddressHelper; use Magento\Framework\Escaper; @@ -42,7 +43,10 @@ class Options */ public function getNamePrefixOptions($store = null) { - return $this->_prepareNamePrefixSuffixOptions($this->addressHelper->getConfig('prefix_options', $store)); + return $this->prepareNamePrefixSuffixOptions( + $this->addressHelper->getConfig('prefix_options', $store), + $this->addressHelper->getConfig('prefix_show', $store) == NooptreqSource::VALUE_OPTIONAL + ); } /** @@ -53,16 +57,34 @@ class Options */ public function getNameSuffixOptions($store = null) { - return $this->_prepareNamePrefixSuffixOptions($this->addressHelper->getConfig('suffix_options', $store)); + return $this->prepareNamePrefixSuffixOptions( + $this->addressHelper->getConfig('suffix_options', $store), + $this->addressHelper->getConfig('suffix_show', $store) == NooptreqSource::VALUE_OPTIONAL + ); + } + + /** + * @param $options + * @param bool $isOptional + * @return array|bool + * + * @deprecated + * @see prepareNamePrefixSuffixOptions() + */ + protected function _prepareNamePrefixSuffixOptions($options, $isOptional = false) + { + return $this->prepareNamePrefixSuffixOptions($options, $isOptional); } /** * Unserialize and clear name prefix or suffix options + * If field is optional, add an empty first option. * * @param string $options + * @param bool $isOptional * @return array|bool */ - protected function _prepareNamePrefixSuffixOptions($options) + private function prepareNamePrefixSuffixOptions($options, $isOptional = false) { $options = trim($options); if (empty($options)) { @@ -74,6 +96,10 @@ class Options $value = $this->escaper->escapeHtml(trim($value)); $result[$value] = $value; } + if ($isOptional && trim(current($options))) { + $result = array_merge([' ' => ' '], $result); + } + return $result; } } diff --git a/app/code/Magento/Customer/Test/Unit/Model/AccountConfirmationTest.php b/app/code/Magento/Customer/Test/Unit/Model/AccountConfirmationTest.php new file mode 100644 index 0000000000000000000000000000000000000000..ae246665b28ed09e9100220f96a7d51838e935d6 --- /dev/null +++ b/app/code/Magento/Customer/Test/Unit/Model/AccountConfirmationTest.php @@ -0,0 +1,93 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Customer\Test\Unit\Model; + +use Magento\Customer\Model\AccountConfirmation; +use Magento\Store\Model\ScopeInterface; +use Magento\Framework\App\Config\ScopeConfigInterface; +use Magento\Framework\Registry; + +/** + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ +class AccountConfirmationTest extends \PHPUnit\Framework\TestCase +{ + /** + * @var AccountConfirmation|\PHPUnit_Framework_MockObject_MockObject + */ + private $accountConfirmation; + + /** + * @var ScopeConfigInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $scopeConfig; + + /** + * @var Registry|\PHPUnit_Framework_MockObject_MockObject + */ + private $registry; + + protected function setUp() + { + $this->scopeConfig = $this->createMock(ScopeConfigInterface::class); + $this->registry = $this->createMock(Registry::class); + + $this->accountConfirmation = new AccountConfirmation( + $this->scopeConfig, + $this->registry + ); + } + + /** + * @param $customerId + * @param $customerEmail + * @param $skipConfirmationIfEmail + * @param $isConfirmationEnabled + * @param $expected + * @dataProvider dataProviderIsConfirmationRequired + */ + public function testIsConfirmationRequired( + $customerId, + $customerEmail, + $skipConfirmationIfEmail, + $isConfirmationEnabled, + $expected + ) { + $websiteId = 1; + + $this->scopeConfig->expects($this->any()) + ->method('getValue') + ->with( + $this->accountConfirmation::XML_PATH_IS_CONFIRM, + ScopeInterface::SCOPE_WEBSITES, + $websiteId + )->willReturn($isConfirmationEnabled); + + $this->registry->expects($this->any()) + ->method('registry') + ->with('skip_confirmation_if_email') + ->willReturn($skipConfirmationIfEmail); + + self::assertEquals( + $expected, + $this->accountConfirmation->isConfirmationRequired($websiteId, $customerId, $customerEmail) + ); + } + + /** + * @return array + */ + public function dataProviderIsConfirmationRequired() + { + return [ + [null, 'customer@example.com', null, true, true], + [null, 'customer@example.com', null, false, false], + [1, 'customer@example.com', 'customer@example.com', true, false], + [1, 'customer@example.com', 'customer1@example.com', false, false], + [1, 'customer@example.com', 'customer1@example.com', true, true], + ]; + } +} diff --git a/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php b/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php index 676e9c98a2008eebe06aca66f14602573f88c036..d72d7ec87ec3dba1454f76413f821f0159e01f7f 100644 --- a/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php +++ b/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php @@ -6,6 +6,7 @@ namespace Magento\Customer\Test\Unit\Model; use Magento\Customer\Model\AccountManagement; +use Magento\Customer\Model\AccountConfirmation; use Magento\Customer\Model\AuthenticationInterface; use Magento\Customer\Model\EmailNotificationInterface; use Magento\Framework\App\Area; @@ -120,6 +121,11 @@ class AccountManagementTest extends \PHPUnit\Framework\TestCase */ private $dateTimeFactory; + /** + * @var AccountConfirmation|\PHPUnit_Framework_MockObject_MockObject + */ + private $accountConfirmation; + /** * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ @@ -170,6 +176,7 @@ class AccountManagementTest extends \PHPUnit\Framework\TestCase ->getMock(); $this->dateTimeFactory = $this->createMock(DateTimeFactory::class); + $this->accountConfirmation = $this->createMock(AccountConfirmation::class); $this->objectManagerHelper = new ObjectManagerHelper($this); $this->accountManagement = $this->objectManagerHelper->getObject( @@ -199,6 +206,7 @@ class AccountManagementTest extends \PHPUnit\Framework\TestCase 'objectFactory' => $this->objectFactory, 'extensibleDataObjectConverter' => $this->extensibleDataObjectConverter, 'dateTimeFactory' => $this->dateTimeFactory, + 'accountConfirmation' => $this->accountConfirmation ] ); $reflection = new \ReflectionClass(get_class($this->accountManagement)); @@ -1467,14 +1475,12 @@ class AccountManagementTest extends \PHPUnit\Framework\TestCase } /** - * @param string|null $skipConfirmationIfEmail * @param int $isConfirmationRequired * @param string|null $confirmation * @param string $expected * @dataProvider dataProviderGetConfirmationStatus */ public function testGetConfirmationStatus( - $skipConfirmationIfEmail, $isConfirmationRequired, $confirmation, $expected @@ -1492,21 +1498,16 @@ class AccountManagementTest extends \PHPUnit\Framework\TestCase $customerMock->expects($this->any()) ->method('getConfirmation') ->willReturn($confirmation); - $customerMock->expects($this->any()) + $customerMock->expects($this->once()) ->method('getEmail') ->willReturn($customerEmail); - $customerMock->expects($this->any()) + $customerMock->expects($this->once()) ->method('getWebsiteId') ->willReturn($websiteId); - $this->registry->expects($this->once()) - ->method('registry') - ->with('skip_confirmation_if_email') - ->willReturn($skipConfirmationIfEmail); - - $this->scopeConfig->expects($this->any()) - ->method('getValue') - ->with(AccountManagement::XML_PATH_IS_CONFIRM, ScopeInterface::SCOPE_WEBSITES, $websiteId) + $this->accountConfirmation->expects($this->once()) + ->method('isConfirmationRequired') + ->with($websiteId, $customerId, $customerEmail) ->willReturn($isConfirmationRequired); $this->customerRepository->expects($this->once()) @@ -1523,11 +1524,11 @@ class AccountManagementTest extends \PHPUnit\Framework\TestCase public function dataProviderGetConfirmationStatus() { return [ - [null, 0, null, AccountManagement::ACCOUNT_CONFIRMATION_NOT_REQUIRED], - ['test1@example.com', 0, null, AccountManagement::ACCOUNT_CONFIRMATION_NOT_REQUIRED], - ['test2@example.com', 0, null, AccountManagement::ACCOUNT_CONFIRMATION_NOT_REQUIRED], - ['test2@example.com', 1, null, AccountManagement::ACCOUNT_CONFIRMED], - ['test2@example.com', 1, 'test', AccountManagement::ACCOUNT_CONFIRMATION_REQUIRED], + [0, null, AccountManagement::ACCOUNT_CONFIRMATION_NOT_REQUIRED], + [0, null, AccountManagement::ACCOUNT_CONFIRMATION_NOT_REQUIRED], + [0, null, AccountManagement::ACCOUNT_CONFIRMATION_NOT_REQUIRED], + [1, null, AccountManagement::ACCOUNT_CONFIRMED], + [1, 'test', AccountManagement::ACCOUNT_CONFIRMATION_REQUIRED], ]; } diff --git a/app/code/Magento/Customer/Test/Unit/Model/CustomerTest.php b/app/code/Magento/Customer/Test/Unit/Model/CustomerTest.php index 8b3f7875e3c97d7badbca770d9edd25cb853ab2f..f5b7f08d2906d47849e4b2b96c529b12da21ab03 100644 --- a/app/code/Magento/Customer/Test/Unit/Model/CustomerTest.php +++ b/app/code/Magento/Customer/Test/Unit/Model/CustomerTest.php @@ -12,7 +12,7 @@ namespace Magento\Customer\Test\Unit\Model; use Magento\Customer\Model\Customer; -use Magento\Store\Model\ScopeInterface; +use Magento\Customer\Model\AccountConfirmation; /** * @SuppressWarnings(PHPMD.CouplingBetweenObjects) @@ -63,6 +63,11 @@ class CustomerTest extends \PHPUnit\Framework\TestCase */ private $dataObjectProcessor; + /** + * @var AccountConfirmation|\PHPUnit_Framework_MockObject_MockObject + */ + private $accountConfirmation; + protected function setUp() { $this->_website = $this->createMock(\Magento\Store\Model\Website::class); @@ -94,6 +99,7 @@ class CustomerTest extends \PHPUnit\Framework\TestCase $this->registryMock = $this->createPartialMock(\Magento\Framework\Registry::class, ['registry']); $this->_encryptor = $this->createMock(\Magento\Framework\Encryption\EncryptorInterface::class); $helper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + $this->accountConfirmation = $this->createMock(AccountConfirmation::class); $this->_model = $helper->getObject( \Magento\Customer\Model\Customer::class, [ @@ -105,7 +111,8 @@ class CustomerTest extends \PHPUnit\Framework\TestCase 'attributeFactory' => $this->attributeFactoryMock, 'registry' => $this->registryMock, 'resource' => $this->resourceMock, - 'dataObjectProcessor' => $this->dataObjectProcessor + 'dataObjectProcessor' => $this->dataObjectProcessor, + 'accountConfirmation' => $this->accountConfirmation ] ); } @@ -215,32 +222,27 @@ class CustomerTest extends \PHPUnit\Framework\TestCase /** * @param int $customerId * @param int $websiteId - * @param string|null $skipConfirmationIfEmail + * @param bool $isConfirmationRequired * @param bool $expected * @dataProvider dataProviderIsConfirmationRequired */ public function testIsConfirmationRequired( $customerId, $websiteId, - $skipConfirmationIfEmail, + $isConfirmationRequired, $expected ) { $customerEmail = 'test1@example.com'; - $this->registryMock->expects($this->any()) - ->method('registry') - ->with('skip_confirmation_if_email') - ->willReturn($skipConfirmationIfEmail); - - $this->_scopeConfigMock->expects($this->any()) - ->method('getValue') - ->with(Customer::XML_PATH_IS_CONFIRM, ScopeInterface::SCOPE_WEBSITES, $websiteId) - ->willReturn($expected); - $this->_model->setData('id', $customerId); $this->_model->setData('website_id', $websiteId); $this->_model->setData('email', $customerEmail); + $this->accountConfirmation->expects($this->once()) + ->method('isConfirmationRequired') + ->with($websiteId, $customerId, $customerEmail) + ->willReturn($isConfirmationRequired); + $this->assertEquals($expected, $this->_model->isConfirmationRequired()); } @@ -250,12 +252,9 @@ class CustomerTest extends \PHPUnit\Framework\TestCase public function dataProviderIsConfirmationRequired() { return [ - [null, null, null, false], - [1, 1, null, false], - [1, 1, 'test1@example.com', false], - [1, 1, 'test2@example.com', true], - [1, 0, 'test2@example.com', true], - [1, null, 'test2@example.com', true], + [null, null, false, false], + [1, 1, true, true], + [1, null, true, true], ]; } diff --git a/app/code/Magento/Customer/Test/Unit/Ui/Component/Listing/Column/ConfirmationTest.php b/app/code/Magento/Customer/Test/Unit/Ui/Component/Listing/Column/ConfirmationTest.php index e55cee49b5c94d5795c62076839fb823348110cb..b712c0f30b4307d8450013d4c0fb8bc96c6dae2a 100644 --- a/app/code/Magento/Customer/Test/Unit/Ui/Component/Listing/Column/ConfirmationTest.php +++ b/app/code/Magento/Customer/Test/Unit/Ui/Component/Listing/Column/ConfirmationTest.php @@ -5,13 +5,12 @@ */ namespace Magento\Customer\Test\Unit\Ui\Component\Listing\Column; -use Magento\Customer\Model\AccountManagement; +use Magento\Customer\Model\AccountConfirmation; use Magento\Customer\Ui\Component\Listing\Column\Confirmation; use Magento\Framework\App\Config\ScopeConfigInterface; use Magento\Framework\View\Element\UiComponent\ContextInterface; use Magento\Framework\View\Element\UiComponent\Processor; use Magento\Framework\View\Element\UiComponentFactory; -use Magento\Store\Model\ScopeInterface; class ConfirmationTest extends \PHPUnit\Framework\TestCase { @@ -40,6 +39,11 @@ class ConfirmationTest extends \PHPUnit\Framework\TestCase */ protected $processor; + /** + * @var AccountConfirmation|\PHPUnit_Framework_MockObject_MockObject + */ + protected $accountConfirmation; + public function setup() { $this->processor = $this->getMockBuilder(\Magento\Framework\View\Element\UiComponent\Processor::class) @@ -60,12 +64,15 @@ class ConfirmationTest extends \PHPUnit\Framework\TestCase $this->scopeConfig = $this->getMockBuilder(\Magento\Framework\App\Config\ScopeConfigInterface::class) ->getMockForAbstractClass(); + $this->accountConfirmation = $this->createMock(AccountConfirmation::class); + $this->confirmation = new Confirmation( $this->context, $this->uiComponentFactory, $this->scopeConfig, [], - [] + [], + $this->accountConfirmation ); } @@ -81,12 +88,17 @@ class ConfirmationTest extends \PHPUnit\Framework\TestCase $expected ) { $websiteId = 1; + $customerId = 1; + $customerEmail = 'customer@example.com'; $dataSource = [ 'data' => [ 'items' => [ [ + 'id_field_name' => 'entity_id', + 'entity_id' => $customerId, 'confirmation' => $confirmation, + 'email' => $customerEmail, 'website_id' => [ $websiteId, ], @@ -100,9 +112,9 @@ class ConfirmationTest extends \PHPUnit\Framework\TestCase ->with($this->confirmation) ->willReturnSelf(); - $this->scopeConfig->expects($this->once()) - ->method('getValue') - ->with(AccountManagement::XML_PATH_IS_CONFIRM, ScopeInterface::SCOPE_WEBSITES, $websiteId) + $this->accountConfirmation->expects($this->once()) + ->method('isConfirmationRequired') + ->with($websiteId, $customerId, $customerEmail) ->willReturn($isConfirmationRequired); $this->confirmation->setData('name', 'confirmation'); diff --git a/app/code/Magento/Customer/Ui/Component/Listing/Column/Confirmation.php b/app/code/Magento/Customer/Ui/Component/Listing/Column/Confirmation.php index dcaaa665ad392e12f8a4bad3988a44e01a45c300..1786c52844a750ca8eba53335ddc1aa404faccd9 100644 --- a/app/code/Magento/Customer/Ui/Component/Listing/Column/Confirmation.php +++ b/app/code/Magento/Customer/Ui/Component/Listing/Column/Confirmation.php @@ -5,35 +5,42 @@ */ namespace Magento\Customer\Ui\Component\Listing\Column; -use Magento\Customer\Model\AccountManagement; use Magento\Framework\App\Config\ScopeConfigInterface; use Magento\Framework\View\Element\UiComponent\ContextInterface; use Magento\Framework\View\Element\UiComponentFactory; -use Magento\Store\Model\ScopeInterface; use Magento\Ui\Component\Listing\Columns\Column; +use Magento\Framework\App\ObjectManager; +use Magento\Customer\Model\AccountConfirmation; +/** + * Class Confirmation column. + */ class Confirmation extends Column { /** - * @var ScopeConfigInterface + * @var AccountConfirmation */ - private $scopeConfig; + private $accountConfirmation; /** * @param ContextInterface $context * @param UiComponentFactory $uiComponentFactory - * @param ScopeConfigInterface $scopeConfig + * @param ScopeConfigInterface $scopeConfig @deprecated * @param array $components * @param array $data + * @param AccountConfirmation $accountConfirmation + * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ public function __construct( ContextInterface $context, UiComponentFactory $uiComponentFactory, ScopeConfigInterface $scopeConfig, array $components, - array $data + array $data, + AccountConfirmation $accountConfirmation = null ) { - $this->scopeConfig = $scopeConfig; + $this->accountConfirmation = $accountConfirmation ?: ObjectManager::getInstance() + ->get(AccountConfirmation::class); parent::__construct($context, $uiComponentFactory, $components, $data); } @@ -58,7 +65,13 @@ class Confirmation extends Column */ private function getFieldLabel(array $item) { - if ($this->isConfirmationRequired($item)) { + $isConfirmationRequired = $this->accountConfirmation->isConfirmationRequired( + $item['website_id'][0], + $item[$item['id_field_name']], + $item['email'] + ); + + if ($isConfirmationRequired) { if ($item[$this->getData('name')] === null) { return __('Confirmed'); } @@ -66,19 +79,4 @@ class Confirmation extends Column } return __('Confirmation Not Required'); } - - /** - * Check if confirmation is required - * - * @param array $item - * @return bool - */ - private function isConfirmationRequired(array $item) - { - return (bool)$this->scopeConfig->getValue( - AccountManagement::XML_PATH_IS_CONFIRM, - ScopeInterface::SCOPE_WEBSITES, - $item['website_id'][0] - ); - } } diff --git a/app/code/Magento/Customer/etc/adminhtml/system.xml b/app/code/Magento/Customer/etc/adminhtml/system.xml index fa1566af0c9436cca2061221a7f0811434ba4034..31e968de14d99f49a6a7201141ca3567863366d2 100644 --- a/app/code/Magento/Customer/etc/adminhtml/system.xml +++ b/app/code/Magento/Customer/etc/adminhtml/system.xml @@ -210,7 +210,7 @@ <field id="prefix_options" translate="label comment" sortOrder="30" showInDefault="1" showInWebsite="1" showInStore="0"> <label>Prefix Dropdown Options</label> <comment> - <![CDATA[Semicolon (;) separated values.<br/>Put semicolon in the beginning for empty first option.<br/>Leave empty for open text field.]]> + <![CDATA[Semicolon (;) separated values.<br/>Leave empty for open text field.]]> </comment> </field> <field id="middlename_show" translate="label comment" type="select" sortOrder="40" showInDefault="1" showInWebsite="1" showInStore="0"> @@ -228,7 +228,7 @@ <field id="suffix_options" translate="label comment" sortOrder="60" showInDefault="1" showInWebsite="1" showInStore="0"> <label>Suffix Dropdown Options</label> <comment> - <![CDATA[Semicolon (;) separated values.<br/>Put semicolon in the beginning for empty first option.<br/>Leave empty for open text field.]]> + <![CDATA[Semicolon (;) separated values.<br/>Leave empty for open text field.]]> </comment> </field> <field id="dob_show" translate="label" type="select" sortOrder="70" showInDefault="1" showInWebsite="1" showInStore="0"> diff --git a/app/code/Magento/Customer/i18n/en_US.csv b/app/code/Magento/Customer/i18n/en_US.csv index aececbf6deeb4699c8db9cddcb54bf353324f553..8768426b5c9497c88e1ad53437e03a4ec10945c4 100644 --- a/app/code/Magento/Customer/i18n/en_US.csv +++ b/app/code/Magento/Customer/i18n/en_US.csv @@ -479,9 +479,9 @@ Strong,Strong "The title that goes before name (Mr., Mrs., etc.)","The title that goes before name (Mr., Mrs., etc.)" "Prefix Dropdown Options","Prefix Dropdown Options" " - Semicolon (;) separated values.<br/>Put semicolon in the beginning for empty first option.<br/>Leave empty for open text field. + Semicolon (;) separated values.<br/>Leave empty for open text field. "," - Semicolon (;) separated values.<br/>Put semicolon in the beginning for empty first option.<br/>Leave empty for open text field. + Semicolon (;) separated values.<br/>Leave empty for open text field. " "Show Middle Name (initial)","Show Middle Name (initial)" "Always optional.","Always optional." diff --git a/app/code/Magento/Developer/Model/XmlCatalog/Format/PhpStorm.php b/app/code/Magento/Developer/Model/XmlCatalog/Format/PhpStorm.php index 30684b7177c997f0d2b1ddf9bcf55ea9f28596f5..1ced906cce7637251778a877ceca14fbe1f69418 100644 --- a/app/code/Magento/Developer/Model/XmlCatalog/Format/PhpStorm.php +++ b/app/code/Magento/Developer/Model/XmlCatalog/Format/PhpStorm.php @@ -6,11 +6,12 @@ namespace Magento\Developer\Model\XmlCatalog\Format; +use Magento\Framework\App\ObjectManager; +use Magento\Framework\DomDocument\DomDocumentFactory; use Magento\Framework\Exception\FileSystemException; use Magento\Framework\Filesystem\Directory\ReadFactory; use Magento\Framework\Filesystem\Directory\ReadInterface; -use Magento\Framework\Filesystem\Directory\WriteFactory; -use Magento\Framework\Filesystem\Directory\WriteInterface; +use Magento\Framework\Filesystem\File\WriteFactory; /** * Class PhpStorm generates URN catalog for PhpStorm 9 @@ -23,20 +24,28 @@ class PhpStorm implements FormatInterface private $currentDirRead; /** - * @var \Magento\Framework\Filesystem\File\WriteFactory + * @var WriteFactory */ private $fileWriteFactory; + /** + * @var DomDocumentFactory + */ + private $domDocumentFactory; + /** * @param ReadFactory $readFactory - * @param \Magento\Framework\Filesystem\File\WriteFactory $fileWriteFactory + * @param WriteFactory $fileWriteFactory + * @param DomDocumentFactory $domDocumentFactory */ public function __construct( ReadFactory $readFactory, - \Magento\Framework\Filesystem\File\WriteFactory $fileWriteFactory + WriteFactory $fileWriteFactory, + DomDocumentFactory $domDocumentFactory = null ) { $this->currentDirRead = $readFactory->create(getcwd()); $this->fileWriteFactory = $fileWriteFactory; + $this->domDocumentFactory = $domDocumentFactory ?: ObjectManager::getInstance()->get(DomDocumentFactory::class); } /** @@ -57,26 +66,21 @@ class PhpStorm implements FormatInterface \Magento\Framework\Filesystem\DriverPool::FILE, 'r' ); - $dom = new \DOMDocument(); - $dom->loadXML($file->readAll()); + $dom = $this->domDocumentFactory->create(); + $fileContent = $file->readAll(); + if (!empty($fileContent)) { + $dom->loadXML($fileContent); + } else { + $this->initEmptyFile($dom); + } $xpath = new \DOMXPath($dom); $nodeList = $xpath->query('/project'); $projectNode = $nodeList->item(0); $file->close(); } catch (FileSystemException $f) { //create file if does not exists - $dom = new \DOMDocument(); - $projectNode = $dom->createElement('project'); - - //PhpStorm 9 version for component is "4" - $projectNode->setAttribute('version', '4'); - $dom->appendChild($projectNode); - $rootComponentNode = $dom->createElement('component'); - - //PhpStorm 9 version for ProjectRootManager is "2" - $rootComponentNode->setAttribute('version', '2'); - $rootComponentNode->setAttribute('name', 'ProjectRootManager'); - $projectNode->appendChild($rootComponentNode); + $dom = $this->domDocumentFactory->create(); + $projectNode = $this->initEmptyFile($dom); } $xpath = new \DOMXPath($dom); @@ -103,4 +107,26 @@ class PhpStorm implements FormatInterface $file->write($dom->saveXML()); $file->close(); } + + /** + * Setup basic empty dom elements + * + * @param \DOMDocument $dom + * @return \DOMElement + */ + private function initEmptyFile(\DOMDocument $dom) + { + $projectNode = $dom->createElement('project'); + + //PhpStorm 9 version for component is "4" + $projectNode->setAttribute('version', '4'); + $dom->appendChild($projectNode); + $rootComponentNode = $dom->createElement('component'); + + //PhpStorm 9 version for ProjectRootManager is "2" + $rootComponentNode->setAttribute('version', '2'); + $rootComponentNode->setAttribute('name', 'ProjectRootManager'); + $projectNode->appendChild($rootComponentNode); + return $projectNode; + } } diff --git a/app/code/Magento/Eav/Model/Attribute/GroupRepository.php b/app/code/Magento/Eav/Model/Attribute/GroupRepository.php index 9d0fa78668382d5c8b99641cbe844a66ad83c825..0714f8efac88cf6f6d51455267c99889f955793b 100644 --- a/app/code/Magento/Eav/Model/Attribute/GroupRepository.php +++ b/app/code/Magento/Eav/Model/Attribute/GroupRepository.php @@ -117,16 +117,6 @@ class GroupRepository implements \Magento\Eav\Api\AttributeGroupRepositoryInterf */ public function getList(\Magento\Framework\Api\SearchCriteriaInterface $searchCriteria) { - $attributeSetId = $this->retrieveAttributeSetIdFromSearchCriteria($searchCriteria); - if (!$attributeSetId) { - throw InputException::requiredField('attribute_set_id'); - } - try { - $this->setRepository->get($attributeSetId); - } catch (\Exception $exception) { - throw NoSuchEntityException::singleField('attributeSetId', $attributeSetId); - } - /** @var \Magento\Eav\Model\ResourceModel\Entity\Attribute\Group\Collection $collection */ $collection = $this->groupListFactory->create(); $this->joinProcessor->process($collection); @@ -188,6 +178,7 @@ class GroupRepository implements \Magento\Eav\Api\AttributeGroupRepositoryInterf /** * @param \Magento\Framework\Api\SearchCriteriaInterface $searchCriteria * @return null|string + * @deprecated */ protected function retrieveAttributeSetIdFromSearchCriteria( \Magento\Framework\Api\SearchCriteriaInterface $searchCriteria diff --git a/app/code/Magento/Eav/Test/Unit/Model/Attribute/GroupRepositoryTest.php b/app/code/Magento/Eav/Test/Unit/Model/Attribute/GroupRepositoryTest.php index c07122e049a7483515572b18b18f21d8573203b9..9b0f9704887bbd677830615d138e099fa4538b2d 100644 --- a/app/code/Magento/Eav/Test/Unit/Model/Attribute/GroupRepositoryTest.php +++ b/app/code/Magento/Eav/Test/Unit/Model/Attribute/GroupRepositoryTest.php @@ -266,8 +266,6 @@ class GroupRepositoryTest extends \PHPUnit\Framework\TestCase */ public function testGetList() { - $attributeSetId = 'filter'; - $filterInterfaceMock = $this->getMockBuilder(\Magento\Framework\Api\Search\FilterGroup::class) ->disableOriginalConstructor() ->setMethods([ @@ -275,24 +273,18 @@ class GroupRepositoryTest extends \PHPUnit\Framework\TestCase 'getValue', ]) ->getMock(); - $filterInterfaceMock->expects($this->once()) - ->method('getField') - ->willReturn('attribute_set_id'); - $filterInterfaceMock->expects($this->once()) - ->method('getValue') - ->willReturn($attributeSetId); $filterGroupMock = $this->getMockBuilder(\Magento\Framework\Api\Search\FilterGroup::class) ->disableOriginalConstructor() ->getMock(); - $filterGroupMock->expects($this->once()) + $filterGroupMock->expects($this->any()) ->method('getFilters') ->willReturn([$filterInterfaceMock]); $searchCriteriaMock = $this->getMockBuilder(\Magento\Framework\Api\SearchCriteriaInterface::class) ->disableOriginalConstructor() ->getMock(); - $searchCriteriaMock->expects($this->once()) + $searchCriteriaMock->expects($this->any()) ->method('getFilterGroups') ->willReturn([$filterGroupMock]); @@ -324,52 +316,6 @@ class GroupRepositoryTest extends \PHPUnit\Framework\TestCase $this->assertEquals($searchResultsMock, $this->model->getList($searchCriteriaMock)); } - /** - * Test get list with invalid input exception - * - * @expectedException \Magento\Framework\Exception\InputException - * @expectedExceptionMessage attribute_set_id is a required field. - * @throws \Magento\Framework\Exception\InputException - * @throws \Magento\Framework\Exception\NoSuchEntityException - * @return void - */ - public function testGetListWithInvalidInputException() - { - $searchCriteriaMock = $this->createMock(\Magento\Framework\Api\SearchCriteriaInterface::class); - $searchCriteriaMock->expects($this->once())->method('getFilterGroups')->willReturn([]); - $this->model->getList($searchCriteriaMock); - } - - /** - * Test get list with no such entity exception - * - * @expectedException \Magento\Framework\Exception\NoSuchEntityException - * @expectedExceptionMessage No such entity with attributeSetId = filter - * @throws \Magento\Framework\Exception\InputException - * @throws \Magento\Framework\Exception\NoSuchEntityException - * @return void - */ - public function testGetListWithNoSuchEntityException() - { - $attributeSetId = 'filter'; - $searchCriteriaMock = $this->createMock(\Magento\Framework\Api\SearchCriteriaInterface::class); - $filterGroupMock = $this->createMock(\Magento\Framework\Api\Search\FilterGroup::class); - $filterInterfaceMock = $this->createMock(\Magento\Framework\Api\Filter::class); - - $searchCriteriaMock->expects($this->once())->method('getFilterGroups')->willReturn([$filterGroupMock]); - - $filterGroupMock->expects($this->once())->method('getFilters')->willReturn([$filterInterfaceMock]); - $filterInterfaceMock->expects($this->once())->method('getField')->willReturn('attribute_set_id'); - $filterInterfaceMock->expects($this->once())->method('getValue')->willReturn($attributeSetId); - - $searchCriteriaMock->expects($this->once())->method('getFilterGroups')->willReturn([]); - $this->setRepositoryMock->expects($this->once()) - ->method('get') - ->with($attributeSetId) - ->willThrowException(new \Exception()); - $this->model->getList($searchCriteriaMock); - } - /** * Test get * diff --git a/app/code/Magento/Newsletter/Model/Subscriber.php b/app/code/Magento/Newsletter/Model/Subscriber.php index cc143fdc52e3b4466be0a293b67d7fb85f31ec1e..b8d7ccf83af7ccc29a6e322e769cd39b267030d5 100644 --- a/app/code/Magento/Newsletter/Model/Subscriber.php +++ b/app/code/Magento/Newsletter/Model/Subscriber.php @@ -633,6 +633,8 @@ class Subscriber extends \Magento\Framework\Model\AbstractModel $this->setStatus(self::STATUS_SUBSCRIBED) ->setStatusChanged(true) ->save(); + + $this->sendConfirmationSuccessEmail(); return true; } diff --git a/app/code/Magento/Newsletter/Test/Unit/Model/SubscriberTest.php b/app/code/Magento/Newsletter/Test/Unit/Model/SubscriberTest.php index 5a4032dc4dffd8361f385e0b88c7e35cc0727531..7dd96be11bcbe8b7db60f83fc19e77453f5e6eee 100644 --- a/app/code/Magento/Newsletter/Test/Unit/Model/SubscriberTest.php +++ b/app/code/Magento/Newsletter/Test/Unit/Model/SubscriberTest.php @@ -341,6 +341,21 @@ class SubscriberTest extends \PHPUnit\Framework\TestCase $code = 111; $this->subscriber->setCode($code); $this->resource->expects($this->once())->method('save')->willReturnSelf(); + $storeModel = $this->getMockBuilder(\Magento\Store\Model\Store::class) + ->disableOriginalConstructor() + ->setMethods(['getId']) + ->getMock(); + $transport = $this->createMock(\Magento\Framework\Mail\TransportInterface::class); + $this->scopeConfig->expects($this->any())->method('getValue')->willReturn(true); + $this->transportBuilder->expects($this->once())->method('setTemplateIdentifier')->willReturnSelf(); + $this->transportBuilder->expects($this->once())->method('setTemplateOptions')->willReturnSelf(); + $this->transportBuilder->expects($this->once())->method('setTemplateVars')->willReturnSelf(); + $this->transportBuilder->expects($this->once())->method('setFrom')->willReturnSelf(); + $this->transportBuilder->expects($this->once())->method('addTo')->willReturnSelf(); + $this->storeManager->expects($this->any())->method('getStore')->willReturn($storeModel); + $storeModel->expects($this->any())->method('getId')->willReturn(1); + $this->transportBuilder->expects($this->once())->method('getTransport')->willReturn($transport); + $transport->expects($this->once())->method('sendMessage')->willReturnSelf(); $this->assertTrue($this->subscriber->confirm($code)); } diff --git a/app/code/Magento/Sales/Model/Order/Pdf/AbstractPdf.php b/app/code/Magento/Sales/Model/Order/Pdf/AbstractPdf.php index 850e9cf08413bc795ee6759335c16963f63e63c7..1a25ff7bfdb80ffd079669adcdb3ea421e9ee6b1 100644 --- a/app/code/Magento/Sales/Model/Order/Pdf/AbstractPdf.php +++ b/app/code/Magento/Sales/Model/Order/Pdf/AbstractPdf.php @@ -953,7 +953,7 @@ abstract class AbstractPdf extends \Magento\Framework\DataObject * feed int; x position (required) * font string; font style, optional: bold, italic, regular * font_file string; path to font file (optional for use your custom font) - * font_size int; font size (default 7) + * font_size int; font size (default 10) * align string; text align (also see feed parametr), optional left, right * height int;line spacing (default 10) * @@ -1005,24 +1005,8 @@ abstract class AbstractPdf extends \Magento\Framework\DataObject foreach ($lines as $line) { $maxHeight = 0; foreach ($line as $column) { - $fontSize = empty($column['font_size']) ? 10 : $column['font_size']; - if (!empty($column['font_file'])) { - $font = \Zend_Pdf_Font::fontWithPath($column['font_file']); - $page->setFont($font, $fontSize); - } else { - $fontStyle = empty($column['font']) ? 'regular' : $column['font']; - switch ($fontStyle) { - case 'bold': - $font = $this->_setFontBold($page, $fontSize); - break; - case 'italic': - $font = $this->_setFontItalic($page, $fontSize); - break; - default: - $font = $this->_setFontRegular($page, $fontSize); - break; - } - } + $font = $this->setFont($page, $column); + $fontSize = $column['font_size']; if (!is_array($column['text'])) { $column['text'] = [$column['text']]; @@ -1033,6 +1017,8 @@ abstract class AbstractPdf extends \Magento\Framework\DataObject foreach ($column['text'] as $part) { if ($this->y - $lineSpacing < 15) { $page = $this->newPage($pageSettings); + $font = $this->setFont($page, $column); + $fontSize = $column['font_size']; } $feed = $column['feed']; @@ -1066,4 +1052,42 @@ abstract class AbstractPdf extends \Magento\Framework\DataObject return $page; } + + /** + * Set page font. + * + * column array format + * font string; font style, optional: bold, italic, regular + * font_file string; path to font file (optional for use your custom font) + * font_size int; font size (default 10) + * + * @param \Zend_Pdf_Page $page + * @param array $column + * @return \Zend_Pdf_Resource_Font + * @throws \Zend_Pdf_Exception + */ + private function setFont($page, &$column) + { + $fontSize = empty($column['font_size']) ? 10 : $column['font_size']; + $column['font_size'] = $fontSize; + if (!empty($column['font_file'])) { + $font = \Zend_Pdf_Font::fontWithPath($column['font_file']); + $page->setFont($font, $fontSize); + } else { + $fontStyle = empty($column['font']) ? 'regular' : $column['font']; + switch ($fontStyle) { + case 'bold': + $font = $this->_setFontBold($page, $fontSize); + break; + case 'italic': + $font = $this->_setFontItalic($page, $fontSize); + break; + default: + $font = $this->_setFontRegular($page, $fontSize); + break; + } + } + + return $font; + } } diff --git a/dev/tests/integration/testsuite/Magento/Cms/Model/BlockTest.php b/dev/tests/integration/testsuite/Magento/Cms/Model/BlockTest.php new file mode 100644 index 0000000000000000000000000000000000000000..9b2bb67c55da1de625657b4cb862a5ceb3b92816 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Cms/Model/BlockTest.php @@ -0,0 +1,90 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Cms\Model; + +use Magento\Cms\Api\BlockRepositoryInterface; +use Magento\Cms\Model\BlockFactory; +use Magento\Cms\Model\ResourceModel\Block; +use Magento\Framework\ObjectManagerInterface; +use Magento\Framework\Stdlib\DateTime\DateTime; +use Magento\TestFramework\Helper\Bootstrap; +use PHPUnit\Framework\TestCase; + +/** + * @magentoAppArea adminhtml + */ +class BlockTest extends TestCase +{ + /** + * @var ObjectManagerInterface + */ + private $objectManager; + + /** + * @var Block + */ + private $blockResource; + + /** + * @var BlockFactory + */ + private $blockFactory; + + /** + * @var BlockRepositoryInterface + */ + private $blockRepository; + + protected function setUp() + { + $this->objectManager = Bootstrap::getObjectManager(); + + /** @var BlockFactory $blockFactory */ + /** @var Block $blockResource */ + $this->blockResource = $this->objectManager->create(Block::class); + $this->blockFactory = $this->objectManager->create(BlockFactory::class); + $this->blockRepository = $this->objectManager->create(BlockRepositoryInterface::class); + } + + /** + * Test UpdateTime + * @param array $blockData + * @throws \Exception + * @magentoDbIsolation enabled + * @dataProvider testUpdateTimeDataProvider + */ + public function testUpdateTime(array $blockData) + { + # Prepare and save the temporary block + $tempBlock = $this->blockFactory->create(); + $tempBlock->setData($blockData); + $this->blockResource->save($tempBlock); + + # Load previously created block and compare update_time field + $block = $this->blockRepository->getById($tempBlock->getId()); + $date = $this->objectManager->get(DateTime::class)->date(); + $this->assertEquals($date, $block->getUpdateTime()); + } + + /** + * Data provider "testUpdateTime" method + * @return array + */ + public function testUpdateTimeDataProvider() + { + return [ + [ + 'data' => [ + 'title' => 'Test title', + 'stores' => [0], + 'identifier' => 'test-identifier', + 'content' => 'Test content', + 'is_active' => 1 + ] + ] + ]; + } +} diff --git a/dev/tests/integration/testsuite/Magento/Cms/Model/PageTest.php b/dev/tests/integration/testsuite/Magento/Cms/Model/PageTest.php index 7a04ddce8fa083e35f1069db561741a1d54213e7..c8040861b08ebb2a37b59741846dbc76607a03f6 100644 --- a/dev/tests/integration/testsuite/Magento/Cms/Model/PageTest.php +++ b/dev/tests/integration/testsuite/Magento/Cms/Model/PageTest.php @@ -6,17 +6,13 @@ namespace Magento\Cms\Model; use Magento\Cms\Api\PageRepositoryInterface; +use Magento\Framework\Stdlib\DateTime\DateTime; /** * @magentoAppArea adminhtml */ class PageTest extends \PHPUnit\Framework\TestCase { - /** - * @var \Magento\Cms\Model\Page - */ - protected $model; - protected function setUp() { $user = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( @@ -51,15 +47,14 @@ class PageTest extends \PHPUnit\Framework\TestCase */ public function testUpdateTime() { - $updateTime = '2016-09-01 00:00:00'; $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); /** @var \Magento\Cms\Model\Page $page */ $page = $objectManager->create(\Magento\Cms\Model\Page::class); $page->setData(['title' => 'Test', 'stores' => [1]]); - $page->setUpdateTime($updateTime); $page->save(); $page = $objectManager->get(PageRepositoryInterface::class)->getById($page->getId()); - $this->assertEquals($updateTime, $page->getUpdateTime()); + $date = $objectManager->get(DateTime::class)->date(); + $this->assertEquals($date, $page->getUpdateTime()); } public function generateIdentifierFromTitleDataProvider() diff --git a/dev/tests/integration/testsuite/Magento/Sales/Model/Order/Pdf/AbstractPdfTest.php b/dev/tests/integration/testsuite/Magento/Sales/Model/Order/Pdf/AbstractPdfTest.php new file mode 100644 index 0000000000000000000000000000000000000000..a70d4a3b6f0c1fe313a8df65982f87e9c8b22ef5 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Sales/Model/Order/Pdf/AbstractPdfTest.php @@ -0,0 +1,86 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Sales\Model\Order\Pdf; + +use PHPUnit_Framework_MockObject_MockObject as MockObject; + +/** + * Tests Sales Order PDF abstract model. + * + * @see \Magento\Sales\Model\Order\Pdf\AbstarctPdf + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ +class AbstractPdfTest extends \PHPUnit\Framework\TestCase +{ + /** + * Tests Draw lines method. + * Test case when text block cover more than one page. + */ + public function testDrawLineBlocks() + { + $objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager(); + + // Setup most constructor dependencies + $paymentData = $objectManager->create(\Magento\Payment\Helper\Data::class); + $string = $objectManager->create(\Magento\Framework\Stdlib\StringUtils::class); + $scopeConfig = $objectManager->create(\Magento\Framework\App\Config\ScopeConfigInterface::class); + $filesystem = $objectManager->create(\Magento\Framework\Filesystem::class); + $config = $objectManager->create(\Magento\Sales\Model\Order\Pdf\Config::class); + $pdfTotalFactory = $objectManager->create(\Magento\Sales\Model\Order\Pdf\Total\Factory::class); + $pdfItemsFactory = $objectManager->create(\Magento\Sales\Model\Order\Pdf\ItemsFactory::class); + $locale = $objectManager->create(\Magento\Framework\Stdlib\DateTime\TimezoneInterface::class); + $translate = $objectManager->create(\Magento\Framework\Translate\Inline\StateInterface::class); + $addressRenderer = $objectManager->create(\Magento\Sales\Model\Order\Address\Renderer::class); + + // Test model + /** @var \Magento\Sales\Model\Order\Pdf\AbstractPdf|MockObject $model */ + $model = $this->getMockForAbstractClass( + \Magento\Sales\Model\Order\Pdf\AbstractPdf::class, + [ + $paymentData, + $string, + $scopeConfig, + $filesystem, + $config, + $pdfTotalFactory, + $pdfItemsFactory, + $locale, + $translate, + $addressRenderer, + ], + '', + true, + true, + true, + ['getPdf', '_getPdf'] + ); + $pdf = new \Zend_Pdf(); + $model->expects($this->any())->method('getPdf')->will($this->returnValue($pdf)); + $model->expects($this->any())->method('_getPdf')->will($this->returnValue($pdf)); + + /** Generate multiline block, that cover more than one page */ + $lines = []; + for ($lineNumber = 1; $lineNumber <= 100; $lineNumber++) { + $lines[] = [[ + 'feed' => 0, + 'font_size' => 10, + 'text' => 'Text line ' . $lineNumber, + ]]; + } + $draw = [[ + 'height' => 12, + 'lines' => $lines, + ]]; + + $page = $model->newPage(['page_size' => \Zend_Pdf_Page::SIZE_A4]); + + $model->drawLineBlocks($page, $draw); + $this->assertEquals( + 3, + count($pdf->pages) + ); + } +} diff --git a/lib/internal/Magento/Framework/DomDocument/DomDocumentFactory.php b/lib/internal/Magento/Framework/DomDocument/DomDocumentFactory.php index 677e4d654e52c4334b4bee2775805a86afa3aa7e..d2e16700bc904fdbac6b5596a6c09baf50777f8a 100644 --- a/lib/internal/Magento/Framework/DomDocument/DomDocumentFactory.php +++ b/lib/internal/Magento/Framework/DomDocument/DomDocumentFactory.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\Framework\DomDocument; /** diff --git a/lib/internal/Magento/Framework/Test/Unit/DomDocument/DomDocumentFactoryTest.php b/lib/internal/Magento/Framework/Test/Unit/DomDocument/DomDocumentFactoryTest.php new file mode 100644 index 0000000000000000000000000000000000000000..e3ea74339e0436567166a6520f31e06b45563a47 --- /dev/null +++ b/lib/internal/Magento/Framework/Test/Unit/DomDocument/DomDocumentFactoryTest.php @@ -0,0 +1,21 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Framework\Test\Unit\DomDocument; + +use Magento\Framework\DomDocument\DomDocumentFactory; + +class DomDocumentFactoryTest extends \PHPUnit\Framework\TestCase +{ + public function testCreateReturnsDomDocument() + { + $domDocumentFactory = new DomDocumentFactory(); + $this->assertInstanceOf( + \DOMDocument::class, + $domDocumentFactory->create() + ); + } +}