diff --git a/app/code/Magento/Backend/Test/Mftf/Data/GeneralLocalConfigsData.xml b/app/code/Magento/Backend/Test/Mftf/Data/GeneralLocalConfigsData.xml index 22d595c39407f..0477befccc06e 100644 --- a/app/code/Magento/Backend/Test/Mftf/Data/GeneralLocalConfigsData.xml +++ b/app/code/Magento/Backend/Test/Mftf/Data/GeneralLocalConfigsData.xml @@ -20,4 +20,10 @@ base en_US + + general/locale/code + websites + base + es_MX + diff --git a/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/AdminCatalogPriceRuleDeleteAllActionGroup.xml b/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/AdminCatalogPriceRuleDeleteAllActionGroup.xml new file mode 100644 index 0000000000000..1170b08b1add9 --- /dev/null +++ b/app/code/Magento/CatalogRule/Test/Mftf/ActionGroup/AdminCatalogPriceRuleDeleteAllActionGroup.xml @@ -0,0 +1,29 @@ + + + + + + Open Catalog Price Rule grid and delete all rules one by one. Need to avoid interference with other tests that test catalog price rules. + + + + + + + + {{AdminDataGridTableSection.firstNotEmptyRow}} + {{AdminConfirmationModalSection.ok}} + {{AdminMainActionsSection.delete}} + {{AdminMessagesSection.success}} + You deleted the rule. + + + + + diff --git a/app/code/Magento/CatalogRule/Test/Mftf/Helper/CatalogPriceRuleHelper.php b/app/code/Magento/CatalogRule/Test/Mftf/Helper/CatalogPriceRuleHelper.php new file mode 100644 index 0000000000000..2119f5c6ca45d --- /dev/null +++ b/app/code/Magento/CatalogRule/Test/Mftf/Helper/CatalogPriceRuleHelper.php @@ -0,0 +1,62 @@ +getModule('\Magento\FunctionalTestingFramework\Module\MagentoWebDriver'); + /** @var FacebookWebDriver $webDriver */ + $webDriver = $magentoWebDriver->webDriver; + $rows = $webDriver->findElements(WebDriverBy::cssSelector($firstNotEmptyRow)); + while (!empty($rows)) { + $rows[0]->click(); + $magentoWebDriver->waitForPageLoad(30); + $magentoWebDriver->click($deleteButton); + $magentoWebDriver->waitForPageLoad(30); + $magentoWebDriver->waitForElementVisible($modalAcceptButton, 10); + $magentoWebDriver->waitForPageLoad(60); + $magentoWebDriver->click($modalAcceptButton); + $magentoWebDriver->waitForPageLoad(60); + $magentoWebDriver->waitForLoadingMaskToDisappear(); + $magentoWebDriver->waitForElementVisible($successMessageContainer, 10); + $magentoWebDriver->see($successMessage, $successMessageContainer); + $rows = $webDriver->findElements(WebDriverBy::cssSelector($firstNotEmptyRow)); + } + } catch (\Exception $e) { + $this->fail($e->getMessage()); + } + } +} diff --git a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontApplyPromoCodeDuringCheckoutTest.xml b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontApplyPromoCodeDuringCheckoutTest.xml index 3648ac361ccc9..4320eb8e6160f 100644 --- a/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontApplyPromoCodeDuringCheckoutTest.xml +++ b/app/code/Magento/Checkout/Test/Mftf/Test/StorefrontApplyPromoCodeDuringCheckoutTest.xml @@ -29,21 +29,23 @@ + + + - - + - + @@ -56,16 +58,18 @@ - + + + @@ -76,16 +80,13 @@ - - - - + - + diff --git a/app/code/Magento/CurrencySymbol/Test/Mftf/Data/CurrencyRatesConfigData.xml b/app/code/Magento/CurrencySymbol/Test/Mftf/Data/CurrencyRatesConfigData.xml index 6194287dd058b..d22430e3c0218 100644 --- a/app/code/Magento/CurrencySymbol/Test/Mftf/Data/CurrencyRatesConfigData.xml +++ b/app/code/Magento/CurrencySymbol/Test/Mftf/Data/CurrencyRatesConfigData.xml @@ -20,6 +20,36 @@ websites base + + currency/options/base + JPY + websites + base + + + currency/options/base + CAD + websites + base + + + currency/options/base + AUD + websites + base + + + currency/options/base + HKD + websites + base + + + currency/options/base + NZD + websites + base + currency/options/allow USD @@ -32,6 +62,36 @@ websites base + + currency/options/allow + JPY + websites + base + + + currency/options/allow + CAD + websites + base + + + currency/options/allow + AUD + websites + base + + + currency/options/allow + HKD + websites + base + + + currency/options/allow + NZD + websites + base + currency/options/allow RUB @@ -44,6 +104,36 @@ websites base + + currency/options/default + JPY + websites + base + + + currency/options/default + CAD + websites + base + + + currency/options/default + AUD + websites + base + + + currency/options/default + HKD + websites + base + + + currency/options/default + NZD + websites + base + currency/options/default USD diff --git a/app/code/Magento/Customer/Test/Mftf/ActionGroup/SignUpNewUserFromStorefrontActionGroup.xml b/app/code/Magento/Customer/Test/Mftf/ActionGroup/SignUpNewUserFromStorefrontActionGroup.xml index 56afa8854ce0d..e4b07e44c0306 100644 --- a/app/code/Magento/Customer/Test/Mftf/ActionGroup/SignUpNewUserFromStorefrontActionGroup.xml +++ b/app/code/Magento/Customer/Test/Mftf/ActionGroup/SignUpNewUserFromStorefrontActionGroup.xml @@ -24,6 +24,7 @@ + diff --git a/app/code/Magento/LoginAsCustomer/Cron/DeleteExpiredAuthenticationData.php b/app/code/Magento/LoginAsCustomer/Cron/DeleteExpiredAuthenticationData.php new file mode 100644 index 0000000000000..5acb602491f0b --- /dev/null +++ b/app/code/Magento/LoginAsCustomer/Cron/DeleteExpiredAuthenticationData.php @@ -0,0 +1,49 @@ +deleteOldSecretsProcessor = $deleteOldSecretsProcessor; + $this->config = $config; + } + + /** + * Delete expired authentication data + */ + public function execute(): void + { + if ($this->config->isEnabled()) { + $this->deleteOldSecretsProcessor->execute(); + } + } +} diff --git a/app/code/Magento/LoginAsCustomer/LICENSE.txt b/app/code/Magento/LoginAsCustomer/LICENSE.txt new file mode 100644 index 0000000000000..49525fd99da9c --- /dev/null +++ b/app/code/Magento/LoginAsCustomer/LICENSE.txt @@ -0,0 +1,48 @@ + +Open Software License ("OSL") v. 3.0 + +This Open Software License (the "License") applies to any original work of authorship (the "Original Work") whose owner (the "Licensor") has placed the following licensing notice adjacent to the copyright notice for the Original Work: + +Licensed under the Open Software License version 3.0 + + 1. Grant of Copyright License. Licensor grants You a worldwide, royalty-free, non-exclusive, sublicensable license, for the duration of the copyright, to do the following: + + 1. to reproduce the Original Work in copies, either alone or as part of a collective work; + + 2. to translate, adapt, alter, transform, modify, or arrange the Original Work, thereby creating derivative works ("Derivative Works") based upon the Original Work; + + 3. to distribute or communicate copies of the Original Work and Derivative Works to the public, with the proviso that copies of Original Work or Derivative Works that You distribute or communicate shall be licensed under this Open Software License; + + 4. to perform the Original Work publicly; and + + 5. to display the Original Work publicly. + + 2. Grant of Patent License. Licensor grants You a worldwide, royalty-free, non-exclusive, sublicensable license, under patent claims owned or controlled by the Licensor that are embodied in the Original Work as furnished by the Licensor, for the duration of the patents, to make, use, sell, offer for sale, have made, and import the Original Work and Derivative Works. + + 3. Grant of Source Code License. The term "Source Code" means the preferred form of the Original Work for making modifications to it and all available documentation describing how to modify the Original Work. Licensor agrees to provide a machine-readable copy of the Source Code of the Original Work along with each copy of the Original Work that Licensor distributes. Licensor reserves the right to satisfy this obligation by placing a machine-readable copy of the Source Code in an information repository reasonably calculated to permit inexpensive and convenient access by You for as long as Licensor continues to distribute the Original Work. + + 4. Exclusions From License Grant. Neither the names of Licensor, nor the names of any contributors to the Original Work, nor any of their trademarks or service marks, may be used to endorse or promote products derived from this Original Work without express prior permission of the Licensor. Except as expressly stated herein, nothing in this License grants any license to Licensor's trademarks, copyrights, patents, trade secrets or any other intellectual property. No patent license is granted to make, use, sell, offer for sale, have made, or import embodiments of any patent claims other than the licensed claims defined in Section 2. No license is granted to the trademarks of Licensor even if such marks are included in the Original Work. Nothing in this License shall be interpreted to prohibit Licensor from licensing under terms different from this License any Original Work that Licensor otherwise would have a right to license. + + 5. External Deployment. The term "External Deployment" means the use, distribution, or communication of the Original Work or Derivative Works in any way such that the Original Work or Derivative Works may be used by anyone other than You, whether those works are distributed or communicated to those persons or made available as an application intended for use over a network. As an express condition for the grants of license hereunder, You must treat any External Deployment by You of the Original Work or a Derivative Work as a distribution under section 1(c). + + 6. Attribution Rights. You must retain, in the Source Code of any Derivative Works that You create, all copyright, patent, or trademark notices from the Source Code of the Original Work, as well as any notices of licensing and any descriptive text identified therein as an "Attribution Notice." You must cause the Source Code for any Derivative Works that You create to carry a prominent Attribution Notice reasonably calculated to inform recipients that You have modified the Original Work. + + 7. Warranty of Provenance and Disclaimer of Warranty. Licensor warrants that the copyright in and to the Original Work and the patent rights granted herein by Licensor are owned by the Licensor or are sublicensed to You under the terms of this License with the permission of the contributor(s) of those copyrights and patent rights. Except as expressly stated in the immediately preceding sentence, the Original Work is provided under this License on an "AS IS" BASIS and WITHOUT WARRANTY, either express or implied, including, without limitation, the warranties of non-infringement, merchantability or fitness for a particular purpose. THE ENTIRE RISK AS TO THE QUALITY OF THE ORIGINAL WORK IS WITH YOU. This DISCLAIMER OF WARRANTY constitutes an essential part of this License. No license to the Original Work is granted by this License except under this disclaimer. + + 8. Limitation of Liability. Under no circumstances and under no legal theory, whether in tort (including negligence), contract, or otherwise, shall the Licensor be liable to anyone for any indirect, special, incidental, or consequential damages of any character arising as a result of this License or the use of the Original Work including, without limitation, damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses. This limitation of liability shall not apply to the extent applicable law prohibits such limitation. + + 9. Acceptance and Termination. If, at any time, You expressly assented to this License, that assent indicates your clear and irrevocable acceptance of this License and all of its terms and conditions. If You distribute or communicate copies of the Original Work or a Derivative Work, You must make a reasonable effort under the circumstances to obtain the express assent of recipients to the terms of this License. This License conditions your rights to undertake the activities listed in Section 1, including your right to create Derivative Works based upon the Original Work, and doing so without honoring these terms and conditions is prohibited by copyright law and international treaty. Nothing in this License is intended to affect copyright exceptions and limitations (including 'fair use' or 'fair dealing'). This License shall terminate immediately and You may no longer exercise any of the rights granted to You by this License upon your failure to honor the conditions in Section 1(c). + + 10. Termination for Patent Action. This License shall terminate automatically and You may no longer exercise any of the rights granted to You by this License as of the date You commence an action, including a cross-claim or counterclaim, against Licensor or any licensee alleging that the Original Work infringes a patent. This termination provision shall not apply for an action alleging patent infringement by combinations of the Original Work with other software or hardware. + + 11. Jurisdiction, Venue and Governing Law. Any action or suit relating to this License may be brought only in the courts of a jurisdiction wherein the Licensor resides or in which Licensor conducts its primary business, and under the laws of that jurisdiction excluding its conflict-of-law provisions. The application of the United Nations Convention on Contracts for the International Sale of Goods is expressly excluded. Any use of the Original Work outside the scope of this License or after its termination shall be subject to the requirements and penalties of copyright or patent law in the appropriate jurisdiction. This section shall survive the termination of this License. + + 12. Attorneys' Fees. In any action to enforce the terms of this License or seeking damages relating thereto, the prevailing party shall be entitled to recover its costs and expenses, including, without limitation, reasonable attorneys' fees and costs incurred in connection with such action, including any appeal of such action. This section shall survive the termination of this License. + + 13. Miscellaneous. If any provision of this License is held to be unenforceable, such provision shall be reformed only to the extent necessary to make it enforceable. + + 14. Definition of "You" in This License. "You" throughout this License, whether in upper or lower case, means an individual or a legal entity exercising rights under, and complying with all of the terms of, this License. For legal entities, "You" includes any entity that controls, is controlled by, or is under common control with you. For purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + + 15. Right to Use. You may use the Original Work in all ways not otherwise restricted or conditioned by this License or by law, and Licensor promises not to interfere with or be responsible for such uses by You. + + 16. Modification of This License. This License is Copyright (C) 2005 Lawrence Rosen. Permission is granted to copy, distribute, or communicate this License without modification. Nothing in this License permits You to modify this License as applied to the Original Work or to Derivative Works. However, You may modify the text of this License and copy, distribute or communicate your modified version (the "Modified License") and apply it to other original works of authorship subject to the following conditions: (i) You may not indicate in any way that your Modified License is the "Open Software License" or "OSL" and you may not use those names in the name of your Modified License; (ii) You must replace the notice specified in the first paragraph above with the notice "Licensed under " or with a notice of your own that is not confusingly similar to the notice in this License; and (iii) You may not claim that your original works are open source software unless your Modified License has been approved by Open Source Initiative (OSI) and You comply with its license review and certification process. \ No newline at end of file diff --git a/app/code/Magento/LoginAsCustomer/LICENSE_AFL.txt b/app/code/Magento/LoginAsCustomer/LICENSE_AFL.txt new file mode 100644 index 0000000000000..f39d641b18a19 --- /dev/null +++ b/app/code/Magento/LoginAsCustomer/LICENSE_AFL.txt @@ -0,0 +1,48 @@ + +Academic Free License ("AFL") v. 3.0 + +This Academic Free License (the "License") applies to any original work of authorship (the "Original Work") whose owner (the "Licensor") has placed the following licensing notice adjacent to the copyright notice for the Original Work: + +Licensed under the Academic Free License version 3.0 + + 1. Grant of Copyright License. Licensor grants You a worldwide, royalty-free, non-exclusive, sublicensable license, for the duration of the copyright, to do the following: + + 1. to reproduce the Original Work in copies, either alone or as part of a collective work; + + 2. to translate, adapt, alter, transform, modify, or arrange the Original Work, thereby creating derivative works ("Derivative Works") based upon the Original Work; + + 3. to distribute or communicate copies of the Original Work and Derivative Works to the public, under any license of your choice that does not contradict the terms and conditions, including Licensor's reserved rights and remedies, in this Academic Free License; + + 4. to perform the Original Work publicly; and + + 5. to display the Original Work publicly. + + 2. Grant of Patent License. Licensor grants You a worldwide, royalty-free, non-exclusive, sublicensable license, under patent claims owned or controlled by the Licensor that are embodied in the Original Work as furnished by the Licensor, for the duration of the patents, to make, use, sell, offer for sale, have made, and import the Original Work and Derivative Works. + + 3. Grant of Source Code License. The term "Source Code" means the preferred form of the Original Work for making modifications to it and all available documentation describing how to modify the Original Work. Licensor agrees to provide a machine-readable copy of the Source Code of the Original Work along with each copy of the Original Work that Licensor distributes. Licensor reserves the right to satisfy this obligation by placing a machine-readable copy of the Source Code in an information repository reasonably calculated to permit inexpensive and convenient access by You for as long as Licensor continues to distribute the Original Work. + + 4. Exclusions From License Grant. Neither the names of Licensor, nor the names of any contributors to the Original Work, nor any of their trademarks or service marks, may be used to endorse or promote products derived from this Original Work without express prior permission of the Licensor. Except as expressly stated herein, nothing in this License grants any license to Licensor's trademarks, copyrights, patents, trade secrets or any other intellectual property. No patent license is granted to make, use, sell, offer for sale, have made, or import embodiments of any patent claims other than the licensed claims defined in Section 2. No license is granted to the trademarks of Licensor even if such marks are included in the Original Work. Nothing in this License shall be interpreted to prohibit Licensor from licensing under terms different from this License any Original Work that Licensor otherwise would have a right to license. + + 5. External Deployment. The term "External Deployment" means the use, distribution, or communication of the Original Work or Derivative Works in any way such that the Original Work or Derivative Works may be used by anyone other than You, whether those works are distributed or communicated to those persons or made available as an application intended for use over a network. As an express condition for the grants of license hereunder, You must treat any External Deployment by You of the Original Work or a Derivative Work as a distribution under section 1(c). + + 6. Attribution Rights. You must retain, in the Source Code of any Derivative Works that You create, all copyright, patent, or trademark notices from the Source Code of the Original Work, as well as any notices of licensing and any descriptive text identified therein as an "Attribution Notice." You must cause the Source Code for any Derivative Works that You create to carry a prominent Attribution Notice reasonably calculated to inform recipients that You have modified the Original Work. + + 7. Warranty of Provenance and Disclaimer of Warranty. Licensor warrants that the copyright in and to the Original Work and the patent rights granted herein by Licensor are owned by the Licensor or are sublicensed to You under the terms of this License with the permission of the contributor(s) of those copyrights and patent rights. Except as expressly stated in the immediately preceding sentence, the Original Work is provided under this License on an "AS IS" BASIS and WITHOUT WARRANTY, either express or implied, including, without limitation, the warranties of non-infringement, merchantability or fitness for a particular purpose. THE ENTIRE RISK AS TO THE QUALITY OF THE ORIGINAL WORK IS WITH YOU. This DISCLAIMER OF WARRANTY constitutes an essential part of this License. No license to the Original Work is granted by this License except under this disclaimer. + + 8. Limitation of Liability. Under no circumstances and under no legal theory, whether in tort (including negligence), contract, or otherwise, shall the Licensor be liable to anyone for any indirect, special, incidental, or consequential damages of any character arising as a result of this License or the use of the Original Work including, without limitation, damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses. This limitation of liability shall not apply to the extent applicable law prohibits such limitation. + + 9. Acceptance and Termination. If, at any time, You expressly assented to this License, that assent indicates your clear and irrevocable acceptance of this License and all of its terms and conditions. If You distribute or communicate copies of the Original Work or a Derivative Work, You must make a reasonable effort under the circumstances to obtain the express assent of recipients to the terms of this License. This License conditions your rights to undertake the activities listed in Section 1, including your right to create Derivative Works based upon the Original Work, and doing so without honoring these terms and conditions is prohibited by copyright law and international treaty. Nothing in this License is intended to affect copyright exceptions and limitations (including "fair use" or "fair dealing"). This License shall terminate immediately and You may no longer exercise any of the rights granted to You by this License upon your failure to honor the conditions in Section 1(c). + + 10. Termination for Patent Action. This License shall terminate automatically and You may no longer exercise any of the rights granted to You by this License as of the date You commence an action, including a cross-claim or counterclaim, against Licensor or any licensee alleging that the Original Work infringes a patent. This termination provision shall not apply for an action alleging patent infringement by combinations of the Original Work with other software or hardware. + + 11. Jurisdiction, Venue and Governing Law. Any action or suit relating to this License may be brought only in the courts of a jurisdiction wherein the Licensor resides or in which Licensor conducts its primary business, and under the laws of that jurisdiction excluding its conflict-of-law provisions. The application of the United Nations Convention on Contracts for the International Sale of Goods is expressly excluded. Any use of the Original Work outside the scope of this License or after its termination shall be subject to the requirements and penalties of copyright or patent law in the appropriate jurisdiction. This section shall survive the termination of this License. + + 12. Attorneys' Fees. In any action to enforce the terms of this License or seeking damages relating thereto, the prevailing party shall be entitled to recover its costs and expenses, including, without limitation, reasonable attorneys' fees and costs incurred in connection with such action, including any appeal of such action. This section shall survive the termination of this License. + + 13. Miscellaneous. If any provision of this License is held to be unenforceable, such provision shall be reformed only to the extent necessary to make it enforceable. + + 14. Definition of "You" in This License. "You" throughout this License, whether in upper or lower case, means an individual or a legal entity exercising rights under, and complying with all of the terms of, this License. For legal entities, "You" includes any entity that controls, is controlled by, or is under common control with you. For purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + + 15. Right to Use. You may use the Original Work in all ways not otherwise restricted or conditioned by this License or by law, and Licensor promises not to interfere with or be responsible for such uses by You. + + 16. Modification of This License. This License is Copyright © 2005 Lawrence Rosen. Permission is granted to copy, distribute, or communicate this License without modification. Nothing in this License permits You to modify this License as applied to the Original Work or to Derivative Works. However, You may modify the text of this License and copy, distribute or communicate your modified version (the "Modified License") and apply it to other original works of authorship subject to the following conditions: (i) You may not indicate in any way that your Modified License is the "Academic Free License" or "AFL" and you may not use those names in the name of your Modified License; (ii) You must replace the notice specified in the first paragraph above with the notice "Licensed under " or with a notice of your own that is not confusingly similar to the notice in this License; and (iii) You may not claim that your original works are open source software unless your Modified License has been approved by Open Source Initiative (OSI) and You comply with its license review and certification process. diff --git a/app/code/Magento/LoginAsCustomer/Model/AuthenticateCustomer.php b/app/code/Magento/LoginAsCustomer/Model/AuthenticateCustomer.php new file mode 100644 index 0000000000000..df51a1e43f525 --- /dev/null +++ b/app/code/Magento/LoginAsCustomer/Model/AuthenticateCustomer.php @@ -0,0 +1,53 @@ +customerSession = $customerSession; + } + + /** + * @inheritdoc + */ + public function execute(AuthenticationDataInterface $authenticationData): void + { + if ($this->customerSession->getId()) { + $this->customerSession->logout(); + } + + $result = $this->customerSession->loginById($authenticationData->getCustomerId()); + if (false === $result) { + throw new LocalizedException(__('Login was not successful.')); + } + + $this->customerSession->regenerateId(); + $this->customerSession->setLoggedAsCustomerAdmindId($authenticationData->getAdminId()); + } +} diff --git a/app/code/Magento/LoginAsCustomer/Model/AuthenticationData.php b/app/code/Magento/LoginAsCustomer/Model/AuthenticationData.php new file mode 100644 index 0000000000000..17d85b970a2ff --- /dev/null +++ b/app/code/Magento/LoginAsCustomer/Model/AuthenticationData.php @@ -0,0 +1,71 @@ +customerId = $customerId; + $this->adminId = $adminId; + $this->extensionAttributes = $extensionAttributes; + } + + /** + * @inheritdoc + */ + public function getCustomerId(): int + { + return $this->customerId; + } + + /** + * @inheritdoc + */ + public function getAdminId(): int + { + return $this->adminId; + } + + /** + * @inheritdoc + */ + public function getExtensionAttributes(): ?AuthenticationDataExtensionInterface + { + return $this->extensionAttributes; + } +} diff --git a/app/code/Magento/LoginAsCustomer/Model/Config.php b/app/code/Magento/LoginAsCustomer/Model/Config.php new file mode 100644 index 0000000000000..2cfafa6ac09a3 --- /dev/null +++ b/app/code/Magento/LoginAsCustomer/Model/Config.php @@ -0,0 +1,65 @@ +scopeConfig = $scopeConfig; + } + + /** + * @inheritdoc + */ + public function isEnabled(): bool + { + return (bool)$this->scopeConfig->getValue(self::XML_PATH_ENABLED); + } + + /** + * @inheritdoc + */ + public function isStoreManualChoiceEnabled(): bool + { + return (bool)$this->scopeConfig->getValue(self::XML_PATH_STORE_VIEW_MANUAL_CHOICE_ENABLED); + } + + /** + * @inheritdoc + */ + public function getAuthenticationDataExpirationTime(): int + { + return (int)$this->scopeConfig->getValue(self::XML_PATH_AUTHENTICATION_EXPIRATION_TIME); + } +} diff --git a/app/code/Magento/LoginAsCustomer/Model/ResourceModel/DeleteAuthenticationDataBySecret.php b/app/code/Magento/LoginAsCustomer/Model/ResourceModel/DeleteAuthenticationDataBySecret.php new file mode 100644 index 0000000000000..6c12d4458ef1e --- /dev/null +++ b/app/code/Magento/LoginAsCustomer/Model/ResourceModel/DeleteAuthenticationDataBySecret.php @@ -0,0 +1,47 @@ +resourceConnection = $resourceConnection; + } + + /** + * @inheritdoc + */ + public function execute(string $secret): void + { + $connection = $this->resourceConnection->getConnection(); + $tableName = $this->resourceConnection->getTableName('login_as_customer'); + + $connection->delete( + $tableName, + [ + 'secret = ?' => $secret + ] + ); + } +} diff --git a/app/code/Magento/LoginAsCustomer/Model/ResourceModel/DeleteExpiredAuthenticationData.php b/app/code/Magento/LoginAsCustomer/Model/ResourceModel/DeleteExpiredAuthenticationData.php new file mode 100644 index 0000000000000..d838ba88b7d50 --- /dev/null +++ b/app/code/Magento/LoginAsCustomer/Model/ResourceModel/DeleteExpiredAuthenticationData.php @@ -0,0 +1,70 @@ +resourceConnection = $resourceConnection; + $this->dateTime = $dateTime; + $this->config = $config; + } + + /** + * @inheritdoc + */ + public function execute(): void + { + $connection = $this->resourceConnection->getConnection(); + $tableName = $this->resourceConnection->getTableName('login_as_customer'); + + $timePoint = date( + 'Y-m-d H:i:s', + $this->dateTime->gmtTimestamp() - $this->config->getAuthenticationDataExpirationTime() + ); + + $connection->delete( + $tableName, + [ + 'created_at < ?' => $timePoint + ] + ); + } +} diff --git a/app/code/Magento/LoginAsCustomer/Model/ResourceModel/GetAuthenticationDataBySecret.php b/app/code/Magento/LoginAsCustomer/Model/ResourceModel/GetAuthenticationDataBySecret.php new file mode 100644 index 0000000000000..7580668358b5a --- /dev/null +++ b/app/code/Magento/LoginAsCustomer/Model/ResourceModel/GetAuthenticationDataBySecret.php @@ -0,0 +1,95 @@ +resourceConnection = $resourceConnection; + $this->dateTime = $dateTime; + $this->config = $config; + $this->authenticationDataFactory = $authenticationDataFactory; + } + + /** + * @inheritdoc + */ + public function execute(string $secretKey): AuthenticationDataInterface + { + $connection = $this->resourceConnection->getConnection(); + $tableName = $this->resourceConnection->getTableName('login_as_customer'); + + $timePoint = date( + 'Y-m-d H:i:s', + $this->dateTime->gmtTimestamp() - $this->config->getAuthenticationDataExpirationTime() + ); + + $select = $connection->select() + ->from(['main_table' => $tableName]) + ->where('main_table.secret = ?', $secretKey) + ->where('main_table.created_at > ?', $timePoint); + + $data = $connection->fetchRow($select); + + if (!$data) { + throw new LocalizedException(__('Secret key is not found or was expired.')); + } + + /** @var AuthenticationDataInterface $authenticationData */ + $authenticationData = $this->authenticationDataFactory->create( + [ + 'customerId' => (int)$data['admin_id'], + 'adminId' => (int)$data['customer_id'], + 'extensionAttributes' => null, + ] + ); + return $authenticationData; + } +} diff --git a/app/code/Magento/LoginAsCustomer/Model/ResourceModel/SaveAuthenticationData.php b/app/code/Magento/LoginAsCustomer/Model/ResourceModel/SaveAuthenticationData.php new file mode 100644 index 0000000000000..d120b0eae392e --- /dev/null +++ b/app/code/Magento/LoginAsCustomer/Model/ResourceModel/SaveAuthenticationData.php @@ -0,0 +1,72 @@ +resourceConnection = $resourceConnection; + $this->dateTime = $dateTime; + $this->random = $random; + } + + /** + * @inheritdoc + */ + public function execute(AuthenticationDataInterface $authenticationData): string + { + $connection = $this->resourceConnection->getConnection(); + $tableName = $this->resourceConnection->getTableName('login_as_customer'); + + $secret = $this->random->getRandomString(64); + + $connection->insert( + $tableName, + [ + 'customer_id' => $authenticationData->getCustomerId(), + 'admin_id' => $authenticationData->getAdminId(), + 'secret' => $secret, + 'created_at' => $this->dateTime->gmtDate(), + ] + ); + return $secret; + } +} diff --git a/app/code/Magento/LoginAsCustomer/README.md b/app/code/Magento/LoginAsCustomer/README.md new file mode 100644 index 0000000000000..17d37bf553278 --- /dev/null +++ b/app/code/Magento/LoginAsCustomer/README.md @@ -0,0 +1,3 @@ +# Magento_LoginAsCustomer module + +The Magento_LoginAsCustomer module is responsible for ability to login into customer account using the admin panel. diff --git a/app/code/Magento/LoginAsCustomer/composer.json b/app/code/Magento/LoginAsCustomer/composer.json new file mode 100755 index 0000000000000..eeef8604feff2 --- /dev/null +++ b/app/code/Magento/LoginAsCustomer/composer.json @@ -0,0 +1,21 @@ +{ + "name": "magento/module-login-as-customer", + "description": "Allow for admin to enter a customer account", + "require": { + "php": "~7.1.3||~7.2.0||~7.3.0", + "magento/framework": "*", + "magento/module-customer": "*", + "magento/module-login-as-customer-api": "*" + }, + "type": "magento2-module", + "license": [ + "OSL-3.0", + "AFL-3.0" + ], + "autoload": { + "files": [ "registration.php" ], + "psr-4": { + "Magento\\LoginAsCustomer\\": "" + } + } +} diff --git a/app/code/Magento/LoginAsCustomer/etc/config.xml b/app/code/Magento/LoginAsCustomer/etc/config.xml new file mode 100644 index 0000000000000..936ae1ff2f05d --- /dev/null +++ b/app/code/Magento/LoginAsCustomer/etc/config.xml @@ -0,0 +1,19 @@ + + + + + + + 0 + 0 + 60 + + + + diff --git a/app/code/Magento/LoginAsCustomer/etc/crontab.xml b/app/code/Magento/LoginAsCustomer/etc/crontab.xml new file mode 100644 index 0000000000000..eaeef8cf8d759 --- /dev/null +++ b/app/code/Magento/LoginAsCustomer/etc/crontab.xml @@ -0,0 +1,16 @@ + + + + + + 15 * * * * + + + diff --git a/app/code/Magento/LoginAsCustomer/etc/db_schema.xml b/app/code/Magento/LoginAsCustomer/etc/db_schema.xml new file mode 100644 index 0000000000000..a693946f0c3ba --- /dev/null +++ b/app/code/Magento/LoginAsCustomer/etc/db_schema.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + diff --git a/app/code/Magento/LoginAsCustomer/etc/db_schema_whitelist.json b/app/code/Magento/LoginAsCustomer/etc/db_schema_whitelist.json new file mode 100644 index 0000000000000..397ea4525aee2 --- /dev/null +++ b/app/code/Magento/LoginAsCustomer/etc/db_schema_whitelist.json @@ -0,0 +1,16 @@ +{ + "login_as_customer": { + "column": { + "secret": true, + "customer_id": true, + "admin_id": true, + "created_at": true + }, + "index": { + "LOGIN_AS_CUSTOMER_CREATED_AT": true + }, + "constraint": { + "PRIMARY": true + } + } +} diff --git a/app/code/Magento/LoginAsCustomer/etc/di.xml b/app/code/Magento/LoginAsCustomer/etc/di.xml new file mode 100755 index 0000000000000..764e2cbd792e7 --- /dev/null +++ b/app/code/Magento/LoginAsCustomer/etc/di.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + diff --git a/app/code/Magento/LoginAsCustomer/etc/module.xml b/app/code/Magento/LoginAsCustomer/etc/module.xml new file mode 100755 index 0000000000000..d577dc0da5e4f --- /dev/null +++ b/app/code/Magento/LoginAsCustomer/etc/module.xml @@ -0,0 +1,11 @@ + + + + + diff --git a/app/code/Magento/LoginAsCustomer/i18n/en_US.csv b/app/code/Magento/LoginAsCustomer/i18n/en_US.csv new file mode 100644 index 0000000000000..6ce6cfc532221 --- /dev/null +++ b/app/code/Magento/LoginAsCustomer/i18n/en_US.csv @@ -0,0 +1,2 @@ +"Close Session","Close Session" +"You are connected as %1 on %2","You are connected as %1 on %2" diff --git a/app/code/Magento/LoginAsCustomer/registration.php b/app/code/Magento/LoginAsCustomer/registration.php new file mode 100755 index 0000000000000..ac43a6d812e9b --- /dev/null +++ b/app/code/Magento/LoginAsCustomer/registration.php @@ -0,0 +1,11 @@ +" or with a notice of your own that is not confusingly similar to the notice in this License; and (iii) You may not claim that your original works are open source software unless your Modified License has been approved by Open Source Initiative (OSI) and You comply with its license review and certification process. \ No newline at end of file diff --git a/app/code/Magento/LoginAsCustomerApi/LICENSE_AFL.txt b/app/code/Magento/LoginAsCustomerApi/LICENSE_AFL.txt new file mode 100644 index 0000000000000..f39d641b18a19 --- /dev/null +++ b/app/code/Magento/LoginAsCustomerApi/LICENSE_AFL.txt @@ -0,0 +1,48 @@ + +Academic Free License ("AFL") v. 3.0 + +This Academic Free License (the "License") applies to any original work of authorship (the "Original Work") whose owner (the "Licensor") has placed the following licensing notice adjacent to the copyright notice for the Original Work: + +Licensed under the Academic Free License version 3.0 + + 1. Grant of Copyright License. Licensor grants You a worldwide, royalty-free, non-exclusive, sublicensable license, for the duration of the copyright, to do the following: + + 1. to reproduce the Original Work in copies, either alone or as part of a collective work; + + 2. to translate, adapt, alter, transform, modify, or arrange the Original Work, thereby creating derivative works ("Derivative Works") based upon the Original Work; + + 3. to distribute or communicate copies of the Original Work and Derivative Works to the public, under any license of your choice that does not contradict the terms and conditions, including Licensor's reserved rights and remedies, in this Academic Free License; + + 4. to perform the Original Work publicly; and + + 5. to display the Original Work publicly. + + 2. Grant of Patent License. Licensor grants You a worldwide, royalty-free, non-exclusive, sublicensable license, under patent claims owned or controlled by the Licensor that are embodied in the Original Work as furnished by the Licensor, for the duration of the patents, to make, use, sell, offer for sale, have made, and import the Original Work and Derivative Works. + + 3. Grant of Source Code License. The term "Source Code" means the preferred form of the Original Work for making modifications to it and all available documentation describing how to modify the Original Work. Licensor agrees to provide a machine-readable copy of the Source Code of the Original Work along with each copy of the Original Work that Licensor distributes. Licensor reserves the right to satisfy this obligation by placing a machine-readable copy of the Source Code in an information repository reasonably calculated to permit inexpensive and convenient access by You for as long as Licensor continues to distribute the Original Work. + + 4. Exclusions From License Grant. Neither the names of Licensor, nor the names of any contributors to the Original Work, nor any of their trademarks or service marks, may be used to endorse or promote products derived from this Original Work without express prior permission of the Licensor. Except as expressly stated herein, nothing in this License grants any license to Licensor's trademarks, copyrights, patents, trade secrets or any other intellectual property. No patent license is granted to make, use, sell, offer for sale, have made, or import embodiments of any patent claims other than the licensed claims defined in Section 2. No license is granted to the trademarks of Licensor even if such marks are included in the Original Work. Nothing in this License shall be interpreted to prohibit Licensor from licensing under terms different from this License any Original Work that Licensor otherwise would have a right to license. + + 5. External Deployment. The term "External Deployment" means the use, distribution, or communication of the Original Work or Derivative Works in any way such that the Original Work or Derivative Works may be used by anyone other than You, whether those works are distributed or communicated to those persons or made available as an application intended for use over a network. As an express condition for the grants of license hereunder, You must treat any External Deployment by You of the Original Work or a Derivative Work as a distribution under section 1(c). + + 6. Attribution Rights. You must retain, in the Source Code of any Derivative Works that You create, all copyright, patent, or trademark notices from the Source Code of the Original Work, as well as any notices of licensing and any descriptive text identified therein as an "Attribution Notice." You must cause the Source Code for any Derivative Works that You create to carry a prominent Attribution Notice reasonably calculated to inform recipients that You have modified the Original Work. + + 7. Warranty of Provenance and Disclaimer of Warranty. Licensor warrants that the copyright in and to the Original Work and the patent rights granted herein by Licensor are owned by the Licensor or are sublicensed to You under the terms of this License with the permission of the contributor(s) of those copyrights and patent rights. Except as expressly stated in the immediately preceding sentence, the Original Work is provided under this License on an "AS IS" BASIS and WITHOUT WARRANTY, either express or implied, including, without limitation, the warranties of non-infringement, merchantability or fitness for a particular purpose. THE ENTIRE RISK AS TO THE QUALITY OF THE ORIGINAL WORK IS WITH YOU. This DISCLAIMER OF WARRANTY constitutes an essential part of this License. No license to the Original Work is granted by this License except under this disclaimer. + + 8. Limitation of Liability. Under no circumstances and under no legal theory, whether in tort (including negligence), contract, or otherwise, shall the Licensor be liable to anyone for any indirect, special, incidental, or consequential damages of any character arising as a result of this License or the use of the Original Work including, without limitation, damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses. This limitation of liability shall not apply to the extent applicable law prohibits such limitation. + + 9. Acceptance and Termination. If, at any time, You expressly assented to this License, that assent indicates your clear and irrevocable acceptance of this License and all of its terms and conditions. If You distribute or communicate copies of the Original Work or a Derivative Work, You must make a reasonable effort under the circumstances to obtain the express assent of recipients to the terms of this License. This License conditions your rights to undertake the activities listed in Section 1, including your right to create Derivative Works based upon the Original Work, and doing so without honoring these terms and conditions is prohibited by copyright law and international treaty. Nothing in this License is intended to affect copyright exceptions and limitations (including "fair use" or "fair dealing"). This License shall terminate immediately and You may no longer exercise any of the rights granted to You by this License upon your failure to honor the conditions in Section 1(c). + + 10. Termination for Patent Action. This License shall terminate automatically and You may no longer exercise any of the rights granted to You by this License as of the date You commence an action, including a cross-claim or counterclaim, against Licensor or any licensee alleging that the Original Work infringes a patent. This termination provision shall not apply for an action alleging patent infringement by combinations of the Original Work with other software or hardware. + + 11. Jurisdiction, Venue and Governing Law. Any action or suit relating to this License may be brought only in the courts of a jurisdiction wherein the Licensor resides or in which Licensor conducts its primary business, and under the laws of that jurisdiction excluding its conflict-of-law provisions. The application of the United Nations Convention on Contracts for the International Sale of Goods is expressly excluded. Any use of the Original Work outside the scope of this License or after its termination shall be subject to the requirements and penalties of copyright or patent law in the appropriate jurisdiction. This section shall survive the termination of this License. + + 12. Attorneys' Fees. In any action to enforce the terms of this License or seeking damages relating thereto, the prevailing party shall be entitled to recover its costs and expenses, including, without limitation, reasonable attorneys' fees and costs incurred in connection with such action, including any appeal of such action. This section shall survive the termination of this License. + + 13. Miscellaneous. If any provision of this License is held to be unenforceable, such provision shall be reformed only to the extent necessary to make it enforceable. + + 14. Definition of "You" in This License. "You" throughout this License, whether in upper or lower case, means an individual or a legal entity exercising rights under, and complying with all of the terms of, this License. For legal entities, "You" includes any entity that controls, is controlled by, or is under common control with you. For purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + + 15. Right to Use. You may use the Original Work in all ways not otherwise restricted or conditioned by this License or by law, and Licensor promises not to interfere with or be responsible for such uses by You. + + 16. Modification of This License. This License is Copyright © 2005 Lawrence Rosen. Permission is granted to copy, distribute, or communicate this License without modification. Nothing in this License permits You to modify this License as applied to the Original Work or to Derivative Works. However, You may modify the text of this License and copy, distribute or communicate your modified version (the "Modified License") and apply it to other original works of authorship subject to the following conditions: (i) You may not indicate in any way that your Modified License is the "Academic Free License" or "AFL" and you may not use those names in the name of your Modified License; (ii) You must replace the notice specified in the first paragraph above with the notice "Licensed under " or with a notice of your own that is not confusingly similar to the notice in this License; and (iii) You may not claim that your original works are open source software unless your Modified License has been approved by Open Source Initiative (OSI) and You comply with its license review and certification process. diff --git a/app/code/Magento/LoginAsCustomerApi/README.md b/app/code/Magento/LoginAsCustomerApi/README.md new file mode 100644 index 0000000000000..caf2f23b49f43 --- /dev/null +++ b/app/code/Magento/LoginAsCustomerApi/README.md @@ -0,0 +1,3 @@ +# Magento_LoginAsCustomer module + +The Magento_LoginAsCustomerApi module provides API for ability to login into customer account for an admin user. diff --git a/app/code/Magento/LoginAsCustomerApi/composer.json b/app/code/Magento/LoginAsCustomerApi/composer.json new file mode 100644 index 0000000000000..c99c117bda7c3 --- /dev/null +++ b/app/code/Magento/LoginAsCustomerApi/composer.json @@ -0,0 +1,19 @@ +{ + "name": "magento/module-login-as-customer-api", + "description": "Allow for admin to enter a customer account", + "require": { + "php": "~7.1.3||~7.2.0||~7.3.0", + "magento/framework": "*" + }, + "type": "magento2-module", + "license": [ + "OSL-3.0", + "AFL-3.0" + ], + "autoload": { + "files": [ "registration.php" ], + "psr-4": { + "Magento\\LoginAsCustomerApi\\": "" + } + } +} diff --git a/app/code/Magento/LoginAsCustomerApi/etc/module.xml b/app/code/Magento/LoginAsCustomerApi/etc/module.xml new file mode 100644 index 0000000000000..cdfefb80e9b3b --- /dev/null +++ b/app/code/Magento/LoginAsCustomerApi/etc/module.xml @@ -0,0 +1,11 @@ + + + + + diff --git a/app/code/Magento/LoginAsCustomerApi/registration.php b/app/code/Magento/LoginAsCustomerApi/registration.php new file mode 100644 index 0000000000000..344d110e46f43 --- /dev/null +++ b/app/code/Magento/LoginAsCustomerApi/registration.php @@ -0,0 +1,14 @@ +removeButton('add'); + } +} diff --git a/app/code/Magento/LoginAsCustomerLog/Controller/Adminhtml/Login/Grid.php b/app/code/Magento/LoginAsCustomerLog/Controller/Adminhtml/Login/Grid.php new file mode 100644 index 0000000000000..ca47050199598 --- /dev/null +++ b/app/code/Magento/LoginAsCustomerLog/Controller/Adminhtml/Login/Grid.php @@ -0,0 +1,36 @@ +resultFactory->create(ResultFactory::TYPE_PAGE); + } +} diff --git a/app/code/Magento/LoginAsCustomerLog/Controller/Adminhtml/Login/Index.php b/app/code/Magento/LoginAsCustomerLog/Controller/Adminhtml/Login/Index.php new file mode 100644 index 0000000000000..b1a65efc217e1 --- /dev/null +++ b/app/code/Magento/LoginAsCustomerLog/Controller/Adminhtml/Login/Index.php @@ -0,0 +1,51 @@ +getRequest()->isXmlHttpRequest()) { + $resultForward = $this->resultFactory->create(ResultFactory::TYPE_FORWARD); + $resultForward->forward('grid'); + return $resultForward; + } + + /** @var Page $resultPage */ + $resultPage = $this->resultFactory->create(ResultFactory::TYPE_PAGE); + $resultPage->setActiveMenu('Magento_LoginAsCustomerLog::login_log') + ->addBreadcrumb(__('Customer'), __('Login As Customer Log')); + $resultPage->getConfig()->getTitle()->prepend(__('Login As Customer Log')); + + return $resultPage; + } +} diff --git a/app/code/Magento/LoginAsCustomerLog/Model/Login.php b/app/code/Magento/LoginAsCustomerLog/Model/Login.php new file mode 100644 index 0000000000000..e8092dbd02dc3 --- /dev/null +++ b/app/code/Magento/LoginAsCustomerLog/Model/Login.php @@ -0,0 +1,22 @@ +_init(\Magento\LoginAsCustomerLog\Model\ResourceModel\Login::class); + } +} diff --git a/app/code/Magento/LoginAsCustomerLog/Model/ResourceModel/Login.php b/app/code/Magento/LoginAsCustomerLog/Model/ResourceModel/Login.php new file mode 100644 index 0000000000000..91c360e3717c0 --- /dev/null +++ b/app/code/Magento/LoginAsCustomerLog/Model/ResourceModel/Login.php @@ -0,0 +1,22 @@ +_init('login_as_customer', 'secret'); + } +} diff --git a/app/code/Magento/LoginAsCustomerLog/Model/ResourceModel/Login/Collection.php b/app/code/Magento/LoginAsCustomerLog/Model/ResourceModel/Login/Collection.php new file mode 100644 index 0000000000000..8b2f270499987 --- /dev/null +++ b/app/code/Magento/LoginAsCustomerLog/Model/ResourceModel/Login/Collection.php @@ -0,0 +1,26 @@ +_init( + \Magento\LoginAsCustomerLog\Model\Login::class, + \Magento\LoginAsCustomerLog\Model\ResourceModel\Login::class + ); + } +} diff --git a/app/code/Magento/LoginAsCustomerLog/Model/ResourceModel/Login/Grid/Collection.php b/app/code/Magento/LoginAsCustomerLog/Model/ResourceModel/Login/Grid/Collection.php new file mode 100644 index 0000000000000..1b91d2afc11b2 --- /dev/null +++ b/app/code/Magento/LoginAsCustomerLog/Model/ResourceModel/Login/Grid/Collection.php @@ -0,0 +1,44 @@ +_map['fields']['email'] = 'c.email'; + } + + /** + * Init collection select + * + * @return $this + */ + protected function _initSelect(): self + { + parent::_initSelect(); + $this->getSelect() + ->joinLeft( + ['c' => $this->getTable('customer_entity')], + 'c.entity_id = main_table.customer_id', + ['email'] + )->joinLeft( + ['a' => $this->getTable('admin_user')], + 'a.user_id = main_table.admin_id', + ['username'] + ); + return $this; + } +} diff --git a/app/code/Magento/LoginAsCustomerLog/README.md b/app/code/Magento/LoginAsCustomerLog/README.md new file mode 100644 index 0000000000000..a44ae014f2c83 --- /dev/null +++ b/app/code/Magento/LoginAsCustomerLog/README.md @@ -0,0 +1,3 @@ +# Magento_LoginAsCustomerLog module + +The Magento_LoginAsCustomerLog module provides log for Login As Customer functionality diff --git a/app/code/Magento/LoginAsCustomerLog/composer.json b/app/code/Magento/LoginAsCustomerLog/composer.json new file mode 100644 index 0000000000000..7ad41ee1aecee --- /dev/null +++ b/app/code/Magento/LoginAsCustomerLog/composer.json @@ -0,0 +1,23 @@ +{ + "name": "magento/module-login-as-customer-log", + "description": "", + "require": { + "php": "~7.1.3||~7.2.0||~7.3.0", + "magento/framework": "*", + "magento/module-backend": "*" + }, + "suggest": { + "magento/module-login-as-customer": "*" + }, + "type": "magento2-module", + "license": [ + "OSL-3.0", + "AFL-3.0" + ], + "autoload": { + "files": [ "registration.php" ], + "psr-4": { + "Magento\\LoginAsCustomerLog\\": "" + } + } +} diff --git a/app/code/Magento/LoginAsCustomerLog/etc/acl.xml b/app/code/Magento/LoginAsCustomerLog/etc/acl.xml new file mode 100644 index 0000000000000..aaf4eb009368e --- /dev/null +++ b/app/code/Magento/LoginAsCustomerLog/etc/acl.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + diff --git a/app/code/Magento/LoginAsCustomerLog/etc/adminhtml/menu.xml b/app/code/Magento/LoginAsCustomerLog/etc/adminhtml/menu.xml new file mode 100644 index 0000000000000..f3fd02874e04e --- /dev/null +++ b/app/code/Magento/LoginAsCustomerLog/etc/adminhtml/menu.xml @@ -0,0 +1,19 @@ + + + + + + + diff --git a/app/code/Magento/LoginAsCustomerLog/etc/adminhtml/routes.xml b/app/code/Magento/LoginAsCustomerLog/etc/adminhtml/routes.xml new file mode 100644 index 0000000000000..3c3df84a63424 --- /dev/null +++ b/app/code/Magento/LoginAsCustomerLog/etc/adminhtml/routes.xml @@ -0,0 +1,15 @@ + + + + + + + + + diff --git a/app/code/Magento/LoginAsCustomerLog/etc/module.xml b/app/code/Magento/LoginAsCustomerLog/etc/module.xml new file mode 100644 index 0000000000000..aef4e21780c4e --- /dev/null +++ b/app/code/Magento/LoginAsCustomerLog/etc/module.xml @@ -0,0 +1,11 @@ + + + + + diff --git a/app/code/Magento/LoginAsCustomerLog/registration.php b/app/code/Magento/LoginAsCustomerLog/registration.php new file mode 100644 index 0000000000000..2a4594d2218f6 --- /dev/null +++ b/app/code/Magento/LoginAsCustomerLog/registration.php @@ -0,0 +1,14 @@ + + + + + + + + + diff --git a/app/code/Magento/LoginAsCustomerLog/view/adminhtml/layout/loginascustomer_login_grid_block.xml b/app/code/Magento/LoginAsCustomerLog/view/adminhtml/layout/loginascustomer_login_grid_block.xml new file mode 100644 index 0000000000000..68f0d857be082 --- /dev/null +++ b/app/code/Magento/LoginAsCustomerLog/view/adminhtml/layout/loginascustomer_login_grid_block.xml @@ -0,0 +1,66 @@ + + + + + + + + subscriberGrid + Magento\LoginAsCustomerLog\Model\ResourceModel\Login\Grid\Collection + created_at + desc + 1 + + + + + + Customer ID + customer_id + col-title + col-title + + + + + Customer Email + email + col-title + col-title + + + + + Admin ID + admin_id + col-title + col-title + + + + + Admin Name + username + col-title + col-title + + + + + Logged In + created_at + datetime + col-first-name + col-first-name + + + + + + + diff --git a/app/code/Magento/LoginAsCustomerLog/view/adminhtml/layout/loginascustomer_login_index.xml b/app/code/Magento/LoginAsCustomerLog/view/adminhtml/layout/loginascustomer_login_index.xml new file mode 100644 index 0000000000000..50d0a83210176 --- /dev/null +++ b/app/code/Magento/LoginAsCustomerLog/view/adminhtml/layout/loginascustomer_login_index.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + diff --git a/app/code/Magento/LoginAsCustomerPageCache/Plugin/PageCache/Model/Config/DisablePageCacheIfNeededPlugin.php b/app/code/Magento/LoginAsCustomerPageCache/Plugin/PageCache/Model/Config/DisablePageCacheIfNeededPlugin.php new file mode 100644 index 0000000000000..6b36a0720ecb3 --- /dev/null +++ b/app/code/Magento/LoginAsCustomerPageCache/Plugin/PageCache/Model/Config/DisablePageCacheIfNeededPlugin.php @@ -0,0 +1,68 @@ +scopeConfig = $scopeConfig; + $this->customerSession = $customerSession; + } + + /** + * Disable page cache if needed when admin is logged as customer + * + * @param Config $subject + * @param bool $isEnabled + * @return bool + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function afterIsEnabled(Config $subject, $isEnabled): bool + { + if ($isEnabled) { + $disable = $this->scopeConfig->getValue( + 'login_as_customer/general/disable_page_cache', + ScopeInterface::SCOPE_STORE + ); + $adminId = $this->customerSession->getLoggedAsCustomerAdmindId(); + if ($disable && $adminId) { + $isEnabled = false; + } + } + return $isEnabled; + } +} diff --git a/app/code/Magento/LoginAsCustomerPageCache/README.md b/app/code/Magento/LoginAsCustomerPageCache/README.md new file mode 100644 index 0000000000000..91fa43fb4e833 --- /dev/null +++ b/app/code/Magento/LoginAsCustomerPageCache/README.md @@ -0,0 +1,3 @@ +# LoginAsCustomerPageCache module + +The Magento_LoginAsCustomerPageCache module provides adaptation to PageCache functionality diff --git a/app/code/Magento/LoginAsCustomerPageCache/composer.json b/app/code/Magento/LoginAsCustomerPageCache/composer.json new file mode 100644 index 0000000000000..3412c9fcb611c --- /dev/null +++ b/app/code/Magento/LoginAsCustomerPageCache/composer.json @@ -0,0 +1,24 @@ +{ + "name": "magento/module-login-as-customer-page-cache", + "description": "", + "require": { + "php": "~7.1.3||~7.2.0||~7.3.0", + "magento/framework": "*", + "magento/module-customer": "*", + "magento/module-store": "*" + }, + "suggest": { + "magento/module-page-cache": "*" + }, + "type": "magento2-module", + "license": [ + "OSL-3.0", + "AFL-3.0" + ], + "autoload": { + "files": [ "registration.php" ], + "psr-4": { + "Magento\\LoginAsCustomerPageCache\\": "" + } + } +} diff --git a/app/code/Magento/LoginAsCustomerPageCache/etc/adminhtml/system.xml b/app/code/Magento/LoginAsCustomerPageCache/etc/adminhtml/system.xml new file mode 100644 index 0000000000000..7fc1826932ce4 --- /dev/null +++ b/app/code/Magento/LoginAsCustomerPageCache/etc/adminhtml/system.xml @@ -0,0 +1,20 @@ + + + + + + + + Disable Page Cache For Admin User + Magento\Config\Model\Config\Source\Yesno + + + + + + diff --git a/app/code/Magento/LoginAsCustomerPageCache/etc/config.xml b/app/code/Magento/LoginAsCustomerPageCache/etc/config.xml new file mode 100644 index 0000000000000..ba3f954f4980b --- /dev/null +++ b/app/code/Magento/LoginAsCustomerPageCache/etc/config.xml @@ -0,0 +1,17 @@ + + + + + + + 1 + + + + diff --git a/app/code/Magento/LoginAsCustomerPageCache/etc/frontend/di.xml b/app/code/Magento/LoginAsCustomerPageCache/etc/frontend/di.xml new file mode 100644 index 0000000000000..1419c80d918dc --- /dev/null +++ b/app/code/Magento/LoginAsCustomerPageCache/etc/frontend/di.xml @@ -0,0 +1,14 @@ + + + + + + + \ No newline at end of file diff --git a/app/code/Magento/LoginAsCustomerPageCache/etc/module.xml b/app/code/Magento/LoginAsCustomerPageCache/etc/module.xml new file mode 100644 index 0000000000000..15c845a995794 --- /dev/null +++ b/app/code/Magento/LoginAsCustomerPageCache/etc/module.xml @@ -0,0 +1,11 @@ + + + + + diff --git a/app/code/Magento/LoginAsCustomerPageCache/registration.php b/app/code/Magento/LoginAsCustomerPageCache/registration.php new file mode 100644 index 0000000000000..587c3d56050d7 --- /dev/null +++ b/app/code/Magento/LoginAsCustomerPageCache/registration.php @@ -0,0 +1,14 @@ +userSession = $session; + } + + /** + * Add comment after order placed by admin using admin panel. + * + * @param Order $subject + * @param Order $result + * @return Order + */ + public function afterPlace(Order $subject, Order $result): Order + { + $adminUser = $this->userSession->getUser(); + if ($adminUser) { + $subject->addCommentToStatusHistory( + 'Order Placed by Store Administrator', + false, + true + )->setIsCustomerNotified(false); + $subject->addCommentToStatusHistory( + "Order Placed by {$adminUser->getFirstName()} {$adminUser->getLastName()} using Admin Panel", + false, + false + )->setIsCustomerNotified(false); + } + + return $result; + } +} diff --git a/app/code/Magento/LoginAsCustomerSales/Plugin/AuthenticateCustomerPlugin.php b/app/code/Magento/LoginAsCustomerSales/Plugin/AuthenticateCustomerPlugin.php new file mode 100644 index 0000000000000..8299f224042fc --- /dev/null +++ b/app/code/Magento/LoginAsCustomerSales/Plugin/AuthenticateCustomerPlugin.php @@ -0,0 +1,100 @@ +customerSession = $customerSession; + $this->checkoutSession = $checkoutSession; + $this->quoteRepository = $quoteRepository; + } + + /** + * Remove all items from guest shopping cart + * + * @param AuthenticateCustomerInterface $subject + * @param AuthenticationDataInterface $authenticationData + * @return null + * @throws LocalizedException + * + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function beforeExecute( + AuthenticateCustomerInterface $subject, + AuthenticationDataInterface $authenticationData + ) { + if (!$this->customerSession->getId()) { + $quote = $this->checkoutSession->getQuote(); + /* Remove items from guest cart */ + $quote->removeAllItems(); + } + return null; + } + + /** + * Mark customer cart as not-guest + * + * @param AuthenticateCustomerInterface $subject + * @param void $result + * @param AuthenticationDataInterface $authenticationData + * @return void + * @throws LocalizedException + * + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function afterExecute( + AuthenticateCustomerInterface $subject, + $result, + AuthenticationDataInterface $authenticationData + ) { + $this->checkoutSession->loadCustomerQuote(); + $quote = $this->checkoutSession->getQuote(); + + $quote->setCustomerIsGuest(0); + $this->quoteRepository->save($quote); + } +} diff --git a/app/code/Magento/LoginAsCustomerSales/Plugin/FrontAddCommentOnOrderPlacementPlugin.php b/app/code/Magento/LoginAsCustomerSales/Plugin/FrontAddCommentOnOrderPlacementPlugin.php new file mode 100644 index 0000000000000..cbb804253c7bc --- /dev/null +++ b/app/code/Magento/LoginAsCustomerSales/Plugin/FrontAddCommentOnOrderPlacementPlugin.php @@ -0,0 +1,69 @@ +customerSession = $session; + $this->userFactory = $userFactory; + } + + /** + * Add comment after order placed by admin using login-as-customer. + * + * @param Order $subject + * @param Order $result + * @return Order + */ + public function afterPlace(Order $subject, Order $result): Order + { + $adminId = $this->customerSession->getLoggedAsCustomerAdmindId(); + if ($adminId) { + $adminUser = $this->userFactory->create()->load($adminId); + $subject->addCommentToStatusHistory( + 'Order Placed by Store Administrator', + false, + true + )->setIsCustomerNotified(false); + $subject->addCommentToStatusHistory( + "Order Placed by {$adminUser->getFirstName()} {$adminUser->getLastName()} using Login as Customer", + false, + false + )->setIsCustomerNotified(false); + } + + return $result; + } +} diff --git a/app/code/Magento/LoginAsCustomerSales/README.md b/app/code/Magento/LoginAsCustomerSales/README.md new file mode 100644 index 0000000000000..d5e38d8ec5909 --- /dev/null +++ b/app/code/Magento/LoginAsCustomerSales/README.md @@ -0,0 +1,3 @@ +# Magento_LoginAsCustomerSales module + +The Magento_LoginAsCustomerSales module is responsible for comunication between Magento_LoginAsCustomer and shopping cart state. diff --git a/app/code/Magento/LoginAsCustomerSales/composer.json b/app/code/Magento/LoginAsCustomerSales/composer.json new file mode 100644 index 0000000000000..32c800561784c --- /dev/null +++ b/app/code/Magento/LoginAsCustomerSales/composer.json @@ -0,0 +1,30 @@ +{ + "name": "magento/module-login-as-customer-sales", + "description": "", + "require": { + "php": "~7.1.3||~7.2.0||~7.3.0", + "magento/framework": "*", + "magento/module-backend": "*", + "magento/module-checkout": "*", + "magento/module-customer": "*", + "magento/module-quote": "*", + "magento/module-user": "*" + }, + "suggest": { + "magento/module-sales": "*", + "magento/module-login-as-customer-api": "*" + }, + "type": "magento2-module", + "license": [ + "OSL-3.0", + "AFL-3.0" + ], + "autoload": { + "files": [ + "registration.php" + ], + "psr-4": { + "Magento\\LoginAsCustomerSales\\": "" + } + } +} diff --git a/app/code/Magento/LoginAsCustomerSales/etc/adminhtml/di.xml b/app/code/Magento/LoginAsCustomerSales/etc/adminhtml/di.xml new file mode 100644 index 0000000000000..225688a8c7bab --- /dev/null +++ b/app/code/Magento/LoginAsCustomerSales/etc/adminhtml/di.xml @@ -0,0 +1,12 @@ + + + + + + + diff --git a/app/code/Magento/LoginAsCustomerSales/etc/di.xml b/app/code/Magento/LoginAsCustomerSales/etc/di.xml new file mode 100644 index 0000000000000..f267fc3850234 --- /dev/null +++ b/app/code/Magento/LoginAsCustomerSales/etc/di.xml @@ -0,0 +1,14 @@ + + + + + + + \ No newline at end of file diff --git a/app/code/Magento/LoginAsCustomerSales/etc/module.xml b/app/code/Magento/LoginAsCustomerSales/etc/module.xml new file mode 100644 index 0000000000000..91f62000c58f5 --- /dev/null +++ b/app/code/Magento/LoginAsCustomerSales/etc/module.xml @@ -0,0 +1,11 @@ + + + + + diff --git a/app/code/Magento/LoginAsCustomerSales/etc/webapi_rest/di.xml b/app/code/Magento/LoginAsCustomerSales/etc/webapi_rest/di.xml new file mode 100644 index 0000000000000..1a010fcdead85 --- /dev/null +++ b/app/code/Magento/LoginAsCustomerSales/etc/webapi_rest/di.xml @@ -0,0 +1,12 @@ + + + + + + + diff --git a/app/code/Magento/LoginAsCustomerSales/registration.php b/app/code/Magento/LoginAsCustomerSales/registration.php new file mode 100644 index 0000000000000..4ee5647f5e837 --- /dev/null +++ b/app/code/Magento/LoginAsCustomerSales/registration.php @@ -0,0 +1,11 @@ +authSession = $authSession; + $this->storeManager = $storeManager; + $this->customerRepository = $customerRepository; + $this->config = $config; + $this->authenticationDataFactory = $authenticationDataFactory; + $this->saveAuthenticationData = $saveAuthenticationData; + $this->url = $url; + } + + /** + * Login as customer + * + * @return ResultInterface + * @throws NoSuchEntityException + * @throws LocalizedException + */ + public function execute(): ResultInterface + { + /** @var Redirect $resultRedirect */ + $resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT); + + if (!$this->config->isEnabled()) { + $this->messageManager->addErrorMessage(__('Login As Customer is disabled.')); + return $resultRedirect->setPath('customer/index/index'); + } + + $customerId = (int)$this->_request->getParam('customer_id'); + if (!$customerId) { + $customerId = (int)$this->_request->getParam('entity_id'); + } + + try { + $this->customerRepository->getById($customerId); + } catch (NoSuchEntityException $e) { + $this->messageManager->addErrorMessage(__('Customer with this ID are no longer exist.')); + return $resultRedirect->setPath('customer/index/index'); + } + + $storeId = $this->_request->getParam('store_id'); + if (empty($storeId) && $this->config->isStoreManualChoiceEnabled()) { + $this->messageManager->addNoticeMessage(__('Please select a Store View to login in.')); + return $resultRedirect->setPath('loginascustomer/login/manual', ['customer_id' => $customerId]); + } + + $adminUser = $this->authSession->getUser(); + + /** @var AuthenticationDataInterface $authenticationData */ + $authenticationData = $this->authenticationDataFactory->create( + [ + 'customerId' => $customerId, + 'adminId' => (int)$adminUser->getId(), + 'extensionAttributes' => null, + ] + ); + $secret = $this->saveAuthenticationData->execute($authenticationData); + + $redirectUrl = $this->getLoginProceedRedirectUrl($secret, $storeId); + $resultRedirect->setUrl($redirectUrl); + return $resultRedirect; + } + + /** + * Get login proceed redirect url + * + * @param string $secret + * @param int|null $storeId + * @return string + * @throws NoSuchEntityException + */ + private function getLoginProceedRedirectUrl(string $secret, ?int $storeId): string + { + if (null === $storeId) { + $store = $this->storeManager->getDefaultStoreView(); + } else { + $store = $this->storeManager->getStore($storeId); + } + + return $this->url + ->setScope($store) + ->getUrl('loginascustomer/login/index', ['secret' => $secret, '_nosid' => true]); + } +} diff --git a/app/code/Magento/LoginAsCustomerUi/Controller/Adminhtml/Login/Manual.php b/app/code/Magento/LoginAsCustomerUi/Controller/Adminhtml/Login/Manual.php new file mode 100755 index 0000000000000..e41e6896d7de1 --- /dev/null +++ b/app/code/Magento/LoginAsCustomerUi/Controller/Adminhtml/Login/Manual.php @@ -0,0 +1,43 @@ +resultFactory->create(ResultFactory::TYPE_PAGE); + $resultPage->setActiveMenu('Magento_Customer::customer') + ->addBreadcrumb(__('Customer'), __('Login As Customer Log'), __('Store View To Login In')); + $resultPage->getConfig()->getTitle()->prepend(__('Store View To Login In')); + + return $resultPage; + } +} diff --git a/app/code/Magento/LoginAsCustomerUi/Controller/Login/Index.php b/app/code/Magento/LoginAsCustomerUi/Controller/Login/Index.php new file mode 100755 index 0000000000000..0532846cf2535 --- /dev/null +++ b/app/code/Magento/LoginAsCustomerUi/Controller/Login/Index.php @@ -0,0 +1,143 @@ +resultFactory = $resultFactory; + $this->request = $request; + $this->customerRepository = $customerRepository; + $this->getAuthenticationDataBySecret = $getAuthenticateDataProcessor; + $this->authenticateCustomer = $authenticateCustomerProcessor; + $this->deleteAuthenticationDataBySecret = $deleteSecretProcessor; + $this->messageManager = $messageManager; + $this->logger = $logger; + } + + /** + * Login As Customer storefront login + * + * @return ResultInterface + */ + public function execute(): ResultInterface + { + /** @var Redirect $resultRedirect */ + $resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT); + + try { + $secret = $this->request->getParam('secret'); + if (empty($secret) || !is_string($secret)) { + throw new LocalizedException(__('Cannot login to account. No secret key provided.')); + } + + $authenticateData = $this->getAuthenticationDataBySecret->execute($secret); + + $this->deleteAuthenticationDataBySecret->execute($secret); + + try { + $customer = $this->customerRepository->getById($authenticateData->getCustomerId()); + } catch (NoSuchEntityException $e) { + throw new LocalizedException(__('Customer are no longer exist.')); + } + + $this->authenticateCustomer->execute($authenticateData); + + $this->messageManager->addSuccessMessage( + __('You are logged in as customer: %1', $customer->getFirstname() . ' ' . $customer->getLastname()) + ); + $resultRedirect->setPath('*/*/proceed'); + + } catch (LocalizedException $e) { + $this->messageManager->addErrorMessage($e->getMessage()); + $resultRedirect->setPath('/'); + } catch (\Exception $e) { + $this->logger->error($e->getMessage()); + + $this->messageManager->addErrorMessage(__('Cannot login to account.')); + $resultRedirect->setPath('/'); + } + return $resultRedirect; + } +} diff --git a/app/code/Magento/LoginAsCustomerUi/Controller/Login/Proceed.php b/app/code/Magento/LoginAsCustomerUi/Controller/Login/Proceed.php new file mode 100755 index 0000000000000..b722218bef705 --- /dev/null +++ b/app/code/Magento/LoginAsCustomerUi/Controller/Login/Proceed.php @@ -0,0 +1,46 @@ +resultFactory = $resultFactory; + } + + /** + * Proxy page + * + * @return ResultInterface + */ + public function execute(): ResultInterface + { + /** @var Page $resultPage */ + $resultPage = $this->resultFactory->create(ResultFactory::TYPE_PAGE); + $resultPage->getConfig()->getTitle()->set(__('You are logged in')); + return $this->resultFactory->create(ResultFactory::TYPE_PAGE); + } +} diff --git a/app/code/Magento/LoginAsCustomerUi/CustomerData/LoginAsCustomerUi.php b/app/code/Magento/LoginAsCustomerUi/CustomerData/LoginAsCustomerUi.php new file mode 100644 index 0000000000000..be30ee332f621 --- /dev/null +++ b/app/code/Magento/LoginAsCustomerUi/CustomerData/LoginAsCustomerUi.php @@ -0,0 +1,61 @@ +customerSession = $customerSession; + $this->storeManager = $storeManager; + } + + /** + * Retrieve private customer data for the logged_as_customer section + * + * @return array + * @throws LocalizedException + */ + public function getSectionData(): array + { + if (!$this->customerSession->getCustomerId()) { + return []; + } + + return [ + 'adminUserId' => $this->customerSession->getLoggedAsCustomerAdmindId(), + 'websiteName' => $this->storeManager->getWebsite()->getName() + ]; + } +} diff --git a/app/code/Magento/LoginAsCustomerUi/Model/Config/Source/StoreViewLogin.php b/app/code/Magento/LoginAsCustomerUi/Model/Config/Source/StoreViewLogin.php new file mode 100644 index 0000000000000..3d1d627fd7b93 --- /dev/null +++ b/app/code/Magento/LoginAsCustomerUi/Model/Config/Source/StoreViewLogin.php @@ -0,0 +1,35 @@ + self::AUTODETECT, 'label' => __('Auto-Detection (default)')], + ['value' => self::MANUAL, 'label' => __('Manual Choose')], + ]; + } +} diff --git a/app/code/Magento/LoginAsCustomerUi/Plugin/Button/ToolbarPlugin.php b/app/code/Magento/LoginAsCustomerUi/Plugin/Button/ToolbarPlugin.php new file mode 100644 index 0000000000000..3fa54309300ca --- /dev/null +++ b/app/code/Magento/LoginAsCustomerUi/Plugin/Button/ToolbarPlugin.php @@ -0,0 +1,96 @@ +authorization = $authorization; + $this->url = $url; + } + + /** + * Add Login As Customer button. + * + * @param \Magento\Backend\Block\Widget\Button\Toolbar $subject + * @param \Magento\Framework\View\Element\AbstractBlock $context + * @param \Magento\Backend\Block\Widget\Button\ButtonList $buttonList + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + public function beforePushButtons( + Toolbar $subject, + AbstractBlock $context, + ButtonList $buttonList + ):void { + $order = false; + $nameInLayout = $context->getNameInLayout(); + + if ('sales_order_edit' == $nameInLayout) { + $order = $context->getOrder(); + } elseif ('sales_invoice_view' == $nameInLayout) { + $order = $context->getInvoice()->getOrder(); + } elseif ('sales_shipment_view' == $nameInLayout) { + $order = $context->getShipment()->getOrder(); + } elseif ('sales_creditmemo_view' == $nameInLayout) { + $order = $context->getCreditmemo()->getOrder(); + } + if ($order) { + if ($this->isAllowed()) { + if (!empty($order['customer_id'])) { + $buttonUrl = $context->getUrl('loginascustomer/login/login', [ + 'customer_id' => $order['customer_id'] + ]); + $buttonList->add( + 'guest_to_customer', + [ + 'label' => __('Login As Customer'), + 'onclick' => 'window.open(\'' . $buttonUrl . '\')', + 'class' => 'reset' + ], + -1 + ); + } + } + } + } + + /** + * Check is allowed access + * + * @return bool + */ + private function isAllowed(): bool + { + return (bool)$this->authorization->isAllowed('Magento_LoginAsCustomer::login_button'); + } +} diff --git a/app/code/Magento/LoginAsCustomerUi/README.md b/app/code/Magento/LoginAsCustomerUi/README.md new file mode 100644 index 0000000000000..11e8da9310920 --- /dev/null +++ b/app/code/Magento/LoginAsCustomerUi/README.md @@ -0,0 +1,3 @@ +# Magento_LoginAsCustomerSales module + +The Magento_LoginAsCustomerUi module provides UI for Magento_LoginAsCustomerUi diff --git a/app/code/Magento/LoginAsCustomerUi/Ui/Customer/Component/Control/LoginAsCustomerButton.php b/app/code/Magento/LoginAsCustomerUi/Ui/Customer/Component/Control/LoginAsCustomerButton.php new file mode 100644 index 0000000000000..a56dc31b45297 --- /dev/null +++ b/app/code/Magento/LoginAsCustomerUi/Ui/Customer/Component/Control/LoginAsCustomerButton.php @@ -0,0 +1,65 @@ +authorization = $context->getAuthorization(); + } + + /** + * @inheritdoc + */ + public function getButtonData(): array + { + $customerId = $this->getCustomerId(); + $data = []; + $canModify = $customerId && $this->authorization->isAllowed('Magento_LoginAsCustomer::login_button'); + if ($canModify) { + $data = [ + 'label' => __('Login As Customer'), + 'class' => 'login login-button', + 'on_click' => 'window.open( \'' . $this->getLoginUrl() . + '\')', + 'sort_order' => 70, + ]; + } + + return $data; + } + + /** + * Get Login As Customer login url. + * + * @return string + */ + public function getLoginUrl(): string + { + return $this->getUrl('loginascustomer/login/login', ['customer_id' => $this->getCustomerId()]); + } +} diff --git a/app/code/Magento/LoginAsCustomerUi/Ui/Store/Component/Control/LoginAsCustomerButton.php b/app/code/Magento/LoginAsCustomerUi/Ui/Store/Component/Control/LoginAsCustomerButton.php new file mode 100644 index 0000000000000..265e1addc48ab --- /dev/null +++ b/app/code/Magento/LoginAsCustomerUi/Ui/Store/Component/Control/LoginAsCustomerButton.php @@ -0,0 +1,34 @@ + __('Login As Customer'), + 'class' => 'save primary', + 'data_attribute' => [ + 'mage-init' => ['button' => ['event' => 'save']], + 'form-role' => 'save', + ], + 'sort_order' => 90, + ]; + } +} diff --git a/app/code/Magento/LoginAsCustomerUi/Ui/Store/DataProvider/Form/StoreDataProvider.php b/app/code/Magento/LoginAsCustomerUi/Ui/Store/DataProvider/Form/StoreDataProvider.php new file mode 100644 index 0000000000000..03549c69c2879 --- /dev/null +++ b/app/code/Magento/LoginAsCustomerUi/Ui/Store/DataProvider/Form/StoreDataProvider.php @@ -0,0 +1,37 @@ +collection = $collectionFactory->create(); + parent::__construct($name, $primaryFieldName, $requestFieldName, $meta, $data); + } +} diff --git a/app/code/Magento/LoginAsCustomerUi/ViewModel/Configuration.php b/app/code/Magento/LoginAsCustomerUi/ViewModel/Configuration.php new file mode 100644 index 0000000000000..7cbe30b116194 --- /dev/null +++ b/app/code/Magento/LoginAsCustomerUi/ViewModel/Configuration.php @@ -0,0 +1,59 @@ +config = $config; + $this->httpContext = $httpContext; + } + + /** + * Retrieve true if login as a customer is enabled + * + * @return bool + */ + public function isEnabled(): bool + { + return $this->config->isEnabled() && $this->isLoggedIn(); + } + + /** + * Is logged in + * + * @return bool + */ + private function isLoggedIn(): bool + { + return (bool)$this->httpContext->getValue(Context::CONTEXT_AUTH); + } +} diff --git a/app/code/Magento/LoginAsCustomerUi/composer.json b/app/code/Magento/LoginAsCustomerUi/composer.json new file mode 100644 index 0000000000000..954b5bd1d66e1 --- /dev/null +++ b/app/code/Magento/LoginAsCustomerUi/composer.json @@ -0,0 +1,27 @@ +{ + "name": "magento/module-login-as-customer-ui", + "description": "", + "require": { + "php": "~7.1.3||~7.2.0||~7.3.0", + "magento/framework": "*", + "magento/module-login-as-customer-api": "*", + "magento/module-backend": "*", + "magento/module-customer": "*", + "magento/module-store": "*", + "magento/module-ui": "*" + }, + "suggest": { + "magento/module-login-as-customer": "*" + }, + "type": "magento2-module", + "license": [ + "OSL-3.0", + "AFL-3.0" + ], + "autoload": { + "files": [ "registration.php" ], + "psr-4": { + "Magento\\LoginAsCustomerUi\\": "" + } + } +} diff --git a/app/code/Magento/LoginAsCustomerUi/etc/acl.xml b/app/code/Magento/LoginAsCustomerUi/etc/acl.xml new file mode 100755 index 0000000000000..f49526f6bbb04 --- /dev/null +++ b/app/code/Magento/LoginAsCustomerUi/etc/acl.xml @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/code/Magento/LoginAsCustomerUi/etc/adminhtml/di.xml b/app/code/Magento/LoginAsCustomerUi/etc/adminhtml/di.xml new file mode 100644 index 0000000000000..ba85241397dd3 --- /dev/null +++ b/app/code/Magento/LoginAsCustomerUi/etc/adminhtml/di.xml @@ -0,0 +1,12 @@ + + + + + + + diff --git a/app/code/Magento/LoginAsCustomerUi/etc/adminhtml/routes.xml b/app/code/Magento/LoginAsCustomerUi/etc/adminhtml/routes.xml new file mode 100755 index 0000000000000..1122e490db306 --- /dev/null +++ b/app/code/Magento/LoginAsCustomerUi/etc/adminhtml/routes.xml @@ -0,0 +1,14 @@ + + + + + + + + + diff --git a/app/code/Magento/LoginAsCustomerUi/etc/adminhtml/system.xml b/app/code/Magento/LoginAsCustomerUi/etc/adminhtml/system.xml new file mode 100755 index 0000000000000..d0c5da375ecbe --- /dev/null +++ b/app/code/Magento/LoginAsCustomerUi/etc/adminhtml/system.xml @@ -0,0 +1,32 @@ + + + + + + separator-top + Login As Customer + customer + Magento_LoginAsCustomer::config_section + + Login As Customer Information + + Enable Extension + Magento\Config\Model\Config\Source\Yesno + + + Store View To Login In + Magento\LoginAsCustomerUi\Model\Config\Source\StoreViewLogin + + + + + + diff --git a/app/code/Magento/LoginAsCustomerUi/etc/frontend/di.xml b/app/code/Magento/LoginAsCustomerUi/etc/frontend/di.xml new file mode 100755 index 0000000000000..b102505de49f8 --- /dev/null +++ b/app/code/Magento/LoginAsCustomerUi/etc/frontend/di.xml @@ -0,0 +1,16 @@ + + + + + + + Magento\LoginAsCustomerUi\CustomerData\LoginAsCustomerUi + + + + diff --git a/app/code/Magento/LoginAsCustomerUi/etc/frontend/routes.xml b/app/code/Magento/LoginAsCustomerUi/etc/frontend/routes.xml new file mode 100755 index 0000000000000..7336b032b21c6 --- /dev/null +++ b/app/code/Magento/LoginAsCustomerUi/etc/frontend/routes.xml @@ -0,0 +1,14 @@ + + + + + + + + + diff --git a/app/code/Magento/LoginAsCustomerUi/etc/module.xml b/app/code/Magento/LoginAsCustomerUi/etc/module.xml new file mode 100644 index 0000000000000..c937de225c306 --- /dev/null +++ b/app/code/Magento/LoginAsCustomerUi/etc/module.xml @@ -0,0 +1,11 @@ + + + + + diff --git a/app/code/Magento/LoginAsCustomerUi/registration.php b/app/code/Magento/LoginAsCustomerUi/registration.php new file mode 100644 index 0000000000000..501dc6a7ca382 --- /dev/null +++ b/app/code/Magento/LoginAsCustomerUi/registration.php @@ -0,0 +1,12 @@ + + + + + + + + + diff --git a/app/code/Magento/LoginAsCustomerUi/view/adminhtml/ui_component/customer_form.xml b/app/code/Magento/LoginAsCustomerUi/view/adminhtml/ui_component/customer_form.xml new file mode 100755 index 0000000000000..96aefae34299e --- /dev/null +++ b/app/code/Magento/LoginAsCustomerUi/view/adminhtml/ui_component/customer_form.xml @@ -0,0 +1,16 @@ + + + + + + + + + diff --git a/app/code/Magento/LoginAsCustomerUi/view/adminhtml/ui_component/manual_store_form.xml b/app/code/Magento/LoginAsCustomerUi/view/adminhtml/ui_component/manual_store_form.xml new file mode 100644 index 0000000000000..9c0b2068b31be --- /dev/null +++ b/app/code/Magento/LoginAsCustomerUi/view/adminhtml/ui_component/manual_store_form.xml @@ -0,0 +1,80 @@ + + + + + + + manual_store_form.manual_store_form_data_source + + templates/form/collapsible + + + + + + data + + manual_store_form.manual_store_form_data_source + + + + + + + + + entity_id + entity_id + + + + + + + Stores + false + + + + + page + + + + false + text + entity_id + + + + + + page + 0 + + + + Store View + int + store_id + + true + + + + + + + + + + + + diff --git a/app/code/Magento/LoginAsCustomerUi/view/frontend/layout/default.xml b/app/code/Magento/LoginAsCustomerUi/view/frontend/layout/default.xml new file mode 100644 index 0000000000000..c27f3adcf23cc --- /dev/null +++ b/app/code/Magento/LoginAsCustomerUi/view/frontend/layout/default.xml @@ -0,0 +1,23 @@ + + + + + + + + Magento\LoginAsCustomerUi\ViewModel\Configuration + + + + + + + + + diff --git a/app/code/Magento/LoginAsCustomerUi/view/frontend/layout/loginascustomer_login_proceed.xml b/app/code/Magento/LoginAsCustomerUi/view/frontend/layout/loginascustomer_login_proceed.xml new file mode 100644 index 0000000000000..e7c3010a86364 --- /dev/null +++ b/app/code/Magento/LoginAsCustomerUi/view/frontend/layout/loginascustomer_login_proceed.xml @@ -0,0 +1,19 @@ + + + + + + + You are logged in. + + + + + + + diff --git a/app/code/Magento/LoginAsCustomerUi/view/frontend/templates/html/notices.phtml b/app/code/Magento/LoginAsCustomerUi/view/frontend/templates/html/notices.phtml new file mode 100644 index 0000000000000..a2358cdb2f18b --- /dev/null +++ b/app/code/Magento/LoginAsCustomerUi/view/frontend/templates/html/notices.phtml @@ -0,0 +1,42 @@ +getViewFileUrl('Magento_LoginAsCustomerUi::images/magento-icon.svg'); +?> +getConfig()->isEnabled()): ?> + + + + + + + + + + + = $block->getChildHtml('login-as-customer-notice-links') ?> + + + + + + diff --git a/app/code/Magento/LoginAsCustomerUi/view/frontend/templates/html/notices/logout-link.phtml b/app/code/Magento/LoginAsCustomerUi/view/frontend/templates/html/notices/logout-link.phtml new file mode 100644 index 0000000000000..ae29324ade0a1 --- /dev/null +++ b/app/code/Magento/LoginAsCustomerUi/view/frontend/templates/html/notices/logout-link.phtml @@ -0,0 +1,21 @@ +isLoggedIn()) { + $dataPostParam = sprintf(" data-post='%s'", $block->getPostParams()); +} +?> + +getLinkAttributes() +?>= /* @noEscape */ $dataPostParam ?>> + = $escaper->escapeHtml(__('Close Session')) ?> + + diff --git a/app/code/Magento/LoginAsCustomerUi/view/frontend/templates/login.phtml b/app/code/Magento/LoginAsCustomerUi/view/frontend/templates/login.phtml new file mode 100644 index 0000000000000..2abd8fc204831 --- /dev/null +++ b/app/code/Magento/LoginAsCustomerUi/view/frontend/templates/login.phtml @@ -0,0 +1,17 @@ + + + diff --git a/app/code/Magento/LoginAsCustomerUi/view/frontend/web/css/source/_module.less b/app/code/Magento/LoginAsCustomerUi/view/frontend/web/css/source/_module.less new file mode 100644 index 0000000000000..372405c2635ef --- /dev/null +++ b/app/code/Magento/LoginAsCustomerUi/view/frontend/web/css/source/_module.less @@ -0,0 +1,77 @@ +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +// +// Variables +// --------------------------------------------- + +@lac-notification-background-color: #373330; +@lac-notification-color: #fff; +@lac-notification-links-color: #fff; + +// +// Common +// --------------------------------------------- + +& when (@media-common = true) { + .lac-notification { + background-color: @lac-notification-background-color; + color: @lac-notification-color; + font-size: 16px; + + .lac-notification-icon { + float: left; + margin: 10px 25px 10px 10px; + + .logo-img { + display: block + } + } + + .lac-notification-text { + float: left; + padding: 15px 0; + } + + .lac-notification-links { + float: right; + padding: 15px 0; + + a { + color: @lac-notification-links-color; + font-size: 14px; + } + + .lac-notification-close-link { + &:after { + background: url('../Magento_LoginAsCustomerUi/images/close.svg'); + content: ' '; + display: inline-block; + height: 12px; + margin-left: 5px; + vertical-align: middle; + width: 12px; + } + } + } + } +} + +.media-width(@extremum, @break) when (@extremum = 'max') and (@break = @screen__m) { + .lac-notification { + padding: 5px 0; + + .lac-notification-icon { + display: none; + } + + .lac-notification-text, + .lac-notification-links { + float: none; + padding: 5px 0; + text-align: center; + } + } +} diff --git a/app/code/Magento/LoginAsCustomerUi/view/frontend/web/images/close.svg b/app/code/Magento/LoginAsCustomerUi/view/frontend/web/images/close.svg new file mode 100644 index 0000000000000..0895684d12e63 --- /dev/null +++ b/app/code/Magento/LoginAsCustomerUi/view/frontend/web/images/close.svg @@ -0,0 +1,2 @@ + + diff --git a/app/code/Magento/LoginAsCustomerUi/view/frontend/web/images/magento-icon.svg b/app/code/Magento/LoginAsCustomerUi/view/frontend/web/images/magento-icon.svg new file mode 100644 index 0000000000000..47e64067795ef --- /dev/null +++ b/app/code/Magento/LoginAsCustomerUi/view/frontend/web/images/magento-icon.svg @@ -0,0 +1 @@ + diff --git a/app/code/Magento/LoginAsCustomerUi/view/frontend/web/js/login.js b/app/code/Magento/LoginAsCustomerUi/view/frontend/web/js/login.js new file mode 100644 index 0000000000000..1e59c988015ec --- /dev/null +++ b/app/code/Magento/LoginAsCustomerUi/view/frontend/web/js/login.js @@ -0,0 +1,18 @@ +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +define([ + 'Magento_Customer/js/customer-data', + 'Magento_Customer/js/section-config' +], function (customerData, sectionConfig) { + + 'use strict'; + + return function (config) { + customerData.reload(sectionConfig.getSectionNames()).done(function () { + window.location.href = config.redirectUrl; + }); + }; +}); diff --git a/app/code/Magento/LoginAsCustomerUi/view/frontend/web/js/view/loginAsCustomer.js b/app/code/Magento/LoginAsCustomerUi/view/frontend/web/js/view/loginAsCustomer.js new file mode 100644 index 0000000000000..7f6cad6ce3f2d --- /dev/null +++ b/app/code/Magento/LoginAsCustomerUi/view/frontend/web/js/view/loginAsCustomer.js @@ -0,0 +1,41 @@ +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +define([ + 'jquery', + 'uiComponent', + 'Magento_Customer/js/customer-data', + 'mage/translate' +], function ($, Component, customerData) { + 'use strict'; + + return Component.extend({ + + defaults: { + isVisible: false + }, + + /** @inheritdoc */ + initialize: function () { + this._super(); + + this.customer = customerData.get('customer'); + this.loginAsCustomer = customerData.get('loggedAsCustomer'); + this.isVisible(this.loginAsCustomer().adminUserId); + + this.notificationText = $.mage.__('You are connected as %1 on %2') + .replace('%1', this.customer().fullname) + .replace('%2', this.loginAsCustomer().websiteName); + }, + + /** @inheritdoc */ + initObservable: function () { + this._super() + .observe('isVisible'); + + return this; + } + }); +}); diff --git a/app/code/Magento/Paypal/Controller/Express/GetTokenData.php b/app/code/Magento/Paypal/Controller/Express/GetTokenData.php index 512dac4cdec06..5c41e753e8a95 100644 --- a/app/code/Magento/Paypal/Controller/Express/GetTokenData.php +++ b/app/code/Magento/Paypal/Controller/Express/GetTokenData.php @@ -152,6 +152,10 @@ public function execute(): ResultInterface $responseContent['error_message'] = __('Sorry, but something went wrong'); } + if (!$responseContent['success']) { + $this->messageManager->addErrorMessage($responseContent['error_message']); + } + return $controllerResult->setData($responseContent); } diff --git a/app/code/Magento/Paypal/Controller/Express/OnAuthorization.php b/app/code/Magento/Paypal/Controller/Express/OnAuthorization.php index 0d7ec3fc6f32d..b496c7f10d937 100644 --- a/app/code/Magento/Paypal/Controller/Express/OnAuthorization.php +++ b/app/code/Magento/Paypal/Controller/Express/OnAuthorization.php @@ -10,6 +10,7 @@ use Magento\Framework\Controller\ResultFactory; use Magento\Framework\App\Action\HttpPostActionInterface; use Magento\Framework\Controller\ResultInterface; +use Magento\Framework\Exception\LocalizedException; use Magento\Paypal\Model\Config as PayPalConfig; use Magento\Paypal\Model\Express\Checkout as PayPalCheckout; use Magento\Paypal\Model\Api\ProcessableException as ApiProcessableException; @@ -160,7 +161,7 @@ public function execute(): ResultInterface } catch (ApiProcessableException $e) { $responseContent['success'] = false; $responseContent['error_message'] = $e->getUserMessage(); - } catch (\Magento\Framework\Exception\LocalizedException $e) { + } catch (LocalizedException $e) { $responseContent['success'] = false; $responseContent['error_message'] = $e->getMessage(); } catch (\Exception $e) { @@ -168,6 +169,10 @@ public function execute(): ResultInterface $responseContent['error_message'] = __('We can\'t process Express Checkout approval.'); } + if (!$responseContent['success']) { + $this->messageManager->addErrorMessage($responseContent['error_message']); + } + return $controllerResult->setData($responseContent); } } diff --git a/app/code/Magento/Paypal/Model/Config.php b/app/code/Magento/Paypal/Model/Config.php index 6f6728ebfa47f..c790a4524f18b 100644 --- a/app/code/Magento/Paypal/Model/Config.php +++ b/app/code/Magento/Paypal/Model/Config.php @@ -1512,7 +1512,10 @@ protected function _mapExpressFieldset($fieldName) case 'allow_ba_signup': case 'in_context': case 'merchant_id': + case 'client_id': + case 'sandbox_client_id': case 'supported_locales': + case 'smart_buttons_supported_locales': return "payment/{$this->_methodCode}/{$fieldName}"; default: return $this->_mapMethodFieldset($fieldName); diff --git a/app/code/Magento/Paypal/Model/Express/LocaleResolver.php b/app/code/Magento/Paypal/Model/Express/LocaleResolver.php index c9136d03036d2..656e33b108fa9 100644 --- a/app/code/Magento/Paypal/Model/Express/LocaleResolver.php +++ b/app/code/Magento/Paypal/Model/Express/LocaleResolver.php @@ -89,7 +89,9 @@ public function setLocale($locale = null) public function getLocale(): string { $locale = $this->localeMap[$this->resolver->getLocale()] ?? $this->resolver->getLocale(); - $allowedLocales = $this->config->getValue('supported_locales'); + $allowedLocales =(bool)(int) $this->config->getValue('in_context') + ? $this->config->getValue('smart_buttons_supported_locales') + : $this->config->getValue('supported_locales'); return strpos($allowedLocales, $locale) !== false ? $locale : 'en_US'; } diff --git a/app/code/Magento/Paypal/Model/SmartButtonConfig.php b/app/code/Magento/Paypal/Model/SmartButtonConfig.php index 921dc4679b089..88d68511ae5fe 100644 --- a/app/code/Magento/Paypal/Model/SmartButtonConfig.php +++ b/app/code/Magento/Paypal/Model/SmartButtonConfig.php @@ -11,9 +11,10 @@ use Magento\Framework\App\Config\ScopeConfigInterface; use Magento\Framework\Locale\ResolverInterface; use Magento\Store\Model\ScopeInterface; +use Magento\Paypal\Model\Config as PayPalConfig; /** - * Smart button configuration. + * Provides configuration values for PayPal in-context checkout */ class SmartButtonConfig { @@ -33,35 +34,50 @@ class SmartButtonConfig private $defaultStyles; /** + * @var ScopeConfigInterface + */ + private $scopeConfig; + + /** + * Maps the old checkout SDK configuration values to the current ones * @var array */ - private $allowedFunding; + private $disallowedFundingMap; /** - * @var ScopeConfigInterface + * These payment methods will be added as parameters to the SDK url to disable them. + * @var array */ - private $scopeConfig; + private $unsupportedPaymentMethods; + + /** + * Base url for Paypal SDK + */ + private const BASE_URL = 'https://www.paypal.com/sdk/js?'; /** * @param ResolverInterface $localeResolver * @param ConfigFactory $configFactory * @param ScopeConfigInterface $scopeConfig * @param array $defaultStyles - * @param array $allowedFunding + * @param array $disallowedFundingMap + * @param array $unsupportedPaymentMethods */ public function __construct( ResolverInterface $localeResolver, ConfigFactory $configFactory, ScopeConfigInterface $scopeConfig, $defaultStyles = [], - $allowedFunding = [] + $disallowedFundingMap = [], + $unsupportedPaymentMethods = [] ) { $this->localeResolver = $localeResolver; $this->config = $configFactory->create(); $this->config->setMethod(Config::METHOD_EXPRESS); $this->scopeConfig = $scopeConfig; $this->defaultStyles = $defaultStyles; - $this->allowedFunding = $allowedFunding; + $this->disallowedFundingMap = $disallowedFundingMap; + $this->unsupportedPaymentMethods = $unsupportedPaymentMethods; } /** @@ -76,20 +92,63 @@ public function getConfig(string $page): array Data::XML_PATH_GUEST_CHECKOUT, ScopeInterface::SCOPE_STORE ); + return [ - 'merchantId' => $this->config->getValue('merchant_id'), - 'environment' => ((int)$this->config->getValue('sandbox_flag') ? 'sandbox' : 'production'), - 'locale' => $this->localeResolver->getLocale(), - 'allowedFunding' => $this->getAllowedFunding($page), - 'disallowedFunding' => $this->getDisallowedFunding(), 'styles' => $this->getButtonStyles($page), 'isVisibleOnProductPage' => (bool)$this->config->getValue('visible_on_product'), - 'isGuestCheckoutAllowed' => $isGuestCheckoutAllowed + 'isGuestCheckoutAllowed' => $isGuestCheckoutAllowed, + 'sdkUrl' => $this->generatePaypalSdkUrl($page) ]; } /** - * Returns disallowed funding from configuration + * Generate the url to download the Paypal SDK + * + * @param string $page + * + * @return string + */ + private function generatePaypalSdkUrl(string $page): string + { + $clientId = (int)$this->config->getValue('sandbox_flag') ? + $this->config->getValue('sandbox_client_id') : $this->config->getValue('client_id'); + $disallowedFunding = implode(',', $this->getDisallowedFunding()); + + $commit = $page === 'checkout' ? 'true' : 'false'; + + $params = + [ + 'client-id' => $clientId, + 'commit' => $commit, + 'merchant-id' => $this->config->getValue('merchant_id'), + 'locale' => $this->localeResolver->getLocale(), + 'intent' => $this->getIntent(), + ]; + if ($disallowedFunding) { + $params['disable-funding'] = $disallowedFunding; + } + + return self::BASE_URL . http_build_query($params); + } + + /** + * Return intent value from the configuration payment_action value + * + * @return string + */ + private function getIntent(): string + { + $paymentAction = $this->config->getValue('paymentAction'); + $mappedIntentValues = [ + Config::PAYMENT_ACTION_AUTH => 'authorize', + Config::PAYMENT_ACTION_SALE => 'capture', + Config::PAYMENT_ACTION_ORDER => 'order' + ]; + return $mappedIntentValues[$paymentAction]; + } + + /** + * Returns disallowed funding from configuration after updating values * * @return array */ @@ -103,18 +162,17 @@ private function getDisallowedFunding(): array array_push($result, 'CARD'); } - return $result; - } + // Map old configuration values to current ones + $result = array_map(function ($oldValue) { + return $this->disallowedFundingMap[$oldValue] ?? $oldValue; + }, + $result); - /** - * Returns allowed funding - * - * @param string $page - * @return array - */ - private function getAllowedFunding(string $page): array - { - return array_values(array_diff($this->allowedFunding[$page], $this->getDisallowedFunding())); + //disable unsupported payment methods + $result = array_combine($result, $result); + $result = array_merge($result, $this->unsupportedPaymentMethods); + + return $result; } /** @@ -165,7 +223,7 @@ private function updateStyles(array $styles, string $page): array // Installment label is only available for specific locales if ($styles['label'] === 'installment') { if (array_key_exists($locale, $installmentPeriodLocale)) { - $styles['installmentperiod'] = (int)$this->config->getValue( + $styles['period'] = (int)$this->config->getValue( $page .'_page_button_' . $installmentPeriodLocale[$locale] . '_installment_period' ); } else { diff --git a/app/code/Magento/Paypal/Model/System/Config/Source/ButtonStyles.php b/app/code/Magento/Paypal/Model/System/Config/Source/ButtonStyles.php index 8ad55d045ff1a..d55fd216c06b5 100644 --- a/app/code/Magento/Paypal/Model/System/Config/Source/ButtonStyles.php +++ b/app/code/Magento/Paypal/Model/System/Config/Source/ButtonStyles.php @@ -53,20 +53,6 @@ public function getShape(): array ]; } - /** - * Button size source getter - * - * @return array - */ - public function getSize(): array - { - return [ - 'medium' => __('Medium'), - 'large' => __('Large'), - 'responsive' => __('Responsive') - ]; - } - /** * Button label source getter * @@ -80,7 +66,6 @@ public function getLabel(): array 'buynow' => __('Buy Now'), 'paypal' => __('PayPal'), 'installment' => __('Installment'), - 'credit' => __('Credit') ]; } diff --git a/app/code/Magento/Paypal/Model/System/Config/Source/DisableFundingOptions.php b/app/code/Magento/Paypal/Model/System/Config/Source/DisableFundingOptions.php index 1a9cfe0998fb8..a06949402956d 100644 --- a/app/code/Magento/Paypal/Model/System/Config/Source/DisableFundingOptions.php +++ b/app/code/Magento/Paypal/Model/System/Config/Source/DisableFundingOptions.php @@ -12,24 +12,35 @@ */ class DisableFundingOptions { + + /** + * @var array + */ + private $disallowedFundingOptions; + + /** + * DisableFundingOptions constructor. + * @param array $disallowedFundingOptions + */ + public function __construct($disallowedFundingOptions = []) + { + $this->disallowedFundingOptions = $disallowedFundingOptions; + } + /** * @inheritdoc */ public function toOptionArray(): array { - return [ - [ - 'value' => 'CREDIT', - 'label' => __('PayPal Credit') - ], - [ - 'value' => 'CARD', - 'label' => __('PayPal Guest Checkout Credit Card Icons') - ], - [ - 'value' => 'ELV', - 'label' => __('Elektronisches Lastschriftverfahren - German ELV') - ] - ]; + return array_map( + function ($key, $value) { + return [ + 'value' => $key, + 'label' => __($value) + ]; + }, + array_keys($this->disallowedFundingOptions), + $this->disallowedFundingOptions + ); } } diff --git a/app/code/Magento/Paypal/Setup/Patch/Data/UpdateSmartButtonLabel.php b/app/code/Magento/Paypal/Setup/Patch/Data/UpdateSmartButtonLabel.php new file mode 100644 index 0000000000000..2a8ed1fa07aee --- /dev/null +++ b/app/code/Magento/Paypal/Setup/Patch/Data/UpdateSmartButtonLabel.php @@ -0,0 +1,77 @@ +moduleDataSetup = $moduleDataSetup; + } + + /** + * @inheritdoc + */ + public function apply() + { + $this->moduleDataSetup->getConnection()->startSetup(); + $this->moduleDataSetup->getConnection()->update( + $this->moduleDataSetup->getTable('core_config_data'), + ['value' => 'paypal'], + [ + 'path IN (?)' => [ + 'paypal/style/checkout_page_button_label', + 'paypal/style/cart_page_button_label', + 'paypal/style/mini_cart_page_button_label' + ], + 'value = ? ' => 'credit' + ] + ); + $this->moduleDataSetup->getConnection()->update( + $this->moduleDataSetup->getTable('core_config_data'), + ['value' => 'buynow'], + [ + 'path IN (?)' => ['paypal/style/product_page_button_label'], + 'value = ? ' => 'credit' + ] + ); + return $this->moduleDataSetup->getConnection()->endSetup(); + } + + /** + * @inheritdoc + */ + public static function getDependencies() + { + return []; + } + + /** + * @inheritdoc + */ + public function getAliases() + { + return []; + } +} diff --git a/app/code/Magento/Paypal/Setup/Patch/Data/UpdateSmartButtonSize.php b/app/code/Magento/Paypal/Setup/Patch/Data/UpdateSmartButtonSize.php new file mode 100644 index 0000000000000..349fa64bfcc71 --- /dev/null +++ b/app/code/Magento/Paypal/Setup/Patch/Data/UpdateSmartButtonSize.php @@ -0,0 +1,75 @@ +moduleDataSetup = $moduleDataSetup; + } + + /** + * @inheritdoc + */ + public function apply() + { + $this->moduleDataSetup->getConnection()->startSetup(); + $this->moduleDataSetup->getConnection()->update( + $this->moduleDataSetup->getTable('core_config_data'), + ['value' => 'responsive'], + [ + 'path IN (?)' => $this->sizeSettingsToUpdate, + 'value NOT IN (?) ' => ['responsive'] + ] + ); + return $this->moduleDataSetup->getConnection()->endSetup(); + } + + /** + * @inheritdoc + */ + public static function getDependencies() + { + return []; + } + + /** + * @inheritdoc + */ + public function getAliases() + { + return []; + } +} diff --git a/app/code/Magento/Paypal/Test/Mftf/ActionGroup/AssertPayPalButtonLayoutActionGroup.xml b/app/code/Magento/Paypal/Test/Mftf/ActionGroup/AssertPayPalButtonLayoutActionGroup.xml new file mode 100644 index 0000000000000..d8ad106e8c6da --- /dev/null +++ b/app/code/Magento/Paypal/Test/Mftf/ActionGroup/AssertPayPalButtonLayoutActionGroup.xml @@ -0,0 +1,27 @@ + + + + + + + Assert Paypal button layout when user customize button + + + + + + + + + + + + + + diff --git a/app/code/Magento/Paypal/Test/Mftf/ActionGroup/AssertPayPalButtonLayoutInPaypalLabelActionGroup.xml b/app/code/Magento/Paypal/Test/Mftf/ActionGroup/AssertPayPalButtonLayoutInPaypalLabelActionGroup.xml new file mode 100644 index 0000000000000..28aba7b833f8c --- /dev/null +++ b/app/code/Magento/Paypal/Test/Mftf/ActionGroup/AssertPayPalButtonLayoutInPaypalLabelActionGroup.xml @@ -0,0 +1,19 @@ + + + + + + + Assert Paypal button layout when layout is horizontal + + + + + + diff --git a/app/code/Magento/Paypal/Test/Mftf/ActionGroup/ConfigPayPalExpressCheckoutActionGroup.xml b/app/code/Magento/Paypal/Test/Mftf/ActionGroup/ConfigPayPalExpressCheckoutActionGroup.xml index 90f0a25a8cd69..01ec295d8bf63 100644 --- a/app/code/Magento/Paypal/Test/Mftf/ActionGroup/ConfigPayPalExpressCheckoutActionGroup.xml +++ b/app/code/Magento/Paypal/Test/Mftf/ActionGroup/ConfigPayPalExpressCheckoutActionGroup.xml @@ -28,6 +28,7 @@ + diff --git a/app/code/Magento/Paypal/Test/Mftf/ActionGroup/OpenPayPalButtonCheckoutPageActionGroup.xml b/app/code/Magento/Paypal/Test/Mftf/ActionGroup/OpenPayPalButtonCheckoutPageActionGroup.xml index 2b559085a83b5..bf4bce4a8fa09 100644 --- a/app/code/Magento/Paypal/Test/Mftf/ActionGroup/OpenPayPalButtonCheckoutPageActionGroup.xml +++ b/app/code/Magento/Paypal/Test/Mftf/ActionGroup/OpenPayPalButtonCheckoutPageActionGroup.xml @@ -15,7 +15,7 @@ - + diff --git a/app/code/Magento/Paypal/Test/Mftf/ActionGroup/PayPalAssertTransferLineAndShippingMethodActionGroup.xml b/app/code/Magento/Paypal/Test/Mftf/ActionGroup/PayPalAssertTransferLineAndShippingMethodActionGroup.xml new file mode 100644 index 0000000000000..f9cef514c2bf0 --- /dev/null +++ b/app/code/Magento/Paypal/Test/Mftf/ActionGroup/PayPalAssertTransferLineAndShippingMethodActionGroup.xml @@ -0,0 +1,23 @@ + + + + + + + Assert Transfer Cart Line and Shipping Method + + + + + + + + + + diff --git a/app/code/Magento/Paypal/Test/Mftf/ActionGroup/PayPalAssertTransferLineAndShippingMethodNotExistActionGroup.xml b/app/code/Magento/Paypal/Test/Mftf/ActionGroup/PayPalAssertTransferLineAndShippingMethodNotExistActionGroup.xml new file mode 100644 index 0000000000000..b90c3e70db097 --- /dev/null +++ b/app/code/Magento/Paypal/Test/Mftf/ActionGroup/PayPalAssertTransferLineAndShippingMethodNotExistActionGroup.xml @@ -0,0 +1,18 @@ + + + + + + + Assert Transfer Cart Line and Shipping Method not exist on paypal side + + + + + diff --git a/app/code/Magento/Paypal/Test/Mftf/ActionGroup/StorefrontLoginToPayPalPaymentAccountOneStepActionGroup.xml b/app/code/Magento/Paypal/Test/Mftf/ActionGroup/StorefrontLoginToPayPalPaymentAccountOneStepActionGroup.xml new file mode 100644 index 0000000000000..c4cad5f3d4cd4 --- /dev/null +++ b/app/code/Magento/Paypal/Test/Mftf/ActionGroup/StorefrontLoginToPayPalPaymentAccountOneStepActionGroup.xml @@ -0,0 +1,16 @@ + + + + + + EXTENDS: StorefrontLoginToPayPalPaymentAccountOneStepActionGroup. Remove extra Continue step on PayPal site + + + + diff --git a/app/code/Magento/Paypal/Test/Mftf/ActionGroup/StorefrontLoginToPayPalPaymentAccountTwoStepActionGroup.xml b/app/code/Magento/Paypal/Test/Mftf/ActionGroup/StorefrontLoginToPayPalPaymentAccountTwoStepActionGroup.xml new file mode 100644 index 0000000000000..5619aa27860ce --- /dev/null +++ b/app/code/Magento/Paypal/Test/Mftf/ActionGroup/StorefrontLoginToPayPalPaymentAccountTwoStepActionGroup.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/code/Magento/Paypal/Test/Mftf/ActionGroup/StorefrontLoginToPayPalPaymentFromCartActionGroup.xml b/app/code/Magento/Paypal/Test/Mftf/ActionGroup/StorefrontLoginToPayPalPaymentFromCartActionGroup.xml new file mode 100644 index 0000000000000..f627b9158f868 --- /dev/null +++ b/app/code/Magento/Paypal/Test/Mftf/ActionGroup/StorefrontLoginToPayPalPaymentFromCartActionGroup.xml @@ -0,0 +1,14 @@ + + + + + + + + diff --git a/app/code/Magento/Paypal/Test/Mftf/ActionGroup/StorefrontPayOrderOnPayPalCheckoutActionGroup.xml b/app/code/Magento/Paypal/Test/Mftf/ActionGroup/StorefrontPayOrderOnPayPalCheckoutActionGroup.xml index b7ebf7dab1c8b..8e337abfb2610 100644 --- a/app/code/Magento/Paypal/Test/Mftf/ActionGroup/StorefrontPayOrderOnPayPalCheckoutActionGroup.xml +++ b/app/code/Magento/Paypal/Test/Mftf/ActionGroup/StorefrontPayOrderOnPayPalCheckoutActionGroup.xml @@ -18,7 +18,7 @@ - + diff --git a/app/code/Magento/Paypal/Test/Mftf/ActionGroup/StorefrontPayPalPaymentActionGroup.xml b/app/code/Magento/Paypal/Test/Mftf/ActionGroup/StorefrontPayPalPaymentActionGroup.xml index 331acc1de628a..655a93b2e5044 100644 --- a/app/code/Magento/Paypal/Test/Mftf/ActionGroup/StorefrontPayPalPaymentActionGroup.xml +++ b/app/code/Magento/Paypal/Test/Mftf/ActionGroup/StorefrontPayPalPaymentActionGroup.xml @@ -9,13 +9,12 @@ xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd"> - - + - + - + diff --git a/app/code/Magento/Paypal/Test/Mftf/ActionGroup/StorefrontPaypalSwitchBackToMagentoActionGroup.xml b/app/code/Magento/Paypal/Test/Mftf/ActionGroup/StorefrontPaypalSwitchBackToMagentoActionGroup.xml new file mode 100644 index 0000000000000..5fff967ebdb7d --- /dev/null +++ b/app/code/Magento/Paypal/Test/Mftf/ActionGroup/StorefrontPaypalSwitchBackToMagentoActionGroup.xml @@ -0,0 +1,23 @@ + + + + + + + Click continue button on Paypal site and go back to Magento site + + + + + + + + + + diff --git a/app/code/Magento/Paypal/Test/Mftf/ActionGroup/StorefrontPaypalSwitchBackToMagentoFromCheckoutPageActionGroup.xml b/app/code/Magento/Paypal/Test/Mftf/ActionGroup/StorefrontPaypalSwitchBackToMagentoFromCheckoutPageActionGroup.xml new file mode 100644 index 0000000000000..1053a08951d40 --- /dev/null +++ b/app/code/Magento/Paypal/Test/Mftf/ActionGroup/StorefrontPaypalSwitchBackToMagentoFromCheckoutPageActionGroup.xml @@ -0,0 +1,20 @@ + + + + + + + Click submit button on Paypal site and go back to Magento site + + + + + + + diff --git a/app/code/Magento/Paypal/Test/Mftf/ActionGroup/StorefrontPlaceOrderOnOrderReviewPageActionGroup.xml b/app/code/Magento/Paypal/Test/Mftf/ActionGroup/StorefrontPlaceOrderOnOrderReviewPageActionGroup.xml new file mode 100644 index 0000000000000..07b8302a941b0 --- /dev/null +++ b/app/code/Magento/Paypal/Test/Mftf/ActionGroup/StorefrontPlaceOrderOnOrderReviewPageActionGroup.xml @@ -0,0 +1,17 @@ + + + + + + Place order on Order Review Page after back from PayPal side + + + + + diff --git a/app/code/Magento/Paypal/Test/Mftf/ActionGroup/StorefrontSelectShippingMethodOnOrderReviewPageActionGroup.xml b/app/code/Magento/Paypal/Test/Mftf/ActionGroup/StorefrontSelectShippingMethodOnOrderReviewPageActionGroup.xml new file mode 100644 index 0000000000000..003ef5645c147 --- /dev/null +++ b/app/code/Magento/Paypal/Test/Mftf/ActionGroup/StorefrontSelectShippingMethodOnOrderReviewPageActionGroup.xml @@ -0,0 +1,21 @@ + + + + + + Select Shipping method on Order Review page + + + + + + + + + diff --git a/app/code/Magento/Paypal/Test/Mftf/ActionGroup/StorefrontSwitchToPayPalButtonIframeActionGroup.xml b/app/code/Magento/Paypal/Test/Mftf/ActionGroup/StorefrontSwitchToPayPalButtonIframeActionGroup.xml new file mode 100644 index 0000000000000..bd7774465bb38 --- /dev/null +++ b/app/code/Magento/Paypal/Test/Mftf/ActionGroup/StorefrontSwitchToPayPalButtonIframeActionGroup.xml @@ -0,0 +1,19 @@ + + + + + + + EXTENDS: SwitchToPayPalGroupBtnActionGroup. Switches to PayPal Smart Button iFrame. + + + + + + diff --git a/app/code/Magento/Paypal/Test/Mftf/ActionGroup/SwitchToPayPalGroupBtnActionGroup.xml b/app/code/Magento/Paypal/Test/Mftf/ActionGroup/SwitchToPayPalGroupBtnActionGroup.xml new file mode 100644 index 0000000000000..2e57bdf6265b1 --- /dev/null +++ b/app/code/Magento/Paypal/Test/Mftf/ActionGroup/SwitchToPayPalGroupBtnActionGroup.xml @@ -0,0 +1,26 @@ + + + + + + + Switch to Paypal group button + + + + + + + + + + + + + diff --git a/app/code/Magento/Paypal/Test/Mftf/Data/PaypalConfigData.xml b/app/code/Magento/Paypal/Test/Mftf/Data/PaypalConfigData.xml index 0744207494108..1ad7642f6408a 100644 --- a/app/code/Magento/Paypal/Test/Mftf/Data/PaypalConfigData.xml +++ b/app/code/Magento/Paypal/Test/Mftf/Data/PaypalConfigData.xml @@ -49,4 +49,268 @@ No 0 + + payment/paypal_express/line_items_enabled + 1 + No + 1 + + + payment/paypal_express/line_items_enabled + 1 + No + 0 + + + payment/paypal_express/transfer_shipping_options + 1 + No + 1 + + + payment/paypal_express/transfer_shipping_options + 1 + No + 0 + + + payment/paypal_express/payment_action + 1 + No + Authorization + + + payment/paypal_express/payment_action + 1 + No + Sale + + + payment/paypal_express/payment_action + 1 + No + Order + + + payment/paypal_express/solution_type + 1 + Yes + Sole + + + payment/paypal_express/solution_type + 1 + No + Mark + + + paypal/style/checkout_page_button_customize + 1 + Yes + 1 + + + paypal/style/checkout_page_button_customize + 1 + No + 0 + + + paypal/style/checkout_page_button_label + 1 + PayPal + paypal + + + paypal/style/checkout_page_button_label + 1 + Pay + pay + + + paypal/style/checkout_page_button_layout + 1 + Horizontal + horizontal + + + paypal/style/checkout_page_button_layout + 1 + Vertical + vertical + + + paypal/style/checkout_page_button_shape + 1 + Pill + pill + + + paypal/style/checkout_page_button_shape + 1 + Rectangle + rect + + + paypal/style/checkout_page_button_color + 1 + Blue + blue + + + paypal/style/product_page_button_customize + 1 + Yes + 1 + + + paypal/style/product_page_button_customize + 1 + No + 0 + + + paypal/style/product_page_button_label + 1 + PayPal + paypal + + + paypal/style/product_page_button_label + 1 + Buy Now + buynow + + + paypal/style/product_page_button_layout + 1 + Horizontal + horizontal + + + paypal/style/product_page_button_layout + 1 + Vertical + vertical + + + paypal/style/product_page_button_shape + 1 + Pill + pill + + + paypal/style/product_page_button_shape + 1 + Rectangle + rect + + + paypal/style/product_page_button_color + 1 + Silver + silver + + + paypal/style/cart_page_button_customize + 1 + Yes + 1 + + + paypal/style/cart_page_button_customize + 1 + No + 0 + + + paypal/style/cart_page_button_label + 1 + Checkout + checkout + + + paypal/style/cart_page_button_label + 1 + Pay + pay + + + paypal/style/cart_page_button_layout + 1 + Vertical + vertical + + + paypal/style/cart_page_button_size + 1 + Responsive + responsive + + + paypal/style/cart_page_button_shape + 1 + Pill + pill + + + paypal/style/cart_page_button_shape + 1 + Rectangle + rect + + + paypal/style/cart_page_button_color + 1 + Gold + gold + + + paypal/style/mini_cart_page_button_customize + 1 + Yes + 1 + + + paypal/style/mini_cart_page_button_customize + 1 + No + 0 + + + paypal/style/mini_cart_page_button_label + 1 + Buy Now + buynow + + + paypal/style/mini_cart_page_button_label + 1 + Installment + installment + + + paypal/style/mini_cart_page_button_layout + 1 + Vertical + vertical + + + paypal/style/mini_cart_page_button_shape + 1 + Pill + pill + + + paypal/style/mini_cart_page_button_shape + 1 + Rectangle + rect + + + paypal/style/mini_cart_page_button_color + 1 + Black + black + diff --git a/app/code/Magento/Paypal/Test/Mftf/Data/PaypalData.xml b/app/code/Magento/Paypal/Test/Mftf/Data/PaypalData.xml index ba56243fdb391..f7d872bd43838 100644 --- a/app/code/Magento/Paypal/Test/Mftf/Data/PaypalData.xml +++ b/app/code/Magento/Paypal/Test/Mftf/Data/PaypalData.xml @@ -61,17 +61,12 @@ - - buyer.mpi@gmail.com - 12345678 - - checkout - credit - pay - buy now - pay pal - installment + Checkout + Pay + Buy Now + Paypal + Pagos en horizontal @@ -84,7 +79,7 @@ pill - rectangle + rect gold diff --git a/app/code/Magento/Paypal/Test/Mftf/Data/PaypalMerchantCountryData.xml b/app/code/Magento/Paypal/Test/Mftf/Data/PaypalMerchantCountryData.xml new file mode 100644 index 0000000000000..fa8f936e89d6f --- /dev/null +++ b/app/code/Magento/Paypal/Test/Mftf/Data/PaypalMerchantCountryData.xml @@ -0,0 +1,59 @@ + + + + + + paypal/general/merchant_country + 1 + United States + us + + + paypal/general/merchant_country + 1 + United Kingdon + 0 + + + paypal/general/merchant_country + 1 + Canada + CA + + + paypal/general/merchant_country + 1 + Australia + AU + + + paypal/general/merchant_country + 1 + Japan + JP + + + paypal/general/merchant_country + 1 + France + FR + + + paypal/general/merchant_country + 1 + HongKong + HK + + + paypal/general/merchant_country + 1 + New Zealand + NZ + + diff --git a/app/code/Magento/Paypal/Test/Mftf/Section/PayPalExpressCheckoutConfigSection/CheckoutPaymentSection.xml b/app/code/Magento/Paypal/Test/Mftf/Section/PayPalExpressCheckoutConfigSection/CheckoutPaymentSection.xml index 9c22dd940890e..e6eb4d875c434 100644 --- a/app/code/Magento/Paypal/Test/Mftf/Section/PayPalExpressCheckoutConfigSection/CheckoutPaymentSection.xml +++ b/app/code/Magento/Paypal/Test/Mftf/Section/PayPalExpressCheckoutConfigSection/CheckoutPaymentSection.xml @@ -11,6 +11,7 @@ + diff --git a/app/code/Magento/Paypal/Test/Mftf/Section/PayPalExpressCheckoutConfigSection/PayPalCheckoutAsGuestSection.xml b/app/code/Magento/Paypal/Test/Mftf/Section/PayPalExpressCheckoutConfigSection/PayPalCheckoutAsGuestSection.xml new file mode 100644 index 0000000000000..120ad4025ff09 --- /dev/null +++ b/app/code/Magento/Paypal/Test/Mftf/Section/PayPalExpressCheckoutConfigSection/PayPalCheckoutAsGuestSection.xml @@ -0,0 +1,13 @@ + + + + + + + diff --git a/app/code/Magento/Paypal/Test/Mftf/Section/PayPalExpressCheckoutConfigSection/PayPalPaymentSection.xml b/app/code/Magento/Paypal/Test/Mftf/Section/PayPalExpressCheckoutConfigSection/PayPalPaymentSection.xml index a64ff13e8f627..361016c40539c 100644 --- a/app/code/Magento/Paypal/Test/Mftf/Section/PayPalExpressCheckoutConfigSection/PayPalPaymentSection.xml +++ b/app/code/Magento/Paypal/Test/Mftf/Section/PayPalExpressCheckoutConfigSection/PayPalPaymentSection.xml @@ -16,8 +16,13 @@ - + + + + + + diff --git a/app/code/Magento/Paypal/Test/Mftf/Section/PayPalExpressCheckoutConfigSection/PayPalButtonOnStorefrontSection.xml b/app/code/Magento/Paypal/Test/Mftf/Section/PayPalExpressCheckoutConfigSection/StorefrontPayPalSmartButtonStylesSection.xml similarity index 52% rename from app/code/Magento/Paypal/Test/Mftf/Section/PayPalExpressCheckoutConfigSection/PayPalButtonOnStorefrontSection.xml rename to app/code/Magento/Paypal/Test/Mftf/Section/PayPalExpressCheckoutConfigSection/StorefrontPayPalSmartButtonStylesSection.xml index d97c0260adb0d..e9674a321ec0e 100644 --- a/app/code/Magento/Paypal/Test/Mftf/Section/PayPalExpressCheckoutConfigSection/PayPalButtonOnStorefrontSection.xml +++ b/app/code/Magento/Paypal/Test/Mftf/Section/PayPalExpressCheckoutConfigSection/StorefrontPayPalSmartButtonStylesSection.xml @@ -7,9 +7,10 @@ --> - - - + + + + diff --git a/app/code/Magento/Paypal/Test/Mftf/Section/StorefrontPayPalOrderReviewSection.xml b/app/code/Magento/Paypal/Test/Mftf/Section/StorefrontPayPalOrderReviewSection.xml new file mode 100644 index 0000000000000..d739a5731e052 --- /dev/null +++ b/app/code/Magento/Paypal/Test/Mftf/Section/StorefrontPayPalOrderReviewSection.xml @@ -0,0 +1,15 @@ + + + + + + + + + diff --git a/app/code/Magento/Paypal/Test/Mftf/Suite/InContextPaypalSuite.xml b/app/code/Magento/Paypal/Test/Mftf/Suite/InContextPaypalSuite.xml new file mode 100644 index 0000000000000..b52fc05ca5a11 --- /dev/null +++ b/app/code/Magento/Paypal/Test/Mftf/Suite/InContextPaypalSuite.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/code/Magento/Paypal/Test/Mftf/Test/StorefrontCheckCreditButtonConfigurationTest.xml b/app/code/Magento/Paypal/Test/Mftf/Test/StorefrontCheckCreditButtonConfigurationTest.xml deleted file mode 100644 index c8089085b7ee5..0000000000000 --- a/app/code/Magento/Paypal/Test/Mftf/Test/StorefrontCheckCreditButtonConfigurationTest.xml +++ /dev/null @@ -1,80 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/app/code/Magento/Paypal/Test/Mftf/Test/StorefrontCheckPayPalSmartButtonWithBuyNowLabelOnMiniCartTest.xml b/app/code/Magento/Paypal/Test/Mftf/Test/StorefrontCheckPayPalSmartButtonWithBuyNowLabelOnMiniCartTest.xml new file mode 100644 index 0000000000000..19d73ae4d5277 --- /dev/null +++ b/app/code/Magento/Paypal/Test/Mftf/Test/StorefrontCheckPayPalSmartButtonWithBuyNowLabelOnMiniCartTest.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/code/Magento/Paypal/Test/Mftf/Test/StorefrontCheckPayPalSmartButtonWithBuyNowLabelOnProductPageTest.xml b/app/code/Magento/Paypal/Test/Mftf/Test/StorefrontCheckPayPalSmartButtonWithBuyNowLabelOnProductPageTest.xml new file mode 100644 index 0000000000000..f8e8e4b921779 --- /dev/null +++ b/app/code/Magento/Paypal/Test/Mftf/Test/StorefrontCheckPayPalSmartButtonWithBuyNowLabelOnProductPageTest.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/code/Magento/Paypal/Test/Mftf/Test/StorefrontCheckPayPalSmartButtonWithCheckoutLabelOnCartPageTest.xml b/app/code/Magento/Paypal/Test/Mftf/Test/StorefrontCheckPayPalSmartButtonWithCheckoutLabelOnCartPageTest.xml new file mode 100644 index 0000000000000..f49900337546b --- /dev/null +++ b/app/code/Magento/Paypal/Test/Mftf/Test/StorefrontCheckPayPalSmartButtonWithCheckoutLabelOnCartPageTest.xml @@ -0,0 +1,51 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/code/Magento/Paypal/Test/Mftf/Test/StorefrontCheckPayPalSmartButtonWithPayLabelOnCartPageTest.xml b/app/code/Magento/Paypal/Test/Mftf/Test/StorefrontCheckPayPalSmartButtonWithPayLabelOnCartPageTest.xml new file mode 100644 index 0000000000000..5564476596b1e --- /dev/null +++ b/app/code/Magento/Paypal/Test/Mftf/Test/StorefrontCheckPayPalSmartButtonWithPayLabelOnCartPageTest.xml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/code/Magento/Paypal/Test/Mftf/Test/StorefrontCheckPayPalSmartButtonWithPayLabelOnCheckoutPageTest.xml b/app/code/Magento/Paypal/Test/Mftf/Test/StorefrontCheckPayPalSmartButtonWithPayLabelOnCheckoutPageTest.xml new file mode 100644 index 0000000000000..7b877d66f27ea --- /dev/null +++ b/app/code/Magento/Paypal/Test/Mftf/Test/StorefrontCheckPayPalSmartButtonWithPayLabelOnCheckoutPageTest.xml @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/code/Magento/Paypal/Test/Mftf/Test/StorefrontCheckPayPalSmartButtonWithPayPalLabelOnCheckoutPageTest.xml b/app/code/Magento/Paypal/Test/Mftf/Test/StorefrontCheckPayPalSmartButtonWithPayPalLabelOnCheckoutPageTest.xml new file mode 100644 index 0000000000000..400e0cfe3cc13 --- /dev/null +++ b/app/code/Magento/Paypal/Test/Mftf/Test/StorefrontCheckPayPalSmartButtonWithPayPalLabelOnCheckoutPageTest.xml @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/code/Magento/Paypal/Test/Mftf/Test/StorefrontCheckPayPalSmartButtonWithPayPalLabelOnProductPageTest.xml b/app/code/Magento/Paypal/Test/Mftf/Test/StorefrontCheckPayPalSmartButtonWithPayPalLabelOnProductPageTest.xml new file mode 100644 index 0000000000000..6e84ffa25871b --- /dev/null +++ b/app/code/Magento/Paypal/Test/Mftf/Test/StorefrontCheckPayPalSmartButtonWithPayPalLabelOnProductPageTest.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/code/Magento/Paypal/Test/Mftf/Test/StorefrontPaypalSmartButtonInCheckoutPageTest.xml b/app/code/Magento/Paypal/Test/Mftf/Test/StorefrontPaypalSmartButtonInCheckoutPageTest.xml index f999566869061..d27ac4c4a92f5 100644 --- a/app/code/Magento/Paypal/Test/Mftf/Test/StorefrontPaypalSmartButtonInCheckoutPageTest.xml +++ b/app/code/Magento/Paypal/Test/Mftf/Test/StorefrontPaypalSmartButtonInCheckoutPageTest.xml @@ -11,49 +11,38 @@ - - - + + + - - - - + - + + - + - - - - - + + + - - - - - + + - - - - - - - + + + - + @@ -65,19 +54,57 @@ + + + + + + + - - - - + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/code/Magento/Paypal/Test/Mftf/Test/StorefrontPaypalSmartButtonInMiniCartPageTest.xml b/app/code/Magento/Paypal/Test/Mftf/Test/StorefrontPaypalSmartButtonInMiniCartPageTest.xml new file mode 100644 index 0000000000000..f50d2fc9ad9a4 --- /dev/null +++ b/app/code/Magento/Paypal/Test/Mftf/Test/StorefrontPaypalSmartButtonInMiniCartPageTest.xml @@ -0,0 +1,92 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/code/Magento/Paypal/Test/Mftf/Test/StorefrontPaypalSmartButtonInProductPageTest.xml b/app/code/Magento/Paypal/Test/Mftf/Test/StorefrontPaypalSmartButtonInProductPageTest.xml new file mode 100644 index 0000000000000..3e4f5c8b4da30 --- /dev/null +++ b/app/code/Magento/Paypal/Test/Mftf/Test/StorefrontPaypalSmartButtonInProductPageTest.xml @@ -0,0 +1,115 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/code/Magento/Paypal/Test/Mftf/Test/StorefrontPaypalSmartButtonInShoppingCartPageTest.xml b/app/code/Magento/Paypal/Test/Mftf/Test/StorefrontPaypalSmartButtonInShoppingCartPageTest.xml new file mode 100644 index 0000000000000..62ebeea2d65be --- /dev/null +++ b/app/code/Magento/Paypal/Test/Mftf/Test/StorefrontPaypalSmartButtonInShoppingCartPageTest.xml @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/code/Magento/Paypal/Test/Mftf/Test/StorefrontPaypalSmartButtonWithAUDCurrencyTest.xml b/app/code/Magento/Paypal/Test/Mftf/Test/StorefrontPaypalSmartButtonWithAUDCurrencyTest.xml new file mode 100644 index 0000000000000..4d4f4e8b89957 --- /dev/null +++ b/app/code/Magento/Paypal/Test/Mftf/Test/StorefrontPaypalSmartButtonWithAUDCurrencyTest.xml @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + grabRate + [AUD / USD rate:] + + + diff --git a/app/code/Magento/Paypal/Test/Mftf/Test/StorefrontPaypalSmartButtonWithCADCurrencyTest.xml b/app/code/Magento/Paypal/Test/Mftf/Test/StorefrontPaypalSmartButtonWithCADCurrencyTest.xml new file mode 100644 index 0000000000000..aa35f36268270 --- /dev/null +++ b/app/code/Magento/Paypal/Test/Mftf/Test/StorefrontPaypalSmartButtonWithCADCurrencyTest.xml @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + grabRate + [CAD / USD rate:] + + + diff --git a/app/code/Magento/Paypal/Test/Mftf/Test/StorefrontPaypalSmartButtonWithEuroCurrencyTest.xml b/app/code/Magento/Paypal/Test/Mftf/Test/StorefrontPaypalSmartButtonWithEuroCurrencyTest.xml new file mode 100644 index 0000000000000..1adfe3b5d3a70 --- /dev/null +++ b/app/code/Magento/Paypal/Test/Mftf/Test/StorefrontPaypalSmartButtonWithEuroCurrencyTest.xml @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/code/Magento/Paypal/Test/Mftf/Test/StorefrontPaypalSmartButtonWithFranceMerchantCountryTest.xml b/app/code/Magento/Paypal/Test/Mftf/Test/StorefrontPaypalSmartButtonWithFranceMerchantCountryTest.xml new file mode 100644 index 0000000000000..0efb3f33739fa --- /dev/null +++ b/app/code/Magento/Paypal/Test/Mftf/Test/StorefrontPaypalSmartButtonWithFranceMerchantCountryTest.xml @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/code/Magento/Paypal/Test/Mftf/Test/StorefrontPaypalSmartButtonWithHKDCurrencyTest.xml b/app/code/Magento/Paypal/Test/Mftf/Test/StorefrontPaypalSmartButtonWithHKDCurrencyTest.xml new file mode 100644 index 0000000000000..75a4a5f084b49 --- /dev/null +++ b/app/code/Magento/Paypal/Test/Mftf/Test/StorefrontPaypalSmartButtonWithHKDCurrencyTest.xml @@ -0,0 +1,71 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + grabRate + [HKD / USD rate:] + + + diff --git a/app/code/Magento/Paypal/Test/Mftf/Test/StorefrontPaypalSmartButtonWithNZDCurrencyTest.xml b/app/code/Magento/Paypal/Test/Mftf/Test/StorefrontPaypalSmartButtonWithNZDCurrencyTest.xml new file mode 100644 index 0000000000000..4cddf674c9bfe --- /dev/null +++ b/app/code/Magento/Paypal/Test/Mftf/Test/StorefrontPaypalSmartButtonWithNZDCurrencyTest.xml @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + grabRate + [NZD / USD rate:] + + + diff --git a/app/code/Magento/Paypal/Test/Mftf/Test/StorefrontPaypalSmartButtonWithYENCurrencyTest.xml b/app/code/Magento/Paypal/Test/Mftf/Test/StorefrontPaypalSmartButtonWithYENCurrencyTest.xml new file mode 100644 index 0000000000000..b5b42b2a6bcbd --- /dev/null +++ b/app/code/Magento/Paypal/Test/Mftf/Test/StorefrontPaypalSmartButtonWithYENCurrencyTest.xml @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + grabRate + [JPY / USD rate:] + + + diff --git a/app/code/Magento/Paypal/Test/Unit/Model/Express/LocaleResolverTest.php b/app/code/Magento/Paypal/Test/Unit/Model/Express/LocaleResolverTest.php index b9e2c959b4f7d..ccd991aa3ff0c 100644 --- a/app/code/Magento/Paypal/Test/Unit/Model/Express/LocaleResolverTest.php +++ b/app/code/Magento/Paypal/Test/Unit/Model/Express/LocaleResolverTest.php @@ -13,12 +13,12 @@ use Magento\Paypal\Model\Express\LocaleResolver as ExpressLocaleResolver; /** - * Class LocaleResolverTest + * Test for PayPal express checkout resolver */ class LocaleResolverTest extends \PHPUnit\Framework\TestCase { /** - * @var \PHPUnit_Framework_MockObject_MockObject|ResolverInterface + * @var \PHPUnit\Framework\MockObject\MockObject|ResolverInterface */ private $resolver; @@ -27,18 +27,20 @@ class LocaleResolverTest extends \PHPUnit\Framework\TestCase */ private $model; + /** + * @var Config + */ + private $config; + protected function setUp() { $this->resolver = $this->createMock(ResolverInterface::class); /** @var Config $config */ - $config = $this->createMock(Config::class); - $config->method('getValue') - ->with('supported_locales') - ->willReturn('zh_CN,zh_HK,zh_TW,fr_FR'); + $this->config = $this->createMock(Config::class); /** @var ConfigFactory $configFactory */ $configFactory = $this->createPartialMock(ConfigFactory::class, ['create']); - $configFactory->method('create')->willReturn($config); + $configFactory->method('create')->willReturn($this->config); $this->model = new ExpressLocaleResolver($this->resolver, $configFactory); } @@ -54,7 +56,14 @@ public function testGetLocale(string $locale, string $expectedLocale) { $this->resolver->method('getLocale') ->willReturn($locale); - + $this->config->method('getValue')->will( + $this->returnValueMap( + [ + ['in_context', null, false], + ['supported_locales', null, 'zh_CN,zh_HK,zh_TW,fr_FR'], + ] + ) + ); $this->assertEquals($expectedLocale, $this->model->getLocale()); } @@ -71,4 +80,23 @@ public function getLocaleDataProvider(): array ['locale' => 'unknown', 'expectedLocale' => 'en_US'], ]; } + + /** + * Tests retrieving locales for PayPal Express Smart Buttons. + * + */ + public function testGetLocaleForSmartButtons() + { + $this->resolver->method('getLocale') + ->willReturn('zh_Hans_CN'); + $this->config->method('getValue')->will( + $this->returnValueMap( + [ + ['in_context', null, true], + ['smart_buttons_supported_locales', null, 'zh_CN,zh_HK,zh_TW,fr_FR'], + ] + ) + ); + $this->assertEquals('zh_CN', $this->model->getLocale()); + } } diff --git a/app/code/Magento/Paypal/Test/Unit/Model/SmartButtonConfigTest.php b/app/code/Magento/Paypal/Test/Unit/Model/SmartButtonConfigTest.php index 4002c78bb0ecc..063f98bf3d3ea 100644 --- a/app/code/Magento/Paypal/Test/Unit/Model/SmartButtonConfigTest.php +++ b/app/code/Magento/Paypal/Test/Unit/Model/SmartButtonConfigTest.php @@ -61,7 +61,8 @@ protected function setUp() $configFactoryMock, $scopeConfigMock, $this->getDefaultStyles(), - $this->getAllowedFundings() + $this->getDisallowedFundingMap(), + $this->getUnsupportedPaymentMethods() ); } @@ -73,7 +74,6 @@ protected function setUp() * @param bool $isCustomize * @param string $disallowedFundings * @param string $layout - * @param string $size * @param string $shape * @param string $label * @param string $color @@ -90,7 +90,6 @@ public function testGetConfig( bool $isCustomize, ?string $disallowedFundings, string $layout, - string $size, string $shape, string $label, string $color, @@ -103,6 +102,7 @@ public function testGetConfig( $this->configMock->method('getValue')->will( $this->returnValueMap( [ + ['sandbox_client_id', null, 'sb'], ['merchant_id', null, 'merchant'], [ 'solution_type', @@ -110,10 +110,10 @@ public function testGetConfig( $isPaypalGuestCheckoutEnabled ? Config::EC_SOLUTION_TYPE_SOLE : Config::EC_SOLUTION_TYPE_MARK ], ['sandbox_flag', null, true], + ['paymentAction', null, 'Authorization'], ['disable_funding_options', null, $disallowedFundings], ["{$page}_page_button_customize", null, $isCustomize], ["{$page}_page_button_layout", null, $layout], - ["{$page}_page_button_size", null, $size], ["{$page}_page_button_color", null, $color], ["{$page}_page_button_shape", null, $shape], ["{$page}_page_button_label", null, $label], @@ -150,12 +150,22 @@ private function getDefaultStyles() } /** - * Get allowed fundings + * Get disallowed funding map * * @return array */ - private function getAllowedFundings() + private function getDisallowedFundingMap() { - return include __DIR__ . '/_files/allowed_fundings.php'; + return include __DIR__ . '/_files/disallowed_funding_map.php'; + } + + /** + * Get unsupported payment methods + * + * @return array + */ + private function getUnsupportedPaymentMethods() + { + return include __DIR__ . '/_files/unsupported_payment_methods.php'; } } diff --git a/app/code/Magento/Paypal/Test/Unit/Model/_files/allowed_fundings.php b/app/code/Magento/Paypal/Test/Unit/Model/_files/allowed_fundings.php deleted file mode 100644 index 6b6f8ccb87e14..0000000000000 --- a/app/code/Magento/Paypal/Test/Unit/Model/_files/allowed_fundings.php +++ /dev/null @@ -1,24 +0,0 @@ - [ - 'CREDIT', - 'ELV' - ], - 'cart' => [ - 'CREDIT', - 'ELV' - ], - 'mini_cart' => [ - 'CREDIT', - 'ELV' - ], - 'product' => [ - 'CREDIT' - ] -]; diff --git a/app/code/Magento/Paypal/Test/Unit/Model/_files/disallowed_funding_map.php b/app/code/Magento/Paypal/Test/Unit/Model/_files/disallowed_funding_map.php new file mode 100644 index 0000000000000..ea543454975f4 --- /dev/null +++ b/app/code/Magento/Paypal/Test/Unit/Model/_files/disallowed_funding_map.php @@ -0,0 +1,12 @@ + 'credit', + "CARD" => 'card', + "ELV" => 'sepa' +]; diff --git a/app/code/Magento/Paypal/Test/Unit/Model/_files/expected_config.php b/app/code/Magento/Paypal/Test/Unit/Model/_files/expected_config.php index f17b9f9fb4979..6089b8b20b1ac 100644 --- a/app/code/Magento/Paypal/Test/Unit/Model/_files/expected_config.php +++ b/app/code/Magento/Paypal/Test/Unit/Model/_files/expected_config.php @@ -5,6 +5,16 @@ */ declare(strict_types=1); +/** + * Generates expected PayPal SDK url + * @param array $params + * @return String + */ +function generateExpectedPaypalSdkUrl(array $params) : String +{ + return 'https://www.paypal.com/sdk/js?' . http_build_query($params); +} + return [ 'cart' => [ 'cart', @@ -12,29 +22,36 @@ true, 'CREDIT', 'horizontal', - 'small', - 'pillow', + 'pill', 'installment', 'blue', 'my_label', 'mx', true, [ - 'merchantId' => 'merchant', - 'environment' => 'sandbox', - 'locale' => 'es_MX', - 'allowedFunding' => ['ELV'], - 'disallowedFunding' => ['CREDIT'], 'styles' => [ 'layout' => 'horizontal', - 'size' => 'small', + 'size' => null, 'color' => 'blue', - 'shape' => 'pillow', + 'shape' => 'pill', 'label' => 'installment', - 'installmentperiod' => 0 + 'period' => 0 ], 'isVisibleOnProductPage' => false, - 'isGuestCheckoutAllowed' => true + 'isGuestCheckoutAllowed' => true, + 'sdkUrl' => generateExpectedPaypalSdkUrl( + [ + 'client-id' => 'sb', + 'commit' => 'false', + 'merchant-id' => 'merchant', + 'locale' => 'es_MX', + 'intent' => 'authorize', + 'disable-funding' => implode( + ',', + ['credit', 'venmo', 'bancontact', 'eps', 'giropay', 'ideal', 'mybank', 'p24', 'sofort'] + ) + ] + ) ] ], 'checkout' => [ @@ -43,50 +60,51 @@ true, null, 'horizontal', - 'small', - 'pillow', + 'pill', 'installment', 'blue', 'my_label', 'br', true, [ - 'merchantId' => 'merchant', - 'environment' => 'sandbox', - 'locale' => 'en_BR', - 'allowedFunding' => ['CREDIT', 'ELV'], - 'disallowedFunding' => [], 'styles' => [ 'layout' => 'horizontal', - 'size' => 'small', + 'size' => null, 'color' => 'blue', - 'shape' => 'pillow', + 'shape' => 'pill', 'label' => 'installment', - 'installmentperiod' => 0 + 'period' => 0 ], 'isVisibleOnProductPage' => false, - 'isGuestCheckoutAllowed' => true + 'isGuestCheckoutAllowed' => true, + 'sdkUrl' => generateExpectedPaypalSdkUrl( + [ + 'client-id' => 'sb', + 'commit' => 'false', + 'merchant-id' => 'merchant', + 'locale' => 'en_BR', + 'intent' => 'authorize', + 'disable-funding' => implode( + ',', + ['venmo', 'bancontact', 'eps', 'giropay', 'ideal', 'mybank', 'p24', 'sofort'] + ) + ] + ) ] ], 'mini_cart' => [ 'cart', - 'en', + 'en_US', false, null, 'horizontal', - 'small', - 'pillow', + 'pill', 'installment', 'blue', 'my_label', 'br', true, [ - 'merchantId' => 'merchant', - 'environment' => 'sandbox', - 'locale' => 'en', - 'allowedFunding' => ['CREDIT', 'ELV'], - 'disallowedFunding' => [], 'styles' => [ 'layout' => 'vertical', 'size' => 'responsive', @@ -95,28 +113,35 @@ 'label' => 'paypal' ], 'isVisibleOnProductPage' => false, - 'isGuestCheckoutAllowed' => true + 'isGuestCheckoutAllowed' => true, + 'sdkUrl' => generateExpectedPaypalSdkUrl( + [ + 'client-id' => 'sb', + 'commit' => 'false', + 'merchant-id' => 'merchant', + 'locale' => 'en_US', + 'intent' => 'authorize', + 'disable-funding' => implode( + ',', + ['venmo', 'bancontact', 'eps', 'giropay', 'ideal', 'mybank', 'p24', 'sofort'] + ) + ] + ) ] ], 'product' => [ 'cart', - 'en', + 'en_US', false, 'CREDIT', 'horizontal', - 'small', - 'pillow', + 'pill', 'installment', 'blue', 'my_label', 'br', true, [ - 'merchantId' => 'merchant', - 'environment' => 'sandbox', - 'locale' => 'en', - 'allowedFunding' => ['ELV'], - 'disallowedFunding' => ['CREDIT'], 'styles' => [ 'layout' => 'vertical', 'size' => 'responsive', @@ -125,7 +150,20 @@ 'label' => 'paypal', ], 'isVisibleOnProductPage' => false, - 'isGuestCheckoutAllowed' => true + 'isGuestCheckoutAllowed' => true, + 'sdkUrl' => generateExpectedPaypalSdkUrl( + [ + 'client-id' => 'sb', + 'commit' => 'false', + 'merchant-id' => 'merchant', + 'locale' => 'en_US', + 'intent' => 'authorize', + 'disable-funding' => implode( + ',', + ['credit','venmo', 'bancontact', 'eps', 'giropay', 'ideal', 'mybank', 'p24', 'sofort'] + ) + ] + ) ] ], 'checkout_with_paypal_guest_checkout_disabled' => [ @@ -134,29 +172,36 @@ true, null, 'horizontal', - 'small', - 'pillow', + 'pill', 'installment', 'blue', 'my_label', 'br', false, [ - 'merchantId' => 'merchant', - 'environment' => 'sandbox', - 'locale' => 'en_BR', - 'allowedFunding' => ['CREDIT', 'ELV'], - 'disallowedFunding' => ['CARD'], 'styles' => [ 'layout' => 'horizontal', - 'size' => 'small', + 'size' => null, 'color' => 'blue', - 'shape' => 'pillow', + 'shape' => 'pill', 'label' => 'installment', - 'installmentperiod' => 0 + 'period' => 0 ], 'isVisibleOnProductPage' => false, - 'isGuestCheckoutAllowed' => true + 'isGuestCheckoutAllowed' => true, + 'sdkUrl' => generateExpectedPaypalSdkUrl( + [ + 'client-id' => 'sb', + 'commit' => 'false', + 'merchant-id' => 'merchant', + 'locale' => 'en_BR', + 'intent' => 'authorize', + 'disable-funding' => implode( + ',', + ['card','venmo', 'bancontact', 'eps', 'giropay', 'ideal', 'mybank', 'p24', 'sofort'] + ) + ] + ) ] ], ]; diff --git a/app/code/Magento/Paypal/Test/Unit/Model/_files/unsupported_payment_methods.php b/app/code/Magento/Paypal/Test/Unit/Model/_files/unsupported_payment_methods.php new file mode 100644 index 0000000000000..f4b4c72762d93 --- /dev/null +++ b/app/code/Magento/Paypal/Test/Unit/Model/_files/unsupported_payment_methods.php @@ -0,0 +1,17 @@ + 'venmo', + 'bancontact' => 'bancontact', + 'eps' => 'eps', + 'giropay' => 'giropay', + 'ideal' => 'ideal', + 'mybank' => 'mybank', + 'p24' => 'p24', + 'sofort' => 'sofort' +]; diff --git a/app/code/Magento/Paypal/etc/adminhtml/system/express_checkout.xml b/app/code/Magento/Paypal/etc/adminhtml/system/express_checkout.xml index 04d5fae435816..fe3ed6ce5e00e 100644 --- a/app/code/Magento/Paypal/etc/adminhtml/system/express_checkout.xml +++ b/app/code/Magento/Paypal/etc/adminhtml/system/express_checkout.xml @@ -155,10 +155,10 @@ You can look up your merchant ID by logging into https://www.paypal.com/. Click the profile icon on the top right side of the page and then select Profile and settings in the Business Profile menu. (If you do not see the profile icon at the top of the page, click Profile, which appears in the top menu when the My Account tab is selected.) Click My business info on the left, and the Merchant account ID is displayed in the list of profile items on the right. payment/paypal_express/merchant_id Magento\Paypal\Block\Adminhtml\System\Config\Field\Depends\MerchantId + required-entry 1 - required-entry Enable PayPal Credit @@ -703,16 +703,6 @@ 1 - - Size - paypal/style/checkout_page_button_size - Magento\Paypal\Model\System\Config\Source\ButtonStyles::getSize - Select Responsive to ensure the PayPal button renders correctly on mobile devices. - - 1 - - 1 - Shape paypal/style/checkout_page_button_shape @@ -765,12 +755,6 @@ credit - - paypal/style/product_page_button_size - - 1 - - paypal/style/product_page_button_shape @@ -817,12 +801,6 @@ credit - - paypal/style/cart_page_button_size - - 1 - - paypal/style/cart_page_button_shape @@ -869,12 +847,6 @@ credit - - paypal/style/mini_cart_page_button_size - - 1 - - paypal/style/mini_cart_page_button_shape diff --git a/app/code/Magento/Paypal/etc/config.xml b/app/code/Magento/Paypal/etc/config.xml index 24bb54a86103d..f93572537ffd7 100644 --- a/app/code/Magento/Paypal/etc/config.xml +++ b/app/code/Magento/Paypal/etc/config.xml @@ -69,6 +69,10 @@ 1 1 ar_EG,cs_CZ,da_DK,de_DE,el_GR,en_AU,en_GB,en_IN,en_US,es_ES,es_XC,fi_FI,fr_CA,fr_FR,fr_XC,he_IL,hu_HU,id_ID,it_IT,ja_JP,ko_KR,nl_NL,no_NO,pl_PL,pt_BR,pt_PT,ru_RU,sk_SK,sv_SE,th_TH,zh_CN,zh_HK,zh_TW,zh_XC + + en_AD,fr_AD,es_AD,zh_AD,en_AE,fr_AE,es_AE,zh_AE,ar_AE,en_AG,fr_AG,es_AG,zh_AG,en_AI,fr_AI,es_AI,zh_AI,en_AL,en_AM,fr_AM,es_AM,zh_AM,en_AN,fr_AN,es_AN,zh_AN,en_AO,fr_AO,es_AO,zh_AO,es_AR,en_AR, de_AT,en_AT,en_AU,en_AW,fr_AW,es_AW,zh_AW,en_AZ,fr_AZ,es_AZ,zh_AZ,en_BA,en_BB,fr_BB,es_BB,zh_BB,en_BE,nl_BE,fr_BE,fr_BF,en_BF,es_BF,zh_BF,en_BG,ar_BH,en_BH,fr_BH,es_BH,zh_BH,fr_BI,en_BI,es_BI,zh_BI,fr_BJ,en_BJ,es_BJ,zh_BJ,en_BM,fr_BM,es_BM,zh_BM,en_BN,es_BO,en_BO,fr_BO,zh_BO,pt_BR,en_BR,en_BS,fr_BS,es_BS,zh_BS,en_BT,en_BW,fr_BW,es_BW,zh_BW,en_BY,en_BZ,es_BZ,fr_BZ,zh_BZ,en_CA,fr_CA,fr_CD,en_CD,es_CD,zh_CD,en_CG,fr_CG,es_CG,zh_CG,de_CH,fr_CH,en_CH,fr_CI,en_CI,en_CK,fr_CK,es_CK,zh_CK,es_CL,en_CL,fr_CL,zh_CL,fr_CM,en_CM,zh_CN,es_CO,en_CO,fr_CO,zh_CO,es_CR,en_CR,fr_CR,zh_CR,en_CV,fr_CV,es_CV,zh_CV,en_CY,cs_CZ,en_CZ,fr_CZ,es_CZ,zh_CZ,de_DE,en_DE,fr_DJ,en_DJ,es_DJ,zh_DJ,da_DK,en_DK,en_DM,fr_DM,es_DM,zh_DM,es_DO,en_DO,fr_DO,zh_DO,ar_DZ,en_DZ,fr_DZ,es_DZ,zh_DZ,es_EC,en_EC,fr_EC,zh_EC,en_EE,ru_EE,fr_EE,es_EE,zh_EE,ar_EG,en_EG,fr_EG,es_EG,zh_EG,en_ER,fr_ER,es_ER,zh_ER,es_ES,en_ES,en_ET,fr_ET,es_ET,zh_ET,fi_FI,en_FI,fr_FI,es_FI,zh_FI,en_FJ,fr_FJ,es_FJ,zh_FJ,en_FK,fr_FK,es_FK,zh_FK,en_FM,da_FO,en_FO,fr_FO,es_FO,zh_FO,fr_FR,en_FR,fr_GA,en_GA,es_GA,zh_GA,en_GB,en_GD,fr_GD,es_GD,zh_GD,en_GE,fr_GE,es_GE,zh_GE,en_GF,fr_GF,es_GF,zh_GF,en_GI,fr_GI,es_GI,zh_GI,da_GL,en_GL,fr_GL,es_GL,zh_GL,en_GM,fr_GM,es_GM,zh_GM,fr_GN,en_GN,es_GN,zh_GN,en_GP,fr_GP,es_GP,zh_GP,el_GR,en_GR,fr_GR,es_GR,zh_GR,es_GT,en_GT,fr_GT,zh_GT,en_GW,fr_GW,es_GW,zh_GW,en_GY,fr_GY,es_GY,zh_GY,en_HK,zh_HK,es_HN,en_HN,fr_HN,zh_HN,en_HR,hu_HU,en_HU,fr_HU,es_HU,zh_HU,id_ID,en_ID,en_IE,fr_IE,es_IE,zh_IE,he_IL,en_IL,en_IN,en_IS,it_IT,en_IT,en_JM,es_JM,fr_JM,zh_JM,ar_JO,en_JO,fr_JO,es_JO,zh_JO,ja_JP,en_JP,en_KE,fr_KE,es_KE,zh_KE,en_KG,fr_KG,es_KG,zh_KG,en_KH,en_KI,fr_KI,es_KI,zh_KI,fr_KM,en_KM,es_KM,zh_KM,en_KN,fr_KN,es_KN,zh_KN,ko_KR,en_KR,ar_KW,en_KW,fr_KW,es_KW,zh_KW,en_KY,fr_KY,es_KY,zh_KY,en_KZ,fr_KZ,es_KZ,zh_KZ,en_LA,en_LC,fr_LC,es_LC,zh_LC,en_LI,fr_LI,es_LI,zh_LI,en_LK,en_LS,fr_LS,es_LS,zh_LS,en_LT,ru_LT,fr_LT,es_LT,zh_LT,en_LU,de_LU,fr_LU,es_LU,zh_LU,en_LV,ru_LV,fr_LV,es_LV,zh_LV,ar_MA,en_MA,fr_MA,es_MA,zh_MA,fr_MC,en_MC,en_MD,en_ME,en_MG,fr_MG,es_MG,zh_MG,en_MH,fr_MH,es_MH,zh_MH,en_MK,fr_ML,en_ML,es_ML,zh_ML,en_MN,en_MQ,fr_MQ,es_MQ,zh_MQ,en_MR,fr_MR,es_MR,zh_MR,en_MS,fr_MS,es_MS,zh_MS,en_MT,en_MU,fr_MU,es_MU,zh_MU,en_MV,en_MW,fr_MW,es_MW,zh_MW,es_MX,en_MX,en_MY,en_MZ,fr_MZ,es_MZ,zh_MZ,en_NA,fr_NA,es_NA,zh_NA,en_NC,fr_NC,es_NC,zh_NC,fr_NE,en_NE,es_NE,zh_NE,en_NF,fr_NF,es_NF,zh_NF,en_NG,es_NI,en_NI,fr_NI,zh_NI,nl_NL,en_NL,no_NO,en_NO,en_NP,en_NR,fr_NR,es_NR,zh_NR,en_NU,fr_NU,es_NU,zh_NU,en_NZ,fr_NZ,es_NZ,zh_NZ,ar_OM,en_OM,fr_OM,es_OM,zh_OM,es_PA,en_PA,fr_PA,zh_PA,es_PE,en_PE,fr_PE,zh_PE,en_PF,fr_PF,es_PF,zh_PF,en_PG,fr_PG,es_PG,zh_PG,en_PH,pl_PL,en_PL,en_PM,fr_PM,es_PM,zh_PM,en_PN,fr_PN,es_PN,zh_PN,pt_PT,en_PT,en_PW,fr_PW,es_PW,zh_PW,es_PY,en_PY,en_QA,fr_QA,es_QA,zh_QA,ar_QA,en_RE,fr_RE,es_RE,zh_RE,en_RO,fr_RO,es_RO,zh_RO,en_RS,fr_RS,es_RS,zh_RS,ru_RU,en_RU,fr_RW,en_RW,es_RW,zh_RW,ar_SA,en_SA,fr_SA,es_SA,zh_SA,en_SB,fr_SB,es_SB,zh_SB,fr_SC,en_SC,es_SC,zh_SC,sv_SE,en_SE,en_SG,en_SH,fr_SH,es_SH,zh_SH,en_SI,fr_SI,es_SI,zh_SI,en_SJ,fr_SJ,es_SJ,zh_SJ,sk_SK,en_SK,fr_SK,es_SK,zh_SK,en_SL,fr_SL,es_SL,zh_SL,en_SM,fr_SM,es_SM,zh_SM,fr_SN,en_SN,es_SN,zh_SN,en_SO,fr_SO,es_SO,zh_SO,en_SR,fr_SR,es_SR,zh_SR,en_ST,fr_ST,es_ST,zh_ST,es_SV,en_SV,fr_SV,zh_SV,en_SZ,fr_SZ,es_SZ,zh_SZ,en_TC,fr_TC,es_TC,zh_TC,fr_TD,en_TD,es_TD,zh_TD,fr_TG,en_TG,es_TG,zh_TG,th_TH,en_TH,en_TJ,fr_TJ,es_TJ,zh_TJ,en_TM,fr_TM,es_TM,zh_TM,ar_TN,en_TN,fr_TN,es_TN,zh_TN,en_TO,tr_TR,en_TR,en_TT,fr_TT,es_TT,zh_TT,en_TV,fr_TV,es_TV,zh_TV,zh_TW,en_TW,en_TZ,fr_TZ,es_TZ,zh_TZ,en_UA,ru_UA,fr_UA,es_UA,zh_UA,en_UG,fr_UG,es_UG,zh_UG,en_US,fr_US,es_US,zh_US,es_UY,en_UY,fr_UY,zh_UY,en_VA,fr_VA,es_VA,zh_VA,en_VC,fr_VC,es_VC,zh_VC,es_VE,en_VE,fr_VE,zh_VE,en_VG,fr_VG,es_VG,zh_VG,en_VN,en_VU,fr_VU,es_VU,zh_VU,en_WF,fr_WF,es_WF,zh_WF,en_WS,ar_YE,en_YE,fr_YE,es_YE,zh_YE,en_YT,fr_YT,es_YT,zh_YT,en_ZA,fr_ZA,es_ZA,zh_ZA,en_ZM,fr_ZM,es_ZM,zh_ZM,en_ZW + ATDZ9_ECFh-fudesZo4kz3fGTSO1pzuWCS4IjZMq4JKdRK7hQR3Rxyafx39H2fP363WtmlQNYXjUiAae + AUZfbDQ_4m8ibp82qV9pi9wxGkGrdGILVYWbWaTWreW9mmTm6LjQorLZxpP7kjymXc7flRnepHBFSQWp Magento\Paypal\Model\Bml diff --git a/app/code/Magento/Paypal/etc/di.xml b/app/code/Magento/Paypal/etc/di.xml index e148320fdaf17..9ea451a213af2 100644 --- a/app/code/Magento/Paypal/etc/di.xml +++ b/app/code/Magento/Paypal/etc/di.xml @@ -258,4 +258,13 @@ + + + + PayPal Credit + PayPal Guest Checkout Credit Card Icons + Elektronisches Lastschriftverfahren - German ELV + + + diff --git a/app/code/Magento/Paypal/etc/frontend/di.xml b/app/code/Magento/Paypal/etc/frontend/di.xml index a728f5583a8d6..ac3fccff39f75 100644 --- a/app/code/Magento/Paypal/etc/frontend/di.xml +++ b/app/code/Magento/Paypal/etc/frontend/di.xml @@ -158,22 +158,20 @@ buynow - - - CREDIT - ELV - - - CREDIT - ELV - - - CREDIT - ELV - - - CREDIT - + + credit + card + sepa + + + venmo + bancontact + eps + giropay + ideal + mybank + p24 + sofort Magento\Paypal\Model\Express\LocaleResolver diff --git a/app/code/Magento/Paypal/i18n/en_US.csv b/app/code/Magento/Paypal/i18n/en_US.csv index 912b99e2e6427..852bf39c57966 100644 --- a/app/code/Magento/Paypal/i18n/en_US.csv +++ b/app/code/Magento/Paypal/i18n/en_US.csv @@ -707,7 +707,6 @@ User,User "Label","Label" "The installment feature is available only in these locales: en_MX, es_MX, en_BR, pt_BR.","The installment feature is available only in these locales: en_MX, es_MX, en_BR, pt_BR." "Checkout","Checkout" -"Credit","Credit" "Pay","Pay" "Buy Now","Buy Now" "PayPal","PayPal" @@ -718,8 +717,6 @@ User,User "Vertical","Vertical" "Horizontal","Horizontal" "Size","Size" -"Medium","Medium" -"Large","Large" "Responsive","Responsive" "Shape","Shape" "Pill","Pill" diff --git a/app/code/Magento/Paypal/view/frontend/layout/default.xml b/app/code/Magento/Paypal/view/frontend/layout/default.xml index cb2126cec718f..aa47b43fa153a 100644 --- a/app/code/Magento/Paypal/view/frontend/layout/default.xml +++ b/app/code/Magento/Paypal/view/frontend/layout/default.xml @@ -9,8 +9,7 @@ + name="paypal.express-in-context.component"> true diff --git a/app/code/Magento/Paypal/view/frontend/requirejs-config.js b/app/code/Magento/Paypal/view/frontend/requirejs-config.js index 223ade43d86e5..1f318a717f8aa 100644 --- a/app/code/Magento/Paypal/view/frontend/requirejs-config.js +++ b/app/code/Magento/Paypal/view/frontend/requirejs-config.js @@ -10,13 +10,5 @@ var config = { 'Magento_Paypal/order-review': 'Magento_Paypal/js/order-review', paypalCheckout: 'Magento_Paypal/js/paypal-checkout' } - }, - paths: { - paypalInContextExpressCheckout: 'https://www.paypalobjects.com/api/checkout' - }, - shim: { - paypalInContextExpressCheckout: { - exports: 'paypal' - } } }; diff --git a/app/code/Magento/Paypal/view/frontend/templates/express/in-context/component.phtml b/app/code/Magento/Paypal/view/frontend/templates/express/in-context/component.phtml deleted file mode 100644 index c102b21830de8..0000000000000 --- a/app/code/Magento/Paypal/view/frontend/templates/express/in-context/component.phtml +++ /dev/null @@ -1,38 +0,0 @@ - SmartButton::PAYPAL_BUTTON_ID, - 'path' => $block->getUrl( - 'paypal/express/gettoken', - [ - '_secure' => $block->getRequest()->isSecure() - ] - ), - 'merchantId' => $block->getMerchantId(), - 'button' => $block->isButtonContext(), - 'clientConfig' => [ - 'locale' => $block->getLocale(), - 'environment' => $block->getEnvironment(), - 'button' => [ - SmartButton::PAYPAL_BUTTON_ID, - ] - ] -]; - -?> - - diff --git a/app/code/Magento/Paypal/view/frontend/templates/express/shortcut_button.phtml b/app/code/Magento/Paypal/view/frontend/templates/express/shortcut_button.phtml index 76d034f462a7a..ce07ba2293bb8 100644 --- a/app/code/Magento/Paypal/view/frontend/templates/express/shortcut_button.phtml +++ b/app/code/Magento/Paypal/view/frontend/templates/express/shortcut_button.phtml @@ -4,6 +4,7 @@ * See COPYING.txt for license details. */ +// phpcs:disable Magento2.Templates.ThisInTemplate /** * @var \Magento\Paypal\Block\Express\InContext\SmartButton $block */ @@ -12,4 +13,5 @@ $widgetConfig = $this->helper(\Magento\Framework\Json\Helper\Data::class)->jsonE $widget['Magento_Paypal/js/in-context/product-express-checkout'] ); ?> - + diff --git a/app/code/Magento/Paypal/view/frontend/web/js/in-context/button.js b/app/code/Magento/Paypal/view/frontend/web/js/in-context/button.js index 012a1f18f9ae5..719be7b2590a9 100644 --- a/app/code/Magento/Paypal/view/frontend/web/js/in-context/button.js +++ b/app/code/Magento/Paypal/view/frontend/web/js/in-context/button.js @@ -45,7 +45,6 @@ define([ /** @inheritdoc */ prepareClientConfig: function () { this._super(); - this.clientConfig.commit = false; return this.clientConfig; } diff --git a/app/code/Magento/Paypal/view/frontend/web/js/in-context/express-checkout-smart-buttons.js b/app/code/Magento/Paypal/view/frontend/web/js/in-context/express-checkout-smart-buttons.js index ad7e86f2e99e0..9100236490848 100644 --- a/app/code/Magento/Paypal/view/frontend/web/js/in-context/express-checkout-smart-buttons.js +++ b/app/code/Magento/Paypal/view/frontend/web/js/in-context/express-checkout-smart-buttons.js @@ -2,122 +2,126 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +/* eslint-disable max-nested-callbacks */ define([ 'underscore', - 'paypalInContextExpressCheckout' -], function (_, paypal) { + 'jquery', + 'Magento_Paypal/js/in-context/paypal-sdk', + 'domReady!' +], function (_, $, paypalSdk) { 'use strict'; /** - * Returns array of allowed funding + * Triggers beforePayment action on PayPal buttons * - * @param {Object} config - * @return {Array} + * @param {Object} clientConfig + * @returns {Object} jQuery promise */ - function getFunding(config) { - return _.map(config, function (name) { - return paypal.FUNDING[name]; - }); - } - - return function (clientConfig, element) { - paypal.Button.render({ - env: clientConfig.environment, - client: clientConfig.client, - locale: clientConfig.locale, - funding: { - allowed: getFunding(clientConfig.allowedFunding), - disallowed: getFunding(clientConfig.disallowedFunding) - }, - style: clientConfig.styles, - - // Enable Pay Now checkout flow (optional) - commit: clientConfig.commit, + function performCreateOrder(clientConfig) { + var params = { + 'quote_id': clientConfig.quoteId, + 'customer_id': clientConfig.customerId || '', + 'form_key': clientConfig.formKey, + button: clientConfig.button + }; - /** - * Validate payment method - * - * @param {Object} actions - */ - validate: function (actions) { - clientConfig.rendererComponent.validate(actions); - }, - - /** - * Execute logic on Paypal button click - */ - onClick: function () { - clientConfig.rendererComponent.onClick(); - }, + return $.Deferred(function (deferred) { + clientConfig.rendererComponent.beforePayment(deferred.resolve, deferred.reject).then(function () { + $.post(clientConfig.getTokenUrl, params).done(function (res) { + clientConfig.rendererComponent.afterPayment(res, deferred.resolve, deferred.reject); + }).fail(function (jqXHR, textStatus, err) { + clientConfig.rendererComponent.catchPayment(err, deferred.resolve, deferred.reject); + }); + }); + }).promise(); + } - /** - * Set up a payment - * - * @return {*} - */ - payment: function () { - var params = { - 'quote_id': clientConfig.quoteId, - 'customer_id': clientConfig.customerId || '', - 'form_key': clientConfig.formKey, - button: clientConfig.button - }; + /** + * Triggers beforeOnAuthorize action on PayPal buttons + * @param {Object} clientConfig + * @param {Object} data + * @param {Object} actions + * @returns {Object} jQuery promise + */ + function performOnApprove(clientConfig, data, actions) { + var params = { + paymentToken: data.orderID, + payerId: data.payerID, + quoteId: clientConfig.quoteId || '', + customerId: clientConfig.customerId || '', + 'form_key': clientConfig.formKey + }; - return new paypal.Promise(function (resolve, reject) { - clientConfig.rendererComponent.beforePayment(resolve, reject).then(function () { - paypal.request.post(clientConfig.getTokenUrl, params).then(function (res) { - return clientConfig.rendererComponent.afterPayment(res, resolve, reject); - }).catch(function (err) { - return clientConfig.rendererComponent.catchPayment(err, resolve, reject); - }); + return $.Deferred(function (deferred) { + clientConfig.rendererComponent.beforeOnAuthorize(deferred.resolve, deferred.reject, actions) + .then(function () { + $.post(clientConfig.onAuthorizeUrl, params).done(function (res) { + clientConfig.rendererComponent + .afterOnAuthorize(res, deferred.resolve, deferred.reject, actions); + }).fail(function (jqXHR, textStatus, err) { + clientConfig.rendererComponent.catchOnAuthorize(err, deferred.resolve, deferred.reject); }); }); - }, + }).promise(); + } - /** - * Execute the payment - * - * @param {Object} data - * @param {Object} actions - * @return {*} - */ - onAuthorize: function (data, actions) { - var params = { - paymentToken: data.paymentToken, - payerId: data.payerID, - quoteId: clientConfig.quoteId || '', - customerId: clientConfig.customerId || '', - 'form_key': clientConfig.formKey - }; + return function (clientConfig, element) { + paypalSdk(clientConfig.sdkUrl).done(function (paypal) { + paypal.Buttons({ + style: clientConfig.styles, - return new paypal.Promise(function (resolve, reject) { - clientConfig.rendererComponent.beforeOnAuthorize(resolve, reject, actions).then(function () { - paypal.request.post(clientConfig.onAuthorizeUrl, params).then(function (res) { - clientConfig.rendererComponent.afterOnAuthorize(res, resolve, reject, actions); - }).catch(function (err) { - return clientConfig.rendererComponent.catchOnAuthorize(err, resolve, reject); - }); - }); - }); + /** + * onInit is called when the button first renders + * @param {Object} data + * @param {Object} actions + */ + onInit: function (data, actions) { + clientConfig.rendererComponent.validate(actions); + }, + + /** + * Triggers beforePayment action on PayPal buttons + * @returns {Object} jQuery promise + */ + createOrder: function () { + return performCreateOrder(clientConfig); + }, - }, + /** + * Triggers beforeOnAuthorize action on PayPal buttons + * @param {Object} data + * @param {Object} actions + */ + onApprove: function (data, actions) { + performOnApprove(clientConfig, data, actions); + }, - /** - * Process cancel action - * - * @param {Object} data - * @param {Object} actions - */ - onCancel: function (data, actions) { - clientConfig.rendererComponent.onCancel(data, actions); - }, + /** + * Execute logic on Paypal button click + */ + onClick: function () { + clientConfig.rendererComponent.validate(); + clientConfig.rendererComponent.onClick(); + }, - /** - * Process errors - */ - onError: function (err) { - clientConfig.rendererComponent.onError(err); - } - }, element); + /** + * Process cancel action + * @param {Object} data + * @param {Object} actions + */ + onCancel: function (data, actions) { + clientConfig.rendererComponent.onCancel(data, actions); + }, + + /** + * Process errors + * + * @param {Error} err + */ + onError: function (err) { + clientConfig.rendererComponent.onError(err); + } + }).render(element); + }); }; }); diff --git a/app/code/Magento/Paypal/view/frontend/web/js/in-context/express-checkout-wrapper.js b/app/code/Magento/Paypal/view/frontend/web/js/in-context/express-checkout-wrapper.js index 905f860fe2651..c5ec5d28ddd06 100644 --- a/app/code/Magento/Paypal/view/frontend/web/js/in-context/express-checkout-wrapper.js +++ b/app/code/Magento/Paypal/view/frontend/web/js/in-context/express-checkout-wrapper.js @@ -7,8 +7,9 @@ define([ 'mage/translate', 'Magento_Customer/js/customer-data', 'Magento_Paypal/js/in-context/express-checkout-smart-buttons', + 'Magento_Ui/js/modal/alert', 'mage/cookies' -], function ($, $t, customerData, checkoutSmartButtons) { +], function ($, $t, customerData, checkoutSmartButtons, alert) { 'use strict'; return { @@ -59,12 +60,11 @@ define([ * @return {*} */ afterPayment: function (res, resolve, reject) { + if (res.success) { return resolve(res.token); } - this.addError(res['error_message']); - return reject(new Error(res['error_message'])); }, @@ -76,7 +76,7 @@ define([ * @param {Function} reject */ catchPayment: function (err, resolve, reject) { - this.addError(this.paymentActionError); + this.addAlert(this.paymentActionError); reject(err); }, @@ -90,6 +90,9 @@ define([ * @return {jQuery.Deferred} */ beforeOnAuthorize: function (resolve, reject, actions) { //eslint-disable-line no-unused-vars + //display loading widget. + $('body').trigger('processStart'); + return $.Deferred().resolve(); }, @@ -104,14 +107,14 @@ define([ * @return {*} */ afterOnAuthorize: function (res, resolve, reject, actions) { + $('body').trigger('processStop'); + if (res.success) { resolve(); - return actions.redirect(window, res.redirectUrl); + return actions.redirect(res.redirectUrl); } - this.addError(res['error_message']); - return reject(new Error(res['error_message'])); }, @@ -123,7 +126,8 @@ define([ * @param {Function} reject */ catchOnAuthorize: function (err, resolve, reject) { - this.addError(this.paymentActionError); + $('body').trigger('processStop'); + this.addAlert(this.paymentActionError); reject(err); }, @@ -134,7 +138,8 @@ define([ * @param {Object} actions */ onCancel: function (data, actions) { - actions.redirect(window, this.clientConfig.onCancelUrl); + $('body').trigger('processStop'); + actions.redirect(this.clientConfig.onCancelUrl); }, /** @@ -163,6 +168,17 @@ define([ }); }, + /** + * Add alert message + * + * @param {String} message + */ + addAlert: function (message) { + alert({ + content: message + }); + }, + /** * @returns {String} */ @@ -176,8 +192,6 @@ define([ * @return {Object} */ prepareClientConfig: function () { - this.clientConfig.client = {}; - this.clientConfig.client[this.clientConfig.environment] = this.clientConfig.merchantId; this.clientConfig.rendererComponent = this; this.clientConfig.formKey = $.mage.cookies.get('form_key'); diff --git a/app/code/Magento/Paypal/view/frontend/web/js/in-context/express-checkout.js b/app/code/Magento/Paypal/view/frontend/web/js/in-context/express-checkout.js deleted file mode 100644 index 80c1dfc44977b..0000000000000 --- a/app/code/Magento/Paypal/view/frontend/web/js/in-context/express-checkout.js +++ /dev/null @@ -1,89 +0,0 @@ -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ -define([ - 'underscore', - 'jquery', - 'uiComponent', - 'paypalInContextExpressCheckout', - 'Magento_Customer/js/customer-data', - 'domReady!' -], function (_, $, Component, paypalExpressCheckout, customerData) { - 'use strict'; - - return Component.extend({ - - defaults: { - clientConfig: { - - checkoutInited: false, - - /** - * @param {Object} event - */ - click: function (event) { - $('body').trigger('processStart'); - - event.preventDefault(); - - if (!this.clientConfig.checkoutInited) { - paypalExpressCheckout.checkout.initXO(); - this.clientConfig.checkoutInited = true; - } else { - paypalExpressCheckout.checkout.closeFlow(); - } - - $.getJSON(this.path, { - button: 1 - }).done(function (response) { - var message = response && response.message; - - if (message) { - customerData.set('messages', { - messages: [message] - }); - } - - if (response && response.url) { - paypalExpressCheckout.checkout.startFlow(response.url); - - return; - } - - paypalExpressCheckout.checkout.closeFlow(); - }).fail(function () { - paypalExpressCheckout.checkout.closeFlow(); - }).always(function () { - $('body').trigger('processStop'); - customerData.invalidate(['cart']); - }); - } - } - }, - - /** - * @returns {Object} - */ - initialize: function () { - this._super(); - - return this.initClient(); - }, - - /** - * @returns {Object} - */ - initClient: function () { - _.each(this.clientConfig, function (fn, name) { - if (typeof fn === 'function') { - this.clientConfig[name] = fn.bind(this); - } - }, this); - - paypalExpressCheckout.checkout.setup(this.merchantId, this.clientConfig); - - return this; - } - }); -}); diff --git a/app/code/Magento/Paypal/view/frontend/web/js/in-context/paypal-sdk.js b/app/code/Magento/Paypal/view/frontend/web/js/in-context/paypal-sdk.js new file mode 100644 index 0000000000000..bc2928fb623ba --- /dev/null +++ b/app/code/Magento/Paypal/view/frontend/web/js/in-context/paypal-sdk.js @@ -0,0 +1,37 @@ +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +define([ + 'jquery' +], function ($) { + 'use strict'; + + var dfd = $.Deferred(); + + /** + * Loads the PayPal SDK object + * @param {String} paypalUrl - the url of the PayPal SDK + */ + return function loadPaypalScript(paypalUrl) { + //configuration for loaded PayPal script + require.config({ + paths: { + paypalSdk: paypalUrl + }, + shim: { + paypalSdk: { + exports: 'paypal' + } + } + }); + + if (dfd.state() !== 'resolved') { + require(['paypalSdk'], function (paypalObject) { + dfd.resolve(paypalObject); + }); + } + + return dfd.promise(); + }; +}); diff --git a/app/code/Magento/Paypal/view/frontend/web/js/in-context/product-express-checkout.js b/app/code/Magento/Paypal/view/frontend/web/js/in-context/product-express-checkout.js index b2be5fe2b3d2b..9469e168cdc6b 100644 --- a/app/code/Magento/Paypal/view/frontend/web/js/in-context/product-express-checkout.js +++ b/app/code/Magento/Paypal/view/frontend/web/js/in-context/product-express-checkout.js @@ -15,7 +15,8 @@ define([ defaults: { productFormSelector: '#product_addtocart_form', declinePayment: false, - formInvalid: false + formInvalid: false, + productAddedToCart: false }, /** @inheritdoc */ @@ -45,9 +46,10 @@ define([ onClick: function () { var $form = $(this.productFormSelector); - if (!this.declinePayment) { + if (!this.declinePayment && !this.productAddedToCart) { $form.submit(); this.formInvalid = !$form.validation('isValid'); + this.productAddedToCart = true; } }, @@ -74,14 +76,51 @@ define([ return promise; }, + /** + * After payment execute + * + * @param {Object} res + * @param {Function} resolve + * @param {Function} reject + * + * @return {*} + */ + afterPayment: function (res, resolve, reject) { + if (res.success) { + return resolve(res.token); + } + + this.addAlert(res['error_message']); + + return reject(new Error(res['error_message'])); + }, + /** @inheritdoc */ prepareClientConfig: function () { this._super(); this.clientConfig.quoteId = ''; this.clientConfig.customerId = ''; - this.clientConfig.commit = false; return this.clientConfig; + }, + + /** @inheritdoc */ + onError: function (err) { + this.productAddedToCart = false; + this._super(err); + }, + + /** @inheritdoc */ + onCancel: function (data, actions) { + this.productAddedToCart = false; + this._super(data, actions); + }, + + /** @inheritdoc */ + afterOnAuthorize: function (res, resolve, reject, actions) { + this.productAddedToCart = false; + + return this._super(res, resolve, reject, actions); } }); }); diff --git a/app/code/Magento/Paypal/view/frontend/web/js/view/payment/method-renderer/in-context/checkout-express.js b/app/code/Magento/Paypal/view/frontend/web/js/view/payment/method-renderer/in-context/checkout-express.js index 5c509238fe5cc..206355f5a9839 100644 --- a/app/code/Magento/Paypal/view/frontend/web/js/view/payment/method-renderer/in-context/checkout-express.js +++ b/app/code/Magento/Paypal/view/frontend/web/js/view/payment/method-renderer/in-context/checkout-express.js @@ -75,9 +75,7 @@ define([ this._super(); this.clientConfig.quoteId = window.checkoutConfig.quoteData['entity_id']; this.clientConfig.customerId = window.customerData.id; - this.clientConfig.merchantId = this.merchantId; this.clientConfig.button = 0; - this.clientConfig.commit = true; return this.clientConfig; }, @@ -99,6 +97,47 @@ define([ messageList.addErrorMessage({ message: message }); + }, + + /** + * After payment execute + * + * @param {Object} res + * @param {Function} resolve + * @param {Function} reject + * + * @return {*} + */ + afterPayment: function (res, resolve, reject) { + if (res.success) { + return resolve(res.token); + } + + this.addError(res['error_message']); + + return reject(new Error(res['error_message'])); + }, + + /** + * After onAuthorize execute + * + * @param {Object} res + * @param {Function} resolve + * @param {Function} reject + * @param {Object} actions + * + * @return {*} + */ + afterOnAuthorize: function (res, resolve, reject, actions) { + if (res.success) { + resolve(); + + return actions.redirect(res.redirectUrl); + } + + this.addError(res['error_message']); + + return reject(new Error(res['error_message'])); } }); }); diff --git a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminAssertAuthorizeButtonOnOrderPageActionGroup.xml b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminAssertAuthorizeButtonOnOrderPageActionGroup.xml new file mode 100644 index 0000000000000..c105a89509ef4 --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminAssertAuthorizeButtonOnOrderPageActionGroup.xml @@ -0,0 +1,17 @@ + + + + + + + Assert that order waiting for authorization. + + + + diff --git a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminAssertCurrencyInOrderActionGroup.xml b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminAssertCurrencyInOrderActionGroup.xml new file mode 100644 index 0000000000000..385799fb86dac --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminAssertCurrencyInOrderActionGroup.xml @@ -0,0 +1,20 @@ + + + + + + + Admin assert different currencies + + + + + + + diff --git a/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminAssertNoAuthorizeButtonOnOrderPageActionGroup.xml b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminAssertNoAuthorizeButtonOnOrderPageActionGroup.xml new file mode 100644 index 0000000000000..e88e0cfac30b2 --- /dev/null +++ b/app/code/Magento/Sales/Test/Mftf/ActionGroup/AdminAssertNoAuthorizeButtonOnOrderPageActionGroup.xml @@ -0,0 +1,17 @@ + + + + + + + Assert that order not waiting for authorization. + + + + diff --git a/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderDetailsMainActionsSection.xml b/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderDetailsMainActionsSection.xml index ecdf9e34de55a..9ce111663720d 100644 --- a/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderDetailsMainActionsSection.xml +++ b/app/code/Magento/Sales/Test/Mftf/Section/AdminOrderDetailsMainActionsSection.xml @@ -25,5 +25,6 @@ + diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminReorderWithCatalogPriceRuleDiscountTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminReorderWithCatalogPriceRuleDiscountTest.xml index 0a4445f338960..0ff5080bd8df2 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminReorderWithCatalogPriceRuleDiscountTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminReorderWithCatalogPriceRuleDiscountTest.xml @@ -24,6 +24,7 @@ + @@ -43,9 +44,7 @@ - - - + diff --git a/app/code/Magento/Tax/Test/Mftf/ActionGroup/StorefrontAssertOrderReviewSummaryWithTaxActionGroup.xml b/app/code/Magento/Tax/Test/Mftf/ActionGroup/StorefrontAssertOrderReviewSummaryWithTaxActionGroup.xml new file mode 100644 index 0000000000000..a6d16cf49d81f --- /dev/null +++ b/app/code/Magento/Tax/Test/Mftf/ActionGroup/StorefrontAssertOrderReviewSummaryWithTaxActionGroup.xml @@ -0,0 +1,20 @@ + + + + + + + Validates that the provided Subtotal, Shipping Total and Summary Total prices are present and correct on the Storefront Checkout page. + + + + + + + diff --git a/app/code/Magento/Tax/Test/Mftf/Section/StorefrontOrderReviewSection.xml b/app/code/Magento/Tax/Test/Mftf/Section/StorefrontOrderReviewSection.xml new file mode 100644 index 0000000000000..af9721d784862 --- /dev/null +++ b/app/code/Magento/Tax/Test/Mftf/Section/StorefrontOrderReviewSection.xml @@ -0,0 +1,14 @@ + + + + + + + + diff --git a/app/code/Magento/Ui/Test/Mftf/Section/AdminDataGridTableSection.xml b/app/code/Magento/Ui/Test/Mftf/Section/AdminDataGridTableSection.xml index e0f8408a1c30c..fcee31c0bd80c 100644 --- a/app/code/Magento/Ui/Test/Mftf/Section/AdminDataGridTableSection.xml +++ b/app/code/Magento/Ui/Test/Mftf/Section/AdminDataGridTableSection.xml @@ -21,5 +21,6 @@ + diff --git a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminCheckUrlRewritesCorrectlyGeneratedForMultipleStoreviewsDuringProductImportTest/AdminCheckUrlRewritesCorrectlyGeneratedForMultipleStoreviewsDuringProductImportTest.xml b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminCheckUrlRewritesCorrectlyGeneratedForMultipleStoreviewsDuringProductImportTest/AdminCheckUrlRewritesMultipleStoreviewsProductImportTest.xml similarity index 99% rename from app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminCheckUrlRewritesCorrectlyGeneratedForMultipleStoreviewsDuringProductImportTest/AdminCheckUrlRewritesCorrectlyGeneratedForMultipleStoreviewsDuringProductImportTest.xml rename to app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminCheckUrlRewritesCorrectlyGeneratedForMultipleStoreviewsDuringProductImportTest/AdminCheckUrlRewritesMultipleStoreviewsProductImportTest.xml index b9f726aec668e..4e46ed8e4fc79 100644 --- a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminCheckUrlRewritesCorrectlyGeneratedForMultipleStoreviewsDuringProductImportTest/AdminCheckUrlRewritesCorrectlyGeneratedForMultipleStoreviewsDuringProductImportTest.xml +++ b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminCheckUrlRewritesCorrectlyGeneratedForMultipleStoreviewsDuringProductImportTest/AdminCheckUrlRewritesMultipleStoreviewsProductImportTest.xml @@ -7,7 +7,7 @@ --> - + diff --git a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminCheckUrlRewritesCorrectlyGeneratedForMultipleStoreviewsDuringProductImportTest/AdminUrlRewriteGeneratedForMultipleStoreviewsDuringProductImportWithConfigTurnedOffTest.xml b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminCheckUrlRewritesCorrectlyGeneratedForMultipleStoreviewsDuringProductImportTest/AdminUrlRewriteMultipleStoreviewsProductImportWithConfigTurnedOffTest.xml similarity index 99% rename from app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminCheckUrlRewritesCorrectlyGeneratedForMultipleStoreviewsDuringProductImportTest/AdminUrlRewriteGeneratedForMultipleStoreviewsDuringProductImportWithConfigTurnedOffTest.xml rename to app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminCheckUrlRewritesCorrectlyGeneratedForMultipleStoreviewsDuringProductImportTest/AdminUrlRewriteMultipleStoreviewsProductImportWithConfigTurnedOffTest.xml index f9003ce8c0897..1d604ef7648dc 100644 --- a/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminCheckUrlRewritesCorrectlyGeneratedForMultipleStoreviewsDuringProductImportTest/AdminUrlRewriteGeneratedForMultipleStoreviewsDuringProductImportWithConfigTurnedOffTest.xml +++ b/app/code/Magento/UrlRewrite/Test/Mftf/Test/AdminCheckUrlRewritesCorrectlyGeneratedForMultipleStoreviewsDuringProductImportTest/AdminUrlRewriteMultipleStoreviewsProductImportWithConfigTurnedOffTest.xml @@ -7,7 +7,7 @@ --> - + diff --git a/composer.json b/composer.json index 2a19802e4fb2a..1d157e9d8d23f 100644 --- a/composer.json +++ b/composer.json @@ -193,6 +193,12 @@ "magento/module-instant-purchase": "*", "magento/module-integration": "*", "magento/module-layered-navigation": "*", + "magento/module-login-as-customer": "*", + "magento/module-login-as-customer-api": "*", + "magento/module-login-as-customer-log": "*", + "magento/module-login-as-customer-page-cache": "*", + "magento/module-login-as-customer-sales": "*", + "magento/module-login-as-customer-ui": "*", "magento/module-media-content": "*", "magento/module-media-content-api": "*", "magento/module-media-content-catalog": "*", diff --git a/composer.lock b/composer.lock index f1095dc95b150..f60616149be56 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "b7ee4a27d76ea68e295d5025c986854d", + "content-hash": "8af3f2640736569dc2a0d9b00b1c6e1e", "packages": [ { "name": "braintree/braintree_php", @@ -343,6 +343,16 @@ "dependency", "package" ], + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + }, + { + "url": "https://tidelift.com/funding/github/packagist/composer/composer", + "type": "tidelift" + } + ], "time": "2020-04-10T09:44:22+00:00" }, { @@ -508,6 +518,12 @@ "Xdebug", "performance" ], + "funding": [ + { + "url": "https://packagist.com", + "type": "custom" + } + ], "time": "2020-03-01T12:26:26+00:00" }, { @@ -3306,6 +3322,12 @@ "laminas", "zf" ], + "funding": [ + { + "url": "https://funding.communitybridge.org/projects/laminas-project", + "type": "community_bridge" + } + ], "time": "2020-04-03T16:01:00+00:00" }, { @@ -3961,6 +3983,20 @@ "x.509", "x509" ], + "funding": [ + { + "url": "https://github.com/terrafrost", + "type": "github" + }, + { + "url": "https://www.patreon.com/phpseclib", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpseclib/phpseclib", + "type": "tidelift" + } + ], "time": "2020-04-04T23:17:33+00:00" }, { @@ -4208,11 +4244,6 @@ "MIT" ], "authors": [ - { - "name": "Ben Ramsey", - "email": "ben@benramsey.com", - "homepage": "https://benramsey.com" - }, { "name": "Marijn Huizendveld", "email": "marijn.huizendveld@gmail.com" @@ -4220,6 +4251,11 @@ { "name": "Thibaud Fabre", "email": "thibaud@aztech.io" + }, + { + "name": "Ben Ramsey", + "email": "ben@benramsey.com", + "homepage": "https://benramsey.com" } ], "description": "Formerly rhumsaa/uuid. A PHP 5.4+ library for generating RFC 4122 version 1, 3, 4, and 5 universally unique identifiers (UUID).", @@ -4444,6 +4480,20 @@ ], "description": "Symfony Console Component", "homepage": "https://symfony.com", + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], "time": "2020-03-30T11:41:10+00:00" }, { @@ -4703,6 +4753,20 @@ ], "description": "Symfony Filesystem Component", "homepage": "https://symfony.com", + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], "time": "2020-03-27T16:54:36+00:00" }, { @@ -4824,6 +4888,20 @@ "polyfill", "portable" ], + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], "time": "2020-02-27T09:26:54+00:00" }, { @@ -4886,6 +4964,20 @@ "portable", "shim" ], + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], "time": "2020-03-09T19:04:49+00:00" }, { @@ -4945,6 +5037,20 @@ "portable", "shim" ], + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], "time": "2020-03-09T19:04:49+00:00" }, { @@ -5000,6 +5106,20 @@ "portable", "shim" ], + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], "time": "2020-02-27T09:26:54+00:00" }, { @@ -5058,6 +5178,20 @@ "portable", "shim" ], + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], "time": "2020-02-27T09:26:54+00:00" }, { @@ -5107,6 +5241,20 @@ ], "description": "Symfony Process Component", "homepage": "https://symfony.com", + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], "time": "2020-03-27T16:54:36+00:00" }, { @@ -6817,6 +6965,12 @@ "sftp", "storage" ], + "funding": [ + { + "url": "https://offset.earth/frankdejonge", + "type": "other" + } + ], "time": "2020-04-16T13:21:26+00:00" }, { @@ -7946,6 +8100,20 @@ "MIT" ], "description": "PHPStan - PHP Static Analysis Tool", + "funding": [ + { + "url": "https://github.com/ondrejmirtes", + "type": "github" + }, + { + "url": "https://www.patreon.com/phpstan", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpstan/phpstan", + "type": "tidelift" + } + ], "time": "2020-03-22T16:51:47+00:00" }, { @@ -9273,6 +9441,20 @@ ], "description": "Symfony Config Component", "homepage": "https://symfony.com", + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], "time": "2020-03-27T16:54:36+00:00" }, { @@ -9346,6 +9528,20 @@ ], "description": "Symfony DependencyInjection Component", "homepage": "https://symfony.com", + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], "time": "2020-03-30T10:09:30+00:00" }, { @@ -9476,6 +9672,20 @@ ], "description": "Symfony HttpFoundation Component", "homepage": "https://symfony.com", + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], "time": "2020-03-30T14:14:32+00:00" }, { @@ -9538,6 +9748,20 @@ "mime", "mime-type" ], + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], "time": "2020-03-27T16:56:45+00:00" }, { @@ -9788,6 +10012,20 @@ ], "description": "Symfony Yaml Component", "homepage": "https://symfony.com", + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], "time": "2020-03-30T11:41:10+00:00" }, { @@ -9925,6 +10163,12 @@ "env", "environment" ], + "funding": [ + { + "url": "https://tidelift.com/funding/github/packagist/vlucas/phpdotenv", + "type": "tidelift" + } + ], "time": "2020-04-12T15:11:38+00:00" }, { diff --git a/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/product_configurable_12345.php b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/product_configurable_12345.php index 70aa7c07ed536..b16a312488131 100644 --- a/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/product_configurable_12345.php +++ b/dev/tests/integration/testsuite/Magento/ConfigurableProduct/_files/product_configurable_12345.php @@ -21,7 +21,7 @@ /** @var ProductRepositoryInterface $productRepository */ $productRepository = Bootstrap::getObjectManager() - ->create(ProductRepositoryInterface::class); + ->get(ProductRepositoryInterface::class); /** @var $installer CategorySetup */ $installer = Bootstrap::getObjectManager()->create(CategorySetup::class); @@ -105,7 +105,7 @@ $registry->unregister('isSecureArea'); $registry->register('isSecureArea', true); try { - $productToDelete = $productRepository->getById(11); + $productToDelete = $productRepository->getById(111); $productRepository->delete($productToDelete); /** @var \Magento\Quote\Model\ResourceModel\Quote\Item $itemResource */ diff --git a/dev/tests/js/jasmine/tests/app/code/Magento/Paypal/frontend/js/in-context/express-checkout.test.js b/dev/tests/js/jasmine/tests/app/code/Magento/Paypal/frontend/js/in-context/express-checkout.test.js deleted file mode 100644 index 0420256e20ef5..0000000000000 --- a/dev/tests/js/jasmine/tests/app/code/Magento/Paypal/frontend/js/in-context/express-checkout.test.js +++ /dev/null @@ -1,133 +0,0 @@ -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ - -/* eslint-disable max-nested-callbacks */ -define([ - 'squire', - 'jquery' -], function (Squire, $) { - 'use strict'; - - describe('Magento_Paypal/js/in-context/express-checkout', function () { - - var model, - event, - paypalExpressCheckout, - injector = new Squire(), - mocks = { - 'paypalInContextExpressCheckout': { - checkout: jasmine.createSpyObj('checkout', - ['setup', 'initXO', 'startFlow', 'closeFlow'] - ) - }, - 'Magento_Customer/js/customer-data': { - set: jasmine.createSpy(), - invalidate: jasmine.createSpy() - } - }; - - /** - * Run before each test method - * - * @return void - */ - beforeEach(function (done) { - event = { - /** Stub */ - preventDefault: jasmine.createSpy('preventDefault') - }; - - injector.mock(mocks); - - injector.require([ - 'paypalInContextExpressCheckout', - 'Magento_Paypal/js/in-context/express-checkout'], function (PayPal, Constr) { - paypalExpressCheckout = PayPal; - model = new Constr(); - - done(); - }); - }); - - afterEach(function () { - try { - injector.clean(); - injector.remove(); - } catch (e) {} - }); - - describe('clientConfig.click method', function () { - - it('Check for properties defined ', function () { - expect(model.hasOwnProperty('clientConfig')).toBeDefined(); - expect(model.clientConfig.hasOwnProperty('click')).toBeDefined(); - expect(model.clientConfig.hasOwnProperty('checkoutInited')).toBeDefined(); - }); - - it('Check properties type', function () { - expect(typeof model.clientConfig.checkoutInited).toEqual('boolean'); - expect(typeof model.clientConfig.click).toEqual('function'); - }); - - it('Check properties value', function () { - expect(model.clientConfig.checkoutInited).toEqual(false); - }); - - it('Check call "click" method', function () { - - spyOn(jQuery.fn, 'trigger'); - spyOn(jQuery, 'get').and.callFake(function () { - var d = $.Deferred(); - - d.resolve({ - 'url': true - }); - - return d.promise(); - }); - - model.clientConfig.click(event); - - expect(event.preventDefault).toHaveBeenCalled(); - expect(paypalExpressCheckout.checkout.initXO).toHaveBeenCalled(); - expect(model.clientConfig.checkoutInited).toEqual(true); - expect(jQuery.get).toHaveBeenCalled(); - expect(jQuery('body').trigger).toHaveBeenCalledWith( - jasmine.arrayContaining(['processStart'], ['processStop']) - ); - }); - - it('Check call "click" method', function () { - var message = { - text: 'text', - type: 'error' - }; - - spyOn(jQuery.fn, 'trigger'); - spyOn(jQuery, 'get').and.callFake(function () { - var d = $.Deferred(); - - d.resolve({ - message: message - }); - - return d.promise(); - }); - - model.clientConfig.click(event); - expect(mocks['Magento_Customer/js/customer-data'].set).toHaveBeenCalledWith('messages', { - messages: [message] - }); - expect(event.preventDefault).toHaveBeenCalled(); - expect(paypalExpressCheckout.checkout.initXO).toHaveBeenCalled(); - expect(model.clientConfig.checkoutInited).toEqual(true); - expect(jQuery.get).toHaveBeenCalled(); - expect(jQuery('body').trigger).toHaveBeenCalledWith( - jasmine.arrayContaining(['processStart'], ['processStop']) - ); - }); - }); - }); -}); diff --git a/dev/tests/static/testsuite/Magento/Test/Integrity/Magento/Framework/Api/_files/ExtensibleInterfacesTest/blacklist_ce.txt b/dev/tests/static/testsuite/Magento/Test/Integrity/Magento/Framework/Api/_files/ExtensibleInterfacesTest/blacklist_ce.txt index e9b1e6e428e03..c544cf71dfce1 100644 --- a/dev/tests/static/testsuite/Magento/Test/Integrity/Magento/Framework/Api/_files/ExtensibleInterfacesTest/blacklist_ce.txt +++ b/dev/tests/static/testsuite/Magento/Test/Integrity/Magento/Framework/Api/_files/ExtensibleInterfacesTest/blacklist_ce.txt @@ -1,4 +1,5 @@ module Magento_Payment Model/Info.php module Magento_Customer Model/Address/AbstractAddress.php library magento/framework MessageQueue/Rpc/Publisher.php -module Magento_GraphQl Model/Query/ContextInterface.php \ No newline at end of file +module Magento_GraphQl Model/Query/ContextInterface.php +module Magento_LoginAsCustomerApi Api/Data/AuthenticationDataInterface.php \ No newline at end of file