From 4e7c3cbd5d64d299965ff258cab84b11c3d6379d Mon Sep 17 00:00:00 2001 From: Roman Ganin Date: Tue, 19 Jun 2018 15:36:06 -0500 Subject: [PATCH 01/44] MAGETWO-60034: Cannot ship remaining items in an order for several of one product if credit memo is made for some --- app/code/Magento/Sales/Model/Order/Item.php | 2 +- app/code/Magento/Sales/Test/Unit/Model/Order/ItemTest.php | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/app/code/Magento/Sales/Model/Order/Item.php b/app/code/Magento/Sales/Model/Order/Item.php index d2f5f5ce566..7fa2f615545 100644 --- a/app/code/Magento/Sales/Model/Order/Item.php +++ b/app/code/Magento/Sales/Model/Order/Item.php @@ -232,7 +232,7 @@ public function getQtyToShip() */ public function getSimpleQtyToShip() { - $qty = $this->getQtyOrdered() - $this->getQtyShipped() - $this->getQtyRefunded() - $this->getQtyCanceled(); + $qty = $this->getQtyOrdered() - $this->getQtyShipped() - $this->getQtyCanceled(); return max(round($qty, 8), 0); } diff --git a/app/code/Magento/Sales/Test/Unit/Model/Order/ItemTest.php b/app/code/Magento/Sales/Test/Unit/Model/Order/ItemTest.php index 39fffa23dc1..956152d2e08 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/Order/ItemTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/Order/ItemTest.php @@ -292,14 +292,14 @@ public function getItemQtyVariants() 'qty_ordered' => 12, 'qty_invoiced' => 5, 'qty_refunded' => 5, 'qty_shipped' => 0, 'qty_canceled' => 0, ], - 'expectedResult' => ['to_ship' => 7.0, 'to_invoice' => 7.0] + 'expectedResult' => ['to_ship' => 12.0, 'to_invoice' => 7.0] ], 'partially_refunded' => [ 'options' => [ 'qty_ordered' => 12, 'qty_invoiced' => 12, 'qty_refunded' => 5, 'qty_shipped' => 0, 'qty_canceled' => 0, ], - 'expectedResult' => ['to_ship' => 7.0, 'to_invoice' => 0.0] + 'expectedResult' => ['to_ship' => 12.0, 'to_invoice' => 0.0] ], 'partially_shipped' => [ 'options' => [ @@ -313,7 +313,7 @@ public function getItemQtyVariants() 'qty_ordered' => 12, 'qty_invoiced' => 12, 'qty_refunded' => 5, 'qty_shipped' => 4, 'qty_canceled' => 0 ], - 'expectedResult' => ['to_ship' => 3.0, 'to_invoice' => 0.0] + 'expectedResult' => ['to_ship' => 8.0, 'to_invoice' => 0.0] ], 'complete' => [ 'options' => [ @@ -334,7 +334,7 @@ public function getItemQtyVariants() 'qty_ordered' => 4.4, 'qty_invoiced' => 0.4, 'qty_refunded' => 0.4, 'qty_shipped' => 4, 'qty_canceled' => 0, ], - 'expectedResult' => ['to_ship' => 0.0, 'to_invoice' => 4.0] + 'expectedResult' => ['to_ship' => 0.4, 'to_invoice' => 4.0] ], 'completely_invoiced_using_decimals' => [ 'options' => [ From a73786b1a1342f43977af2f7ad01fd402c77cfd4 Mon Sep 17 00:00:00 2001 From: Deepty Thampy Date: Wed, 27 Jun 2018 16:26:09 -0500 Subject: [PATCH 02/44] MAGETWO-60034: Cannot ship remaining items nan order for several of one product if credit memo is made for some - added functional test --- ...inAbleToShipPartiallyInvoicedItemsTest.xml | 76 +++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Sales/Test/AdminAbleToShipPartiallyInvoicedItemsTest.xml diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Sales/Test/AdminAbleToShipPartiallyInvoicedItemsTest.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Sales/Test/AdminAbleToShipPartiallyInvoicedItemsTest.xml new file mode 100644 index 00000000000..0f5346e619a --- /dev/null +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Sales/Test/AdminAbleToShipPartiallyInvoicedItemsTest.xml @@ -0,0 +1,76 @@ + + + + + + + <description value="Admin should not be able to submit orders without an email address"/> + <severity value="MAJOR"/> + <testCaseId value="MAGETWO-60034"/> + <group value="sales"/> + + </annotations> + <before> + <createData entity="_defaultCategory" stepKey="createCategory"/> + <createData entity="_defaultProduct" stepKey="createSimpleProduct"> + <requiredEntity createDataKey="createCategory"/> + </createData> + </before> + <after> + <deleteData createDataKey="createSimpleProduct" stepKey="deleteProduct"/> + <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> + <amOnPage url="admin/admin/auth/logout/" stepKey="amOnLogoutPage"/> + </after> + <!--Create order via Admin--> + <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> + <comment userInput="Admin creates order" stepKey="adminCreateOrderComment"/> + <!--<actionGroup ref="navigateToNewOrderPageNewCustomer" stepKey="navigateToNewOrderPage"/>--> + <amOnPage url="{{AdminOrdersPage.url}}" stepKey="navigateToOrderIndexPage"/> + <waitForPageLoad stepKey="waitForIndexPageLoad"/> + <see selector="{{AdminHeaderSection.pageTitle}}" userInput="Orders" stepKey="seeIndexPageTitle"/> + <click selector="{{AdminOrdersGridSection.createNewOrder}}" stepKey="clickCreateNewOrder"/> + <click selector="{{AdminOrderFormActionSection.CreateNewCustomer}}" stepKey="clickCreateCustomer"/> + <see selector="{{AdminHeaderSection.pageTitle}}" userInput="Create New Order" stepKey="seeNewOrderPageTitle"/> + <!--<actionGroup ref="checkRequiredFieldsNewOrderForm" stepKey="checkRequiredFieldsNewOrder" after="seeNewOrderPageTitle"/>--> + <!--<scrollToTopOfPage stepKey="scrollToTopOfOrderFormPage" after="checkRequiredFieldsNewOrder"/>--> + <actionGroup ref="addSimpleProductToOrderWithCustomQuantity" stepKey="addSimpleProductToOrderWithUserDefinedQty"> + <argument name="product" value="_defaultProduct"/> + <argument name="quantity" value="10"/> + </actionGroup> + + <!--Fill customer group and customer email which both are now required fields--> + <selectOption selector="{{AdminOrderFormAccountSection.group}}" userInput="{{GeneralCustomerGroup.code}}" stepKey="selectCustomerGroup" after="addSimpleProductToOrder"/> + <fillField selector="{{AdminOrderFormAccountSection.email}}" userInput="{{Simple_US_Customer.email}}" stepKey="fillCustomerEmail" after="selectCustomerGroup"/> + + <!--Fill customer address information--> + <actionGroup ref="fillOrderCustomerInformation" stepKey="fillCustomerAddress" after="fillCustomerEmail"> + <argument name="customer" value="Simple_US_Customer"/> + <argument name="address" value="US_Address_TX"/> + </actionGroup> + <!-- Select shipping --> + <actionGroup ref="orderSelectFlatRateShipping" stepKey="selectFlatRateShipping" after="fillCustomerAddress"/> + + <!--Verify totals on Order page--> + <see selector="{{AdminOrderFormTotalSection.total('Subtotal')}}" userInput="$1230.00" stepKey="seeOrderSubTotal" after="selectFlatRateShipping"/> + <see selector="{{AdminOrderFormTotalSection.total('Shipping')}}" userInput="$50.00" stepKey="seeOrderShipping" after="seeOrderSubTotal"/> + <scrollTo selector="{{AdminOrderFormTotalSection.grandTotal}}" stepKey="scrollToOrderGrandTotal"/> + <see selector="{{AdminOrderFormTotalSection.grandTotal}}" userInput="$1280.00" stepKey="seeCorrectGrandTotal" after="scrollToOrderGrandTotal"/> + + <!--Submit Order and verify information--> + <click selector="{{AdminOrderFormActionSection.SubmitOrder}}" stepKey="clickSubmitOrder" after="seeCorrectGrandTotal"/> + <seeInCurrentUrl url="{{AdminOrderDetailsPage.url}}" stepKey="seeViewOrderPage" after="clickSubmitOrder"/> + <see selector="{{AdminOrderDetailsMessagesSection.successMessage}}" userInput="You created the order." stepKey="seeSuccessMessage" after="seeViewOrderPage"/> + <scrollTo selector="{{AdminOrderItemsOrderedSection.qtyColumn}}" stepKey="scrollToItemsOrdered" after="seeSuccessMessage"/> + <see selector="{{AdminOrderItemsOrderedSection.itemQty('1')}}" userInput="Ordered 10" stepKey="seeQtyOfItemsOrdered" after="scrollToItemsOrdered"/> + + + + </test> +</tests> + From 228eaee9f918a136994c54a6e5e3e4eb1269ef4b Mon Sep 17 00:00:00 2001 From: Deepty Thampy <dthampy@magento.com> Date: Thu, 28 Jun 2018 15:27:52 -0500 Subject: [PATCH 03/44] MAGETWO-60034: Cannot ship remaining items nan order for several of one product if credit memo is made for some - added functional test and updated actionGroup --- .../ActionGroup/AdminOrderActionGroup.xml | 18 +++ ...inAbleToShipPartiallyInvoicedItemsTest.xml | 109 ++++++++++++++++-- .../Section/AdminShipmentItemsSection.xml | 2 +- 3 files changed, 120 insertions(+), 9 deletions(-) diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Sales/ActionGroup/AdminOrderActionGroup.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Sales/ActionGroup/AdminOrderActionGroup.xml index 7461d9010a0..a27ee27c0b8 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Sales/ActionGroup/AdminOrderActionGroup.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Sales/ActionGroup/AdminOrderActionGroup.xml @@ -60,6 +60,24 @@ <click selector="{{AdminOrderFormItemsSection.addSelected}}" stepKey="clickAddSelectedProducts"/> </actionGroup> + <!--Add a simple product to order with user defined quantity--> + <actionGroup name="addSimpleProductToOrderWithCustomQuantity"> + <arguments> + <argument name="product" defaultValue="_defaultProduct"/> + <argument name="quantity" type="string"/> + </arguments> + <waitForLoadingMaskToDisappear stepKey="waitForLoadingMastToDisappear"/> + <waitForElementVisible selector="{{AdminOrderFormItemsSection.addProducts}}" stepKey="waitForAddProductButton"/> + <click selector="{{AdminOrderFormItemsSection.addProducts}}" stepKey="clickAddProducts"/> + <fillField selector="{{AdminOrderFormItemsSection.skuFilter}}" userInput="{{product.sku}}" stepKey="fillSkuFilter"/> + <click selector="{{AdminOrderFormItemsSection.search}}" stepKey="clickSearch"/> + <scrollTo selector="{{AdminOrderFormItemsSection.rowCheck('1')}}" x="0" y="-100" stepKey="scrollToCheckColumn"/> + <checkOption selector="{{AdminOrderFormItemsSection.rowCheck('1')}}" stepKey="selectProduct"/> + <fillField selector="{{AdminOrderFormItemsSection.rowQty('1')}}" userInput="{{quantity}}" stepKey="fillProductQty"/> + <scrollTo selector="{{AdminOrderFormItemsSection.addSelected}}" x="0" y="-100" stepKey="scrollToAddSelectedButton"/> + <click selector="{{AdminOrderFormItemsSection.addSelected}}" stepKey="clickAddSelectedProducts"/> + </actionGroup> + <!--Add configurable product to order --> <actionGroup name="addConfigurableProductToOrder"> <arguments> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Sales/Test/AdminAbleToShipPartiallyInvoicedItemsTest.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Sales/Test/AdminAbleToShipPartiallyInvoicedItemsTest.xml index 0f5346e619a..c477fabe048 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Sales/Test/AdminAbleToShipPartiallyInvoicedItemsTest.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Sales/Test/AdminAbleToShipPartiallyInvoicedItemsTest.xml @@ -27,25 +27,25 @@ <deleteData createDataKey="createCategory" stepKey="deleteCategory"/> <amOnPage url="admin/admin/auth/logout/" stepKey="amOnLogoutPage"/> </after> - <!--Create order via Admin--> + + <!--login to Admin--> <actionGroup ref="LoginAsAdmin" stepKey="loginAsAdmin"/> <comment userInput="Admin creates order" stepKey="adminCreateOrderComment"/> - <!--<actionGroup ref="navigateToNewOrderPageNewCustomer" stepKey="navigateToNewOrderPage"/>--> <amOnPage url="{{AdminOrdersPage.url}}" stepKey="navigateToOrderIndexPage"/> <waitForPageLoad stepKey="waitForIndexPageLoad"/> <see selector="{{AdminHeaderSection.pageTitle}}" userInput="Orders" stepKey="seeIndexPageTitle"/> + + <!--Create new order--> <click selector="{{AdminOrdersGridSection.createNewOrder}}" stepKey="clickCreateNewOrder"/> <click selector="{{AdminOrderFormActionSection.CreateNewCustomer}}" stepKey="clickCreateCustomer"/> <see selector="{{AdminHeaderSection.pageTitle}}" userInput="Create New Order" stepKey="seeNewOrderPageTitle"/> - <!--<actionGroup ref="checkRequiredFieldsNewOrderForm" stepKey="checkRequiredFieldsNewOrder" after="seeNewOrderPageTitle"/>--> - <!--<scrollToTopOfPage stepKey="scrollToTopOfOrderFormPage" after="checkRequiredFieldsNewOrder"/>--> <actionGroup ref="addSimpleProductToOrderWithCustomQuantity" stepKey="addSimpleProductToOrderWithUserDefinedQty"> <argument name="product" value="_defaultProduct"/> <argument name="quantity" value="10"/> </actionGroup> <!--Fill customer group and customer email which both are now required fields--> - <selectOption selector="{{AdminOrderFormAccountSection.group}}" userInput="{{GeneralCustomerGroup.code}}" stepKey="selectCustomerGroup" after="addSimpleProductToOrder"/> + <selectOption selector="{{AdminOrderFormAccountSection.group}}" userInput="{{GeneralCustomerGroup.code}}" stepKey="selectCustomerGroup" after="addSimpleProductToOrderWithUserDefinedQty"/> <fillField selector="{{AdminOrderFormAccountSection.email}}" userInput="{{Simple_US_Customer.email}}" stepKey="fillCustomerEmail" after="selectCustomerGroup"/> <!--Fill customer address information--> @@ -57,20 +57,113 @@ <actionGroup ref="orderSelectFlatRateShipping" stepKey="selectFlatRateShipping" after="fillCustomerAddress"/> <!--Verify totals on Order page--> - <see selector="{{AdminOrderFormTotalSection.total('Subtotal')}}" userInput="$1230.00" stepKey="seeOrderSubTotal" after="selectFlatRateShipping"/> + <see selector="{{AdminOrderFormTotalSection.total('Subtotal')}}" userInput="$1,230.00" stepKey="seeOrderSubTotal" after="selectFlatRateShipping"/> <see selector="{{AdminOrderFormTotalSection.total('Shipping')}}" userInput="$50.00" stepKey="seeOrderShipping" after="seeOrderSubTotal"/> <scrollTo selector="{{AdminOrderFormTotalSection.grandTotal}}" stepKey="scrollToOrderGrandTotal"/> - <see selector="{{AdminOrderFormTotalSection.grandTotal}}" userInput="$1280.00" stepKey="seeCorrectGrandTotal" after="scrollToOrderGrandTotal"/> + <see selector="{{AdminOrderFormTotalSection.grandTotal}}" userInput="$1,280.00" stepKey="seeCorrectGrandTotal" after="scrollToOrderGrandTotal"/> <!--Submit Order and verify information--> <click selector="{{AdminOrderFormActionSection.SubmitOrder}}" stepKey="clickSubmitOrder" after="seeCorrectGrandTotal"/> <seeInCurrentUrl url="{{AdminOrderDetailsPage.url}}" stepKey="seeViewOrderPage" after="clickSubmitOrder"/> <see selector="{{AdminOrderDetailsMessagesSection.successMessage}}" userInput="You created the order." stepKey="seeSuccessMessage" after="seeViewOrderPage"/> - <scrollTo selector="{{AdminOrderItemsOrderedSection.qtyColumn}}" stepKey="scrollToItemsOrdered" after="seeSuccessMessage"/> + <grabTextFrom selector="|Order # (\d+)|" stepKey="getOrderId" after="seeSuccessMessage"/> + <scrollTo selector="{{AdminOrderItemsOrderedSection.qtyColumn}}" stepKey="scrollToItemsOrdered" after="getOrderId"/> <see selector="{{AdminOrderItemsOrderedSection.itemQty('1')}}" userInput="Ordered 10" stepKey="seeQtyOfItemsOrdered" after="scrollToItemsOrdered"/> + <!--Create order invoice for first half of ordered items--> + <comment userInput="Admin creates invoice for order" stepKey="adminCreateInvoiceComment" /> + <click selector="{{AdminOrderDetailsMainActionsSection.invoice}}" stepKey="clickInvoiceActionButton"/> + <!--<seeInCurrentUrl url="{{AdminInvoiceNewPage.url}}" stepKey="seeOrderInvoiceUrl" after="clickInvoiceAction"/>--> + <see selector="{{AdminHeaderSection.pageTitle}}" userInput="New Invoice" stepKey="seePageNameNewInvoicePage" after="clickInvoiceActionButton"/> + <scrollTo selector="{{AdminInvoiceItemsSection.itemQtyToInvoice('1')}}" stepKey="scrollToItemsInvoiced"/> + + <!--Verify items invoiced information--> + + <!--<see selector="{{AdminInvoiceItemsSection.itemQty('1')}}" userInput="Invoiced Partial" stepKey="seeQtyOfItemsInvoiced"/>--> + <fillField selector="{{AdminInvoiceItemsSection.itemQtyToInvoice('1')}}" userInput="5" stepKey="invoiceHalfTheItems"/> + + <click selector="{{AdminInvoiceItemsSection.updateQty}}" stepKey="updateQtyToBeInvoiced"/> + <waitForLoadingMaskToDisappear stepKey="WaitForQtyToUpdate"/> + <waitForElementVisible selector="{{AdminInvoiceMainActionsSection.submitInvoice}}" stepKey="waitforSubmitInvoiceBtn"/> + + <!--Submit Invoice--> + <click selector="{{AdminInvoiceMainActionsSection.submitInvoice}}" stepKey="submitInvoice"/> + <waitForLoadingMaskToDisappear stepKey="WaitForInvoiceToSubmit"/> + <!--<waitForElementVisible selector="{{AdminOrderDetailsMessagesSection.successMessage}}" stepKey="waitUntilInvoiceSucesssMsg"/>--> + + <!--Invoice created successfully--> + <see selector="{{AdminOrderDetailsMessagesSection.successMessage}}" userInput="The invoice has been created." stepKey="seeInvoiceSuccessMessage"/> + <click selector="{{AdminOrderDetailsOrderViewSection.invoices}}" stepKey="clickInvoicesTab"/> + <waitForLoadingMaskToDisappear stepKey="waitForInvoiceGridToLoad" after="clickInvoicesTab"/> + <see selector="{{AdminOrderInvoicesTabSection.gridRow('1')}}" userInput="$665.00" stepKey="seeOrderInvoiceTabInGrid" after="waitForInvoiceGridToLoad"/> + <click selector="{{AdminOrderInvoicesTabSection.viewGridRow('1')}}" stepKey="clickToViewInvoice" after="seeOrderInvoiceTabInGrid"/> + <click selector="{{AdminInvoiceOrderInformationSection.orderId}}" stepKey="clickOrderIdLinkOnInvoice"/> + + <!--Ship Order--> + <comment userInput="Admin creates shipment" stepKey="adminCreatesShipmentComment" before="clickShip"/> + <click selector="{{AdminOrderDetailsMainActionsSection.ship}}" stepKey="clickShip" after="clickOrderIdLinkOnInvoice"/> + <seeInCurrentUrl url="{{AdminShipmentNewPage.url}}" stepKey="OrderShipmentUrl" after="clickShip"/> + <scrollTo selector="{{AdminShipmentItemsSection.itemQtyToShip('1')}}" stepKey="scrollToItemsToShip"/> + <see selector="{{AdminShipmentItemsSection.itemQty('1')}}" userInput="Invoiced 5" stepKey="see5itemsInvoiced"/> + <fillField selector="{{AdminShipmentItemsSection.itemQtyToShip('1')}}" userInput="5" stepKey="fillQtyOfItemsToShip"/> + + <!--Submit Shipment--> + <click selector="{{AdminShipmentMainActionsSection.submitShipment}}" stepKey="submitShipment" after="fillQtyOfItemsToShip"/> + <see selector="{{AdminOrderDetailsMessagesSection.successMessage}}" userInput="The shipment has been created." stepKey="successfullShipmentCreation" after="submitShipment"/> + <see selector="{{AdminHeaderSection.pageTitle}}" userInput="$getOrderId" stepKey="seeOrderIdInPageTitleAfterShip"/> + + <!--Verify Items Status and Shipped Qty in the Items Ordered section--> + <scrollTo selector="{{AdminOrderItemsOrderedSection.itemStatus('1')}}" stepKey="scrollToItemsShipped"/> + <see selector="{{AdminOrderItemsOrderedSection.itemQty('1')}}" userInput="Shipped 5" stepKey="see5itemsShipped"/> + + <!--Create Credit Memo--> + <comment userInput="Admin creates credit memo" stepKey="createCreditMemoComment"/> + <click selector="{{AdminOrderDetailsMainActionsSection.creditMemo}}" stepKey="clickCreateCreditMemo" after="createCreditMemoComment"/> + <see selector="{{AdminHeaderSection.pageTitle}}" userInput="New Memo" stepKey="seeNewMemoInPageTitle"/> + + <!--Update Qty of items to be refunded and submit refund--> + <scrollTo selector="{{AdminCreditMemoItemsSection.itemQtyToRefund('1')}}" stepKey="scrollToItemsToRefund"/> + <fillField selector="{{AdminCreditMemoItemsSection.itemQtyToRefund('1')}}" userInput="5" stepKey="fillQtyOfItemsToRefund" after="scrollToItemsToRefund"/> + <click selector="{{AdminCreditMemoItemsSection.updateQty}}" stepKey="updateRefundQty"/> + <waitForLoadingMaskToDisappear stepKey="waitForRefundQtyToUpdate"/> + <waitForElementVisible selector="{{AdminCreditMemoTotalSection.submitRefundOffline}}" stepKey="seeSubmitRefundBtn"/> + <click selector="{{AdminCreditMemoTotalSection.submitRefundOffline}}" stepKey="submitRefundOffline"/> + <see selector="{{AdminOrderDetailsMessagesSection.successMessage}}" userInput="You created the credit memo." stepKey="seeCreditMemoSuccessMsg" after="submitRefundOffline"/> + + <!--Create invoice for rest of the ordered items--> + <comment userInput="Admin creates invoice for rest of the items" stepKey="adminCreateInvoiceComment2" /> + <click selector="{{AdminOrderDetailsMainActionsSection.invoice}}" stepKey="clickInvoiceActionForRestOfItems"/> + <see selector="{{AdminHeaderSection.pageTitle}}" userInput="New Invoice" stepKey="seePageNameNewInvoicePage2" after="clickInvoiceActionForRestOfItems"/> + + <comment userInput="Qty To Invoice is 5" stepKey="seeRemainderInQtyToInvoice"/> + <scrollTo selector="{{AdminInvoiceItemsSection.itemQtyToInvoice('1')}}" stepKey="scrollToItemsInvoiced2"/> + <!--<see selector="{{AdminInvoiceItemsSection.itemQtyToInvoice('1')}}" stepKey="scrollToItemsInvoiced2"/>--> + <seeInField userInput="5" selector="{{AdminInvoiceItemsSection.itemQtyToInvoice('1')}}" stepKey="see5InTheQtyToInvoice"/> + + <!--Verify items invoiced information--> + <see selector="{{AdminInvoiceItemsSection.itemQty('1')}}" userInput="Refunded 5" stepKey="seeQtyOfItemsRefunded"/> + + <!--Submit Invoice--> + <click selector="{{AdminInvoiceMainActionsSection.submitInvoice}}" stepKey="submitInvoice2" /> + + <!--Invoice created successfully for the rest of the ordered items--> + <see selector="{{AdminOrderDetailsMessagesSection.successMessage}}" userInput="The invoice has been created." stepKey="seeInvoiceSuccessMessage2" after="submitInvoice2"/> + + <!--Verify Ship Action can be done for the rest of the invoiced items --> + <click selector="{{AdminOrderDetailsMainActionsSection.ship}}" stepKey="clickShipActionForRestOfItems" after="seeInvoiceSuccessMessage2"/> + + <!--Verify Items To Ship section --> + <scrollTo selector="{{AdminShipmentItemsSection.itemQtyToShip('1')}}" stepKey="scrollToItemsToShip2"/> + <see selector="{{AdminShipmentItemsSection.itemQty('1')}}" userInput="Invoiced 10" stepKey="SeeAll10ItemsInvoiced"/> + <fillField selector="{{AdminShipmentItemsSection.itemQtyToShip('1')}}" userInput="5" stepKey="fillRestOfItemsToShip"/> + <!--Submit Shipment--> + <click selector="{{AdminShipmentMainActionsSection.submitShipment}}" stepKey="submitShipment2" after="fillRestOfItemsToShip"/> + <see selector="{{AdminOrderDetailsMessagesSection.successMessage}}" userInput="The shipment has been created." stepKey="successfullyCreatedShipment" after="submitShipment2"/> + <!--Verify Items Status and Shipped Qty in the Items Ordered section--> + <scrollTo selector="{{AdminOrderItemsOrderedSection.itemStatus('1')}}" stepKey="scrollToItemsOrdered2"/> + <see selector="{{AdminOrderItemsOrderedSection.itemQty('1')}}" userInput="Shipped 10" stepKey="seeAllItemsShipped"/> </test> </tests> diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Shipping/Section/AdminShipmentItemsSection.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Shipping/Section/AdminShipmentItemsSection.xml index 562ad729fe7..e2191342056 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Shipping/Section/AdminShipmentItemsSection.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Shipping/Section/AdminShipmentItemsSection.xml @@ -12,7 +12,7 @@ <element name="itemName" type="text" selector=".order-shipment-table tbody:nth-of-type({{row}}) .col-product .product-title" parameterized="true"/> <element name="itemSku" type="text" selector=".order-shipment-table tbody:nth-of-type({{row}}) .col-product .product-sku-block" parameterized="true"/> <element name="itemQty" type="text" selector=".order-shipment-table tbody:nth-of-type({{row}}) .col-ordered-qty .qty-table" parameterized="true"/> - <element name="itemQtyToShip" type="input" selector=".order-shipment-table tbody:nth-of-type({{row}}) .col-qty input.qty-item"/> + <element name="itemQtyToShip" type="input" selector=".order-shipment-table tbody:nth-of-type({{row}}) .col-qty input.qty-item" parameterized="true"/> <element name="nameColumn" type="text" selector=".order-shipment-table .col-product .product-title"/> <element name="skuColumn" type="text" selector=".order-shipment-table .col-product .product-sku-block"/> </section> From 34f2b469363c9ec1019e1e895f6b49b5b5491586 Mon Sep 17 00:00:00 2001 From: Deepty Thampy <dthampy@magento.com> Date: Thu, 28 Jun 2018 15:31:46 -0500 Subject: [PATCH 04/44] MAGETWO-60034: Cannot ship remaining items nan order for several of one product if credit memo is made for some - updated testCaseId --- .../Sales/Test/AdminAbleToShipPartiallyInvoicedItemsTest.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Sales/Test/AdminAbleToShipPartiallyInvoicedItemsTest.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Sales/Test/AdminAbleToShipPartiallyInvoicedItemsTest.xml index c477fabe048..2d7fe4d165a 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Sales/Test/AdminAbleToShipPartiallyInvoicedItemsTest.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Sales/Test/AdminAbleToShipPartiallyInvoicedItemsTest.xml @@ -12,7 +12,7 @@ <title value="Email is required to create an order from Admin Panel"/> <description value="Admin should not be able to submit orders without an email address"/> <severity value="MAJOR"/> - <testCaseId value="MAGETWO-60034"/> + <testCaseId value="MAGETWO-93030"/> <group value="sales"/> </annotations> From e52a3265ac0d003ae15f028d14970a5c85528762 Mon Sep 17 00:00:00 2001 From: Deepty Thampy <dthampy@magento.com> Date: Thu, 28 Jun 2018 15:49:52 -0500 Subject: [PATCH 05/44] MAGETWO-60034: Cannot ship remaining items nan order for several of one product if credit memo is made for some - updated description title and severity --- .../Test/AdminAbleToShipPartiallyInvoicedItemsTest.xml | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Sales/Test/AdminAbleToShipPartiallyInvoicedItemsTest.xml b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Sales/Test/AdminAbleToShipPartiallyInvoicedItemsTest.xml index 2d7fe4d165a..9b629f410f4 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Sales/Test/AdminAbleToShipPartiallyInvoicedItemsTest.xml +++ b/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Sales/Test/AdminAbleToShipPartiallyInvoicedItemsTest.xml @@ -9,9 +9,9 @@ xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/Test/etc/testSchema.xsd"> <test name="AdminAbleToShipPartiallyInvoicedItemsTest"> <annotations> - <title value="Email is required to create an order from Admin Panel"/> - <description value="Admin should not be able to submit orders without an email address"/> - <severity value="MAJOR"/> + <title value="Ship Action is available for remaining of the partially invoiced items "/> + <description value="Admin should be able to ship remaining ordered items if some of them are already refunded"/> + <severity value="CRITICAL"/> <testCaseId value="MAGETWO-93030"/> <group value="sales"/> @@ -78,10 +78,7 @@ <scrollTo selector="{{AdminInvoiceItemsSection.itemQtyToInvoice('1')}}" stepKey="scrollToItemsInvoiced"/> <!--Verify items invoiced information--> - - <!--<see selector="{{AdminInvoiceItemsSection.itemQty('1')}}" userInput="Invoiced Partial" stepKey="seeQtyOfItemsInvoiced"/>--> <fillField selector="{{AdminInvoiceItemsSection.itemQtyToInvoice('1')}}" userInput="5" stepKey="invoiceHalfTheItems"/> - <click selector="{{AdminInvoiceItemsSection.updateQty}}" stepKey="updateQtyToBeInvoiced"/> <waitForLoadingMaskToDisappear stepKey="WaitForQtyToUpdate"/> <waitForElementVisible selector="{{AdminInvoiceMainActionsSection.submitInvoice}}" stepKey="waitforSubmitInvoiceBtn"/> From 6421d302bbb8960cc229c3cdbde6b822c8a09538 Mon Sep 17 00:00:00 2001 From: Roman Ganin <rganin@magento.com> Date: Tue, 3 Jul 2018 14:01:28 -0500 Subject: [PATCH 06/44] MAGETWO-60034: Cannot ship remaining items in an order for several of one product if credit memo is made for some - fixing tests for new logic --- .../Magento/Sales/Service/V1/CreditMemoCreateRefundTest.php | 3 ++- .../testsuite/Magento/Sales/Service/V1/RefundOrderTest.php | 5 +++-- .../integration/testsuite/Magento/Paypal/Model/IpnTest.php | 6 ++++-- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/CreditMemoCreateRefundTest.php b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/CreditMemoCreateRefundTest.php index 8262a7e4154..eae0e600434 100644 --- a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/CreditMemoCreateRefundTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/CreditMemoCreateRefundTest.php @@ -115,7 +115,8 @@ public function testInvoke() ); $this->assertNotEmpty($result); $order = $this->objectManager->get(OrderRepositoryInterface::class)->get($order->getId()); - $this->assertEquals(Order::STATE_CLOSED, $order->getState()); + //Totally refunded orders still can be processed and shipped. + $this->assertEquals(Order::STATE_PROCESSING, $order->getState()); } private function getItemsForRest($order) diff --git a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/RefundOrderTest.php b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/RefundOrderTest.php index 12cbe1ca0e5..aacda763ca2 100644 --- a/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/RefundOrderTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/RefundOrderTest.php @@ -86,10 +86,11 @@ public function testShortRequest() 'Failed asserting that proper shipping amount of the Order was refunded' ); - $this->assertNotEquals( + //Totally refunded orders can be processed. + $this->assertEquals( $existingOrder->getStatus(), $updatedOrder->getStatus(), - 'Failed asserting that order status was changed' + 'Failed asserting that order status has not changed' ); } catch (\Magento\Framework\Exception\NoSuchEntityException $e) { $this->fail('Failed asserting that Creditmemo was created'); diff --git a/dev/tests/integration/testsuite/Magento/Paypal/Model/IpnTest.php b/dev/tests/integration/testsuite/Magento/Paypal/Model/IpnTest.php index 1a22ea947f8..f2cd745e96d 100644 --- a/dev/tests/integration/testsuite/Magento/Paypal/Model/IpnTest.php +++ b/dev/tests/integration/testsuite/Magento/Paypal/Model/IpnTest.php @@ -64,7 +64,8 @@ public function testProcessIpnRequestFullRefund() $creditmemoItems = $order->getCreditmemosCollection()->getItems(); $creditmemo = current($creditmemoItems); - $this->assertEquals(Order::STATE_CLOSED, $order->getState()) ; + //Totally refunded orders still can be shipped + $this->assertEquals(Order::STATE_PROCESSING, $order->getState()) ; $this->assertEquals(1, count($creditmemoItems)); $this->assertEquals(Creditmemo::STATE_REFUNDED, $creditmemo->getState()); $this->assertEquals(10, $order->getSubtotalRefunded()); @@ -146,7 +147,8 @@ public function testProcessIpnRequestRestRefund() $creditmemoItems = $order->getCreditmemosCollection()->getItems(); - $this->assertEquals(Order::STATE_CLOSED, $order->getState()) ; + //Totally refunded orders still can be shipped + $this->assertEquals(Order::STATE_PROCESSING, $order->getState()) ; $this->assertEquals(1, count($creditmemoItems)); $this->assertEquals(10, $order->getSubtotalRefunded()); $this->assertEquals(10, $order->getBaseSubtotalRefunded()); From 9864ab822f453e0a4fe0e20bda28d5cfe26cbc36 Mon Sep 17 00:00:00 2001 From: Roman Ganin <rganin@magento.com> Date: Tue, 3 Jul 2018 14:33:08 -0500 Subject: [PATCH 07/44] MAGETWO-60034: Cannot ship remaining items in an order for several of one product if credit memo is made for some - fixed test --- .../app/Magento/Sales/Test/TestCase/MassOrdersUpdateTest.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/MassOrdersUpdateTest.xml b/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/MassOrdersUpdateTest.xml index d4b9856c5e3..e6ab0ff5026 100644 --- a/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/MassOrdersUpdateTest.xml +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/MassOrdersUpdateTest.xml @@ -22,7 +22,7 @@ <data name="steps" xsi:type="string">invoice, shipment|invoice, credit memo</data> <data name="action" xsi:type="string">Cancel</data> <data name="ordersCount" xsi:type="string">2</data> - <data name="resultStatuses" xsi:type="string">Complete,Closed</data> + <data name="resultStatuses" xsi:type="string">Complete,Processing</data> <constraint name="Magento\Sales\Test\Constraint\AssertOrderCancelMassActionFailMessage" /> <constraint name="Magento\Sales\Test\Constraint\AssertOrdersInOrdersGrid" /> </variation> From bd8a83b8308963fb19e9938f09f2b4962982c80f Mon Sep 17 00:00:00 2001 From: Roman Ganin <rganin@magento.com> Date: Thu, 12 Jul 2018 14:50:12 -0500 Subject: [PATCH 08/44] MAGETWO-60034: Cannot ship remaining items in an order for several of one product if credit memo is made for some --- app/code/Magento/Sales/Model/Order.php | 8 +- .../Sales/Test/Unit/Model/OrderTest.php | 161 +++++++++++++++++- 2 files changed, 167 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Sales/Model/Order.php b/app/code/Magento/Sales/Model/Order.php index d3b8edbed2e..7f44e286fb8 100644 --- a/app/code/Magento/Sales/Model/Order.php +++ b/app/code/Magento/Sales/Model/Order.php @@ -546,7 +546,13 @@ public function canCancel() break; } } - if ($allInvoiced) { + + $allRefunded = true; + foreach ($this->getAllItems() as $orderItem) { + $allRefunded = $allRefunded && ((float)$orderItem->getQtyRefunded() == (float)$orderItem->getQtyInvoiced()); + } + + if ($allInvoiced && !$allRefunded) { return false; } diff --git a/app/code/Magento/Sales/Test/Unit/Model/OrderTest.php b/app/code/Magento/Sales/Test/Unit/Model/OrderTest.php index 7f636334687..b4b42d0da2d 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/OrderTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/OrderTest.php @@ -114,7 +114,9 @@ protected function setUp() 'getParentItemId', 'getQuoteItemId', 'getLockedDoInvoice', - 'getProductId' + 'getProductId', + 'getQtyRefunded', + 'getQtyInvoiced', ]); $this->salesOrderCollectionMock = $this->getMockBuilder( \Magento\Sales\Model\ResourceModel\Order\Collection::class @@ -619,6 +621,163 @@ public function testCanCancelAllInvoiced() $this->item->expects($this->any()) ->method('getQtyToInvoice') ->willReturn(0); + $this->item->expects($this->any()) + ->method('getQtyRefunded') + ->willReturn(0); + $this->item->expects($this->any()) + ->method('getQtyInvoiced') + ->willReturn(1); + + $this->assertFalse($this->order->canCancel()); + } + + public function testCanCancelAllRefunded() + { + $paymentMock = $this->getMockBuilder(\Magento\Sales\Model\ResourceModel\Order\Payment::class) + ->disableOriginalConstructor() + ->setMethods(['isDeleted', 'canReviewPayment', 'canFetchTransactionInfo', '__wakeUp']) + ->getMock(); + $paymentMock->expects($this->any()) + ->method('canReviewPayment') + ->will($this->returnValue(false)); + $paymentMock->expects($this->any()) + ->method('canFetchTransactionInfo') + ->will($this->returnValue(false)); + $collectionMock = $this->createPartialMock( + \Magento\Sales\Model\ResourceModel\Order\Item\Collection::class, + ['getItems', 'setOrderFilter'] + ); + $this->orderItemCollectionFactoryMock->expects($this->any()) + ->method('create') + ->will($this->returnValue($collectionMock)); + $collectionMock->expects($this->any()) + ->method('setOrderFilter') + ->willReturnSelf(); + $this->preparePaymentMock($paymentMock); + + $this->prepareItemMock(0); + + $this->order->setActionFlag(\Magento\Sales\Model\Order::ACTION_FLAG_UNHOLD, false); + $this->order->setState(\Magento\Sales\Model\Order::STATE_NEW); + + $this->item->expects($this->any()) + ->method('isDeleted') + ->willReturn(false); + $this->item->expects($this->any()) + ->method('getQtyToInvoice') + ->willReturn(0); + $this->item->expects($this->any()) + ->method('getQtyRefunded') + ->willReturn(10); + $this->item->expects($this->any()) + ->method('getQtyInvoiced') + ->willReturn(10); + + $this->assertTrue($this->order->canCancel()); + } + + /** + * Test that order can be canceled if some items were partially invoiced with certain qty + * and then refunded for this qty. + * Sample: + * - ordered qty = 20 + * - invoiced = 10 + * - refunded = 10 + */ + public function testCanCancelPartiallyInvoicedAndRefunded() + { + $paymentMock = $this->getMockBuilder(\Magento\Sales\Model\ResourceModel\Order\Payment::class) + ->disableOriginalConstructor() + ->setMethods(['isDeleted', 'canReviewPayment', 'canFetchTransactionInfo', '__wakeUp']) + ->getMock(); + $paymentMock->expects($this->any()) + ->method('canReviewPayment') + ->will($this->returnValue(false)); + $paymentMock->expects($this->any()) + ->method('canFetchTransactionInfo') + ->will($this->returnValue(false)); + $collectionMock = $this->createPartialMock( + \Magento\Sales\Model\ResourceModel\Order\Item\Collection::class, + ['getItems', 'setOrderFilter'] + ); + $this->orderItemCollectionFactoryMock->expects($this->any()) + ->method('create') + ->will($this->returnValue($collectionMock)); + $collectionMock->expects($this->any()) + ->method('setOrderFilter') + ->willReturnSelf(); + $this->preparePaymentMock($paymentMock); + + $this->prepareItemMock(0); + + $this->order->setActionFlag(\Magento\Sales\Model\Order::ACTION_FLAG_UNHOLD, false); + $this->order->setState(\Magento\Sales\Model\Order::STATE_NEW); + + $this->item->expects($this->any()) + ->method('isDeleted') + ->willReturn(false); + $this->item->expects($this->any()) + ->method('getQtyToInvoice') + ->willReturn(10); + $this->item->expects($this->any()) + ->method('getQtyRefunded') + ->willReturn(10); + $this->item->expects($this->any()) + ->method('getQtyInvoiced') + ->willReturn(10); + + $this->assertTrue($this->order->canCancel()); + } + + /** + * Test that order CAN NOT be canceled if some items were partially invoiced with certain qty + * and then refunded for less than that qty. + * Sample: + * - ordered qty = 10 + * - invoiced = 10 + * - refunded = 5 + */ + public function testCanCancelPartiallyInvoicedAndNotFullyRefunded() + { + $paymentMock = $this->getMockBuilder(\Magento\Sales\Model\ResourceModel\Order\Payment::class) + ->disableOriginalConstructor() + ->setMethods(['isDeleted', 'canReviewPayment', 'canFetchTransactionInfo', '__wakeUp']) + ->getMock(); + $paymentMock->expects($this->any()) + ->method('canReviewPayment') + ->will($this->returnValue(false)); + $paymentMock->expects($this->any()) + ->method('canFetchTransactionInfo') + ->will($this->returnValue(false)); + $collectionMock = $this->createPartialMock( + \Magento\Sales\Model\ResourceModel\Order\Item\Collection::class, + ['getItems', 'setOrderFilter'] + ); + $this->orderItemCollectionFactoryMock->expects($this->any()) + ->method('create') + ->will($this->returnValue($collectionMock)); + $collectionMock->expects($this->any()) + ->method('setOrderFilter') + ->willReturnSelf(); + $this->preparePaymentMock($paymentMock); + + $this->prepareItemMock(0); + + $this->order->setActionFlag(\Magento\Sales\Model\Order::ACTION_FLAG_UNHOLD, false); + $this->order->setState(\Magento\Sales\Model\Order::STATE_NEW); + + $this->item->expects($this->any()) + ->method('isDeleted') + ->willReturn(false); + $this->item->expects($this->any()) + ->method('getQtyToInvoice') + ->willReturn(0); + $this->item->expects($this->any()) + ->method('getQtyRefunded') + ->willReturn(5); + $this->item->expects($this->any()) + ->method('getQtyInvoiced') + ->willReturn(10); $this->assertFalse($this->order->canCancel()); } From 0a46c8aeeb0b69615f44bb543e6731d264523104 Mon Sep 17 00:00:00 2001 From: Roman Ganin <rganin@magento.com> Date: Thu, 12 Jul 2018 17:04:29 -0500 Subject: [PATCH 09/44] MAGETWO-60034: Cannot ship remaining items in an order for several of one product if credit memo is made for some --- app/code/Magento/Sales/Test/Unit/Model/OrderTest.php | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/Sales/Test/Unit/Model/OrderTest.php b/app/code/Magento/Sales/Test/Unit/Model/OrderTest.php index b4b42d0da2d..b75e3adb740 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/OrderTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/OrderTest.php @@ -17,6 +17,7 @@ * Test class for \Magento\Sales\Model\Order * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + * @SuppressWarnings(PHPMD.TooManyPublicMethods) */ class OrderTest extends \PHPUnit\Framework\TestCase { From a5b048f9cb84867f5104d288223605f85378e3c9 Mon Sep 17 00:00:00 2001 From: Devagouda Patil <depatil@Devagoudas-MacBook-Pro.local> Date: Wed, 5 Sep 2018 17:24:21 -0500 Subject: [PATCH 10/44] MAGETWO-60034: Cannot ship remaining items in an order for several of one product if credit memo is made for some - Updated Functional test path and schema location --- .../Mftf}/Test/AdminAbleToShipPartiallyInvoicedItemsTest.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) rename {dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Sales => app/code/Magento/Sales/Test/Mftf}/Test/AdminAbleToShipPartiallyInvoicedItemsTest.xml (98%) diff --git a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Sales/Test/AdminAbleToShipPartiallyInvoicedItemsTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminAbleToShipPartiallyInvoicedItemsTest.xml similarity index 98% rename from dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Sales/Test/AdminAbleToShipPartiallyInvoicedItemsTest.xml rename to app/code/Magento/Sales/Test/Mftf/Test/AdminAbleToShipPartiallyInvoicedItemsTest.xml index 9b629f410f4..3fdbb3eae0b 100644 --- a/dev/tests/acceptance/tests/functional/Magento/FunctionalTest/Sales/Test/AdminAbleToShipPartiallyInvoicedItemsTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminAbleToShipPartiallyInvoicedItemsTest.xml @@ -6,7 +6,7 @@ */ --> <tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/magento2-functional-testing-framework/src/Magento/FunctionalTestingFramework/Test/etc/testSchema.xsd"> + xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> <test name="AdminAbleToShipPartiallyInvoicedItemsTest"> <annotations> <title value="Ship Action is available for remaining of the partially invoiced items "/> @@ -64,6 +64,7 @@ <!--Submit Order and verify information--> <click selector="{{AdminOrderFormActionSection.SubmitOrder}}" stepKey="clickSubmitOrder" after="seeCorrectGrandTotal"/> + <waitForPageLoad stepKey="waitForOrderToProcess"/> <seeInCurrentUrl url="{{AdminOrderDetailsPage.url}}" stepKey="seeViewOrderPage" after="clickSubmitOrder"/> <see selector="{{AdminOrderDetailsMessagesSection.successMessage}}" userInput="You created the order." stepKey="seeSuccessMessage" after="seeViewOrderPage"/> <grabTextFrom selector="|Order # (\d+)|" stepKey="getOrderId" after="seeSuccessMessage"/> From df6bc3769f1d5b6c2afc394586aa21113d915d1f Mon Sep 17 00:00:00 2001 From: Max Lesechko <mlesechko@magento.com> Date: Thu, 6 Sep 2018 17:11:24 -0500 Subject: [PATCH 11/44] MAGETWO-94819: Swatch validation breaks the whole attribute form --- .../Catalog/view/adminhtml/web/js/options.js | 12 ++++++-- .../adminhtml/web/js/product-attributes.js | 29 ++++++++++++------- lib/web/mage/backend/validation.js | 2 ++ 3 files changed, 30 insertions(+), 13 deletions(-) diff --git a/app/code/Magento/Catalog/view/adminhtml/web/js/options.js b/app/code/Magento/Catalog/view/adminhtml/web/js/options.js index 6ea00591576..a4b3ca95e45 100644 --- a/app/code/Magento/Catalog/view/adminhtml/web/js/options.js +++ b/app/code/Magento/Catalog/view/adminhtml/web/js/options.js @@ -145,7 +145,9 @@ define([ return optionDefaultInputType; } - }; + }, + formContent = jQuery(), + optionTable = optionPanel.find('table'); if ($('add_new_option_button')) { Event.observe('add_new_option_button', 'click', attributeOption.add.bind(attributeOption, {}, true)); @@ -180,7 +182,7 @@ define([ }); }); } - editForm.on('submit', function () { + editForm.on('beforeSubmit', function () { optionPanel.find('input') .each(function () { if (this.disabled) { @@ -202,9 +204,13 @@ define([ }) .val(JSON.stringify(optionsValues)) .prependTo(editForm); - optionPanel.find('table') + formContent = optionTable.clone(true); + optionTable .replaceWith(jQuery('<div>').text(jQuery.mage.__('Sending attribute values as package.'))); }); + editForm.on('afterValidate.error', function () { + optionTable.replaceWith(formContent); + }); window.attributeOption = attributeOption; window.optionDefaultInputType = attributeOption.getOptionInputType(); diff --git a/app/code/Magento/Swatches/view/adminhtml/web/js/product-attributes.js b/app/code/Magento/Swatches/view/adminhtml/web/js/product-attributes.js index 01411523108..870d1dedefe 100644 --- a/app/code/Magento/Swatches/view/adminhtml/web/js/product-attributes.js +++ b/app/code/Magento/Swatches/view/adminhtml/web/js/product-attributes.js @@ -414,7 +414,15 @@ define([ }; $(function () { - var editForm = $('#edit_form'); + var editForm = $('#edit_form'), + swatchVisualPanel = $('#swatch-visual-options-panel'), + swatchTextPanel = $('#swatch-text-options-panel'), + activePanel, + formContent = $(), + optionTable; + + activePanel = swatchTextPanel.is(':visible') ? swatchTextPanel : swatchVisualPanel; + optionTable = activePanel.find('table'); $('#frontend_input').bind('change', function () { swatchProductAttributes.bindAttributeInputType(); @@ -430,16 +438,11 @@ define([ .collapsable() .collapse('hide'); - editForm.on('submit', function () { - var activePanel, - swatchValues = [], - swatchVisualPanel = $('#swatch-visual-options-panel'), - swatchTextPanel = $('#swatch-text-options-panel'); - - activePanel = swatchTextPanel.is(':visible') ? swatchTextPanel : swatchVisualPanel; + editForm.on('beforeSubmit', function () { + var swatchValues = []; - activePanel - .find('table input') + optionTable + .find('input') .each(function () { swatchValues.push(this.name + '=' + $(this).val()); }); @@ -452,11 +455,17 @@ define([ .val(JSON.stringify(swatchValues)) .prependTo(editForm); + formContent = optionTable.clone(true); + [swatchVisualPanel, swatchTextPanel].forEach(function (el) { $(el).find('table') .replaceWith($('<div>').text($.mage.__('Sending swatch values as package.'))); }); }); + + editForm.on('afterValidate.error', function () { + optionTable.replaceWith(formContent); + }); }); window.saveAttributeInNewSet = swatchProductAttributes.saveAttributeInNewSet; diff --git a/lib/web/mage/backend/validation.js b/lib/web/mage/backend/validation.js index d3ab7dd086a..1043f45a740 100644 --- a/lib/web/mage/backend/validation.js +++ b/lib/web/mage/backend/validation.js @@ -171,6 +171,7 @@ this._submit(); } else { this._showErrors(response); + $(this.element[0]).trigger('afterValidate.error'); $('body').trigger('processStop'); } }, @@ -223,6 +224,7 @@ * @protected */ _onError: function () { + $(this.element[0]).trigger('afterValidate.error'); $('body').trigger('processStop'); if (this.options.errorUrl) { From de672221506c6ec7ce506e6499ac9ab16d69acf3 Mon Sep 17 00:00:00 2001 From: Max Lesechko <mlesechko@magento.com> Date: Fri, 7 Sep 2018 17:06:23 -0500 Subject: [PATCH 12/44] MAGETWO-94819: Swatch validation breaks the whole attribute form --- .../Adminhtml/Product/Attribute/Save.php | 36 +++++++++---- .../Adminhtml/Product/Attribute/Validate.php | 27 ++++++++-- .../Attribute/Option/OptionsDataProvider.php | 39 +++++++++++++++ .../Catalog/view/adminhtml/web/js/options.js | 50 ++++++++++--------- .../Product/Attribute/Plugin/Save.php | 9 ---- 5 files changed, 115 insertions(+), 46 deletions(-) create mode 100644 app/code/Magento/Catalog/Model/Product/Attribute/Option/OptionsDataProvider.php diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Save.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Save.php index 817de6828e4..a7076ba8526 100644 --- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Save.php +++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Save.php @@ -13,6 +13,7 @@ use Magento\Catalog\Controller\Adminhtml\Product\Attribute; use Magento\Catalog\Helper\Product; use Magento\Catalog\Model\Product\Attribute\Frontend\Inputtype\Presentation; +use Magento\Catalog\Model\Product\Attribute\Option\OptionsDataProvider; use Magento\Catalog\Model\Product\AttributeSet\BuildFactory; use Magento\Catalog\Model\ResourceModel\Eav\AttributeFactory; use Magento\Eav\Model\Adminhtml\System\Config\Source\Inputtype\Validator; @@ -75,6 +76,11 @@ class Save extends Attribute */ private $presentation; + /** + * @var OptionsDataProvider|null + */ + private $optionsDataProvider; + /** * @param Context $context * @param FrontendInterface $attributeLabelCache @@ -88,6 +94,7 @@ class Save extends Attribute * @param Product $productHelper * @param LayoutFactory $layoutFactory * @param Presentation|null $presentation + * @param OptionsDataProvider|null $optionsDataProvider * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( @@ -102,7 +109,8 @@ public function __construct( FilterManager $filterManager, Product $productHelper, LayoutFactory $layoutFactory, - Presentation $presentation = null + Presentation $presentation = null, + OptionsDataProvider $optionsDataProvider = null ) { parent::__construct($context, $attributeLabelCache, $coreRegistry, $resultPageFactory); $this->buildFactory = $buildFactory; @@ -113,6 +121,8 @@ public function __construct( $this->groupCollectionFactory = $groupCollectionFactory; $this->layoutFactory = $layoutFactory; $this->presentation = $presentation ?: ObjectManager::getInstance()->get(Presentation::class); + $this->optionsDataProvider = $optionsDataProvider + ?: ObjectManager::getInstance()->get(OptionsDataProvider::class); } /** @@ -123,7 +133,21 @@ public function __construct( */ public function execute() { + try { + $optionData = $this->optionsDataProvider->getOptionsData($this->getRequest()); + } catch (\InvalidArgumentException $e) { + $message = __("The attribute couldn't be saved due to an error. Verify your information and try again. " + . "If the error persists, please try again later."); + $this->messageManager->addErrorMessage($message); + return $this->returnResult('catalog/*/edit', ['_current' => true], ['error' => true]); + } + $data = $this->getRequest()->getPostValue(); + $data = array_merge_recursive( + $data, + $optionData + ); + if ($data) { $this->preprocessOptionsData($data); $setId = $this->getRequest()->getParam('set'); @@ -326,15 +350,7 @@ public function execute() */ private function preprocessOptionsData(&$data) { - if (isset($data['serialized_options'])) { - $serializedOptions = json_decode($data['serialized_options'], JSON_OBJECT_AS_ARRAY); - foreach ($serializedOptions as $serializedOption) { - $option = []; - parse_str($serializedOption, $option); - $data = array_replace_recursive($data, $option); - } - } - unset($data['serialized_options']); + } /** diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Validate.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Validate.php index db452113ada..35cc2a903bc 100644 --- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Validate.php +++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Validate.php @@ -7,6 +7,8 @@ namespace Magento\Catalog\Controller\Adminhtml\Product\Attribute; +use Magento\Catalog\Model\Product\Attribute\Option\OptionsDataProvider; +use Magento\Framework\App\ObjectManager; use Magento\Framework\DataObject; class Validate extends \Magento\Catalog\Controller\Adminhtml\Product\Attribute @@ -28,6 +30,11 @@ class Validate extends \Magento\Catalog\Controller\Adminhtml\Product\Attribute */ private $multipleAttributeList; + /** + * @var OptionsDataProvider|null + */ + private $optionsDataProvider; + /** * Constructor * @@ -38,6 +45,7 @@ class Validate extends \Magento\Catalog\Controller\Adminhtml\Product\Attribute * @param \Magento\Framework\Controller\Result\JsonFactory $resultJsonFactory * @param \Magento\Framework\View\LayoutFactory $layoutFactory * @param array $multipleAttributeList + * @param OptionsDataProvider|null $optionsDataProvider */ public function __construct( \Magento\Backend\App\Action\Context $context, @@ -46,12 +54,15 @@ public function __construct( \Magento\Framework\View\Result\PageFactory $resultPageFactory, \Magento\Framework\Controller\Result\JsonFactory $resultJsonFactory, \Magento\Framework\View\LayoutFactory $layoutFactory, - array $multipleAttributeList = [] + array $multipleAttributeList = [], + OptionsDataProvider $optionsDataProvider = null ) { parent::__construct($context, $attributeLabelCache, $coreRegistry, $resultPageFactory); $this->resultJsonFactory = $resultJsonFactory; $this->layoutFactory = $layoutFactory; $this->multipleAttributeList = $multipleAttributeList; + $this->optionsDataProvider = $optionsDataProvider ?: ObjectManager::getInstance() + ->get(OptionsDataProvider::class); } /** @@ -63,6 +74,14 @@ public function execute() { $response = new DataObject(); $response->setError(false); + try { + $optionsData = $this->optionsDataProvider->getOptionsData($this->getRequest()); + } catch (\InvalidArgumentException $e) { + $message = __("The attribute couldn't be saved due to an error. Verify your information and try again. " + . "If the error persists, please try again later."); + $this->setMessageToResponse($response, [$message]); + $response->setError(true); + } $attributeCode = $this->getRequest()->getParam('attribute_code'); $frontendLabel = $this->getRequest()->getParam('frontend_label'); @@ -102,10 +121,10 @@ public function execute() } $multipleOption = $this->getRequest()->getParam("frontend_input"); - $multipleOption = null == $multipleOption ? 'select' : $multipleOption; + $multipleOption = (null === $multipleOption) ? 'select' : $multipleOption; - if (isset($this->multipleAttributeList[$multipleOption]) && !(null == ($multipleOption))) { - $options = $this->getRequest()->getParam($this->multipleAttributeList[$multipleOption]); + if (isset($this->multipleAttributeList[$multipleOption])) { + $options = $optionsData[$this->multipleAttributeList[$multipleOption]] ?? null; $this->checkUniqueOption( $response, $options diff --git a/app/code/Magento/Catalog/Model/Product/Attribute/Option/OptionsDataProvider.php b/app/code/Magento/Catalog/Model/Product/Attribute/Option/OptionsDataProvider.php new file mode 100644 index 00000000000..a2a1fcb7fb5 --- /dev/null +++ b/app/code/Magento/Catalog/Model/Product/Attribute/Option/OptionsDataProvider.php @@ -0,0 +1,39 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Catalog\Model\Product\Attribute\Option; + +use Magento\Framework\App\RequestInterface; + +class OptionsDataProvider +{ + /** + * @param RequestInterface $request + * @return array + * @throws \InvalidArgumentException + */ + public function getOptionsData(RequestInterface $request): array + { + $serializedOptions = $request->getParam('serialized_options'); + $optionsData = []; + + if ($serializedOptions) { + $encodedOptions = json_decode($serializedOptions, JSON_OBJECT_AS_ARRAY); + + if (json_last_error() !== JSON_ERROR_NONE) { + throw new \InvalidArgumentException('Unable to unserialize options data.'); + } + + foreach ($encodedOptions as $encodedOption) { + $decodedOptionData = []; + parse_str($encodedOption, $decodedOptionData); + $optionsData = array_replace_recursive($optionsData, $decodedOptionData); + } + } + + return $optionsData; + } +} \ No newline at end of file diff --git a/app/code/Magento/Catalog/view/adminhtml/web/js/options.js b/app/code/Magento/Catalog/view/adminhtml/web/js/options.js index a4b3ca95e45..233f554512f 100644 --- a/app/code/Magento/Catalog/view/adminhtml/web/js/options.js +++ b/app/code/Magento/Catalog/view/adminhtml/web/js/options.js @@ -146,8 +146,8 @@ define([ return optionDefaultInputType; } }, - formContent = jQuery(), - optionTable = optionPanel.find('table'); + optionsTableContent = jQuery(), + optionContainer = optionPanel.find('table tbody'); if ($('add_new_option_button')) { Event.observe('add_new_option_button', 'click', attributeOption.add.bind(attributeOption, {}, true)); @@ -183,33 +183,37 @@ define([ }); } editForm.on('beforeSubmit', function () { - optionPanel.find('input') - .each(function () { - if (this.disabled) { - return; - } + if (optionPanel.is(':visible')) { + optionContainer.find('input') + .each(function () { + if (this.disabled) { + return; + } - if (this.type === 'checkbox' || this.type === 'radio') { - if (this.checked) { + if (this.type === 'checkbox' || this.type === 'radio') { + if (this.checked) { + optionsValues.push(this.name + '=' + jQuery(this).val()); + } + } else { optionsValues.push(this.name + '=' + jQuery(this).val()); } - } else { - optionsValues.push(this.name + '=' + jQuery(this).val()); - } - }); - jQuery('<input>') - .attr({ - type: 'hidden', - name: 'serialized_options' - }) - .val(JSON.stringify(optionsValues)) - .prependTo(editForm); - formContent = optionTable.clone(true); - optionTable + }); + jQuery('<input>') + .attr({ + type: 'hidden', + name: 'serialized_options' + }) + .val(JSON.stringify(optionsValues)) + .prependTo(editForm); + } + optionsTableContent = optionContainer.clone(true); + optionContainer .replaceWith(jQuery('<div>').text(jQuery.mage.__('Sending attribute values as package.'))); }); editForm.on('afterValidate.error', function () { - optionTable.replaceWith(formContent); + if (optionPanel.is(':visible')) { + optionContainer.replaceWith(optionsTableContent); + } }); window.attributeOption = attributeOption; window.optionDefaultInputType = attributeOption.getOptionInputType(); diff --git a/app/code/Magento/Swatches/Controller/Adminhtml/Product/Attribute/Plugin/Save.php b/app/code/Magento/Swatches/Controller/Adminhtml/Product/Attribute/Plugin/Save.php index 383c97a166d..9ec65fb0804 100644 --- a/app/code/Magento/Swatches/Controller/Adminhtml/Product/Attribute/Plugin/Save.php +++ b/app/code/Magento/Swatches/Controller/Adminhtml/Product/Attribute/Plugin/Save.php @@ -26,15 +26,6 @@ public function beforeDispatch(Attribute\Save $subject, RequestInterface $reques $data = $request->getPostValue(); if (isset($data['frontend_input'])) { - //Data is serialized to overcome issues caused by max_input_vars value if it's modification is unavailable. - //See subject controller code and comments for more info. - if (isset($data['serialized_swatch_values']) - && in_array($data['frontend_input'], ['swatch_visual', 'swatch_text']) - ) { - $data['serialized_options'] = $data['serialized_swatch_values']; - unset($data['serialized_swatch_values']); - } - switch ($data['frontend_input']) { case 'swatch_visual': $data[Swatch::SWATCH_INPUT_TYPE_KEY] = Swatch::SWATCH_INPUT_TYPE_VISUAL; From 8ec2c30e99f70a7ba78602f51476c38625200f1e Mon Sep 17 00:00:00 2001 From: Max Lesechko <mlesechko@magento.com> Date: Sun, 9 Sep 2018 19:34:52 -0500 Subject: [PATCH 13/44] MAGETWO-94819: Swatch validation breaks the whole attribute form --- .../adminhtml/web/js/product-attributes.js | 43 ++++++++++--------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/app/code/Magento/Swatches/view/adminhtml/web/js/product-attributes.js b/app/code/Magento/Swatches/view/adminhtml/web/js/product-attributes.js index 870d1dedefe..dd1fb4b0a8b 100644 --- a/app/code/Magento/Swatches/view/adminhtml/web/js/product-attributes.js +++ b/app/code/Magento/Swatches/view/adminhtml/web/js/product-attributes.js @@ -417,12 +417,9 @@ define([ var editForm = $('#edit_form'), swatchVisualPanel = $('#swatch-visual-options-panel'), swatchTextPanel = $('#swatch-text-options-panel'), - activePanel, - formContent = $(), - optionTable; - - activePanel = swatchTextPanel.is(':visible') ? swatchTextPanel : swatchVisualPanel; - optionTable = activePanel.find('table'); + optionsTableContent = $(), + optionContainer = $(), + activePanel = $(); $('#frontend_input').bind('change', function () { swatchProductAttributes.bindAttributeInputType(); @@ -441,22 +438,26 @@ define([ editForm.on('beforeSubmit', function () { var swatchValues = []; - optionTable - .find('input') - .each(function () { - swatchValues.push(this.name + '=' + $(this).val()); - }); + activePanel = swatchTextPanel.is(':visible') ? swatchTextPanel : swatchVisualPanel; + optionContainer = activePanel.find('table tbody'); - $('<input>') - .attr({ - type: 'hidden', - name: 'serialized_swatch_values' - }) - .val(JSON.stringify(swatchValues)) - .prependTo(editForm); + if (activePanel.is(':visible')) { + optionContainer + .find('input') + .each(function () { + swatchValues.push(this.name + '=' + $(this).val()); + }); - formContent = optionTable.clone(true); + $('<input>') + .attr({ + type: 'hidden', + name: 'serialized_options' + }) + .val(JSON.stringify(swatchValues)) + .prependTo(editForm); + } + optionsTableContent = optionContainer.clone(true); [swatchVisualPanel, swatchTextPanel].forEach(function (el) { $(el).find('table') .replaceWith($('<div>').text($.mage.__('Sending swatch values as package.'))); @@ -464,7 +465,9 @@ define([ }); editForm.on('afterValidate.error', function () { - optionTable.replaceWith(formContent); + if (activePanel.is(':visible')) { + optionContainer.replaceWith(optionsTableContent); + } }); }); From 616eb6d5a9f0ac88730c8db38b40d151f64e94f4 Mon Sep 17 00:00:00 2001 From: Max Lesechko <mlesechko@magento.com> Date: Mon, 10 Sep 2018 13:20:09 -0500 Subject: [PATCH 14/44] MAGETWO-94819: Swatch validation breaks the whole attribute form --- .../Adminhtml/Product/Attribute/Save.php | 31 +++++-------------- .../Adminhtml/Product/Attribute/Validate.php | 18 +++++------ ...taProvider.php => OptionsDataResolver.php} | 9 ++++-- .../Catalog/view/adminhtml/web/js/options.js | 14 ++++----- .../adminhtml/web/js/product-attributes.js | 15 ++++----- 5 files changed, 37 insertions(+), 50 deletions(-) rename app/code/Magento/Catalog/Model/Product/Attribute/Option/{OptionsDataProvider.php => OptionsDataResolver.php} (88%) diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Save.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Save.php index a7076ba8526..825288b3664 100644 --- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Save.php +++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Save.php @@ -13,7 +13,7 @@ use Magento\Catalog\Controller\Adminhtml\Product\Attribute; use Magento\Catalog\Helper\Product; use Magento\Catalog\Model\Product\Attribute\Frontend\Inputtype\Presentation; -use Magento\Catalog\Model\Product\Attribute\Option\OptionsDataProvider; +use Magento\Catalog\Model\Product\Attribute\Option\OptionsDataResolver; use Magento\Catalog\Model\Product\AttributeSet\BuildFactory; use Magento\Catalog\Model\ResourceModel\Eav\AttributeFactory; use Magento\Eav\Model\Adminhtml\System\Config\Source\Inputtype\Validator; @@ -77,9 +77,9 @@ class Save extends Attribute private $presentation; /** - * @var OptionsDataProvider|null + * @var OptionsDataResolver|null */ - private $optionsDataProvider; + private $optionsDataResolver; /** * @param Context $context @@ -94,7 +94,7 @@ class Save extends Attribute * @param Product $productHelper * @param LayoutFactory $layoutFactory * @param Presentation|null $presentation - * @param OptionsDataProvider|null $optionsDataProvider + * @param OptionsDataResolver|null $optionsDataResolver * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( @@ -110,7 +110,7 @@ public function __construct( Product $productHelper, LayoutFactory $layoutFactory, Presentation $presentation = null, - OptionsDataProvider $optionsDataProvider = null + OptionsDataResolver $optionsDataResolver = null ) { parent::__construct($context, $attributeLabelCache, $coreRegistry, $resultPageFactory); $this->buildFactory = $buildFactory; @@ -121,8 +121,8 @@ public function __construct( $this->groupCollectionFactory = $groupCollectionFactory; $this->layoutFactory = $layoutFactory; $this->presentation = $presentation ?: ObjectManager::getInstance()->get(Presentation::class); - $this->optionsDataProvider = $optionsDataProvider - ?: ObjectManager::getInstance()->get(OptionsDataProvider::class); + $this->optionsDataResolver = $optionsDataResolver + ?: ObjectManager::getInstance()->get(OptionsDataResolver::class); } /** @@ -134,7 +134,7 @@ public function __construct( public function execute() { try { - $optionData = $this->optionsDataProvider->getOptionsData($this->getRequest()); + $optionData = $this->optionsDataResolver->getOptionsData($this->getRequest()); } catch (\InvalidArgumentException $e) { $message = __("The attribute couldn't be saved due to an error. Verify your information and try again. " . "If the error persists, please try again later."); @@ -149,7 +149,6 @@ public function execute() ); if ($data) { - $this->preprocessOptionsData($data); $setId = $this->getRequest()->getParam('set'); $attributeSet = null; @@ -339,20 +338,6 @@ public function execute() return $this->returnResult('catalog/*/', [], ['error' => true]); } - /** - * Extract options data from serialized options field and append to data array. - * - * This logic is required to overcome max_input_vars php limit - * that may vary and/or be inaccessible to change on different instances. - * - * @param array $data - * @return void - */ - private function preprocessOptionsData(&$data) - { - - } - /** * @param string $path * @param array $params diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Validate.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Validate.php index 35cc2a903bc..fa8103f7033 100644 --- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Validate.php +++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Validate.php @@ -7,7 +7,7 @@ namespace Magento\Catalog\Controller\Adminhtml\Product\Attribute; -use Magento\Catalog\Model\Product\Attribute\Option\OptionsDataProvider; +use Magento\Catalog\Model\Product\Attribute\Option\OptionsDataResolver; use Magento\Framework\App\ObjectManager; use Magento\Framework\DataObject; @@ -31,9 +31,9 @@ class Validate extends \Magento\Catalog\Controller\Adminhtml\Product\Attribute private $multipleAttributeList; /** - * @var OptionsDataProvider|null + * @var OptionsDataResolver|null */ - private $optionsDataProvider; + private $optionsDataResolver; /** * Constructor @@ -45,7 +45,7 @@ class Validate extends \Magento\Catalog\Controller\Adminhtml\Product\Attribute * @param \Magento\Framework\Controller\Result\JsonFactory $resultJsonFactory * @param \Magento\Framework\View\LayoutFactory $layoutFactory * @param array $multipleAttributeList - * @param OptionsDataProvider|null $optionsDataProvider + * @param OptionsDataResolver|null $optionsDataResolver */ public function __construct( \Magento\Backend\App\Action\Context $context, @@ -55,14 +55,14 @@ public function __construct( \Magento\Framework\Controller\Result\JsonFactory $resultJsonFactory, \Magento\Framework\View\LayoutFactory $layoutFactory, array $multipleAttributeList = [], - OptionsDataProvider $optionsDataProvider = null + OptionsDataResolver $optionsDataResolver = null ) { parent::__construct($context, $attributeLabelCache, $coreRegistry, $resultPageFactory); $this->resultJsonFactory = $resultJsonFactory; $this->layoutFactory = $layoutFactory; $this->multipleAttributeList = $multipleAttributeList; - $this->optionsDataProvider = $optionsDataProvider ?: ObjectManager::getInstance() - ->get(OptionsDataProvider::class); + $this->optionsDataResolver = $optionsDataResolver ?: ObjectManager::getInstance() + ->get(OptionsDataResolver::class); } /** @@ -75,9 +75,9 @@ public function execute() $response = new DataObject(); $response->setError(false); try { - $optionsData = $this->optionsDataProvider->getOptionsData($this->getRequest()); + $optionsData = $this->optionsDataResolver->getOptionsData($this->getRequest()); } catch (\InvalidArgumentException $e) { - $message = __("The attribute couldn't be saved due to an error. Verify your information and try again. " + $message = __("The attribute couldn't be validated due to an error. Verify your information and try again. " . "If the error persists, please try again later."); $this->setMessageToResponse($response, [$message]); $response->setError(true); diff --git a/app/code/Magento/Catalog/Model/Product/Attribute/Option/OptionsDataProvider.php b/app/code/Magento/Catalog/Model/Product/Attribute/Option/OptionsDataResolver.php similarity index 88% rename from app/code/Magento/Catalog/Model/Product/Attribute/Option/OptionsDataProvider.php rename to app/code/Magento/Catalog/Model/Product/Attribute/Option/OptionsDataResolver.php index a2a1fcb7fb5..20e713be9a4 100644 --- a/app/code/Magento/Catalog/Model/Product/Attribute/Option/OptionsDataProvider.php +++ b/app/code/Magento/Catalog/Model/Product/Attribute/Option/OptionsDataResolver.php @@ -8,9 +8,14 @@ use Magento\Framework\App\RequestInterface; -class OptionsDataProvider +/** + * Attribute options data resolver. + */ +class OptionsDataResolver { /** + * Provides attribute options data from the request. + * * @param RequestInterface $request * @return array * @throws \InvalidArgumentException @@ -36,4 +41,4 @@ public function getOptionsData(RequestInterface $request): array return $optionsData; } -} \ No newline at end of file +} diff --git a/app/code/Magento/Catalog/view/adminhtml/web/js/options.js b/app/code/Magento/Catalog/view/adminhtml/web/js/options.js index 233f554512f..bb06d05371e 100644 --- a/app/code/Magento/Catalog/view/adminhtml/web/js/options.js +++ b/app/code/Magento/Catalog/view/adminhtml/web/js/options.js @@ -20,7 +20,6 @@ define([ return function (config) { var optionPanel = jQuery('#manage-options-panel'), - optionsValues = [], editForm = jQuery('#edit_form'), attributeOption = { table: $('attribute-options-table'), @@ -146,8 +145,7 @@ define([ return optionDefaultInputType; } }, - optionsTableContent = jQuery(), - optionContainer = optionPanel.find('table tbody'); + tableBody = jQuery(); if ($('add_new_option_button')) { Event.observe('add_new_option_button', 'click', attributeOption.add.bind(attributeOption, {}, true)); @@ -183,6 +181,9 @@ define([ }); } editForm.on('beforeSubmit', function () { + var optionsValues = [], + optionContainer = optionPanel.find('table tbody'); + if (optionPanel.is(':visible')) { optionContainer.find('input') .each(function () { @@ -206,13 +207,12 @@ define([ .val(JSON.stringify(optionsValues)) .prependTo(editForm); } - optionsTableContent = optionContainer.clone(true); - optionContainer - .replaceWith(jQuery('<div>').text(jQuery.mage.__('Sending attribute values as package.'))); + tableBody = optionContainer.detach(); }); editForm.on('afterValidate.error', function () { if (optionPanel.is(':visible')) { - optionContainer.replaceWith(optionsTableContent); + optionPanel.find('table').append(tableBody); + jQuery('input[name="serialized_options"]').remove(); } }); window.attributeOption = attributeOption; diff --git a/app/code/Magento/Swatches/view/adminhtml/web/js/product-attributes.js b/app/code/Magento/Swatches/view/adminhtml/web/js/product-attributes.js index dd1fb4b0a8b..49723f4190a 100644 --- a/app/code/Magento/Swatches/view/adminhtml/web/js/product-attributes.js +++ b/app/code/Magento/Swatches/view/adminhtml/web/js/product-attributes.js @@ -417,8 +417,7 @@ define([ var editForm = $('#edit_form'), swatchVisualPanel = $('#swatch-visual-options-panel'), swatchTextPanel = $('#swatch-text-options-panel'), - optionsTableContent = $(), - optionContainer = $(), + tableBody = $(), activePanel = $(); $('#frontend_input').bind('change', function () { @@ -436,7 +435,8 @@ define([ .collapse('hide'); editForm.on('beforeSubmit', function () { - var swatchValues = []; + var swatchValues = [], + optionContainer; activePanel = swatchTextPanel.is(':visible') ? swatchTextPanel : swatchVisualPanel; optionContainer = activePanel.find('table tbody'); @@ -457,16 +457,13 @@ define([ .prependTo(editForm); } - optionsTableContent = optionContainer.clone(true); - [swatchVisualPanel, swatchTextPanel].forEach(function (el) { - $(el).find('table') - .replaceWith($('<div>').text($.mage.__('Sending swatch values as package.'))); - }); + tableBody = optionContainer.detach(); }); editForm.on('afterValidate.error', function () { if (activePanel.is(':visible')) { - optionContainer.replaceWith(optionsTableContent); + activePanel.find('table').append(tableBody); + $('input[name="serialized_options"]').remove(); } }); }); From 897c616e51405900ed0dcce2b21d68d547c085c1 Mon Sep 17 00:00:00 2001 From: Max Lesechko <mlesechko@magento.com> Date: Tue, 11 Sep 2018 16:10:50 -0500 Subject: [PATCH 15/44] MAGETWO-94819: Swatch validation breaks the whole attribute form --- .../Attribute/Option/OptionsDataResolver.php | 4 +- .../AdminProductAttributeActionGroup.xml | 5 +- .../AdminCreateProductAttributeSection.xml | 9 +++ .../Test/Mftf/Data/SwatchAttributeData.xml | 1 + ...ateVisualSwatchWithNonValidOptionsTest.xml | 74 +++++++++++++++++++ 5 files changed, 91 insertions(+), 2 deletions(-) create mode 100644 app/code/Magento/Swatches/Test/Mftf/Test/AdminCreateVisualSwatchWithNonValidOptionsTest.xml diff --git a/app/code/Magento/Catalog/Model/Product/Attribute/Option/OptionsDataResolver.php b/app/code/Magento/Catalog/Model/Product/Attribute/Option/OptionsDataResolver.php index 20e713be9a4..60b183db941 100644 --- a/app/code/Magento/Catalog/Model/Product/Attribute/Option/OptionsDataResolver.php +++ b/app/code/Magento/Catalog/Model/Product/Attribute/Option/OptionsDataResolver.php @@ -4,6 +4,8 @@ * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\Catalog\Model\Product\Attribute\Option; use Magento\Framework\App\RequestInterface; @@ -26,7 +28,7 @@ public function getOptionsData(RequestInterface $request): array $optionsData = []; if ($serializedOptions) { - $encodedOptions = json_decode($serializedOptions, JSON_OBJECT_AS_ARRAY); + $encodedOptions = json_decode($serializedOptions, true); if (json_last_error() !== JSON_ERROR_NONE) { throw new \InvalidArgumentException('Unable to unserialize options data.'); diff --git a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductAttributeActionGroup.xml b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductAttributeActionGroup.xml index fd808386920..23687484f10 100644 --- a/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductAttributeActionGroup.xml +++ b/app/code/Magento/Catalog/Test/Mftf/ActionGroup/AdminProductAttributeActionGroup.xml @@ -14,7 +14,10 @@ </arguments> <amOnPage url="{{AdminProductAttributeGridPage.url}}" stepKey="navigateToProductAttributeGrid"/> <waitForPageLoad stepKey="waitForPageLoad1"/> - <click selector="{{AdminProductAttributeGridSection.AttributeCode(ProductAttribute.attribute_code)}}" stepKey="navigateToAttributeEditPage1" /> + <fillField selector="{{AdminProductAttributeGridSection.FilterByAttributeCode}}" + userInput="{{ProductAttribute.attribute_code}}" stepKey="setAttributeCode"/> + <click selector="{{AdminProductAttributeGridSection.Search}}" stepKey="searchForAttributeFromTheGrid"/> + <click selector="{{AdminProductAttributeGridSection.FirstRow}}" stepKey="clickOnAttributeRow"/> <waitForPageLoad stepKey="waitForPageLoad2" /> </actionGroup> </actionGroups> diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/AdminCreateProductAttributeSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/AdminCreateProductAttributeSection.xml index b83676c2e10..a497233afbd 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Section/AdminCreateProductAttributeSection.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Section/AdminCreateProductAttributeSection.xml @@ -17,6 +17,7 @@ <element name="DefaultValue" type="input" selector="#default_value_text"/> <element name="Scope" type="select" selector="#is_global"/> <element name="Save" type="button" selector="#save" timeout="30"/> + <element name="DeleteAttribute" type="button" selector="#delete" timeout="30"/> <element name="SaveAndEdit" type="button" selector="#save_and_edit_button" timeout="30"/> <element name="TinyMCE4" type="button" selector="//span[text()='Default Value']/parent::label/following-sibling::div//div[@class='mce-branding-powered-by']"/> <element name="checkIfTabOpen" selector="//div[@id='advanced_fieldset-wrapper' and not(contains(@class,'opened'))]" type="button"/> @@ -63,4 +64,12 @@ <element name="SpecialCharacter" type="button" selector=".mce-i-charmap" /> <element name="TextArea" type="input" selector="#default_value_textarea" /> </section> + <section name="AdvancedAttributePropertiesSection"> + <element name="AdvancedAttributePropertiesSectionToggle" + type="button" selector="#advanced_fieldset-wrapper"/> + <element name="AttributeCode" type="text" selector="#attribute_code"/> + <element name="Scope" type="select" selector="#is_global"/> + <element name="AddToColumnOptions" type="select" selector="#is_used_in_grid"/> + <element name="UseInFilterOptions" type="select" selector="#is_filterable_in_grid"/> + </section> </sections> diff --git a/app/code/Magento/Swatches/Test/Mftf/Data/SwatchAttributeData.xml b/app/code/Magento/Swatches/Test/Mftf/Data/SwatchAttributeData.xml index 08e24cfeb38..d7ee6dabce7 100644 --- a/app/code/Magento/Swatches/Test/Mftf/Data/SwatchAttributeData.xml +++ b/app/code/Magento/Swatches/Test/Mftf/Data/SwatchAttributeData.xml @@ -11,5 +11,6 @@ <entity name="visualSwatchAttribute" type="SwatchAttribute"> <data key="default_label" unique="suffix">VisualSwatchAttr</data> <data key="input_type">Visual Swatch</data> + <data key="attribute_code" unique="suffix">visual_swatch_attr</data> </entity> </entities> diff --git a/app/code/Magento/Swatches/Test/Mftf/Test/AdminCreateVisualSwatchWithNonValidOptionsTest.xml b/app/code/Magento/Swatches/Test/Mftf/Test/AdminCreateVisualSwatchWithNonValidOptionsTest.xml new file mode 100644 index 00000000000..00de4cdf937 --- /dev/null +++ b/app/code/Magento/Swatches/Test/Mftf/Test/AdminCreateVisualSwatchWithNonValidOptionsTest.xml @@ -0,0 +1,74 @@ +<?xml version="1.0"?> +<!-- +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<tests xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/testSchema.xsd"> + <test name="AdminCreateVisualSwatchWithNonValidOptionsTest"> + <annotations> + <features value="Swatches"/> + <stories value="Create/configure swatches product attribute"/> + <title value="Admin should be able to create swatch product attribute"/> + <description value="Admin should be able to create swatch product attribute"/> + <severity value="BLOCKER"/> + <testCaseId value="MC-4140"/> + <group value="Swatches"/> + </annotations> + <before> + <actionGroup ref="LoginActionGroup" stepKey="login"/> + </before> + <after> + <!-- Remove attribute --> + <actionGroup ref="navigateToCreatedProductAttribute" stepKey="navigateToAttribute"> + <argument name="ProductAttribute" value="visualSwatchAttribute"/> + </actionGroup> + <click selector="{{AttributePropertiesSection.DeleteAttribute}}" stepKey="deleteAttribute"/> + + <actionGroup ref="logout" stepKey="logout"/> + </after> + + <amOnPage url="{{ProductAttributePage.url}}" stepKey="navigateToNewProductAttributePage"/> + <waitForPageLoad stepKey="waitForPageLoad"/> + + <!-- Set attribute properties --> + <fillField selector="{{AttributePropertiesSection.DefaultLabel}}" + userInput="{{visualSwatchAttribute.default_label}}" stepKey="fillDefaultLabel"/> + <selectOption selector="{{AttributePropertiesSection.InputType}}" + userInput="{{visualSwatchAttribute.input_type}}" stepKey="fillInputType"/> + + <!-- Set advanced attribute properties --> + <click selector="{{AdvancedAttributePropertiesSection.AdvancedAttributePropertiesSectionToggle}}" + stepKey="showAdvancedAttributePropertiesSection"/> + <waitForElementVisible selector="{{AdvancedAttributePropertiesSection.AttributeCode}}" + stepKey="waitForSlideOut"/> + <fillField selector="{{AdvancedAttributePropertiesSection.AttributeCode}}" + userInput="{{visualSwatchAttribute.attribute_code}}" + stepKey="fillAttributeCode"/> + + <!-- Add an empty swatch option --> + <click selector="{{AdminManageSwatchSection.addSwatch}}" stepKey="clickAddSwatch1"/> + + <!-- Save the new product attribute --> + <click selector="{{AttributePropertiesSection.Save}}" stepKey="clickSave1"/> + <waitForElementVisible selector="{{AdminProductMessagesSection.errorMessage}}" stepKey="waitForError"/> + + <!-- Fill options data --> + <actionGroup ref="openSwatchMenuByIndex" stepKey="clickSwatch2"> + <argument name="index" value="0"/> + </actionGroup> + <click selector="{{AdminManageSwatchSection.nthChooseColor('1')}}" stepKey="clickChooseColor1"/> + <actionGroup ref="setColorPickerByHex" stepKey="fillHex1"> + <argument name="nthColorPicker" value="1"/> + <argument name="hexColor" value="ff0000"/> + </actionGroup> + <fillField selector="{{AdminManageSwatchSection.adminInputByIndex('0')}}" + userInput="red" stepKey="fillAdmin1"/> + + <!-- Save the new product attribute --> + <click selector="{{AttributePropertiesSection.Save}}" stepKey="clickSave2"/> + <waitForElementVisible selector="{{AdminProductMessagesSection.successMessage}}" + stepKey="waitForSuccessMessage"/> + </test> +</tests> \ No newline at end of file From 758d65da91f7182ca7cea5bc05f424c34cba8227 Mon Sep 17 00:00:00 2001 From: Max Lesechko <mlesechko@magento.com> Date: Tue, 11 Sep 2018 17:28:12 -0500 Subject: [PATCH 16/44] MAGETWO-94819: Swatch validation breaks the whole attribute form --- .../Controller/Adminhtml/Product/Attribute/Validate.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Validate.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Validate.php index fa8103f7033..9fcfe39f6dd 100644 --- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Validate.php +++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Validate.php @@ -11,6 +11,9 @@ use Magento\Framework\App\ObjectManager; use Magento\Framework\DataObject; +/** + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ class Validate extends \Magento\Catalog\Controller\Adminhtml\Product\Attribute { const DEFAULT_MESSAGE_KEY = 'message'; From 5a283e3ff98079a94249bd3430c945484d8859c1 Mon Sep 17 00:00:00 2001 From: Max Lesechko <mlesechko@magento.com> Date: Wed, 12 Sep 2018 15:31:57 -0500 Subject: [PATCH 17/44] MAGETWO-94819: Swatch validation breaks the whole attribute form --- .../Product/Attribute/ValidateTest.php | 167 +++++++++++------- .../catalog/product/attribute/js.phtml | 5 +- .../Catalog/view/adminhtml/web/js/options.js | 7 +- ...ateVisualSwatchWithNonValidOptionsTest.xml | 14 +- .../adminhtml/web/js/product-attributes.js | 11 +- .../Adminhtml/Product/AttributeTest.php | 17 +- 6 files changed, 134 insertions(+), 87 deletions(-) diff --git a/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Attribute/ValidateTest.php b/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Attribute/ValidateTest.php index 9c747393cc7..60c79a04481 100644 --- a/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Attribute/ValidateTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Attribute/ValidateTest.php @@ -6,6 +6,7 @@ namespace Magento\Catalog\Test\Unit\Controller\Adminhtml\Product\Attribute; use Magento\Catalog\Controller\Adminhtml\Product\Attribute\Validate; +use Magento\Catalog\Model\Product\Attribute\Option\OptionsDataResolver; use Magento\Catalog\Model\ResourceModel\Eav\Attribute; use Magento\Catalog\Test\Unit\Controller\Adminhtml\Product\AttributeTest; use Magento\Eav\Model\Entity\Attribute\Set as AttributeSet; @@ -61,6 +62,11 @@ class ValidateTest extends AttributeTest */ protected $layoutMock; + /** + * @var OptionsDataResolver|\PHPUnit_Framework_MockObject_MockObject + */ + private $optionsDataResolverMock; + protected function setUp() { parent::setUp(); @@ -86,6 +92,8 @@ protected function setUp() ->getMock(); $this->layoutMock = $this->getMockBuilder(LayoutInterface::class) ->getMockForAbstractClass(); + $this->optionsDataResolverMock = $this->getMockBuilder(OptionsDataResolver::class) + ->getMock(); $this->contextMock->expects($this->any()) ->method('getObjectManager') @@ -100,13 +108,14 @@ protected function getModel() return $this->objectManager->getObject( Validate::class, [ - 'context' => $this->contextMock, - 'attributeLabelCache' => $this->attributeLabelCacheMock, - 'coreRegistry' => $this->coreRegistryMock, - 'resultPageFactory' => $this->resultPageFactoryMock, - 'resultJsonFactory' => $this->resultJsonFactoryMock, - 'layoutFactory' => $this->layoutFactoryMock, - 'multipleAttributeList' => ['select' => 'option'] + 'context' => $this->contextMock, + 'attributeLabelCache' => $this->attributeLabelCacheMock, + 'coreRegistry' => $this->coreRegistryMock, + 'resultPageFactory' => $this->resultPageFactoryMock, + 'resultJsonFactory' => $this->resultJsonFactoryMock, + 'layoutFactory' => $this->layoutFactoryMock, + 'multipleAttributeList' => ['select' => 'option'], + 'optionsDataResolver' => $this->optionsDataResolverMock, ] ); } @@ -160,17 +169,22 @@ public function testExecute() */ public function testUniqueValidation(array $options, $isError) { - $countFunctionCalls = ($isError) ? 6 : 5; + $countFunctionCalls = ($isError) ? 5 : 4; $this->requestMock->expects($this->exactly($countFunctionCalls)) ->method('getParam') ->willReturnMap([ ['frontend_label', null, null], ['attribute_code', null, "test_attribute_code"], ['new_attribute_set_name', null, 'test_attribute_set_name'], - ['option', null, $options], ['message_key', null, Validate::DEFAULT_MESSAGE_KEY] ]); + $this->optionsDataResolverMock + ->expects($this->once()) + ->method('getOptionsData') + ->with($this->requestMock) + ->willReturn($options); + $this->objectManagerMock->expects($this->once()) ->method('create') ->willReturn($this->attributeMock); @@ -203,67 +217,77 @@ public function provideUniqueData() return [ 'no values' => [ [ - 'delete' => [ - "option_0" => "", - "option_1" => "", - "option_2" => "", - ] + 'option' => [ + 'delete' => [ + "option_0" => "", + "option_1" => "", + "option_2" => "", + ], + ], ], false ], 'valid options' => [ [ - 'value' => [ - "option_0" => [1, 0], - "option_1" => [2, 0], - "option_2" => [3, 0], + 'option' => [ + 'value' => [ + "option_0" => [1, 0], + "option_1" => [2, 0], + "option_2" => [3, 0], + ], + 'delete' => [ + "option_0" => "", + "option_1" => "", + "option_2" => "", + ], ], - 'delete' => [ - "option_0" => "", - "option_1" => "", - "option_2" => "", - ] ], false ], 'duplicate options' => [ [ - 'value' => [ - "option_0" => [1, 0], - "option_1" => [1, 0], - "option_2" => [3, 0], + 'option' => [ + 'value' => [ + "option_0" => [1, 0], + "option_1" => [1, 0], + "option_2" => [3, 0], + ], + 'delete' => [ + "option_0" => "", + "option_1" => "", + "option_2" => "", + ], ], - 'delete' => [ - "option_0" => "", - "option_1" => "", - "option_2" => "", - ] ], true ], 'duplicate and deleted' => [ [ - 'value' => [ - "option_0" => [1, 0], - "option_1" => [1, 0], - "option_2" => [3, 0], + 'option' => [ + 'value' => [ + "option_0" => [1, 0], + "option_1" => [1, 0], + "option_2" => [3, 0], + ], + 'delete' => [ + "option_0" => "", + "option_1" => "1", + "option_2" => "", + ], ], - 'delete' => [ - "option_0" => "", - "option_1" => "1", - "option_2" => "", - ] ], false ], 'empty and deleted' => [ [ - 'value' => [ - "option_0" => [1, 0], - "option_1" => [2, 0], - "option_2" => ["", ""], + 'option' => [ + 'value' => [ + "option_0" => [1, 0], + "option_1" => [2, 0], + "option_2" => ["", ""], + ], + 'delete' => [ + "option_0" => "", + "option_1" => "", + "option_2" => "1", + ], ], - 'delete' => [ - "option_0" => "", - "option_1" => "", - "option_2" => "1", - ] ], false ], ]; @@ -285,10 +309,15 @@ public function testEmptyOption(array $options, $result) ['frontend_input', 'select', 'multipleselect'], ['attribute_code', null, "test_attribute_code"], ['new_attribute_set_name', null, 'test_attribute_set_name'], - ['option', null, $options], ['message_key', Validate::DEFAULT_MESSAGE_KEY, 'message'], ]); + $this->optionsDataResolverMock + ->expects($this->once()) + ->method('getOptionsData') + ->with($this->requestMock) + ->willReturn($options); + $this->objectManagerMock->expects($this->once()) ->method('create') ->willReturn($this->attributeMock); @@ -320,8 +349,10 @@ public function provideEmptyOption() return [ 'empty admin scope options' => [ [ - 'value' => [ - "option_0" => [''], + 'option' => [ + 'value' => [ + "option_0" => [''], + ], ], ], (object) [ @@ -331,8 +362,10 @@ public function provideEmptyOption() ], 'not empty admin scope options' => [ [ - 'value' => [ - "option_0" => ['asdads'], + 'option' => [ + 'value' => [ + "option_0" => ['asdads'], + ], ], ], (object) [ @@ -341,11 +374,13 @@ public function provideEmptyOption() ], 'empty admin scope options and deleted' => [ [ - 'value' => [ - "option_0" => [''], - ], - 'delete' => [ - 'option_0' => '1', + 'option' => [ + 'value' => [ + "option_0" => [''], + ], + 'delete' => [ + 'option_0' => '1', + ], ], ], (object) [ @@ -354,11 +389,13 @@ public function provideEmptyOption() ], 'empty admin scope options and not deleted' => [ [ - 'value' => [ - "option_0" => [''], - ], - 'delete' => [ - 'option_0' => '0', + 'option' => [ + 'value' => [ + "option_0" => [''], + ], + 'delete' => [ + 'option_0' => '0', + ], ], ], (object) [ diff --git a/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/attribute/js.phtml b/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/attribute/js.phtml index 8a5f1919f78..eeacc90fba9 100644 --- a/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/attribute/js.phtml +++ b/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/attribute/js.phtml @@ -40,13 +40,16 @@ function getFrontTab() { function checkOptionsPanelVisibility(){ if($('manage-options-panel')){ - var panel = $('manage-options-panel').up('.fieldset'); + var panel = $('manage-options-panel').up('.fieldset'), + activePanelClass = 'selected-type-options'; if($('frontend_input') && ($('frontend_input').value=='select' || $('frontend_input').value=='multiselect')){ panel.show(); + panel.addClass(activePanelClass); } else { panel.hide(); + panel.removeClass(activePanelClass); } } } diff --git a/app/code/Magento/Catalog/view/adminhtml/web/js/options.js b/app/code/Magento/Catalog/view/adminhtml/web/js/options.js index bb06d05371e..7c359936704 100644 --- a/app/code/Magento/Catalog/view/adminhtml/web/js/options.js +++ b/app/code/Magento/Catalog/view/adminhtml/web/js/options.js @@ -145,7 +145,8 @@ define([ return optionDefaultInputType; } }, - tableBody = jQuery(); + tableBody = jQuery(), + activePanelClass = 'selected-type-options'; if ($('add_new_option_button')) { Event.observe('add_new_option_button', 'click', attributeOption.add.bind(attributeOption, {}, true)); @@ -184,7 +185,7 @@ define([ var optionsValues = [], optionContainer = optionPanel.find('table tbody'); - if (optionPanel.is(':visible')) { + if (optionPanel.hasClass(activePanelClass)) { optionContainer.find('input') .each(function () { if (this.disabled) { @@ -210,7 +211,7 @@ define([ tableBody = optionContainer.detach(); }); editForm.on('afterValidate.error', function () { - if (optionPanel.is(':visible')) { + if (optionPanel.hasClass(activePanelClass)) { optionPanel.find('table').append(tableBody); jQuery('input[name="serialized_options"]').remove(); } diff --git a/app/code/Magento/Swatches/Test/Mftf/Test/AdminCreateVisualSwatchWithNonValidOptionsTest.xml b/app/code/Magento/Swatches/Test/Mftf/Test/AdminCreateVisualSwatchWithNonValidOptionsTest.xml index 00de4cdf937..92a33487615 100644 --- a/app/code/Magento/Swatches/Test/Mftf/Test/AdminCreateVisualSwatchWithNonValidOptionsTest.xml +++ b/app/code/Magento/Swatches/Test/Mftf/Test/AdminCreateVisualSwatchWithNonValidOptionsTest.xml @@ -47,14 +47,8 @@ userInput="{{visualSwatchAttribute.attribute_code}}" stepKey="fillAttributeCode"/> - <!-- Add an empty swatch option --> + <!-- Add new swatch option without label --> <click selector="{{AdminManageSwatchSection.addSwatch}}" stepKey="clickAddSwatch1"/> - - <!-- Save the new product attribute --> - <click selector="{{AttributePropertiesSection.Save}}" stepKey="clickSave1"/> - <waitForElementVisible selector="{{AdminProductMessagesSection.errorMessage}}" stepKey="waitForError"/> - - <!-- Fill options data --> <actionGroup ref="openSwatchMenuByIndex" stepKey="clickSwatch2"> <argument name="index" value="0"/> </actionGroup> @@ -63,6 +57,12 @@ <argument name="nthColorPicker" value="1"/> <argument name="hexColor" value="ff0000"/> </actionGroup> + + <!-- Save the new product attribute --> + <click selector="{{AttributePropertiesSection.Save}}" stepKey="clickSave1"/> + <waitForElementVisible selector="{{AdminProductMessagesSection.errorMessage}}" stepKey="waitForError"/> + + <!-- Fill options data --> <fillField selector="{{AdminManageSwatchSection.adminInputByIndex('0')}}" userInput="red" stepKey="fillAdmin1"/> diff --git a/app/code/Magento/Swatches/view/adminhtml/web/js/product-attributes.js b/app/code/Magento/Swatches/view/adminhtml/web/js/product-attributes.js index 49723f4190a..9538e8729e4 100644 --- a/app/code/Magento/Swatches/view/adminhtml/web/js/product-attributes.js +++ b/app/code/Magento/Swatches/view/adminhtml/web/js/product-attributes.js @@ -16,7 +16,8 @@ define([ 'use strict'; return function (optionConfig) { - var swatchProductAttributes = { + var activePanelClass = 'selected-type-options', + swatchProductAttributes = { frontendInput: $('#frontend_input'), isFilterable: $('#is_filterable'), isFilterableInSearch: $('#is_filterable_in_search'), @@ -338,6 +339,7 @@ define([ */ _showPanel: function (el) { el.closest('.fieldset').show(); + el.addClass(activePanelClass); this._render(el.attr('id')); }, @@ -347,6 +349,7 @@ define([ */ _hidePanel: function (el) { el.closest('.fieldset').hide(); + el.removeClass(activePanelClass); }, /** @@ -438,10 +441,10 @@ define([ var swatchValues = [], optionContainer; - activePanel = swatchTextPanel.is(':visible') ? swatchTextPanel : swatchVisualPanel; + activePanel = swatchTextPanel.hasClass(this.activePanelClass) ? swatchTextPanel : swatchVisualPanel; optionContainer = activePanel.find('table tbody'); - if (activePanel.is(':visible')) { + if (activePanel.hasClass(activePanelClass)) { optionContainer .find('input') .each(function () { @@ -461,7 +464,7 @@ define([ }); editForm.on('afterValidate.error', function () { - if (activePanel.is(':visible')) { + if (activePanel.hasClass(activePanelClass)) { activePanel.find('table').append(tableBody); $('input[name="serialized_options"]').remove(); } diff --git a/dev/tests/integration/testsuite/Magento/Swatches/Controller/Adminhtml/Product/AttributeTest.php b/dev/tests/integration/testsuite/Magento/Swatches/Controller/Adminhtml/Product/AttributeTest.php index 969d9530ae5..1a0073b154f 100644 --- a/dev/tests/integration/testsuite/Magento/Swatches/Controller/Adminhtml/Product/AttributeTest.php +++ b/dev/tests/integration/testsuite/Magento/Swatches/Controller/Adminhtml/Product/AttributeTest.php @@ -48,12 +48,14 @@ private function getSwatchVisualDataSet(int $optionsCount) : array $optionsData []= "optionvisual[value][option_{$i}][1]={$expectedOptionLabelOnStoreView}"; $optionsData []= "optionvisual[delete][option_{$i}]="; } - $optionsData []= "visual_swatch_validation="; - $optionsData []= "visual_swatch_validation_unique="; return [ 'attribute_data' => array_merge_recursive( [ - 'serialized_swatch_values' => json_encode($optionsData), + 'serialized_options' => json_encode($optionsData), + ], + [ + 'visual_swatch_validation' => '', + 'visual_swatch_validation_unique' => '', ], $this->getAttributePreset(), [ @@ -86,12 +88,14 @@ private function getSwatchTextDataSet(int $optionsCount) : array $optionsData []= "optiontext[value][option_{$i}][1]={$expectedOptionLabelOnStoreView}"; $optionsData []= "optiontext[delete][option_{$i}]="; } - $optionsData []= "text_swatch_validation="; - $optionsData []= "text_swatch_validation_unique="; return [ 'attribute_data' => array_merge_recursive( [ - 'serialized_swatch_values' => json_encode($optionsData), + 'serialized_options' => json_encode($optionsData), + ], + [ + 'text_swatch_validation' => '', + 'text_swatch_validation_unique' => '', ], $this->getAttributePreset(), [ @@ -111,7 +115,6 @@ private function getSwatchTextDataSet(int $optionsCount) : array private function getAttributePreset() : array { return [ - 'serialized_options' => '[]', 'form_key' => 'XxtpPYjm2YPYUlAt', 'frontend_label' => [ 0 => 'asdasd', From aafc793f5d22ac7d087a1e04919f95f7378a2e46 Mon Sep 17 00:00:00 2001 From: Max Lesechko <mlesechko@magento.com> Date: Thu, 13 Sep 2018 17:21:01 -0500 Subject: [PATCH 18/44] MAGETWO-94819: Swatch validation breaks the whole attribute form --- .../Adminhtml/Product/Attribute/Save.php | 17 ++++--- .../Adminhtml/Product/Attribute/Validate.php | 17 ++++--- .../Attribute/Option/OptionsDataResolver.php | 46 ----------------- .../Option/OptionsDataSerializer.php | 50 +++++++++++++++++++ .../adminhtml/web/js/product-attributes.js | 2 +- 5 files changed, 69 insertions(+), 63 deletions(-) delete mode 100644 app/code/Magento/Catalog/Model/Product/Attribute/Option/OptionsDataResolver.php create mode 100644 app/code/Magento/Catalog/Model/Product/Attribute/Option/OptionsDataSerializer.php diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Save.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Save.php index 825288b3664..0c6b2cb52e1 100644 --- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Save.php +++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Save.php @@ -13,7 +13,7 @@ use Magento\Catalog\Controller\Adminhtml\Product\Attribute; use Magento\Catalog\Helper\Product; use Magento\Catalog\Model\Product\Attribute\Frontend\Inputtype\Presentation; -use Magento\Catalog\Model\Product\Attribute\Option\OptionsDataResolver; +use Magento\Catalog\Model\Product\Attribute\Option\OptionsDataSerializer; use Magento\Catalog\Model\Product\AttributeSet\BuildFactory; use Magento\Catalog\Model\ResourceModel\Eav\AttributeFactory; use Magento\Eav\Model\Adminhtml\System\Config\Source\Inputtype\Validator; @@ -77,9 +77,9 @@ class Save extends Attribute private $presentation; /** - * @var OptionsDataResolver|null + * @var OptionsDataSerializer|null */ - private $optionsDataResolver; + private $optionsDataSerializer; /** * @param Context $context @@ -94,7 +94,7 @@ class Save extends Attribute * @param Product $productHelper * @param LayoutFactory $layoutFactory * @param Presentation|null $presentation - * @param OptionsDataResolver|null $optionsDataResolver + * @param OptionsDataSerializer|null $optionsDataSerializer * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( @@ -110,7 +110,7 @@ public function __construct( Product $productHelper, LayoutFactory $layoutFactory, Presentation $presentation = null, - OptionsDataResolver $optionsDataResolver = null + OptionsDataSerializer $optionsDataSerializer = null ) { parent::__construct($context, $attributeLabelCache, $coreRegistry, $resultPageFactory); $this->buildFactory = $buildFactory; @@ -121,8 +121,8 @@ public function __construct( $this->groupCollectionFactory = $groupCollectionFactory; $this->layoutFactory = $layoutFactory; $this->presentation = $presentation ?: ObjectManager::getInstance()->get(Presentation::class); - $this->optionsDataResolver = $optionsDataResolver - ?: ObjectManager::getInstance()->get(OptionsDataResolver::class); + $this->optionsDataSerializer = $optionsDataSerializer + ?: ObjectManager::getInstance()->get(OptionsDataSerializer::class); } /** @@ -134,7 +134,8 @@ public function __construct( public function execute() { try { - $optionData = $this->optionsDataResolver->getOptionsData($this->getRequest()); + $optionData = $this->optionsDataSerializer + ->unserialize($this->getRequest()->getParam('serialized_options')); } catch (\InvalidArgumentException $e) { $message = __("The attribute couldn't be saved due to an error. Verify your information and try again. " . "If the error persists, please try again later."); diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Validate.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Validate.php index 9fcfe39f6dd..ca2ba9d231a 100644 --- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Validate.php +++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Validate.php @@ -7,7 +7,7 @@ namespace Magento\Catalog\Controller\Adminhtml\Product\Attribute; -use Magento\Catalog\Model\Product\Attribute\Option\OptionsDataResolver; +use Magento\Catalog\Model\Product\Attribute\Option\OptionsDataSerializer; use Magento\Framework\App\ObjectManager; use Magento\Framework\DataObject; @@ -34,9 +34,9 @@ class Validate extends \Magento\Catalog\Controller\Adminhtml\Product\Attribute private $multipleAttributeList; /** - * @var OptionsDataResolver|null + * @var OptionsDataSerializer|null */ - private $optionsDataResolver; + private $optionsDataSerializer; /** * Constructor @@ -48,7 +48,7 @@ class Validate extends \Magento\Catalog\Controller\Adminhtml\Product\Attribute * @param \Magento\Framework\Controller\Result\JsonFactory $resultJsonFactory * @param \Magento\Framework\View\LayoutFactory $layoutFactory * @param array $multipleAttributeList - * @param OptionsDataResolver|null $optionsDataResolver + * @param OptionsDataSerializer|null $optionsDataSerializer */ public function __construct( \Magento\Backend\App\Action\Context $context, @@ -58,14 +58,14 @@ public function __construct( \Magento\Framework\Controller\Result\JsonFactory $resultJsonFactory, \Magento\Framework\View\LayoutFactory $layoutFactory, array $multipleAttributeList = [], - OptionsDataResolver $optionsDataResolver = null + OptionsDataSerializer $optionsDataSerializer = null ) { parent::__construct($context, $attributeLabelCache, $coreRegistry, $resultPageFactory); $this->resultJsonFactory = $resultJsonFactory; $this->layoutFactory = $layoutFactory; $this->multipleAttributeList = $multipleAttributeList; - $this->optionsDataResolver = $optionsDataResolver ?: ObjectManager::getInstance() - ->get(OptionsDataResolver::class); + $this->optionsDataSerializer = $optionsDataSerializer ?: ObjectManager::getInstance() + ->get(OptionsDataSerializer::class); } /** @@ -78,7 +78,8 @@ public function execute() $response = new DataObject(); $response->setError(false); try { - $optionsData = $this->optionsDataResolver->getOptionsData($this->getRequest()); + $optionsData = $this->optionsDataSerializer + ->unserialize($this->getRequest()->getParam('serialized_options')); } catch (\InvalidArgumentException $e) { $message = __("The attribute couldn't be validated due to an error. Verify your information and try again. " . "If the error persists, please try again later."); diff --git a/app/code/Magento/Catalog/Model/Product/Attribute/Option/OptionsDataResolver.php b/app/code/Magento/Catalog/Model/Product/Attribute/Option/OptionsDataResolver.php deleted file mode 100644 index 60b183db941..00000000000 --- a/app/code/Magento/Catalog/Model/Product/Attribute/Option/OptionsDataResolver.php +++ /dev/null @@ -1,46 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ - -declare(strict_types=1); - -namespace Magento\Catalog\Model\Product\Attribute\Option; - -use Magento\Framework\App\RequestInterface; - -/** - * Attribute options data resolver. - */ -class OptionsDataResolver -{ - /** - * Provides attribute options data from the request. - * - * @param RequestInterface $request - * @return array - * @throws \InvalidArgumentException - */ - public function getOptionsData(RequestInterface $request): array - { - $serializedOptions = $request->getParam('serialized_options'); - $optionsData = []; - - if ($serializedOptions) { - $encodedOptions = json_decode($serializedOptions, true); - - if (json_last_error() !== JSON_ERROR_NONE) { - throw new \InvalidArgumentException('Unable to unserialize options data.'); - } - - foreach ($encodedOptions as $encodedOption) { - $decodedOptionData = []; - parse_str($encodedOption, $decodedOptionData); - $optionsData = array_replace_recursive($optionsData, $decodedOptionData); - } - } - - return $optionsData; - } -} diff --git a/app/code/Magento/Catalog/Model/Product/Attribute/Option/OptionsDataSerializer.php b/app/code/Magento/Catalog/Model/Product/Attribute/Option/OptionsDataSerializer.php new file mode 100644 index 00000000000..8fe02a9123b --- /dev/null +++ b/app/code/Magento/Catalog/Model/Product/Attribute/Option/OptionsDataSerializer.php @@ -0,0 +1,50 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +declare(strict_types=1); + +namespace Magento\Catalog\Model\Product\Attribute\Option; + +use Magento\Framework\Serialize\SerializerInterface; + +/** + * Attribute options data serializer. + */ +class OptionsDataSerializer +{ + /** + * @var SerializerInterface + */ + private $serializer; + + /** + * @param SerializerInterface $serializer + */ + public function __construct(SerializerInterface $serializer) + { + $this->serializer = $serializer; + } + + /** + * Provides attribute options data from the serialized data. + * + * @param string $serializedOptions + * @return array + */ + public function unserialize(string $serializedOptions): array + { + $optionsData = []; + $encodedOptions = $this->serializer->unserialize($serializedOptions); + + foreach ($encodedOptions as $encodedOption) { + $decodedOptionData = []; + parse_str($encodedOption, $decodedOptionData); + $optionsData = array_replace_recursive($optionsData, $decodedOptionData); + } + + return $optionsData; + } +} diff --git a/app/code/Magento/Swatches/view/adminhtml/web/js/product-attributes.js b/app/code/Magento/Swatches/view/adminhtml/web/js/product-attributes.js index 9538e8729e4..d0eacc94e2c 100644 --- a/app/code/Magento/Swatches/view/adminhtml/web/js/product-attributes.js +++ b/app/code/Magento/Swatches/view/adminhtml/web/js/product-attributes.js @@ -441,7 +441,7 @@ define([ var swatchValues = [], optionContainer; - activePanel = swatchTextPanel.hasClass(this.activePanelClass) ? swatchTextPanel : swatchVisualPanel; + activePanel = swatchTextPanel.hasClass(activePanelClass) ? swatchTextPanel : swatchVisualPanel; optionContainer = activePanel.find('table tbody'); if (activePanel.hasClass(activePanelClass)) { From efceb14099aee0a388c20c4a9696e6e6b67ee8ee Mon Sep 17 00:00:00 2001 From: Max Lesechko <mlesechko@magento.com> Date: Fri, 14 Sep 2018 09:37:21 -0500 Subject: [PATCH 19/44] MAGETWO-94819: Swatch validation breaks the whole attribute form --- .../Adminhtml/Product/Attribute/SaveTest.php | 130 ++++++++++++++++++ .../Product/Attribute/ValidateTest.php | 84 +++++++++-- .../Adminhtml/Product/AttributeTest.php | 19 ++- 3 files changed, 217 insertions(+), 16 deletions(-) diff --git a/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Attribute/SaveTest.php b/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Attribute/SaveTest.php index f493cbc88f1..b9b1aeb9157 100644 --- a/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Attribute/SaveTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Attribute/SaveTest.php @@ -5,7 +5,9 @@ */ namespace Magento\Catalog\Test\Unit\Controller\Adminhtml\Product\Attribute; +use Magento\Catalog\Api\Data\ProductAttributeInterface; use Magento\Catalog\Controller\Adminhtml\Product\Attribute\Save; +use Magento\Catalog\Model\Product\Attribute\Option\OptionsDataSerializer; use Magento\Catalog\Test\Unit\Controller\Adminhtml\Product\AttributeTest; use Magento\Catalog\Model\Product\AttributeSet\BuildFactory; use Magento\Catalog\Model\Product\AttributeSet\Build; @@ -13,11 +15,14 @@ use Magento\Eav\Api\Data\AttributeSetInterface; use Magento\Eav\Model\Adminhtml\System\Config\Source\Inputtype\ValidatorFactory; use Magento\Eav\Model\ResourceModel\Entity\Attribute\Group\CollectionFactory; +use Magento\Framework\Controller\ResultFactory; use Magento\Framework\Filter\FilterManager; use Magento\Catalog\Helper\Product as ProductHelper; +use Magento\Framework\View\Element\Messages; use Magento\Framework\View\LayoutFactory; use Magento\Backend\Model\View\Result\Redirect as ResultRedirect; use Magento\Eav\Model\Adminhtml\System\Config\Source\Inputtype\Validator as InputTypeValidator; +use Magento\Framework\View\LayoutInterface; /** * @SuppressWarnings(PHPMD.CouplingBetweenObjects) @@ -79,6 +84,16 @@ class SaveTest extends AttributeTest */ protected $inputTypeValidatorMock; + /** + * @var OptionsDataSerializer|\PHPUnit_Framework_MockObject_MockObject + */ + private $optionsDataSerializerMock; + + /** + * @var ProductAttributeInterface|\PHPUnit_Framework_MockObject_MockObject + */ + private $productAttributeMock; + protected function setUp() { parent::setUp(); @@ -108,6 +123,7 @@ protected function setUp() ->disableOriginalConstructor() ->getMock(); $this->redirectMock = $this->getMockBuilder(ResultRedirect::class) + ->setMethods(['setData', 'setPath']) ->disableOriginalConstructor() ->getMock(); $this->attributeSetMock = $this->getMockBuilder(AttributeSetInterface::class) @@ -119,6 +135,12 @@ protected function setUp() $this->inputTypeValidatorMock = $this->getMockBuilder(InputTypeValidator::class) ->disableOriginalConstructor() ->getMock(); + $this->optionsDataSerializerMock = $this->getMockBuilder(OptionsDataSerializer::class) + ->disableOriginalConstructor() + ->getMock(); + $this->productAttributeMock = $this->getMockBuilder(ProductAttributeInterface::class) + ->setMethods(['getId', 'get']) + ->getMockForAbstractClass(); $this->buildFactoryMock->expects($this->any()) ->method('create') @@ -126,6 +148,9 @@ protected function setUp() $this->validatorFactoryMock->expects($this->any()) ->method('create') ->willReturn($this->inputTypeValidatorMock); + $this->attributeFactoryMock + ->method('create') + ->willReturn($this->productAttributeMock); } /** @@ -145,11 +170,23 @@ protected function getModel() 'validatorFactory' => $this->validatorFactoryMock, 'groupCollectionFactory' => $this->groupCollectionFactoryMock, 'layoutFactory' => $this->layoutFactoryMock, + 'optionsDataSerializer' => $this->optionsDataSerializerMock, ]); } public function testExecuteWithEmptyData() { + $this->requestMock->expects($this->any()) + ->method('getParam') + ->willReturnMap([ + ['isAjax', null, null], + ['serialized_options', null, ''], + ]); + $this->optionsDataSerializerMock + ->expects($this->once()) + ->method('unserialize') + ->with('') + ->willReturn([]); $this->requestMock->expects($this->once()) ->method('getPostValue') ->willReturn([]); @@ -170,6 +207,23 @@ public function testExecute() 'frontend_input' => 'test_frontend_input', ]; + $this->requestMock->expects($this->any()) + ->method('getParam') + ->willReturnMap([ + ['isAjax', null, null], + ['serialized_options', null, ''], + ]); + $this->optionsDataSerializerMock + ->expects($this->once()) + ->method('unserialize') + ->with('') + ->willReturn([]); + $this->productAttributeMock + ->method('getId') + ->willReturn(1); + $this->productAttributeMock + ->method('getAttributeCode') + ->willReturn('test_code'); $this->requestMock->expects($this->once()) ->method('getPostValue') ->willReturn($data); @@ -203,4 +257,80 @@ public function testExecute() $this->assertInstanceOf(ResultRedirect::class, $this->getModel()->execute()); } + + /** + * @throws \Magento\Framework\Exception\NotFoundException + */ + public function testExecuteWithOptionsDataError() + { + $serializedOptions = '{"key":"value"}'; + $message = "The attribute couldn't be saved due to an error. Verify your information and try again. " + . "If the error persists, please try again later."; + + $this->requestMock->expects($this->any()) + ->method('getParam') + ->willReturnMap([ + ['isAjax', null, true], + ['serialized_options', null, $serializedOptions], + ]); + $this->optionsDataSerializerMock + ->expects($this->once()) + ->method('unserialize') + ->with($serializedOptions) + ->willThrowException(new \InvalidArgumentException('Some exception')); + $this->messageManager + ->expects($this->once()) + ->method('addErrorMessage') + ->with($message); + $this->addReturnResultConditions('catalog/*/edit', ['_current' => true], ['error' => true]); + + $this->getModel()->execute(); + } + + /** + * @param string $path + * @param array $params + * @param array $response + * @return mixed + * @SuppressWarnings(PHPMD.UnusedFormalParameter) + */ + private function addReturnResultConditions(string $path = '', array $params = [], array $response = []) + { + $layoutMock = $this->getMockBuilder(LayoutInterface::class) + ->setMethods(['initMessages', 'getMessagesBlock']) + ->getMockForAbstractClass(); + $this->layoutFactoryMock + ->expects($this->once()) + ->method('create') + ->with() + ->willReturn($layoutMock); + $layoutMock + ->method('initMessages') + ->with(); + $messageBlockMock = $this->getMockBuilder(Messages::class) + ->disableOriginalConstructor() + ->getMock(); + $layoutMock + ->expects($this->once()) + ->method('getMessagesBlock') + ->willReturn($messageBlockMock); + $messageBlockMock + ->expects($this->once()) + ->method('getGroupedHtml') + ->willReturn('message1'); + $this->resultFactoryMock + ->expects($this->once()) + ->method('create') + ->with(ResultFactory::TYPE_JSON) + ->willReturn($this->redirectMock); + $response = array_merge($response, [ + 'messages' => ['message1'], + 'params' => $params, + ]); + $this->redirectMock + ->expects($this->once()) + ->method('setData') + ->with($response) + ->willReturnSelf(); + } } diff --git a/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Attribute/ValidateTest.php b/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Attribute/ValidateTest.php index 60c79a04481..e9fc8bf3362 100644 --- a/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Attribute/ValidateTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Attribute/ValidateTest.php @@ -6,7 +6,7 @@ namespace Magento\Catalog\Test\Unit\Controller\Adminhtml\Product\Attribute; use Magento\Catalog\Controller\Adminhtml\Product\Attribute\Validate; -use Magento\Catalog\Model\Product\Attribute\Option\OptionsDataResolver; +use Magento\Catalog\Model\Product\Attribute\Option\OptionsDataSerializer; use Magento\Catalog\Model\ResourceModel\Eav\Attribute; use Magento\Catalog\Test\Unit\Controller\Adminhtml\Product\AttributeTest; use Magento\Eav\Model\Entity\Attribute\Set as AttributeSet; @@ -63,9 +63,9 @@ class ValidateTest extends AttributeTest protected $layoutMock; /** - * @var OptionsDataResolver|\PHPUnit_Framework_MockObject_MockObject + * @var OptionsDataSerializer|\PHPUnit_Framework_MockObject_MockObject */ - private $optionsDataResolverMock; + private $optionsDataSerializerMock; protected function setUp() { @@ -92,7 +92,8 @@ protected function setUp() ->getMock(); $this->layoutMock = $this->getMockBuilder(LayoutInterface::class) ->getMockForAbstractClass(); - $this->optionsDataResolverMock = $this->getMockBuilder(OptionsDataResolver::class) + $this->optionsDataSerializerMock = $this->getMockBuilder(OptionsDataSerializer::class) + ->disableOriginalConstructor() ->getMock(); $this->contextMock->expects($this->any()) @@ -115,19 +116,21 @@ protected function getModel() 'resultJsonFactory' => $this->resultJsonFactoryMock, 'layoutFactory' => $this->layoutFactoryMock, 'multipleAttributeList' => ['select' => 'option'], - 'optionsDataResolver' => $this->optionsDataResolverMock, + 'optionsDataSerializer' => $this->optionsDataSerializerMock, ] ); } public function testExecute() { + $serializedOptions = '{"key":"value"}'; $this->requestMock->expects($this->any()) ->method('getParam') ->willReturnMap([ ['frontend_label', null, 'test_frontend_label'], ['attribute_code', null, 'test_attribute_code'], ['new_attribute_set_name', null, 'test_attribute_set_name'], + ['serialized_options', null, $serializedOptions], ]); $this->objectManagerMock->expects($this->exactly(2)) ->method('create') @@ -169,20 +172,22 @@ public function testExecute() */ public function testUniqueValidation(array $options, $isError) { - $countFunctionCalls = ($isError) ? 5 : 4; + $serializedOptions = '{"key":"value"}'; + $countFunctionCalls = ($isError) ? 6 : 5; $this->requestMock->expects($this->exactly($countFunctionCalls)) ->method('getParam') ->willReturnMap([ ['frontend_label', null, null], ['attribute_code', null, "test_attribute_code"], ['new_attribute_set_name', null, 'test_attribute_set_name'], - ['message_key', null, Validate::DEFAULT_MESSAGE_KEY] + ['message_key', null, Validate::DEFAULT_MESSAGE_KEY], + ['serialized_options', null, $serializedOptions], ]); - $this->optionsDataResolverMock + $this->optionsDataSerializerMock ->expects($this->once()) - ->method('getOptionsData') - ->with($this->requestMock) + ->method('unserialize') + ->with($serializedOptions) ->willReturn($options); $this->objectManagerMock->expects($this->once()) @@ -302,6 +307,7 @@ public function provideUniqueData() */ public function testEmptyOption(array $options, $result) { + $serializedOptions = '{"key":"value"}'; $this->requestMock->expects($this->any()) ->method('getParam') ->willReturnMap([ @@ -310,12 +316,13 @@ public function testEmptyOption(array $options, $result) ['attribute_code', null, "test_attribute_code"], ['new_attribute_set_name', null, 'test_attribute_set_name'], ['message_key', Validate::DEFAULT_MESSAGE_KEY, 'message'], + ['serialized_options', null, $serializedOptions], ]); - $this->optionsDataResolverMock + $this->optionsDataSerializerMock ->expects($this->once()) - ->method('getOptionsData') - ->with($this->requestMock) + ->method('unserialize') + ->with($serializedOptions) ->willReturn($options); $this->objectManagerMock->expects($this->once()) @@ -405,4 +412,55 @@ public function provideEmptyOption() ], ]; } + + /** + * @throws \Magento\Framework\Exception\NotFoundException + */ + public function testExecuteWithOptionsDataError() + { + $serializedOptions = '{"key":"value"}'; + $message = "The attribute couldn't be validated due to an error. Verify your information and try again. " + . "If the error persists, please try again later."; + $this->requestMock->expects($this->any()) + ->method('getParam') + ->willReturnMap([ + ['frontend_label', null, 'test_frontend_label'], + ['attribute_code', null, 'test_attribute_code'], + ['new_attribute_set_name', null, 'test_attribute_set_name'], + ['message_key', Validate::DEFAULT_MESSAGE_KEY, 'message'], + ['serialized_options', null, $serializedOptions], + ]); + + $this->optionsDataSerializerMock + ->expects($this->once()) + ->method('unserialize') + ->with($serializedOptions) + ->willThrowException(new \InvalidArgumentException('Some exception')); + + $this->objectManagerMock + ->method('create') + ->willReturnMap([ + [\Magento\Catalog\Model\ResourceModel\Eav\Attribute::class, [], $this->attributeMock], + [\Magento\Eav\Model\Entity\Attribute\Set::class, [], $this->attributeSetMock] + ]); + + $this->attributeMock + ->method('loadByCode') + ->willReturnSelf(); + $this->attributeSetMock + ->method('setEntityTypeId') + ->willReturnSelf(); + $this->resultJsonFactoryMock->expects($this->once()) + ->method('create') + ->willReturn($this->resultJson); + $this->resultJson->expects($this->once()) + ->method('setJsonData') + ->with(json_encode([ + 'error' => true, + 'message' => $message + ])) + ->willReturnSelf(); + + $this->getModel()->execute(); + } } diff --git a/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/AttributeTest.php b/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/AttributeTest.php index b85b03852b6..2a75773754f 100644 --- a/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/AttributeTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/AttributeTest.php @@ -9,8 +9,10 @@ use Magento\Catalog\Controller\Adminhtml\Product\Attribute; use Magento\Framework\App\RequestInterface; use Magento\Framework\Cache\FrontendInterface; +use Magento\Framework\Message\ManagerInterface; +use Magento\Framework\ObjectManager\ObjectManager; use Magento\Framework\Registry; -use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; use Magento\Framework\View\Result\PageFactory; use Magento\Framework\Controller\ResultFactory; @@ -20,7 +22,7 @@ class AttributeTest extends \PHPUnit\Framework\TestCase { /** - * @var ObjectManager + * @var ObjectManagerHelper */ protected $objectManager; @@ -54,9 +56,14 @@ class AttributeTest extends \PHPUnit\Framework\TestCase */ protected $resultFactoryMock; + /** + * @var ManagerInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $messageManager; + protected function setUp() { - $this->objectManager = new ObjectManager($this); + $this->objectManager = new ObjectManagerHelper($this); $this->contextMock = $this->getMockBuilder(Context::class) ->disableOriginalConstructor() ->getMock(); @@ -74,6 +81,9 @@ protected function setUp() $this->resultFactoryMock = $this->getMockBuilder(ResultFactory::class) ->disableOriginalConstructor() ->getMock(); + $this->messageManager = $this->getMockBuilder(ManagerInterface::class) + ->disableOriginalConstructor() + ->getMock(); $this->contextMock->expects($this->any()) ->method('getRequest') @@ -81,6 +91,9 @@ protected function setUp() $this->contextMock->expects($this->any()) ->method('getResultFactory') ->willReturn($this->resultFactoryMock); + $this->contextMock + ->method('getMessageManager') + ->willReturn($this->messageManager); } /** From 727ca8cb1a9ebc9d750c3409a0c6acb44a835482 Mon Sep 17 00:00:00 2001 From: Max Lesechko <mlesechko@magento.com> Date: Fri, 14 Sep 2018 11:07:11 -0500 Subject: [PATCH 20/44] MAGETWO-94819: Swatch validation breaks the whole attribute form --- .../Controller/Adminhtml/Product/Attribute/Save.php | 13 ++++++++++--- .../Adminhtml/Product/Attribute/Validate.php | 9 ++++++++- .../Adminhtml/Product/Attribute/Plugin/Save.php | 2 ++ 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Save.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Save.php index 0c6b2cb52e1..e32d84b393a 100644 --- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Save.php +++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Save.php @@ -32,6 +32,8 @@ use Magento\Framework\View\Result\PageFactory; /** + * Product attribute save controller. + * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class Save extends Attribute @@ -126,10 +128,13 @@ public function __construct( } /** + * @inheritdoc + * * @return Redirect * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.NPathComplexity) * @SuppressWarnings(PHPMD.ExcessiveMethodLength) + * @throws \Zend_Validate_Exception */ public function execute() { @@ -158,7 +163,7 @@ public function execute() $name = trim($name); try { - /** @var $attributeSet Set */ + /** @var Set $attributeSet */ $attributeSet = $this->buildFactory->create() ->setEntityTypeId($this->_entityTypeId) ->setSkeletonId($setId) @@ -180,7 +185,7 @@ public function execute() $attributeId = $this->getRequest()->getParam('attribute_id'); - /** @var $model ProductAttributeInterface */ + /** @var ProductAttributeInterface $model */ $model = $this->attributeFactory->create(); if ($attributeId) { $model->load($attributeId); @@ -212,7 +217,7 @@ public function execute() //validate frontend_input if (isset($data['frontend_input'])) { - /** @var $inputType Validator */ + /** @var Validator $inputType */ $inputType = $this->validatorFactory->create(); if (!$inputType->isValid($data['frontend_input'])) { foreach ($inputType->getMessages() as $message) { @@ -340,6 +345,8 @@ public function execute() } /** + * Provides an initialized Result object. + * * @param string $path * @param array $params * @param array $response diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Validate.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Validate.php index ca2ba9d231a..34dcf6639f9 100644 --- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Validate.php +++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Validate.php @@ -12,6 +12,8 @@ use Magento\Framework\DataObject; /** + * Product attribute validate controller. + * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class Validate extends \Magento\Catalog\Controller\Adminhtml\Product\Attribute @@ -69,6 +71,8 @@ public function __construct( } /** + * @inheritdoc + * * @return \Magento\Framework\Controller\ResultInterface * @SuppressWarnings(PHPMD.NPathComplexity) * @SuppressWarnings(PHPMD.CyclomaticComplexity) @@ -146,7 +150,8 @@ public function execute() } /** - * Throws Exception if not unique values into options + * Throws Exception if not unique values into options. + * * @param array $optionsValues * @param array $deletedOptions * @return bool @@ -180,6 +185,8 @@ private function setMessageToResponse($response, $messages) } /** + * Performs checking the uniqueness of the attribute options. + * * @param DataObject $response * @param array|null $options * @return $this diff --git a/app/code/Magento/Swatches/Controller/Adminhtml/Product/Attribute/Plugin/Save.php b/app/code/Magento/Swatches/Controller/Adminhtml/Product/Attribute/Plugin/Save.php index 9ec65fb0804..72d27152d63 100644 --- a/app/code/Magento/Swatches/Controller/Adminhtml/Product/Attribute/Plugin/Save.php +++ b/app/code/Magento/Swatches/Controller/Adminhtml/Product/Attribute/Plugin/Save.php @@ -16,6 +16,8 @@ class Save { /** + * Performs the conversion of the frontend input value. + * * @param Attribute\Save $subject * @param RequestInterface $request * @return array From 6dfd297fb804990486fd0d5b699cd8f9ddd20e71 Mon Sep 17 00:00:00 2001 From: Max Lesechko <mlesechko@magento.com> Date: Fri, 14 Sep 2018 11:42:44 -0500 Subject: [PATCH 21/44] MAGETWO-94819: Swatch validation breaks the whole attribute form --- .../Catalog/Controller/Adminhtml/Product/AttributeTest.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/AttributeTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/AttributeTest.php index 4261873cc8e..ae8005db95a 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/AttributeTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/AttributeTest.php @@ -376,7 +376,8 @@ protected function _getAttributeData() 'used_in_product_listing' => '1', 'used_for_sort_by' => '0', 'apply_to' => ['simple'], - 'frontend_label' => [\Magento\Store\Model\Store::DEFAULT_STORE_ID => 'string to translate'] + 'frontend_label' => [\Magento\Store\Model\Store::DEFAULT_STORE_ID => 'string to translate'], + 'serialized_options' => '[]', ]; } } From d83c61c9d84bf96d925915de881c210d066b2292 Mon Sep 17 00:00:00 2001 From: Max Lesechko <mlesechko@magento.com> Date: Sun, 16 Sep 2018 19:38:15 -0500 Subject: [PATCH 22/44] MAGETWO-94819: Swatch validation breaks the whole attribute form --- ...ateVisualSwatchWithNonValidOptionsTest.xml | 2 +- dev/tests/acceptance/.gitignore | 1 + .../Handler/CatalogProductAttribute/Curl.php | 61 +++++++++++++++++++ .../Handler/SwatchProductAttribute/Curl.php | 4 +- 4 files changed, 66 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Swatches/Test/Mftf/Test/AdminCreateVisualSwatchWithNonValidOptionsTest.xml b/app/code/Magento/Swatches/Test/Mftf/Test/AdminCreateVisualSwatchWithNonValidOptionsTest.xml index 92a33487615..1e9ce849db1 100644 --- a/app/code/Magento/Swatches/Test/Mftf/Test/AdminCreateVisualSwatchWithNonValidOptionsTest.xml +++ b/app/code/Magento/Swatches/Test/Mftf/Test/AdminCreateVisualSwatchWithNonValidOptionsTest.xml @@ -17,7 +17,7 @@ <group value="Swatches"/> </annotations> <before> - <actionGroup ref="LoginActionGroup" stepKey="login"/> + <actionGroup ref="LoginAsAdmin" stepKey="login"/> </before> <after> <!-- Remove attribute --> diff --git a/dev/tests/acceptance/.gitignore b/dev/tests/acceptance/.gitignore index e3ef78df82b..87ce9d4ff35 100755 --- a/dev/tests/acceptance/.gitignore +++ b/dev/tests/acceptance/.gitignore @@ -7,4 +7,5 @@ tests/functional.suite.yml tests/functional/Magento/FunctionalTest/_generated vendor/* mftf.log +/.credentials.example /utils/ \ No newline at end of file diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Handler/CatalogProductAttribute/Curl.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Handler/CatalogProductAttribute/Curl.php index d78095f05fe..57d775cdeb7 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Handler/CatalogProductAttribute/Curl.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Handler/CatalogProductAttribute/Curl.php @@ -134,11 +134,72 @@ public function persist(FixtureInterface $fixture = null) } /** + * Additional data handling. + * * @param array $data * @return array */ protected function changeStructureOfTheData(array $data) { + $serializedOptions = $this->getSerializeOptions($data, ['option']); + if ($serializedOptions) { + $data['serialized_options'] = $serializedOptions; + unset($data['option']); + } + return $data; } + + /** + * Provides serialized product attribute options. + * + * @param array $data + * @param array $optionKeys + * @return array + */ + protected function getSerializeOptions(array $data, array $optionKeys): string + { + $options = []; + foreach ($optionKeys as $optionKey) { + if (!empty($data[$optionKey])) { + $options = array_merge( + $options, + $this->getEncodedOptions([$optionKey => $data[$optionKey]]) + ); + } + } + + return json_encode($options); + } + + /** + * Provides encoded attribute values. + * + * @param array $data + * @return array + */ + private function getEncodedOptions(array $data): array + { + $optionsData = []; + $iterator = new \RecursiveIteratorIterator(new \RecursiveArrayIterator($data)); + foreach ($iterator as $value) { + $depth = $iterator->getDepth(); + $option = ''; + + $level = 0; + $option .= $iterator->getSubIterator($level)->key(); + $level++; + + while ($level <= $depth) { + $option .= '[' . $iterator->getSubIterator($level)->key() . ']'; + $level++; + } + + $option .= '=' . $value; + + $optionsData[] = $option; + } + + return $optionsData; + } } diff --git a/dev/tests/functional/tests/app/Magento/Swatches/Test/Handler/SwatchProductAttribute/Curl.php b/dev/tests/functional/tests/app/Magento/Swatches/Test/Handler/SwatchProductAttribute/Curl.php index 083fa246c96..5e4a5cc45fe 100644 --- a/dev/tests/functional/tests/app/Magento/Swatches/Test/Handler/SwatchProductAttribute/Curl.php +++ b/dev/tests/functional/tests/app/Magento/Swatches/Test/Handler/SwatchProductAttribute/Curl.php @@ -38,12 +38,14 @@ public function __construct(DataInterface $configuration, EventManagerInterface */ protected function changeStructureOfTheData(array $data) { - $data = parent::changeStructureOfTheData($data); $data['optiontext'] = $data['option']; $data['swatchtext'] = [ 'value' => $data['option']['value'] ]; + $data['serialized_options'] = $this->getSerializeOptions($data, ['optiontext', 'swatchtext']); unset($data['option']); + $data = parent::changeStructureOfTheData($data); + return $data; } } From ee0b4526d0afd75342279ec631b2703e09745f2b Mon Sep 17 00:00:00 2001 From: Cristian Partica <cpartica@magento.com> Date: Mon, 17 Sep 2018 11:50:49 -0500 Subject: [PATCH 23/44] MAGETWO-60034: Cannot ship remaining items in an order for several of one product if credit memo is made for some - fix functional tests --- app/code/Magento/Sales/Model/Order.php | 865 +++++++++++++++++-------- 1 file changed, 590 insertions(+), 275 deletions(-) diff --git a/app/code/Magento/Sales/Model/Order.php b/app/code/Magento/Sales/Model/Order.php index 89557be3499..47979591a58 100644 --- a/app/code/Magento/Sales/Model/Order.php +++ b/app/code/Magento/Sales/Model/Order.php @@ -570,6 +570,7 @@ public function canCancel() /** * Getter whether the payment can be voided + * * @return bool */ public function canVoidPayment() @@ -886,7 +887,7 @@ protected function _placePayment() } /** - * {@inheritdoc} + * @inheritdoc */ public function getPayment() { @@ -1013,8 +1014,9 @@ public function addStatusToHistory($status, $comment = '', $isCustomerNotified = } /** - * Add a comment to order - * Different or default status may be specified + * Add a comment to order. + * + * Different or default status may be specified. * * @param string $comment * @param bool|string $status @@ -1028,8 +1030,9 @@ public function addStatusHistoryComment($comment, $status = false) } /** - * Add a comment to order status history - * Different or default status may be specified + * Add a comment to order status history. + * + * Different or default status may be specified. * * @param string $comment * @param bool|string $status @@ -1094,6 +1097,8 @@ public function place() } /** + * Hold + * * @return $this * @throws \Magento\Framework\Exception\LocalizedException */ @@ -1239,6 +1244,8 @@ public function getShippingMethod($asObject = false) /*********************** ADDRESSES ***************************/ /** + * Get addresses collection + * * @return Collection */ public function getAddressesCollection() @@ -1253,6 +1260,8 @@ public function getAddressesCollection() } /** + * Get address by id + * * @param mixed $addressId * @return false */ @@ -1267,6 +1276,8 @@ public function getAddressById($addressId) } /** + * Add address + * * @param \Magento\Sales\Model\Order\Address $address * @return $this */ @@ -1281,6 +1292,8 @@ public function addAddress(\Magento\Sales\Model\Order\Address $address) } /** + * Get items collection + * * @param array $filterByTypes * @param bool $nonChildrenOnly * @return ImportCollection @@ -1353,6 +1366,8 @@ protected function _getItemsRandomCollection($limit, $nonChildrenOnly = false) } /** + * Get all items + * * @return \Magento\Sales\Model\Order\Item[] */ public function getAllItems() @@ -1367,6 +1382,8 @@ public function getAllItems() } /** + * Get all visible items + * * @return array */ public function getAllVisibleItems() @@ -1398,6 +1415,8 @@ public function getItemById($itemId) } /** + * Get item by quote item id + * * @param mixed $quoteItemId * @return \Magento\Framework\DataObject|null */ @@ -1412,6 +1431,8 @@ public function getItemByQuoteItemId($quoteItemId) } /** + * Add item + * * @param \Magento\Sales\Model\Order\Item $item * @return $this */ @@ -1427,6 +1448,8 @@ public function addItem(\Magento\Sales\Model\Order\Item $item) /*********************** PAYMENTS ***************************/ /** + * Get payments collection + * * @return PaymentCollection */ public function getPaymentsCollection() @@ -1441,6 +1464,8 @@ public function getPaymentsCollection() } /** + * Get all payments + * * @return array */ public function getAllPayments() @@ -1455,6 +1480,8 @@ public function getAllPayments() } /** + * Get payment by id + * * @param mixed $paymentId * @return Payment|false */ @@ -1469,7 +1496,9 @@ public function getPaymentById($paymentId) } /** - * {@inheritdoc} + * Set payment + * + * @return \Magento\Sales\Api\Data\OrderPaymentInterface|null */ public function setPayment(\Magento\Sales\Api\Data\OrderPaymentInterface $payment = null) { @@ -1536,6 +1565,8 @@ public function getVisibleStatusHistory() } /** + * GetStatus history by id + * * @param mixed $statusId * @return string|false */ @@ -1550,7 +1581,8 @@ public function getStatusHistoryById($statusId) } /** - * Set the order status history object and the order object to each other + * Set the order status history object and the order object to each other. + * * Adds the object to the status history collection, which is automatically saved when the order is saved. * See the entity_id attribute backend model. * Or the history record can be saved standalone after this. @@ -1570,6 +1602,8 @@ public function addStatusHistory(\Magento\Sales\Model\Order\Status\History $hist } /** + * Get real real_order_id + * * @return string */ public function getRealOrderId() @@ -1608,6 +1642,8 @@ public function formatPrice($price, $addBrackets = false) } /** + * Format price precision + * * @param float $price * @param int $precision * @param bool $addBrackets @@ -1643,6 +1679,8 @@ public function getBaseCurrency() } /** + * Format BasePrice + * * @param float $price * @return string */ @@ -1652,6 +1690,8 @@ public function formatBasePrice($price) } /** + * Format BasePrice Precision + * * @param float $price * @param int $precision * @return string @@ -1662,6 +1702,8 @@ public function formatBasePricePrecision($price, $precision) } /** + * Is currency different + * * @return bool */ public function isCurrencyDifferent() @@ -1694,6 +1736,8 @@ public function getBaseTotalDue() } /** + * Get data + * * @param string $key * @param null|string|int $index * @return mixed @@ -1861,8 +1905,8 @@ public function addRelatedObject(\Magento\Framework\Model\AbstractModel $object) /** * Get formatted order created date in store timezone * - * @param string $format date format type (short|medium|long|full) - * @return string + * @param string $format date format type (short|medium|long|full) + * @return string */ public function getCreatedAtFormatted($format) { @@ -1876,6 +1920,8 @@ public function getCreatedAtFormatted($format) } /** + * Get email customer note + * * @return string */ public function getEmailCustomerNote() @@ -1887,6 +1933,8 @@ public function getEmailCustomerNote() } /** + * Get store group name + * * @return string */ public function getStoreGroupName() @@ -1899,8 +1947,7 @@ public function getStoreGroupName() } /** - * Resets all data in object - * so after another load it will be complete new object + * Reset all data in object so after another load it will be complete new object. * * @return $this */ @@ -1924,6 +1971,8 @@ public function reset() } /** + * Get IsNotVirtual + * * @return bool * @SuppressWarnings(PHPMD.BooleanGetMethodName) */ @@ -1954,7 +2003,7 @@ public function isCanceled() } /** - * Returns increment id + * Return increment id * * @codeCoverageIgnore * @@ -1966,6 +2015,8 @@ public function getIncrementId() } /** + * Get Items + * * @return \Magento\Sales\Api\Data\OrderItemInterface[] */ public function getItems() @@ -1980,7 +2031,9 @@ public function getItems() } /** - * {@inheritdoc} + * Set Items + * + * @return $this * @codeCoverageIgnore */ public function setItems($items) @@ -1989,6 +2042,8 @@ public function setItems($items) } /** + * Get addresses + * * @return \Magento\Sales\Api\Data\OrderAddressInterface[] */ public function getAddresses() @@ -2003,6 +2058,8 @@ public function getAddresses() } /** + * Get status History + * * @return \Magento\Sales\Api\Data\OrderStatusHistoryInterface[]|null */ public function getStatusHistories() @@ -2017,7 +2074,7 @@ public function getStatusHistories() } /** - * {@inheritdoc} + * Get ExtensionAttributes * * @return \Magento\Sales\Api\Data\OrderExtensionInterface|null */ @@ -2027,7 +2084,7 @@ public function getExtensionAttributes() } /** - * {@inheritdoc} + * Set ExtensionAttributes * * @param \Magento\Sales\Api\Data\OrderExtensionInterface $extensionAttributes * @return $this @@ -2040,7 +2097,7 @@ public function setExtensionAttributes(\Magento\Sales\Api\Data\OrderExtensionInt //@codeCoverageIgnoreStart /** - * Returns adjustment_negative + * Return adjustment_negative * * @return float|null */ @@ -2050,7 +2107,7 @@ public function getAdjustmentNegative() } /** - * Returns adjustment_positive + * Return adjustment_positive * * @return float|null */ @@ -2060,7 +2117,7 @@ public function getAdjustmentPositive() } /** - * Returns applied_rule_ids + * Return applied_rule_ids * * @return string|null */ @@ -2070,7 +2127,7 @@ public function getAppliedRuleIds() } /** - * Returns base_adjustment_negative + * Return base_adjustment_negative * * @return float|null */ @@ -2080,7 +2137,7 @@ public function getBaseAdjustmentNegative() } /** - * Returns base_adjustment_positive + * Return base_adjustment_positive * * @return float|null */ @@ -2090,7 +2147,7 @@ public function getBaseAdjustmentPositive() } /** - * Returns base_currency_code + * Return base_currency_code * * @return string|null */ @@ -2100,7 +2157,7 @@ public function getBaseCurrencyCode() } /** - * Returns base_discount_amount + * Return base_discount_amount * * @return float|null */ @@ -2110,7 +2167,7 @@ public function getBaseDiscountAmount() } /** - * Returns base_discount_canceled + * Return base_discount_canceled * * @return float|null */ @@ -2120,7 +2177,7 @@ public function getBaseDiscountCanceled() } /** - * Returns base_discount_invoiced + * Return base_discount_invoiced * * @return float|null */ @@ -2130,7 +2187,7 @@ public function getBaseDiscountInvoiced() } /** - * Returns base_discount_refunded + * Return base_discount_refunded * * @return float|null */ @@ -2140,7 +2197,7 @@ public function getBaseDiscountRefunded() } /** - * Returns base_grand_total + * Return base_grand_total * * @return float */ @@ -2150,7 +2207,7 @@ public function getBaseGrandTotal() } /** - * Returns base_discount_tax_compensation_amount + * Return base_discount_tax_compensation_amount * * @return float|null */ @@ -2160,7 +2217,7 @@ public function getBaseDiscountTaxCompensationAmount() } /** - * Returns base_discount_tax_compensation_invoiced + * Return base_discount_tax_compensation_invoiced * * @return float|null */ @@ -2170,7 +2227,7 @@ public function getBaseDiscountTaxCompensationInvoiced() } /** - * Returns base_discount_tax_compensation_refunded + * Return base_discount_tax_compensation_refunded * * @return float|null */ @@ -2180,7 +2237,7 @@ public function getBaseDiscountTaxCompensationRefunded() } /** - * Returns base_shipping_amount + * Return base_shipping_amount * * @return float|null */ @@ -2190,7 +2247,7 @@ public function getBaseShippingAmount() } /** - * Returns base_shipping_canceled + * Return base_shipping_canceled * * @return float|null */ @@ -2200,7 +2257,7 @@ public function getBaseShippingCanceled() } /** - * Returns base_shipping_discount_amount + * Return base_shipping_discount_amount * * @return float|null */ @@ -2210,7 +2267,7 @@ public function getBaseShippingDiscountAmount() } /** - * Returns base_shipping_discount_tax_compensation_amnt + * Return base_shipping_discount_tax_compensation_amnt * * @return float|null */ @@ -2220,7 +2277,7 @@ public function getBaseShippingDiscountTaxCompensationAmnt() } /** - * Returns base_shipping_incl_tax + * Return base_shipping_incl_tax * * @return float|null */ @@ -2230,8 +2287,8 @@ public function getBaseShippingInclTax() } /** - * Returns base_shipping_invoiced - * + * Return base_shipping_invoiced + * @return float|null */ public function getBaseShippingInvoiced() @@ -2240,7 +2297,7 @@ public function getBaseShippingInvoiced() } /** - * Returns base_shipping_refunded + * Return base_shipping_refunded * * @return float|null */ @@ -2250,7 +2307,7 @@ public function getBaseShippingRefunded() } /** - * Returns base_shipping_tax_amount + * Return base_shipping_tax_amount * * @return float|null */ @@ -2260,7 +2317,7 @@ public function getBaseShippingTaxAmount() } /** - * Returns base_shipping_tax_refunded + * Return base_shipping_tax_refunded * * @return float|null */ @@ -2270,7 +2327,7 @@ public function getBaseShippingTaxRefunded() } /** - * Returns base_subtotal + * Return base_subtotal * * @return float|null */ @@ -2280,7 +2337,7 @@ public function getBaseSubtotal() } /** - * Returns base_subtotal_canceled + * Return base_subtotal_canceled * * @return float|null */ @@ -2290,7 +2347,7 @@ public function getBaseSubtotalCanceled() } /** - * Returns base_subtotal_incl_tax + * Return base_subtotal_incl_tax * * @return float|null */ @@ -2300,7 +2357,7 @@ public function getBaseSubtotalInclTax() } /** - * Returns base_subtotal_invoiced + * Return base_subtotal_invoiced * * @return float|null */ @@ -2310,7 +2367,7 @@ public function getBaseSubtotalInvoiced() } /** - * Returns base_subtotal_refunded + * Return base_subtotal_refunded * * @return float|null */ @@ -2320,7 +2377,7 @@ public function getBaseSubtotalRefunded() } /** - * Returns base_tax_amount + * Return base_tax_amount * * @return float|null */ @@ -2330,7 +2387,7 @@ public function getBaseTaxAmount() } /** - * Returns base_tax_canceled + * Return base_tax_canceled * * @return float|null */ @@ -2340,7 +2397,7 @@ public function getBaseTaxCanceled() } /** - * Returns base_tax_invoiced + * Return base_tax_invoiced * * @return float|null */ @@ -2350,7 +2407,7 @@ public function getBaseTaxInvoiced() } /** - * Returns base_tax_refunded + * Return base_tax_refunded * * @return float|null */ @@ -2360,7 +2417,7 @@ public function getBaseTaxRefunded() } /** - * Returns base_total_canceled + * Return base_total_canceled * * @return float|null */ @@ -2370,7 +2427,7 @@ public function getBaseTotalCanceled() } /** - * Returns base_total_invoiced + * Return base_total_invoiced * * @return float|null */ @@ -2380,7 +2437,7 @@ public function getBaseTotalInvoiced() } /** - * Returns base_total_invoiced_cost + * Return base_total_invoiced_cost * * @return float|null */ @@ -2390,7 +2447,7 @@ public function getBaseTotalInvoicedCost() } /** - * Returns base_total_offline_refunded + * Return base_total_offline_refunded * * @return float|null */ @@ -2400,7 +2457,7 @@ public function getBaseTotalOfflineRefunded() } /** - * Returns base_total_online_refunded + * Return base_total_online_refunded * * @return float|null */ @@ -2410,7 +2467,7 @@ public function getBaseTotalOnlineRefunded() } /** - * Returns base_total_paid + * Return base_total_paid * * @return float|null */ @@ -2420,7 +2477,7 @@ public function getBaseTotalPaid() } /** - * Returns base_total_qty_ordered + * Return base_total_qty_ordered * * @return float|null */ @@ -2430,7 +2487,7 @@ public function getBaseTotalQtyOrdered() } /** - * Returns base_total_refunded + * Return base_total_refunded * * @return float|null */ @@ -2440,7 +2497,7 @@ public function getBaseTotalRefunded() } /** - * Returns base_to_global_rate + * Return base_to_global_rate * * @return float|null */ @@ -2450,7 +2507,7 @@ public function getBaseToGlobalRate() } /** - * Returns base_to_order_rate + * Return base_to_order_rate * * @return float|null */ @@ -2460,7 +2517,7 @@ public function getBaseToOrderRate() } /** - * Returns billing_address_id + * Return billing_address_id * * @return int|null */ @@ -2470,7 +2527,7 @@ public function getBillingAddressId() } /** - * Returns can_ship_partially + * Return can_ship_partially * * @return int|null */ @@ -2480,7 +2537,7 @@ public function getCanShipPartially() } /** - * Returns can_ship_partially_item + * Return can_ship_partially_item * * @return int|null */ @@ -2490,7 +2547,7 @@ public function getCanShipPartiallyItem() } /** - * Returns coupon_code + * Return coupon_code * * @return string|null */ @@ -2500,7 +2557,7 @@ public function getCouponCode() } /** - * Returns created_at + * Return created_at * * @return string|null */ @@ -2510,7 +2567,7 @@ public function getCreatedAt() } /** - * {@inheritdoc} + * @inheritdoc */ public function setCreatedAt($createdAt) { @@ -2518,7 +2575,7 @@ public function setCreatedAt($createdAt) } /** - * Returns customer_dob + * Return customer_dob * * @return string|null */ @@ -2528,7 +2585,7 @@ public function getCustomerDob() } /** - * Returns customer_email + * Return customer_email * * @return string */ @@ -2538,7 +2595,7 @@ public function getCustomerEmail() } /** - * Returns customer_firstname + * Return customer_firstname * * @return string|null */ @@ -2548,7 +2605,7 @@ public function getCustomerFirstname() } /** - * Returns customer_gender + * Return customer_gender * * @return int|null */ @@ -2558,7 +2615,7 @@ public function getCustomerGender() } /** - * Returns customer_group_id + * Return customer_group_id * * @return int|null */ @@ -2568,7 +2625,7 @@ public function getCustomerGroupId() } /** - * Returns customer_id + * Return customer_id * * @return int|null */ @@ -2578,7 +2635,7 @@ public function getCustomerId() } /** - * Returns customer_is_guest + * Return customer_is_guest * * @return int|null */ @@ -2588,7 +2645,7 @@ public function getCustomerIsGuest() } /** - * Returns customer_lastname + * Return customer_lastname * * @return string|null */ @@ -2598,7 +2655,7 @@ public function getCustomerLastname() } /** - * Returns customer_middlename + * Return customer_middlename * * @return string|null */ @@ -2608,7 +2665,7 @@ public function getCustomerMiddlename() } /** - * Returns customer_note + * Return customer_note * * @return string|null */ @@ -2618,7 +2675,7 @@ public function getCustomerNote() } /** - * Returns customer_note_notify + * Return customer_note_notify * * @return int|null */ @@ -2628,7 +2685,7 @@ public function getCustomerNoteNotify() } /** - * Returns customer_prefix + * Return customer_prefix * * @return string|null */ @@ -2638,7 +2695,7 @@ public function getCustomerPrefix() } /** - * Returns customer_suffix + * Return customer_suffix * * @return string|null */ @@ -2648,7 +2705,7 @@ public function getCustomerSuffix() } /** - * Returns customer_taxvat + * Return customer_taxvat * * @return string|null */ @@ -2658,7 +2715,7 @@ public function getCustomerTaxvat() } /** - * Returns discount_amount + * Return discount_amount * * @return float|null */ @@ -2668,7 +2725,7 @@ public function getDiscountAmount() } /** - * Returns discount_canceled + * Return discount_canceled * * @return float|null */ @@ -2678,7 +2735,7 @@ public function getDiscountCanceled() } /** - * Returns discount_description + * Return discount_description * * @return string|null */ @@ -2688,7 +2745,7 @@ public function getDiscountDescription() } /** - * Returns discount_invoiced + * Return discount_invoiced * * @return float|null */ @@ -2698,7 +2755,7 @@ public function getDiscountInvoiced() } /** - * Returns discount_refunded + * Return discount_refunded * * @return float|null */ @@ -2708,7 +2765,7 @@ public function getDiscountRefunded() } /** - * Returns edit_increment + * Return edit_increment * * @return int|null */ @@ -2718,7 +2775,7 @@ public function getEditIncrement() } /** - * Returns email_sent + * Return email_sent * * @return int|null */ @@ -2728,7 +2785,7 @@ public function getEmailSent() } /** - * Returns ext_customer_id + * Return ext_customer_id * * @return string|null */ @@ -2738,7 +2795,7 @@ public function getExtCustomerId() } /** - * Returns ext_order_id + * Return ext_order_id * * @return string|null */ @@ -2748,7 +2805,7 @@ public function getExtOrderId() } /** - * Returns forced_shipment_with_invoice + * Return forced_shipment_with_invoice * * @return int|null */ @@ -2758,7 +2815,7 @@ public function getForcedShipmentWithInvoice() } /** - * Returns global_currency_code + * Return global_currency_code * * @return string|null */ @@ -2768,7 +2825,7 @@ public function getGlobalCurrencyCode() } /** - * Returns grand_total + * Return grand_total * * @return float */ @@ -2778,7 +2835,7 @@ public function getGrandTotal() } /** - * Returns discount_tax_compensation_amount + * Return discount_tax_compensation_amount * * @return float|null */ @@ -2788,7 +2845,7 @@ public function getDiscountTaxCompensationAmount() } /** - * Returns discount_tax_compensation_invoiced + * Return discount_tax_compensation_invoiced * * @return float|null */ @@ -2798,7 +2855,7 @@ public function getDiscountTaxCompensationInvoiced() } /** - * Returns discount_tax_compensation_refunded + * Return discount_tax_compensation_refunded * * @return float|null */ @@ -2808,7 +2865,7 @@ public function getDiscountTaxCompensationRefunded() } /** - * Returns hold_before_state + * Return hold_before_state * * @return string|null */ @@ -2818,7 +2875,7 @@ public function getHoldBeforeState() } /** - * Returns hold_before_status + * Return hold_before_status * * @return string|null */ @@ -2828,7 +2885,7 @@ public function getHoldBeforeStatus() } /** - * Returns is_virtual + * Return is_virtual * * @return int|null */ @@ -2838,7 +2895,7 @@ public function getIsVirtual() } /** - * Returns order_currency_code + * Return order_currency_code * * @return string|null */ @@ -2848,7 +2905,7 @@ public function getOrderCurrencyCode() } /** - * Returns original_increment_id + * Return original_increment_id * * @return string|null */ @@ -2858,7 +2915,7 @@ public function getOriginalIncrementId() } /** - * Returns payment_authorization_amount + * Return payment_authorization_amount * * @return float|null */ @@ -2868,7 +2925,7 @@ public function getPaymentAuthorizationAmount() } /** - * Returns payment_auth_expiration + * Return payment_auth_expiration * * @return int|null */ @@ -2878,7 +2935,7 @@ public function getPaymentAuthExpiration() } /** - * Returns protect_code + * Return protect_code * * @return string|null */ @@ -2888,7 +2945,7 @@ public function getProtectCode() } /** - * Returns quote_address_id + * Return quote_address_id * * @return int|null */ @@ -2898,7 +2955,7 @@ public function getQuoteAddressId() } /** - * Returns quote_id + * Return quote_id * * @return int|null */ @@ -2908,7 +2965,7 @@ public function getQuoteId() } /** - * Returns relation_child_id + * Return relation_child_id * * @return string|null */ @@ -2918,7 +2975,7 @@ public function getRelationChildId() } /** - * Returns relation_child_real_id + * Return relation_child_real_id * * @return string|null */ @@ -2928,7 +2985,7 @@ public function getRelationChildRealId() } /** - * Returns relation_parent_id + * Return relation_parent_id * * @return string|null */ @@ -2938,7 +2995,7 @@ public function getRelationParentId() } /** - * Returns relation_parent_real_id + * Return relation_parent_real_id * * @return string|null */ @@ -2948,7 +3005,7 @@ public function getRelationParentRealId() } /** - * Returns remote_ip + * Return remote_ip * * @return string|null */ @@ -2958,7 +3015,7 @@ public function getRemoteIp() } /** - * Returns shipping_amount + * Return shipping_amount * * @return float|null */ @@ -2968,7 +3025,7 @@ public function getShippingAmount() } /** - * Returns shipping_canceled + * Return shipping_canceled * * @return float|null */ @@ -2978,7 +3035,7 @@ public function getShippingCanceled() } /** - * Returns shipping_description + * Return shipping_description * * @return string|null */ @@ -2988,7 +3045,7 @@ public function getShippingDescription() } /** - * Returns shipping_discount_amount + * Return shipping_discount_amount * * @return float|null */ @@ -2998,7 +3055,7 @@ public function getShippingDiscountAmount() } /** - * Returns shipping_discount_tax_compensation_amount + * Return shipping_discount_tax_compensation_amount * * @return float|null */ @@ -3008,7 +3065,7 @@ public function getShippingDiscountTaxCompensationAmount() } /** - * Returns shipping_incl_tax + * Return shipping_incl_tax * * @return float|null */ @@ -3018,7 +3075,7 @@ public function getShippingInclTax() } /** - * Returns shipping_invoiced + * Return shipping_invoiced * * @return float|null */ @@ -3028,7 +3085,7 @@ public function getShippingInvoiced() } /** - * Returns shipping_refunded + * Return shipping_refunded * * @return float|null */ @@ -3038,7 +3095,7 @@ public function getShippingRefunded() } /** - * Returns shipping_tax_amount + * Return shipping_tax_amount * * @return float|null */ @@ -3048,7 +3105,7 @@ public function getShippingTaxAmount() } /** - * Returns shipping_tax_refunded + * Return shipping_tax_refunded * * @return float|null */ @@ -3058,7 +3115,7 @@ public function getShippingTaxRefunded() } /** - * Returns state + * Return state * * @return string|null */ @@ -3068,7 +3125,7 @@ public function getState() } /** - * Returns status + * Return status * * @return string|null */ @@ -3078,7 +3135,7 @@ public function getStatus() } /** - * Returns store_currency_code + * Return store_currency_code * * @return string|null */ @@ -3088,7 +3145,7 @@ public function getStoreCurrencyCode() } /** - * Returns store_id + * Return store_id * * @return int|null */ @@ -3098,7 +3155,7 @@ public function getStoreId() } /** - * Returns store_name + * Return store_name * * @return string|null */ @@ -3108,7 +3165,7 @@ public function getStoreName() } /** - * Returns store_to_base_rate + * Return store_to_base_rate * * @return float|null */ @@ -3118,7 +3175,7 @@ public function getStoreToBaseRate() } /** - * Returns store_to_order_rate + * Return store_to_order_rate * * @return float|null */ @@ -3128,7 +3185,7 @@ public function getStoreToOrderRate() } /** - * Returns subtotal + * Return subtotal * * @return float|null */ @@ -3138,7 +3195,7 @@ public function getSubtotal() } /** - * Returns subtotal_canceled + * Return subtotal_canceled * * @return float|null */ @@ -3148,7 +3205,7 @@ public function getSubtotalCanceled() } /** - * Returns subtotal_incl_tax + * Return subtotal_incl_tax * * @return float|null */ @@ -3158,7 +3215,7 @@ public function getSubtotalInclTax() } /** - * Returns subtotal_invoiced + * Return subtotal_invoiced * * @return float|null */ @@ -3168,7 +3225,7 @@ public function getSubtotalInvoiced() } /** - * Returns subtotal_refunded + * Return subtotal_refunded * * @return float|null */ @@ -3178,7 +3235,7 @@ public function getSubtotalRefunded() } /** - * Returns tax_amount + * Return tax_amount * * @return float|null */ @@ -3188,7 +3245,7 @@ public function getTaxAmount() } /** - * Returns tax_canceled + * Return tax_canceled * * @return float|null */ @@ -3198,7 +3255,7 @@ public function getTaxCanceled() } /** - * Returns tax_invoiced + * Return tax_invoiced * * @return float|null */ @@ -3208,7 +3265,7 @@ public function getTaxInvoiced() } /** - * Returns tax_refunded + * Return tax_refunded * * @return float|null */ @@ -3218,7 +3275,7 @@ public function getTaxRefunded() } /** - * Returns total_canceled + * Return total_canceled * * @return float|null */ @@ -3228,7 +3285,7 @@ public function getTotalCanceled() } /** - * Returns total_invoiced + * Return total_invoiced * * @return float|null */ @@ -3238,7 +3295,7 @@ public function getTotalInvoiced() } /** - * Returns total_item_count + * Return total_item_count * * @return int|null */ @@ -3248,7 +3305,7 @@ public function getTotalItemCount() } /** - * Returns total_offline_refunded + * Return total_offline_refunded * * @return float|null */ @@ -3258,7 +3315,7 @@ public function getTotalOfflineRefunded() } /** - * Returns total_online_refunded + * Return total_online_refunded * * @return float|null */ @@ -3268,7 +3325,7 @@ public function getTotalOnlineRefunded() } /** - * Returns total_paid + * Return total_paid * * @return float|null */ @@ -3278,7 +3335,7 @@ public function getTotalPaid() } /** - * Returns total_qty_ordered + * Return total_qty_ordered * * @return float|null */ @@ -3288,7 +3345,7 @@ public function getTotalQtyOrdered() } /** - * Returns total_refunded + * Return total_refunded * * @return float|null */ @@ -3298,7 +3355,7 @@ public function getTotalRefunded() } /** - * Returns updated_at + * Return updated_at * * @return string|null */ @@ -3308,7 +3365,7 @@ public function getUpdatedAt() } /** - * Returns weight + * Return weight * * @return float|null */ @@ -3318,7 +3375,7 @@ public function getWeight() } /** - * Returns x_forwarded_for + * Return x_forwarded_for * * @return string|null */ @@ -3328,7 +3385,9 @@ public function getXForwardedFor() } /** - * {@inheritdoc} + * Set StatusHistories + * + * @return $this */ public function setStatusHistories(array $statusHistories = null) { @@ -3336,7 +3395,9 @@ public function setStatusHistories(array $statusHistories = null) } /** - * {@inheritdoc} + * Set Status + * + * @return $this */ public function setStatus($status) { @@ -3344,7 +3405,9 @@ public function setStatus($status) } /** - * {@inheritdoc} + * Set CouponCode + * + * @return $this */ public function setCouponCode($code) { @@ -3352,7 +3415,9 @@ public function setCouponCode($code) } /** - * {@inheritdoc} + * Set ProtectCode + * + * @return $this */ public function setProtectCode($code) { @@ -3360,7 +3425,9 @@ public function setProtectCode($code) } /** - * {@inheritdoc} + * Set ShippingDescription + * + * @return $this */ public function setShippingDescription($description) { @@ -3368,7 +3435,9 @@ public function setShippingDescription($description) } /** - * {@inheritdoc} + * Set IsVirtual + * + * @return $this */ public function setIsVirtual($isVirtual) { @@ -3376,7 +3445,9 @@ public function setIsVirtual($isVirtual) } /** - * {@inheritdoc} + * Set StoreId + * + * @return $this */ public function setStoreId($id) { @@ -3384,7 +3455,9 @@ public function setStoreId($id) } /** - * {@inheritdoc} + * Set CustomerId + * + * @return $this */ public function setCustomerId($id) { @@ -3392,7 +3465,9 @@ public function setCustomerId($id) } /** - * {@inheritdoc} + * Set BaseDiscountAmount + * + * @return $this */ public function setBaseDiscountAmount($amount) { @@ -3400,7 +3475,9 @@ public function setBaseDiscountAmount($amount) } /** - * {@inheritdoc} + * Set BaseDiscountCanceled + * + * @return $this */ public function setBaseDiscountCanceled($baseDiscountCanceled) { @@ -3408,7 +3485,9 @@ public function setBaseDiscountCanceled($baseDiscountCanceled) } /** - * {@inheritdoc} + * Set BaseDiscountInvoiced + * + * @return $this */ public function setBaseDiscountInvoiced($baseDiscountInvoiced) { @@ -3416,7 +3495,9 @@ public function setBaseDiscountInvoiced($baseDiscountInvoiced) } /** - * {@inheritdoc} + * Set BaseDiscountRefunded + * + * @return $this */ public function setBaseDiscountRefunded($baseDiscountRefunded) { @@ -3424,7 +3505,9 @@ public function setBaseDiscountRefunded($baseDiscountRefunded) } /** - * {@inheritdoc} + * Set BaseGrandTotal + * + * @return $this */ public function setBaseGrandTotal($amount) { @@ -3432,7 +3515,9 @@ public function setBaseGrandTotal($amount) } /** - * {@inheritdoc} + * Set BaseShippingAmount + * + * @return $this */ public function setBaseShippingAmount($amount) { @@ -3440,7 +3525,9 @@ public function setBaseShippingAmount($amount) } /** - * {@inheritdoc} + * Set BaseShippingCanceled + * + * @return $this */ public function setBaseShippingCanceled($baseShippingCanceled) { @@ -3448,7 +3535,9 @@ public function setBaseShippingCanceled($baseShippingCanceled) } /** - * {@inheritdoc} + * Set BaseShippingInvoiced + * + * @return $this */ public function setBaseShippingInvoiced($baseShippingInvoiced) { @@ -3456,7 +3545,9 @@ public function setBaseShippingInvoiced($baseShippingInvoiced) } /** - * {@inheritdoc} + * Set BaseShippingRefunded + * + * @return $this */ public function setBaseShippingRefunded($baseShippingRefunded) { @@ -3464,7 +3555,9 @@ public function setBaseShippingRefunded($baseShippingRefunded) } /** - * {@inheritdoc} + * Set BaseShippingTaxAmount + * + * @return $this */ public function setBaseShippingTaxAmount($amount) { @@ -3472,7 +3565,9 @@ public function setBaseShippingTaxAmount($amount) } /** - * {@inheritdoc} + * Set BaseShippingTaxRefunded + * + * @return $this */ public function setBaseShippingTaxRefunded($baseShippingTaxRefunded) { @@ -3480,7 +3575,9 @@ public function setBaseShippingTaxRefunded($baseShippingTaxRefunded) } /** - * {@inheritdoc} + * Set BaseSubtotal + * + * @return $this */ public function setBaseSubtotal($amount) { @@ -3488,7 +3585,9 @@ public function setBaseSubtotal($amount) } /** - * {@inheritdoc} + * Set BaseSubtotalCanceled + * + * @return $this */ public function setBaseSubtotalCanceled($baseSubtotalCanceled) { @@ -3496,7 +3595,9 @@ public function setBaseSubtotalCanceled($baseSubtotalCanceled) } /** - * {@inheritdoc} + * Set BaseSubtotalInvoiced + * + * @return $this */ public function setBaseSubtotalInvoiced($baseSubtotalInvoiced) { @@ -3504,7 +3605,9 @@ public function setBaseSubtotalInvoiced($baseSubtotalInvoiced) } /** - * {@inheritdoc} + * Set BaseSubtotalRefunded + * + * @return $this */ public function setBaseSubtotalRefunded($baseSubtotalRefunded) { @@ -3512,7 +3615,9 @@ public function setBaseSubtotalRefunded($baseSubtotalRefunded) } /** - * {@inheritdoc} + * Set BaseTaxAmount + * + * @return $this */ public function setBaseTaxAmount($amount) { @@ -3520,7 +3625,9 @@ public function setBaseTaxAmount($amount) } /** - * {@inheritdoc} + * Set BaseTaxCanceled + * + * @return $this */ public function setBaseTaxCanceled($baseTaxCanceled) { @@ -3528,7 +3635,9 @@ public function setBaseTaxCanceled($baseTaxCanceled) } /** - * {@inheritdoc} + * Set BaseTaxInvoiced + * + * @return $this */ public function setBaseTaxInvoiced($baseTaxInvoiced) { @@ -3536,7 +3645,9 @@ public function setBaseTaxInvoiced($baseTaxInvoiced) } /** - * {@inheritdoc} + * Set BaseTaxRefunded + * + * @return $this */ public function setBaseTaxRefunded($baseTaxRefunded) { @@ -3544,7 +3655,9 @@ public function setBaseTaxRefunded($baseTaxRefunded) } /** - * {@inheritdoc} + * Set BaseToGlobalRate + * + * @return $this */ public function setBaseToGlobalRate($rate) { @@ -3552,7 +3665,9 @@ public function setBaseToGlobalRate($rate) } /** - * {@inheritdoc} + * Set BaseToOrderRate + * + * @return $this */ public function setBaseToOrderRate($rate) { @@ -3560,7 +3675,9 @@ public function setBaseToOrderRate($rate) } /** - * {@inheritdoc} + * Set BaseTotalCanceled + * + * @return $this */ public function setBaseTotalCanceled($baseTotalCanceled) { @@ -3568,7 +3685,9 @@ public function setBaseTotalCanceled($baseTotalCanceled) } /** - * {@inheritdoc} + * Set BaseTotalInvoiced + * + * @return $this */ public function setBaseTotalInvoiced($baseTotalInvoiced) { @@ -3576,7 +3695,9 @@ public function setBaseTotalInvoiced($baseTotalInvoiced) } /** - * {@inheritdoc} + * Set BaseTotalInvoicedCost + * + * @return $this */ public function setBaseTotalInvoicedCost($baseTotalInvoicedCost) { @@ -3584,7 +3705,9 @@ public function setBaseTotalInvoicedCost($baseTotalInvoicedCost) } /** - * {@inheritdoc} + * Set BaseTotalOfflineRefunded + * + * @return $this */ public function setBaseTotalOfflineRefunded($baseTotalOfflineRefunded) { @@ -3592,7 +3715,9 @@ public function setBaseTotalOfflineRefunded($baseTotalOfflineRefunded) } /** - * {@inheritdoc} + * Set BaseTotalOnlineRefunded + * + * @return $this */ public function setBaseTotalOnlineRefunded($baseTotalOnlineRefunded) { @@ -3600,7 +3725,9 @@ public function setBaseTotalOnlineRefunded($baseTotalOnlineRefunded) } /** - * {@inheritdoc} + * Set BaseTotalPaid + * + * @return $this */ public function setBaseTotalPaid($baseTotalPaid) { @@ -3608,7 +3735,9 @@ public function setBaseTotalPaid($baseTotalPaid) } /** - * {@inheritdoc} + * Set BaseTotalQtyOrdered + * + * @return $this */ public function setBaseTotalQtyOrdered($baseTotalQtyOrdered) { @@ -3616,7 +3745,9 @@ public function setBaseTotalQtyOrdered($baseTotalQtyOrdered) } /** - * {@inheritdoc} + * Set BaseTotalRefunded + * + * @return $this */ public function setBaseTotalRefunded($baseTotalRefunded) { @@ -3624,7 +3755,9 @@ public function setBaseTotalRefunded($baseTotalRefunded) } /** - * {@inheritdoc} + * Set DiscountAmount + * + * @return $this */ public function setDiscountAmount($amount) { @@ -3632,7 +3765,9 @@ public function setDiscountAmount($amount) } /** - * {@inheritdoc} + * Set DiscountCanceled + * + * @return $this */ public function setDiscountCanceled($discountCanceled) { @@ -3640,7 +3775,9 @@ public function setDiscountCanceled($discountCanceled) } /** - * {@inheritdoc} + * Set DiscountInvoiced + * + * @return $this */ public function setDiscountInvoiced($discountInvoiced) { @@ -3648,7 +3785,9 @@ public function setDiscountInvoiced($discountInvoiced) } /** - * {@inheritdoc} + * Set DiscountRefunded + * + * @return $this */ public function setDiscountRefunded($discountRefunded) { @@ -3656,7 +3795,9 @@ public function setDiscountRefunded($discountRefunded) } /** - * {@inheritdoc} + * Set GrandTotal + * + * @return $this */ public function setGrandTotal($amount) { @@ -3664,7 +3805,9 @@ public function setGrandTotal($amount) } /** - * {@inheritdoc} + * Set ShippingAmount + * + * @return $this */ public function setShippingAmount($amount) { @@ -3672,7 +3815,9 @@ public function setShippingAmount($amount) } /** - * {@inheritdoc} + * Set ShippingCanceled + * + * @return $this */ public function setShippingCanceled($shippingCanceled) { @@ -3680,7 +3825,9 @@ public function setShippingCanceled($shippingCanceled) } /** - * {@inheritdoc} + * Set ShippingInvoiced + * + * @return $this */ public function setShippingInvoiced($shippingInvoiced) { @@ -3688,7 +3835,9 @@ public function setShippingInvoiced($shippingInvoiced) } /** - * {@inheritdoc} + * Set ShippingRefunded + * + * @return $this */ public function setShippingRefunded($shippingRefunded) { @@ -3696,7 +3845,9 @@ public function setShippingRefunded($shippingRefunded) } /** - * {@inheritdoc} + * Set ShippingTaxAmount + * + * @return $this */ public function setShippingTaxAmount($amount) { @@ -3704,7 +3855,9 @@ public function setShippingTaxAmount($amount) } /** - * {@inheritdoc} + * Set ShippingTaxRefunded + * + * @return $this */ public function setShippingTaxRefunded($shippingTaxRefunded) { @@ -3712,7 +3865,9 @@ public function setShippingTaxRefunded($shippingTaxRefunded) } /** - * {@inheritdoc} + * Set StoreToBaseRate + * + * @return $this */ public function setStoreToBaseRate($rate) { @@ -3720,7 +3875,9 @@ public function setStoreToBaseRate($rate) } /** - * {@inheritdoc} + * Set StoreToOrderRate + * + * @return $this */ public function setStoreToOrderRate($rate) { @@ -3728,7 +3885,9 @@ public function setStoreToOrderRate($rate) } /** - * {@inheritdoc} + * Set Subtotal + * + * @return $this */ public function setSubtotal($amount) { @@ -3736,7 +3895,9 @@ public function setSubtotal($amount) } /** - * {@inheritdoc} + * Set SubtotalCanceled + * + * @return $this */ public function setSubtotalCanceled($subtotalCanceled) { @@ -3744,7 +3905,9 @@ public function setSubtotalCanceled($subtotalCanceled) } /** - * {@inheritdoc} + * Set SubtotalInvoiced + * + * @return $this */ public function setSubtotalInvoiced($subtotalInvoiced) { @@ -3752,7 +3915,9 @@ public function setSubtotalInvoiced($subtotalInvoiced) } /** - * {@inheritdoc} + * Set SubtotalRefunded + * + * @return $this */ public function setSubtotalRefunded($subtotalRefunded) { @@ -3760,7 +3925,9 @@ public function setSubtotalRefunded($subtotalRefunded) } /** - * {@inheritdoc} + * Set TaxAmount + * + * @return $this */ public function setTaxAmount($amount) { @@ -3768,7 +3935,9 @@ public function setTaxAmount($amount) } /** - * {@inheritdoc} + * Set TaxCanceled + * + * @return $this */ public function setTaxCanceled($taxCanceled) { @@ -3776,7 +3945,9 @@ public function setTaxCanceled($taxCanceled) } /** - * {@inheritdoc} + * Set TaxInvoiced + * + * @return $this */ public function setTaxInvoiced($taxInvoiced) { @@ -3784,7 +3955,9 @@ public function setTaxInvoiced($taxInvoiced) } /** - * {@inheritdoc} + * Set TaxRefunded + * + * @return $this */ public function setTaxRefunded($taxRefunded) { @@ -3792,7 +3965,9 @@ public function setTaxRefunded($taxRefunded) } /** - * {@inheritdoc} + * Set TotalCanceled + * + * @return $this */ public function setTotalCanceled($totalCanceled) { @@ -3800,7 +3975,9 @@ public function setTotalCanceled($totalCanceled) } /** - * {@inheritdoc} + * Set TotalInvoiced + * + * @return $this */ public function setTotalInvoiced($totalInvoiced) { @@ -3808,7 +3985,9 @@ public function setTotalInvoiced($totalInvoiced) } /** - * {@inheritdoc} + * Set TotalOfflineRefunded + * + * @return $this */ public function setTotalOfflineRefunded($totalOfflineRefunded) { @@ -3816,7 +3995,9 @@ public function setTotalOfflineRefunded($totalOfflineRefunded) } /** - * {@inheritdoc} + * Set TotalOnlineRefunded + * + * @return $this */ public function setTotalOnlineRefunded($totalOnlineRefunded) { @@ -3824,7 +4005,9 @@ public function setTotalOnlineRefunded($totalOnlineRefunded) } /** - * {@inheritdoc} + * Set TotalPaid + * + * @return $this */ public function setTotalPaid($totalPaid) { @@ -3832,7 +4015,9 @@ public function setTotalPaid($totalPaid) } /** - * {@inheritdoc} + * Set TotalQtyOrdered + * + * @return $this */ public function setTotalQtyOrdered($totalQtyOrdered) { @@ -3840,7 +4025,9 @@ public function setTotalQtyOrdered($totalQtyOrdered) } /** - * {@inheritdoc} + * Set TotalRefunded + * + * @return $this */ public function setTotalRefunded($totalRefunded) { @@ -3848,7 +4035,9 @@ public function setTotalRefunded($totalRefunded) } /** - * {@inheritdoc} + * Set CanShipPartially + * + * @return $this */ public function setCanShipPartially($flag) { @@ -3856,7 +4045,9 @@ public function setCanShipPartially($flag) } /** - * {@inheritdoc} + * Set CanShipPartiallyItem + * + * @return $this */ public function setCanShipPartiallyItem($flag) { @@ -3864,7 +4055,9 @@ public function setCanShipPartiallyItem($flag) } /** - * {@inheritdoc} + * Set CustomerIsGuest + * + * @return $this */ public function setCustomerIsGuest($customerIsGuest) { @@ -3872,7 +4065,9 @@ public function setCustomerIsGuest($customerIsGuest) } /** - * {@inheritdoc} + * Set CustomerNoteNotify + * + * @return $this */ public function setCustomerNoteNotify($customerNoteNotify) { @@ -3880,7 +4075,9 @@ public function setCustomerNoteNotify($customerNoteNotify) } /** - * {@inheritdoc} + * Set BillingAddressId + * + * @return $this */ public function setBillingAddressId($id) { @@ -3888,7 +4085,9 @@ public function setBillingAddressId($id) } /** - * {@inheritdoc} + * Set CustomerGroupId + * + * @return $this */ public function setCustomerGroupId($id) { @@ -3896,7 +4095,9 @@ public function setCustomerGroupId($id) } /** - * {@inheritdoc} + * Set EditIncrement + * + * @return $this */ public function setEditIncrement($editIncrement) { @@ -3904,7 +4105,9 @@ public function setEditIncrement($editIncrement) } /** - * {@inheritdoc} + * Set EmailSent + * + * @return $this */ public function setEmailSent($emailSent) { @@ -3912,7 +4115,9 @@ public function setEmailSent($emailSent) } /** - * {@inheritdoc} + * Set ForcedShipmentWithInvoice + * + * @return $this */ public function setForcedShipmentWithInvoice($forcedShipmentWithInvoice) { @@ -3920,7 +4125,9 @@ public function setForcedShipmentWithInvoice($forcedShipmentWithInvoice) } /** - * {@inheritdoc} + * Set PaymentAuthExpiration + * + * @return $this */ public function setPaymentAuthExpiration($paymentAuthExpiration) { @@ -3928,7 +4135,9 @@ public function setPaymentAuthExpiration($paymentAuthExpiration) } /** - * {@inheritdoc} + * Set QuoteAddressId + * + * @return $this */ public function setQuoteAddressId($id) { @@ -3936,7 +4145,9 @@ public function setQuoteAddressId($id) } /** - * {@inheritdoc} + * Set QuoteId + * + * @return $this */ public function setQuoteId($id) { @@ -3944,7 +4155,9 @@ public function setQuoteId($id) } /** - * {@inheritdoc} + * Set AdjustmentNegative + * + * @return $this */ public function setAdjustmentNegative($adjustmentNegative) { @@ -3952,7 +4165,9 @@ public function setAdjustmentNegative($adjustmentNegative) } /** - * {@inheritdoc} + * Set AdjustmentPositive + * + * @return $this */ public function setAdjustmentPositive($adjustmentPositive) { @@ -3960,7 +4175,9 @@ public function setAdjustmentPositive($adjustmentPositive) } /** - * {@inheritdoc} + * Set BaseAdjustmentNegative + * + * @return $this */ public function setBaseAdjustmentNegative($baseAdjustmentNegative) { @@ -3968,7 +4185,9 @@ public function setBaseAdjustmentNegative($baseAdjustmentNegative) } /** - * {@inheritdoc} + * Set BaseAdjustmentPositive + * + * @return $this */ public function setBaseAdjustmentPositive($baseAdjustmentPositive) { @@ -3976,7 +4195,9 @@ public function setBaseAdjustmentPositive($baseAdjustmentPositive) } /** - * {@inheritdoc} + * Set BaseShippingDiscountAmount + * + * @return $this */ public function setBaseShippingDiscountAmount($amount) { @@ -3984,7 +4205,9 @@ public function setBaseShippingDiscountAmount($amount) } /** - * {@inheritdoc} + * Set BaseSubtotalInclTax + * + * @return $this */ public function setBaseSubtotalInclTax($amount) { @@ -3992,7 +4215,9 @@ public function setBaseSubtotalInclTax($amount) } /** - * {@inheritdoc} + * Set BaseTotalDue + * + * @return $this */ public function setBaseTotalDue($baseTotalDue) { @@ -4000,7 +4225,9 @@ public function setBaseTotalDue($baseTotalDue) } /** - * {@inheritdoc} + * Set PaymentAuthorizationAmount + * + * @return $this */ public function setPaymentAuthorizationAmount($amount) { @@ -4008,7 +4235,9 @@ public function setPaymentAuthorizationAmount($amount) } /** - * {@inheritdoc} + * Set ShippingDiscountAmount + * + * @return $this */ public function setShippingDiscountAmount($amount) { @@ -4016,7 +4245,9 @@ public function setShippingDiscountAmount($amount) } /** - * {@inheritdoc} + * Set SubtotalInclTax + * + * @return $this */ public function setSubtotalInclTax($amount) { @@ -4024,7 +4255,9 @@ public function setSubtotalInclTax($amount) } /** - * {@inheritdoc} + * Set TotalDue + * + * @return $this */ public function setTotalDue($totalDue) { @@ -4032,7 +4265,9 @@ public function setTotalDue($totalDue) } /** - * {@inheritdoc} + * Set Weight + * + * @return $this */ public function setWeight($weight) { @@ -4040,7 +4275,9 @@ public function setWeight($weight) } /** - * {@inheritdoc} + * Set CustomerDob + * + * @return $this */ public function setCustomerDob($customerDob) { @@ -4048,7 +4285,9 @@ public function setCustomerDob($customerDob) } /** - * {@inheritdoc} + * Set IncrementId + * + * @return $this */ public function setIncrementId($id) { @@ -4056,7 +4295,9 @@ public function setIncrementId($id) } /** - * {@inheritdoc} + * Set AppliedRuleIds + * + * @return $this */ public function setAppliedRuleIds($appliedRuleIds) { @@ -4064,7 +4305,9 @@ public function setAppliedRuleIds($appliedRuleIds) } /** - * {@inheritdoc} + * Set BaseCurrencyCode + * + * @return $this */ public function setBaseCurrencyCode($code) { @@ -4072,7 +4315,9 @@ public function setBaseCurrencyCode($code) } /** - * {@inheritdoc} + * Set CustomerEmail + * + * @return $this */ public function setCustomerEmail($customerEmail) { @@ -4080,7 +4325,9 @@ public function setCustomerEmail($customerEmail) } /** - * {@inheritdoc} + * Set CustomerFirstname + * + * @return $this */ public function setCustomerFirstname($customerFirstname) { @@ -4088,7 +4335,9 @@ public function setCustomerFirstname($customerFirstname) } /** - * {@inheritdoc} + * Set CustomerLastname + * + * @return $this */ public function setCustomerLastname($customerLastname) { @@ -4096,7 +4345,9 @@ public function setCustomerLastname($customerLastname) } /** - * {@inheritdoc} + * Set CustomerMiddlename + * + * @return $this */ public function setCustomerMiddlename($customerMiddlename) { @@ -4104,7 +4355,9 @@ public function setCustomerMiddlename($customerMiddlename) } /** - * {@inheritdoc} + * Set CustomerPrefix + * + * @return $this */ public function setCustomerPrefix($customerPrefix) { @@ -4112,7 +4365,9 @@ public function setCustomerPrefix($customerPrefix) } /** - * {@inheritdoc} + * Set CustomerSuffix + * + * @return $this */ public function setCustomerSuffix($customerSuffix) { @@ -4120,7 +4375,9 @@ public function setCustomerSuffix($customerSuffix) } /** - * {@inheritdoc} + * Set CustomerTaxvat + * + * @return $this */ public function setCustomerTaxvat($customerTaxvat) { @@ -4128,7 +4385,9 @@ public function setCustomerTaxvat($customerTaxvat) } /** - * {@inheritdoc} + * Set DiscountDescription + * + * @return $this */ public function setDiscountDescription($description) { @@ -4136,7 +4395,9 @@ public function setDiscountDescription($description) } /** - * {@inheritdoc} + * Set ExtCustomerId + * + * @return $this */ public function setExtCustomerId($id) { @@ -4144,7 +4405,9 @@ public function setExtCustomerId($id) } /** - * {@inheritdoc} + * Set ExtOrderId + * + * @return $this */ public function setExtOrderId($id) { @@ -4152,7 +4415,9 @@ public function setExtOrderId($id) } /** - * {@inheritdoc} + * Set GlobalCurrencyCode + * + * @return $this */ public function setGlobalCurrencyCode($code) { @@ -4160,7 +4425,9 @@ public function setGlobalCurrencyCode($code) } /** - * {@inheritdoc} + * Set HoldBeforeState + * + * @return $this */ public function setHoldBeforeState($holdBeforeState) { @@ -4168,7 +4435,9 @@ public function setHoldBeforeState($holdBeforeState) } /** - * {@inheritdoc} + * Set HoldBeforeStatus + * + * @return $this */ public function setHoldBeforeStatus($holdBeforeStatus) { @@ -4176,7 +4445,9 @@ public function setHoldBeforeStatus($holdBeforeStatus) } /** - * {@inheritdoc} + * Set OrderCurrencyCode + * + * @return $this */ public function setOrderCurrencyCode($code) { @@ -4184,7 +4455,9 @@ public function setOrderCurrencyCode($code) } /** - * {@inheritdoc} + * Set OriginalIncrementId + * + * @return $this */ public function setOriginalIncrementId($id) { @@ -4192,7 +4465,9 @@ public function setOriginalIncrementId($id) } /** - * {@inheritdoc} + * Set RelationChildId + * + * @return $this */ public function setRelationChildId($id) { @@ -4200,7 +4475,9 @@ public function setRelationChildId($id) } /** - * {@inheritdoc} + * Set RelationChildRealId + * + * @return $this */ public function setRelationChildRealId($realId) { @@ -4208,7 +4485,9 @@ public function setRelationChildRealId($realId) } /** - * {@inheritdoc} + * Set RelationParentId + * + * @return $this */ public function setRelationParentId($id) { @@ -4216,7 +4495,9 @@ public function setRelationParentId($id) } /** - * {@inheritdoc} + * Set RelationParentRealId + * + * @return $this */ public function setRelationParentRealId($realId) { @@ -4224,7 +4505,9 @@ public function setRelationParentRealId($realId) } /** - * {@inheritdoc} + * Set RemoteIp + * + * @return $this */ public function setRemoteIp($remoteIp) { @@ -4232,7 +4515,9 @@ public function setRemoteIp($remoteIp) } /** - * {@inheritdoc} + * Set StoreCurrencyCode + * + * @return $this */ public function setStoreCurrencyCode($code) { @@ -4240,7 +4525,9 @@ public function setStoreCurrencyCode($code) } /** - * {@inheritdoc} + * Set StoreName + * + * @return $this */ public function setStoreName($storeName) { @@ -4248,7 +4535,9 @@ public function setStoreName($storeName) } /** - * {@inheritdoc} + * Set XForwardedFor + * + * @return $this */ public function setXForwardedFor($xForwardedFor) { @@ -4256,7 +4545,9 @@ public function setXForwardedFor($xForwardedFor) } /** - * {@inheritdoc} + * Set CustomerNote + * + * @return $this */ public function setCustomerNote($customerNote) { @@ -4264,7 +4555,9 @@ public function setCustomerNote($customerNote) } /** - * {@inheritdoc} + * Set UpdatedAt + * + * @return $this */ public function setUpdatedAt($timestamp) { @@ -4272,7 +4565,9 @@ public function setUpdatedAt($timestamp) } /** - * {@inheritdoc} + * Set TotalItemCount + * + * @return $this */ public function setTotalItemCount($totalItemCount) { @@ -4280,7 +4575,9 @@ public function setTotalItemCount($totalItemCount) } /** - * {@inheritdoc} + * Set CustomerGender + * + * @return $this */ public function setCustomerGender($customerGender) { @@ -4288,7 +4585,9 @@ public function setCustomerGender($customerGender) } /** - * {@inheritdoc} + * Set DiscountTaxCompensationAmount + * + * @return $this */ public function setDiscountTaxCompensationAmount($amount) { @@ -4296,7 +4595,9 @@ public function setDiscountTaxCompensationAmount($amount) } /** - * {@inheritdoc} + * Set BaseDiscountTaxCompensationAmount + * + * @return $this */ public function setBaseDiscountTaxCompensationAmount($amount) { @@ -4304,7 +4605,9 @@ public function setBaseDiscountTaxCompensationAmount($amount) } /** - * {@inheritdoc} + * Set ShippingDiscountTaxCompensationAmount + * + * @return $this */ public function setShippingDiscountTaxCompensationAmount($amount) { @@ -4312,7 +4615,9 @@ public function setShippingDiscountTaxCompensationAmount($amount) } /** - * {@inheritdoc} + * Set BaseShippingDiscountTaxCompensationAmnt + * + * @return $this */ public function setBaseShippingDiscountTaxCompensationAmnt($amnt) { @@ -4320,7 +4625,9 @@ public function setBaseShippingDiscountTaxCompensationAmnt($amnt) } /** - * {@inheritdoc} + * Set DiscountTaxCompensationInvoiced + * + * @return $this */ public function setDiscountTaxCompensationInvoiced($discountTaxCompensationInvoiced) { @@ -4328,7 +4635,9 @@ public function setDiscountTaxCompensationInvoiced($discountTaxCompensationInvoi } /** - * {@inheritdoc} + * Set BaseDiscountTaxCompensationInvoiced + * + * @return $this */ public function setBaseDiscountTaxCompensationInvoiced($baseDiscountTaxCompensationInvoiced) { @@ -4339,7 +4648,9 @@ public function setBaseDiscountTaxCompensationInvoiced($baseDiscountTaxCompensat } /** - * {@inheritdoc} + * Set DiscountTaxCompensationRefunded + * + * @return $this */ public function setDiscountTaxCompensationRefunded($discountTaxCompensationRefunded) { @@ -4350,7 +4661,9 @@ public function setDiscountTaxCompensationRefunded($discountTaxCompensationRefun } /** - * {@inheritdoc} + * Set BaseDiscountTaxCompensationRefunded + * + * @return $this */ public function setBaseDiscountTaxCompensationRefunded($baseDiscountTaxCompensationRefunded) { @@ -4361,7 +4674,9 @@ public function setBaseDiscountTaxCompensationRefunded($baseDiscountTaxCompensat } /** - * {@inheritdoc} + * Set ShippingInclTax + * + * @return $this */ public function setShippingInclTax($amount) { @@ -4369,7 +4684,7 @@ public function setShippingInclTax($amount) } /** - * {@inheritdoc} + * @inheritdoc */ public function setBaseShippingInclTax($amount) { From d0b30a999698de2db9e05a89c1abbf4695c5bee1 Mon Sep 17 00:00:00 2001 From: Cristian Partica <cpartica@magento.com> Date: Mon, 17 Sep 2018 12:05:30 -0500 Subject: [PATCH 24/44] MAGETWO-60034: Cannot ship remaining items in an order for several of one product if credit memo is made for some - fix static tests --- app/code/Magento/Sales/Model/Order/Item.php | 210 +++++++++--------- .../Sales/Test/Unit/Model/OrderTest.php | 1 + 2 files changed, 106 insertions(+), 105 deletions(-) diff --git a/app/code/Magento/Sales/Model/Order/Item.php b/app/code/Magento/Sales/Model/Order/Item.php index 7fa2f615545..423d4b8d09d 100644 --- a/app/code/Magento/Sales/Model/Order/Item.php +++ b/app/code/Magento/Sales/Model/Order/Item.php @@ -483,6 +483,7 @@ public function getProductOptions() /** * Get product options array by code. + * * If code is null return all options * * @param string $code @@ -540,8 +541,7 @@ public function getChildrenItems() } /** - * Return checking of what calculation - * type was for this product + * Return checking of what calculation type was for this product * * @return bool */ @@ -581,8 +581,7 @@ public function getForceApplyDiscountToParentItem() } /** - * Return checking of what shipment - * type was for this product + * Return checking of what shipment type was for this product * * @return bool */ @@ -605,9 +604,9 @@ public function isShipSeparately() } /** - * This is Dummy item or not - * if $shipment is true then we checking this for shipping situation if not - * then we checking this for calculation + * This is Dummy item or not. + * + * If $shipment is true then we checking this for shipping situation if not, we checking this for calculation. * * @param bool $shipment * @return bool @@ -652,8 +651,9 @@ public function isDummy($shipment = false) } /** - * Returns formatted buy request - object, holding request received from - * product view page with keys and options for configured product + * Returns formatted buy request. + * + * This object is holding request received from product view page with keys and options for configured product. * * @return \Magento\Framework\DataObject */ @@ -963,7 +963,7 @@ public function getCreatedAt() } /** - * {@inheritdoc} + * @inheritdoc */ public function setCreatedAt($createdAt) { @@ -1621,7 +1621,7 @@ public function getWeight() } /** - * {@inheritdoc} + * @inheritdoc */ public function setUpdatedAt($timestamp) { @@ -1629,7 +1629,7 @@ public function setUpdatedAt($timestamp) } /** - * {@inheritdoc} + * @inheritdoc */ public function setItemId($id) { @@ -1637,7 +1637,7 @@ public function setItemId($id) } /** - * {@inheritdoc} + * @inheritdoc */ public function setOrderId($id) { @@ -1645,7 +1645,7 @@ public function setOrderId($id) } /** - * {@inheritdoc} + * @inheritdoc */ public function setParentItemId($id) { @@ -1653,7 +1653,7 @@ public function setParentItemId($id) } /** - * {@inheritdoc} + * @inheritdoc */ public function setQuoteItemId($id) { @@ -1661,7 +1661,7 @@ public function setQuoteItemId($id) } /** - * {@inheritdoc} + * @inheritdoc */ public function setStoreId($id) { @@ -1669,7 +1669,7 @@ public function setStoreId($id) } /** - * {@inheritdoc} + * @inheritdoc */ public function setProductId($id) { @@ -1677,7 +1677,7 @@ public function setProductId($id) } /** - * {@inheritdoc} + * @inheritdoc */ public function setProductType($productType) { @@ -1685,7 +1685,7 @@ public function setProductType($productType) } /** - * {@inheritdoc} + * @inheritdoc */ public function setWeight($weight) { @@ -1693,7 +1693,7 @@ public function setWeight($weight) } /** - * {@inheritdoc} + * @inheritdoc */ public function setIsVirtual($isVirtual) { @@ -1701,7 +1701,7 @@ public function setIsVirtual($isVirtual) } /** - * {@inheritdoc} + * @inheritdoc */ public function setSku($sku) { @@ -1709,7 +1709,7 @@ public function setSku($sku) } /** - * {@inheritdoc} + * @inheritdoc */ public function setName($name) { @@ -1717,7 +1717,7 @@ public function setName($name) } /** - * {@inheritdoc} + * @inheritdoc */ public function setDescription($description) { @@ -1725,7 +1725,7 @@ public function setDescription($description) } /** - * {@inheritdoc} + * @inheritdoc */ public function setAppliedRuleIds($appliedRuleIds) { @@ -1733,7 +1733,7 @@ public function setAppliedRuleIds($appliedRuleIds) } /** - * {@inheritdoc} + * @inheritdoc */ public function setAdditionalData($additionalData) { @@ -1741,7 +1741,7 @@ public function setAdditionalData($additionalData) } /** - * {@inheritdoc} + * @inheritdoc */ public function setIsQtyDecimal($isQtyDecimal) { @@ -1749,7 +1749,7 @@ public function setIsQtyDecimal($isQtyDecimal) } /** - * {@inheritdoc} + * @inheritdoc */ public function setNoDiscount($noDiscount) { @@ -1757,7 +1757,7 @@ public function setNoDiscount($noDiscount) } /** - * {@inheritdoc} + * @inheritdoc */ public function setQtyBackordered($qtyBackordered) { @@ -1765,7 +1765,7 @@ public function setQtyBackordered($qtyBackordered) } /** - * {@inheritdoc} + * @inheritdoc */ public function setQtyCanceled($qtyCanceled) { @@ -1773,7 +1773,7 @@ public function setQtyCanceled($qtyCanceled) } /** - * {@inheritdoc} + * @inheritdoc */ public function setQtyInvoiced($qtyInvoiced) { @@ -1781,7 +1781,7 @@ public function setQtyInvoiced($qtyInvoiced) } /** - * {@inheritdoc} + * @inheritdoc */ public function setQtyOrdered($qtyOrdered) { @@ -1789,7 +1789,7 @@ public function setQtyOrdered($qtyOrdered) } /** - * {@inheritdoc} + * @inheritdoc */ public function setQtyRefunded($qtyRefunded) { @@ -1797,7 +1797,7 @@ public function setQtyRefunded($qtyRefunded) } /** - * {@inheritdoc} + * @inheritdoc */ public function setQtyShipped($qtyShipped) { @@ -1805,7 +1805,7 @@ public function setQtyShipped($qtyShipped) } /** - * {@inheritdoc} + * @inheritdoc */ public function setBaseCost($baseCost) { @@ -1813,7 +1813,7 @@ public function setBaseCost($baseCost) } /** - * {@inheritdoc} + * @inheritdoc */ public function setPrice($price) { @@ -1821,7 +1821,7 @@ public function setPrice($price) } /** - * {@inheritdoc} + * @inheritdoc */ public function setBasePrice($price) { @@ -1829,7 +1829,7 @@ public function setBasePrice($price) } /** - * {@inheritdoc} + * @inheritdoc */ public function setOriginalPrice($price) { @@ -1837,7 +1837,7 @@ public function setOriginalPrice($price) } /** - * {@inheritdoc} + * @inheritdoc */ public function setBaseOriginalPrice($price) { @@ -1845,7 +1845,7 @@ public function setBaseOriginalPrice($price) } /** - * {@inheritdoc} + * @inheritdoc */ public function setTaxPercent($taxPercent) { @@ -1853,7 +1853,7 @@ public function setTaxPercent($taxPercent) } /** - * {@inheritdoc} + * @inheritdoc */ public function setTaxAmount($amount) { @@ -1861,7 +1861,7 @@ public function setTaxAmount($amount) } /** - * {@inheritdoc} + * @inheritdoc */ public function setBaseTaxAmount($amount) { @@ -1869,7 +1869,7 @@ public function setBaseTaxAmount($amount) } /** - * {@inheritdoc} + * @inheritdoc */ public function setTaxInvoiced($taxInvoiced) { @@ -1877,7 +1877,7 @@ public function setTaxInvoiced($taxInvoiced) } /** - * {@inheritdoc} + * @inheritdoc */ public function setBaseTaxInvoiced($baseTaxInvoiced) { @@ -1885,7 +1885,7 @@ public function setBaseTaxInvoiced($baseTaxInvoiced) } /** - * {@inheritdoc} + * @inheritdoc */ public function setDiscountPercent($discountPercent) { @@ -1893,7 +1893,7 @@ public function setDiscountPercent($discountPercent) } /** - * {@inheritdoc} + * @inheritdoc */ public function setDiscountAmount($amount) { @@ -1901,7 +1901,7 @@ public function setDiscountAmount($amount) } /** - * {@inheritdoc} + * @inheritdoc */ public function setBaseDiscountAmount($amount) { @@ -1909,7 +1909,7 @@ public function setBaseDiscountAmount($amount) } /** - * {@inheritdoc} + * @inheritdoc */ public function setDiscountInvoiced($discountInvoiced) { @@ -1917,7 +1917,7 @@ public function setDiscountInvoiced($discountInvoiced) } /** - * {@inheritdoc} + * @inheritdoc */ public function setBaseDiscountInvoiced($baseDiscountInvoiced) { @@ -1925,7 +1925,7 @@ public function setBaseDiscountInvoiced($baseDiscountInvoiced) } /** - * {@inheritdoc} + * @inheritdoc */ public function setAmountRefunded($amountRefunded) { @@ -1933,7 +1933,7 @@ public function setAmountRefunded($amountRefunded) } /** - * {@inheritdoc} + * @inheritdoc */ public function setBaseAmountRefunded($baseAmountRefunded) { @@ -1941,7 +1941,7 @@ public function setBaseAmountRefunded($baseAmountRefunded) } /** - * {@inheritdoc} + * @inheritdoc */ public function setRowTotal($amount) { @@ -1949,7 +1949,7 @@ public function setRowTotal($amount) } /** - * {@inheritdoc} + * @inheritdoc */ public function setBaseRowTotal($amount) { @@ -1957,7 +1957,7 @@ public function setBaseRowTotal($amount) } /** - * {@inheritdoc} + * @inheritdoc */ public function setRowInvoiced($rowInvoiced) { @@ -1965,7 +1965,7 @@ public function setRowInvoiced($rowInvoiced) } /** - * {@inheritdoc} + * @inheritdoc */ public function setBaseRowInvoiced($baseRowInvoiced) { @@ -1973,7 +1973,7 @@ public function setBaseRowInvoiced($baseRowInvoiced) } /** - * {@inheritdoc} + * @inheritdoc */ public function setRowWeight($rowWeight) { @@ -1981,7 +1981,7 @@ public function setRowWeight($rowWeight) } /** - * {@inheritdoc} + * @inheritdoc */ public function setBaseTaxBeforeDiscount($baseTaxBeforeDiscount) { @@ -1989,7 +1989,7 @@ public function setBaseTaxBeforeDiscount($baseTaxBeforeDiscount) } /** - * {@inheritdoc} + * @inheritdoc */ public function setTaxBeforeDiscount($taxBeforeDiscount) { @@ -1997,7 +1997,7 @@ public function setTaxBeforeDiscount($taxBeforeDiscount) } /** - * {@inheritdoc} + * @inheritdoc */ public function setExtOrderItemId($id) { @@ -2005,7 +2005,7 @@ public function setExtOrderItemId($id) } /** - * {@inheritdoc} + * @inheritdoc */ public function setLockedDoInvoice($flag) { @@ -2013,7 +2013,7 @@ public function setLockedDoInvoice($flag) } /** - * {@inheritdoc} + * @inheritdoc */ public function setLockedDoShip($flag) { @@ -2021,7 +2021,7 @@ public function setLockedDoShip($flag) } /** - * {@inheritdoc} + * @inheritdoc */ public function setPriceInclTax($amount) { @@ -2029,7 +2029,7 @@ public function setPriceInclTax($amount) } /** - * {@inheritdoc} + * @inheritdoc */ public function setBasePriceInclTax($amount) { @@ -2037,7 +2037,7 @@ public function setBasePriceInclTax($amount) } /** - * {@inheritdoc} + * @inheritdoc */ public function setRowTotalInclTax($amount) { @@ -2045,7 +2045,7 @@ public function setRowTotalInclTax($amount) } /** - * {@inheritdoc} + * @inheritdoc */ public function setBaseRowTotalInclTax($amount) { @@ -2053,7 +2053,7 @@ public function setBaseRowTotalInclTax($amount) } /** - * {@inheritdoc} + * @inheritdoc */ public function setDiscountTaxCompensationAmount($amount) { @@ -2061,7 +2061,7 @@ public function setDiscountTaxCompensationAmount($amount) } /** - * {@inheritdoc} + * @inheritdoc */ public function setBaseDiscountTaxCompensationAmount($amount) { @@ -2069,7 +2069,7 @@ public function setBaseDiscountTaxCompensationAmount($amount) } /** - * {@inheritdoc} + * @inheritdoc */ public function setDiscountTaxCompensationInvoiced($discountTaxCompensationInvoiced) { @@ -2077,7 +2077,7 @@ public function setDiscountTaxCompensationInvoiced($discountTaxCompensationInvoi } /** - * {@inheritdoc} + * @inheritdoc */ public function setBaseDiscountTaxCompensationInvoiced($baseDiscountTaxCompensationInvoiced) { @@ -2088,7 +2088,7 @@ public function setBaseDiscountTaxCompensationInvoiced($baseDiscountTaxCompensat } /** - * {@inheritdoc} + * @inheritdoc */ public function setDiscountTaxCompensationRefunded($discountTaxCompensationRefunded) { @@ -2096,7 +2096,7 @@ public function setDiscountTaxCompensationRefunded($discountTaxCompensationRefun } /** - * {@inheritdoc} + * @inheritdoc */ public function setBaseDiscountTaxCompensationRefunded($baseDiscountTaxCompensationRefunded) { @@ -2107,7 +2107,7 @@ public function setBaseDiscountTaxCompensationRefunded($baseDiscountTaxCompensat } /** - * {@inheritdoc} + * @inheritdoc */ public function setTaxCanceled($taxCanceled) { @@ -2115,7 +2115,7 @@ public function setTaxCanceled($taxCanceled) } /** - * {@inheritdoc} + * @inheritdoc */ public function setDiscountTaxCompensationCanceled($discountTaxCompensationCanceled) { @@ -2123,7 +2123,7 @@ public function setDiscountTaxCompensationCanceled($discountTaxCompensationCance } /** - * {@inheritdoc} + * @inheritdoc */ public function setTaxRefunded($taxRefunded) { @@ -2131,7 +2131,7 @@ public function setTaxRefunded($taxRefunded) } /** - * {@inheritdoc} + * @inheritdoc */ public function setBaseTaxRefunded($baseTaxRefunded) { @@ -2139,7 +2139,7 @@ public function setBaseTaxRefunded($baseTaxRefunded) } /** - * {@inheritdoc} + * @inheritdoc */ public function setDiscountRefunded($discountRefunded) { @@ -2147,7 +2147,7 @@ public function setDiscountRefunded($discountRefunded) } /** - * {@inheritdoc} + * @inheritdoc */ public function setBaseDiscountRefunded($baseDiscountRefunded) { @@ -2155,7 +2155,7 @@ public function setBaseDiscountRefunded($baseDiscountRefunded) } /** - * {@inheritdoc} + * @inheritdoc */ public function setGwId($id) { @@ -2163,7 +2163,7 @@ public function setGwId($id) } /** - * {@inheritdoc} + * @inheritdoc */ public function setGwBasePrice($price) { @@ -2171,7 +2171,7 @@ public function setGwBasePrice($price) } /** - * {@inheritdoc} + * @inheritdoc */ public function setGwPrice($price) { @@ -2179,7 +2179,7 @@ public function setGwPrice($price) } /** - * {@inheritdoc} + * @inheritdoc */ public function setGwBaseTaxAmount($amount) { @@ -2187,7 +2187,7 @@ public function setGwBaseTaxAmount($amount) } /** - * {@inheritdoc} + * @inheritdoc */ public function setGwTaxAmount($amount) { @@ -2195,7 +2195,7 @@ public function setGwTaxAmount($amount) } /** - * {@inheritdoc} + * @inheritdoc */ public function setGwBasePriceInvoiced($gwBasePriceInvoiced) { @@ -2203,7 +2203,7 @@ public function setGwBasePriceInvoiced($gwBasePriceInvoiced) } /** - * {@inheritdoc} + * @inheritdoc */ public function setGwPriceInvoiced($gwPriceInvoiced) { @@ -2211,7 +2211,7 @@ public function setGwPriceInvoiced($gwPriceInvoiced) } /** - * {@inheritdoc} + * @inheritdoc */ public function setGwBaseTaxAmountInvoiced($gwBaseTaxAmountInvoiced) { @@ -2219,7 +2219,7 @@ public function setGwBaseTaxAmountInvoiced($gwBaseTaxAmountInvoiced) } /** - * {@inheritdoc} + * @inheritdoc */ public function setGwTaxAmountInvoiced($gwTaxAmountInvoiced) { @@ -2227,7 +2227,7 @@ public function setGwTaxAmountInvoiced($gwTaxAmountInvoiced) } /** - * {@inheritdoc} + * @inheritdoc */ public function setGwBasePriceRefunded($gwBasePriceRefunded) { @@ -2235,7 +2235,7 @@ public function setGwBasePriceRefunded($gwBasePriceRefunded) } /** - * {@inheritdoc} + * @inheritdoc */ public function setGwPriceRefunded($gwPriceRefunded) { @@ -2243,7 +2243,7 @@ public function setGwPriceRefunded($gwPriceRefunded) } /** - * {@inheritdoc} + * @inheritdoc */ public function setGwBaseTaxAmountRefunded($gwBaseTaxAmountRefunded) { @@ -2251,7 +2251,7 @@ public function setGwBaseTaxAmountRefunded($gwBaseTaxAmountRefunded) } /** - * {@inheritdoc} + * @inheritdoc */ public function setGwTaxAmountRefunded($gwTaxAmountRefunded) { @@ -2259,7 +2259,7 @@ public function setGwTaxAmountRefunded($gwTaxAmountRefunded) } /** - * {@inheritdoc} + * @inheritdoc */ public function setFreeShipping($freeShipping) { @@ -2267,7 +2267,7 @@ public function setFreeShipping($freeShipping) } /** - * {@inheritdoc} + * @inheritdoc */ public function setQtyReturned($qtyReturned) { @@ -2275,7 +2275,7 @@ public function setQtyReturned($qtyReturned) } /** - * {@inheritdoc} + * @inheritdoc */ public function setEventId($id) { @@ -2283,7 +2283,7 @@ public function setEventId($id) } /** - * {@inheritdoc} + * @inheritdoc */ public function setBaseWeeeTaxAppliedAmount($amount) { @@ -2291,7 +2291,7 @@ public function setBaseWeeeTaxAppliedAmount($amount) } /** - * {@inheritdoc} + * @inheritdoc */ public function setBaseWeeeTaxAppliedRowAmnt($amnt) { @@ -2299,7 +2299,7 @@ public function setBaseWeeeTaxAppliedRowAmnt($amnt) } /** - * {@inheritdoc} + * @inheritdoc */ public function setWeeeTaxAppliedAmount($amount) { @@ -2307,7 +2307,7 @@ public function setWeeeTaxAppliedAmount($amount) } /** - * {@inheritdoc} + * @inheritdoc */ public function setWeeeTaxAppliedRowAmount($amount) { @@ -2315,7 +2315,7 @@ public function setWeeeTaxAppliedRowAmount($amount) } /** - * {@inheritdoc} + * @inheritdoc */ public function setWeeeTaxApplied($weeeTaxApplied) { @@ -2323,7 +2323,7 @@ public function setWeeeTaxApplied($weeeTaxApplied) } /** - * {@inheritdoc} + * @inheritdoc */ public function setWeeeTaxDisposition($weeeTaxDisposition) { @@ -2331,7 +2331,7 @@ public function setWeeeTaxDisposition($weeeTaxDisposition) } /** - * {@inheritdoc} + * @inheritdoc */ public function setWeeeTaxRowDisposition($weeeTaxRowDisposition) { @@ -2339,7 +2339,7 @@ public function setWeeeTaxRowDisposition($weeeTaxRowDisposition) } /** - * {@inheritdoc} + * @inheritdoc */ public function setBaseWeeeTaxDisposition($baseWeeeTaxDisposition) { @@ -2347,7 +2347,7 @@ public function setBaseWeeeTaxDisposition($baseWeeeTaxDisposition) } /** - * {@inheritdoc} + * @inheritdoc */ public function setBaseWeeeTaxRowDisposition($baseWeeeTaxRowDisposition) { @@ -2355,7 +2355,7 @@ public function setBaseWeeeTaxRowDisposition($baseWeeeTaxRowDisposition) } /** - * {@inheritdoc} + * @inheritdoc */ public function getProductOption() { @@ -2363,7 +2363,7 @@ public function getProductOption() } /** - * {@inheritdoc} + * @inheritdoc */ public function setProductOption(\Magento\Catalog\Api\Data\ProductOptionInterface $productOption) { @@ -2371,7 +2371,7 @@ public function setProductOption(\Magento\Catalog\Api\Data\ProductOptionInterfac } /** - * {@inheritdoc} + * @inheritdoc * * @return \Magento\Sales\Api\Data\OrderItemExtensionInterface|null */ @@ -2381,7 +2381,7 @@ public function getExtensionAttributes() } /** - * {@inheritdoc} + * @inheritdoc * * @param \Magento\Sales\Api\Data\OrderItemExtensionInterface $extensionAttributes * @return $this diff --git a/app/code/Magento/Sales/Test/Unit/Model/OrderTest.php b/app/code/Magento/Sales/Test/Unit/Model/OrderTest.php index b75e3adb740..873cd64e9c3 100644 --- a/app/code/Magento/Sales/Test/Unit/Model/OrderTest.php +++ b/app/code/Magento/Sales/Test/Unit/Model/OrderTest.php @@ -18,6 +18,7 @@ * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) * @SuppressWarnings(PHPMD.TooManyPublicMethods) + * @SuppressWarnings(PHPMD.ExcessivePublicCount) */ class OrderTest extends \PHPUnit\Framework\TestCase { From e1b02178c68dceadb10ca1667ab9ffadd21c3948 Mon Sep 17 00:00:00 2001 From: Cristian Partica <cpartica@magento.com> Date: Mon, 17 Sep 2018 13:35:37 -0500 Subject: [PATCH 25/44] MAGETWO-60034: Cannot ship remaining items in an order for several of one product if credit memo is made for some - fix static tests --- app/code/Magento/Sales/Model/Order.php | 542 +++++--------------- app/code/Magento/Sales/Model/Order/Item.php | 184 +++---- 2 files changed, 233 insertions(+), 493 deletions(-) diff --git a/app/code/Magento/Sales/Model/Order.php b/app/code/Magento/Sales/Model/Order.php index 47979591a58..14c6154f0cb 100644 --- a/app/code/Magento/Sales/Model/Order.php +++ b/app/code/Magento/Sales/Model/Order.php @@ -979,7 +979,7 @@ public function getShippingAddress() } /** - * Set order state + * @inheritdoc * * @param string $state * @return $this @@ -1496,9 +1496,7 @@ public function getPaymentById($paymentId) } /** - * Set payment - * - * @return \Magento\Sales\Api\Data\OrderPaymentInterface|null + * @inheritdoc */ public function setPayment(\Magento\Sales\Api\Data\OrderPaymentInterface $payment = null) { @@ -1581,7 +1579,7 @@ public function getStatusHistoryById($statusId) } /** - * Set the order status history object and the order object to each other. + * @inheritdoc * * Adds the object to the status history collection, which is automatically saved when the order is saved. * See the entity_id attribute backend model. @@ -1632,9 +1630,9 @@ public function getOrderCurrency() /** * Get formatted price value including order currency rate to order website currency * - * @param float $price - * @param bool $addBrackets - * @return string + * @param float $price + * @param bool $addBrackets + * @return string */ public function formatPrice($price, $addBrackets = false) { @@ -1773,7 +1771,7 @@ public function getInvoiceCollection() } /** - * Set order invoices collection + * @inheritdoc * * @param InvoiceCollection $invoices * @return $this @@ -1878,6 +1876,8 @@ public function getRelatedObjects() } /** + * Get customer name + * * @return string */ public function getCustomerName() @@ -2031,9 +2031,7 @@ public function getItems() } /** - * Set Items - * - * @return $this + * @inheritdoc * @codeCoverageIgnore */ public function setItems($items) @@ -2084,7 +2082,7 @@ public function getExtensionAttributes() } /** - * Set ExtensionAttributes + * @inheritdoc * * @param \Magento\Sales\Api\Data\OrderExtensionInterface $extensionAttributes * @return $this @@ -2288,7 +2286,7 @@ public function getBaseShippingInclTax() /** * Return base_shipping_invoiced - + * * @return float|null */ public function getBaseShippingInvoiced() @@ -3385,9 +3383,7 @@ public function getXForwardedFor() } /** - * Set StatusHistories - * - * @return $this + * @inheritdoc */ public function setStatusHistories(array $statusHistories = null) { @@ -3395,9 +3391,7 @@ public function setStatusHistories(array $statusHistories = null) } /** - * Set Status - * - * @return $this + * @inheritdoc */ public function setStatus($status) { @@ -3405,9 +3399,7 @@ public function setStatus($status) } /** - * Set CouponCode - * - * @return $this + * @inheritdoc */ public function setCouponCode($code) { @@ -3415,9 +3407,7 @@ public function setCouponCode($code) } /** - * Set ProtectCode - * - * @return $this + * @inheritdoc */ public function setProtectCode($code) { @@ -3425,9 +3415,7 @@ public function setProtectCode($code) } /** - * Set ShippingDescription - * - * @return $this + * @inheritdoc */ public function setShippingDescription($description) { @@ -3435,9 +3423,7 @@ public function setShippingDescription($description) } /** - * Set IsVirtual - * - * @return $this + * @inheritdoc */ public function setIsVirtual($isVirtual) { @@ -3445,9 +3431,7 @@ public function setIsVirtual($isVirtual) } /** - * Set StoreId - * - * @return $this + * @inheritdoc */ public function setStoreId($id) { @@ -3455,9 +3439,7 @@ public function setStoreId($id) } /** - * Set CustomerId - * - * @return $this + * @inheritdoc */ public function setCustomerId($id) { @@ -3465,9 +3447,7 @@ public function setCustomerId($id) } /** - * Set BaseDiscountAmount - * - * @return $this + * @inheritdoc */ public function setBaseDiscountAmount($amount) { @@ -3475,9 +3455,7 @@ public function setBaseDiscountAmount($amount) } /** - * Set BaseDiscountCanceled - * - * @return $this + * @inheritdoc */ public function setBaseDiscountCanceled($baseDiscountCanceled) { @@ -3485,9 +3463,7 @@ public function setBaseDiscountCanceled($baseDiscountCanceled) } /** - * Set BaseDiscountInvoiced - * - * @return $this + * @inheritdoc */ public function setBaseDiscountInvoiced($baseDiscountInvoiced) { @@ -3495,9 +3471,7 @@ public function setBaseDiscountInvoiced($baseDiscountInvoiced) } /** - * Set BaseDiscountRefunded - * - * @return $this + * @inheritdoc */ public function setBaseDiscountRefunded($baseDiscountRefunded) { @@ -3505,9 +3479,7 @@ public function setBaseDiscountRefunded($baseDiscountRefunded) } /** - * Set BaseGrandTotal - * - * @return $this + * @inheritdoc */ public function setBaseGrandTotal($amount) { @@ -3515,9 +3487,7 @@ public function setBaseGrandTotal($amount) } /** - * Set BaseShippingAmount - * - * @return $this + * @inheritdoc */ public function setBaseShippingAmount($amount) { @@ -3525,9 +3495,7 @@ public function setBaseShippingAmount($amount) } /** - * Set BaseShippingCanceled - * - * @return $this + * @inheritdoc */ public function setBaseShippingCanceled($baseShippingCanceled) { @@ -3535,9 +3503,7 @@ public function setBaseShippingCanceled($baseShippingCanceled) } /** - * Set BaseShippingInvoiced - * - * @return $this + * @inheritdoc */ public function setBaseShippingInvoiced($baseShippingInvoiced) { @@ -3545,9 +3511,7 @@ public function setBaseShippingInvoiced($baseShippingInvoiced) } /** - * Set BaseShippingRefunded - * - * @return $this + * @inheritdoc */ public function setBaseShippingRefunded($baseShippingRefunded) { @@ -3555,9 +3519,7 @@ public function setBaseShippingRefunded($baseShippingRefunded) } /** - * Set BaseShippingTaxAmount - * - * @return $this + * @inheritdoc */ public function setBaseShippingTaxAmount($amount) { @@ -3565,9 +3527,7 @@ public function setBaseShippingTaxAmount($amount) } /** - * Set BaseShippingTaxRefunded - * - * @return $this + * @inheritdoc */ public function setBaseShippingTaxRefunded($baseShippingTaxRefunded) { @@ -3575,9 +3535,7 @@ public function setBaseShippingTaxRefunded($baseShippingTaxRefunded) } /** - * Set BaseSubtotal - * - * @return $this + * @inheritdoc */ public function setBaseSubtotal($amount) { @@ -3585,9 +3543,7 @@ public function setBaseSubtotal($amount) } /** - * Set BaseSubtotalCanceled - * - * @return $this + * @inheritdoc */ public function setBaseSubtotalCanceled($baseSubtotalCanceled) { @@ -3595,9 +3551,7 @@ public function setBaseSubtotalCanceled($baseSubtotalCanceled) } /** - * Set BaseSubtotalInvoiced - * - * @return $this + * @inheritdoc */ public function setBaseSubtotalInvoiced($baseSubtotalInvoiced) { @@ -3605,9 +3559,7 @@ public function setBaseSubtotalInvoiced($baseSubtotalInvoiced) } /** - * Set BaseSubtotalRefunded - * - * @return $this + * @inheritdoc */ public function setBaseSubtotalRefunded($baseSubtotalRefunded) { @@ -3615,9 +3567,7 @@ public function setBaseSubtotalRefunded($baseSubtotalRefunded) } /** - * Set BaseTaxAmount - * - * @return $this + * @inheritdoc */ public function setBaseTaxAmount($amount) { @@ -3625,9 +3575,7 @@ public function setBaseTaxAmount($amount) } /** - * Set BaseTaxCanceled - * - * @return $this + * @inheritdoc */ public function setBaseTaxCanceled($baseTaxCanceled) { @@ -3635,9 +3583,7 @@ public function setBaseTaxCanceled($baseTaxCanceled) } /** - * Set BaseTaxInvoiced - * - * @return $this + * @inheritdoc */ public function setBaseTaxInvoiced($baseTaxInvoiced) { @@ -3645,9 +3591,7 @@ public function setBaseTaxInvoiced($baseTaxInvoiced) } /** - * Set BaseTaxRefunded - * - * @return $this + * @inheritdoc */ public function setBaseTaxRefunded($baseTaxRefunded) { @@ -3655,9 +3599,7 @@ public function setBaseTaxRefunded($baseTaxRefunded) } /** - * Set BaseToGlobalRate - * - * @return $this + * @inheritdoc */ public function setBaseToGlobalRate($rate) { @@ -3665,9 +3607,7 @@ public function setBaseToGlobalRate($rate) } /** - * Set BaseToOrderRate - * - * @return $this + * @inheritdoc */ public function setBaseToOrderRate($rate) { @@ -3675,9 +3615,7 @@ public function setBaseToOrderRate($rate) } /** - * Set BaseTotalCanceled - * - * @return $this + * @inheritdoc */ public function setBaseTotalCanceled($baseTotalCanceled) { @@ -3685,9 +3623,7 @@ public function setBaseTotalCanceled($baseTotalCanceled) } /** - * Set BaseTotalInvoiced - * - * @return $this + * @inheritdoc */ public function setBaseTotalInvoiced($baseTotalInvoiced) { @@ -3695,9 +3631,7 @@ public function setBaseTotalInvoiced($baseTotalInvoiced) } /** - * Set BaseTotalInvoicedCost - * - * @return $this + * @inheritdoc */ public function setBaseTotalInvoicedCost($baseTotalInvoicedCost) { @@ -3705,9 +3639,7 @@ public function setBaseTotalInvoicedCost($baseTotalInvoicedCost) } /** - * Set BaseTotalOfflineRefunded - * - * @return $this + * @inheritdoc */ public function setBaseTotalOfflineRefunded($baseTotalOfflineRefunded) { @@ -3715,9 +3647,7 @@ public function setBaseTotalOfflineRefunded($baseTotalOfflineRefunded) } /** - * Set BaseTotalOnlineRefunded - * - * @return $this + * @inheritdoc */ public function setBaseTotalOnlineRefunded($baseTotalOnlineRefunded) { @@ -3725,9 +3655,7 @@ public function setBaseTotalOnlineRefunded($baseTotalOnlineRefunded) } /** - * Set BaseTotalPaid - * - * @return $this + * @inheritdoc */ public function setBaseTotalPaid($baseTotalPaid) { @@ -3735,9 +3663,7 @@ public function setBaseTotalPaid($baseTotalPaid) } /** - * Set BaseTotalQtyOrdered - * - * @return $this + * @inheritdoc */ public function setBaseTotalQtyOrdered($baseTotalQtyOrdered) { @@ -3745,9 +3671,7 @@ public function setBaseTotalQtyOrdered($baseTotalQtyOrdered) } /** - * Set BaseTotalRefunded - * - * @return $this + * @inheritdoc */ public function setBaseTotalRefunded($baseTotalRefunded) { @@ -3755,9 +3679,7 @@ public function setBaseTotalRefunded($baseTotalRefunded) } /** - * Set DiscountAmount - * - * @return $this + * @inheritdoc */ public function setDiscountAmount($amount) { @@ -3765,9 +3687,7 @@ public function setDiscountAmount($amount) } /** - * Set DiscountCanceled - * - * @return $this + * @inheritdoc */ public function setDiscountCanceled($discountCanceled) { @@ -3775,9 +3695,7 @@ public function setDiscountCanceled($discountCanceled) } /** - * Set DiscountInvoiced - * - * @return $this + * @inheritdoc */ public function setDiscountInvoiced($discountInvoiced) { @@ -3785,9 +3703,7 @@ public function setDiscountInvoiced($discountInvoiced) } /** - * Set DiscountRefunded - * - * @return $this + * @inheritdoc */ public function setDiscountRefunded($discountRefunded) { @@ -3795,9 +3711,7 @@ public function setDiscountRefunded($discountRefunded) } /** - * Set GrandTotal - * - * @return $this + * @inheritdoc */ public function setGrandTotal($amount) { @@ -3805,9 +3719,7 @@ public function setGrandTotal($amount) } /** - * Set ShippingAmount - * - * @return $this + * @inheritdoc */ public function setShippingAmount($amount) { @@ -3815,9 +3727,7 @@ public function setShippingAmount($amount) } /** - * Set ShippingCanceled - * - * @return $this + * @inheritdoc */ public function setShippingCanceled($shippingCanceled) { @@ -3825,9 +3735,7 @@ public function setShippingCanceled($shippingCanceled) } /** - * Set ShippingInvoiced - * - * @return $this + * @inheritdoc */ public function setShippingInvoiced($shippingInvoiced) { @@ -3835,9 +3743,7 @@ public function setShippingInvoiced($shippingInvoiced) } /** - * Set ShippingRefunded - * - * @return $this + * @inheritdoc */ public function setShippingRefunded($shippingRefunded) { @@ -3845,9 +3751,7 @@ public function setShippingRefunded($shippingRefunded) } /** - * Set ShippingTaxAmount - * - * @return $this + * @inheritdoc */ public function setShippingTaxAmount($amount) { @@ -3855,9 +3759,7 @@ public function setShippingTaxAmount($amount) } /** - * Set ShippingTaxRefunded - * - * @return $this + * @inheritdoc */ public function setShippingTaxRefunded($shippingTaxRefunded) { @@ -3865,9 +3767,7 @@ public function setShippingTaxRefunded($shippingTaxRefunded) } /** - * Set StoreToBaseRate - * - * @return $this + * @inheritdoc */ public function setStoreToBaseRate($rate) { @@ -3875,9 +3775,7 @@ public function setStoreToBaseRate($rate) } /** - * Set StoreToOrderRate - * - * @return $this + * @inheritdoc */ public function setStoreToOrderRate($rate) { @@ -3885,9 +3783,7 @@ public function setStoreToOrderRate($rate) } /** - * Set Subtotal - * - * @return $this + * @inheritdoc */ public function setSubtotal($amount) { @@ -3895,9 +3791,7 @@ public function setSubtotal($amount) } /** - * Set SubtotalCanceled - * - * @return $this + * @inheritdoc */ public function setSubtotalCanceled($subtotalCanceled) { @@ -3905,9 +3799,7 @@ public function setSubtotalCanceled($subtotalCanceled) } /** - * Set SubtotalInvoiced - * - * @return $this + * @inheritdoc */ public function setSubtotalInvoiced($subtotalInvoiced) { @@ -3915,9 +3807,7 @@ public function setSubtotalInvoiced($subtotalInvoiced) } /** - * Set SubtotalRefunded - * - * @return $this + * @inheritdoc */ public function setSubtotalRefunded($subtotalRefunded) { @@ -3925,9 +3815,7 @@ public function setSubtotalRefunded($subtotalRefunded) } /** - * Set TaxAmount - * - * @return $this + * @inheritdoc */ public function setTaxAmount($amount) { @@ -3935,9 +3823,7 @@ public function setTaxAmount($amount) } /** - * Set TaxCanceled - * - * @return $this + * @inheritdoc */ public function setTaxCanceled($taxCanceled) { @@ -3945,9 +3831,7 @@ public function setTaxCanceled($taxCanceled) } /** - * Set TaxInvoiced - * - * @return $this + * @inheritdoc */ public function setTaxInvoiced($taxInvoiced) { @@ -3955,9 +3839,7 @@ public function setTaxInvoiced($taxInvoiced) } /** - * Set TaxRefunded - * - * @return $this + * @inheritdoc */ public function setTaxRefunded($taxRefunded) { @@ -3965,9 +3847,7 @@ public function setTaxRefunded($taxRefunded) } /** - * Set TotalCanceled - * - * @return $this + * @inheritdoc */ public function setTotalCanceled($totalCanceled) { @@ -3975,9 +3855,7 @@ public function setTotalCanceled($totalCanceled) } /** - * Set TotalInvoiced - * - * @return $this + * @inheritdoc */ public function setTotalInvoiced($totalInvoiced) { @@ -3985,9 +3863,7 @@ public function setTotalInvoiced($totalInvoiced) } /** - * Set TotalOfflineRefunded - * - * @return $this + * @inheritdoc */ public function setTotalOfflineRefunded($totalOfflineRefunded) { @@ -3995,9 +3871,7 @@ public function setTotalOfflineRefunded($totalOfflineRefunded) } /** - * Set TotalOnlineRefunded - * - * @return $this + * @inheritdoc */ public function setTotalOnlineRefunded($totalOnlineRefunded) { @@ -4005,9 +3879,7 @@ public function setTotalOnlineRefunded($totalOnlineRefunded) } /** - * Set TotalPaid - * - * @return $this + * @inheritdoc */ public function setTotalPaid($totalPaid) { @@ -4015,9 +3887,7 @@ public function setTotalPaid($totalPaid) } /** - * Set TotalQtyOrdered - * - * @return $this + * @inheritdoc */ public function setTotalQtyOrdered($totalQtyOrdered) { @@ -4025,9 +3895,7 @@ public function setTotalQtyOrdered($totalQtyOrdered) } /** - * Set TotalRefunded - * - * @return $this + * @inheritdoc */ public function setTotalRefunded($totalRefunded) { @@ -4035,9 +3903,7 @@ public function setTotalRefunded($totalRefunded) } /** - * Set CanShipPartially - * - * @return $this + * @inheritdoc */ public function setCanShipPartially($flag) { @@ -4045,9 +3911,7 @@ public function setCanShipPartially($flag) } /** - * Set CanShipPartiallyItem - * - * @return $this + * @inheritdoc */ public function setCanShipPartiallyItem($flag) { @@ -4055,9 +3919,7 @@ public function setCanShipPartiallyItem($flag) } /** - * Set CustomerIsGuest - * - * @return $this + * @inheritdoc */ public function setCustomerIsGuest($customerIsGuest) { @@ -4065,9 +3927,7 @@ public function setCustomerIsGuest($customerIsGuest) } /** - * Set CustomerNoteNotify - * - * @return $this + * @inheritdoc */ public function setCustomerNoteNotify($customerNoteNotify) { @@ -4075,9 +3935,7 @@ public function setCustomerNoteNotify($customerNoteNotify) } /** - * Set BillingAddressId - * - * @return $this + * @inheritdoc */ public function setBillingAddressId($id) { @@ -4085,9 +3943,7 @@ public function setBillingAddressId($id) } /** - * Set CustomerGroupId - * - * @return $this + * @inheritdoc */ public function setCustomerGroupId($id) { @@ -4095,9 +3951,7 @@ public function setCustomerGroupId($id) } /** - * Set EditIncrement - * - * @return $this + * @inheritdoc */ public function setEditIncrement($editIncrement) { @@ -4105,9 +3959,7 @@ public function setEditIncrement($editIncrement) } /** - * Set EmailSent - * - * @return $this + * @inheritdoc */ public function setEmailSent($emailSent) { @@ -4115,9 +3967,7 @@ public function setEmailSent($emailSent) } /** - * Set ForcedShipmentWithInvoice - * - * @return $this + * @inheritdoc */ public function setForcedShipmentWithInvoice($forcedShipmentWithInvoice) { @@ -4125,9 +3975,7 @@ public function setForcedShipmentWithInvoice($forcedShipmentWithInvoice) } /** - * Set PaymentAuthExpiration - * - * @return $this + * @inheritdoc */ public function setPaymentAuthExpiration($paymentAuthExpiration) { @@ -4135,9 +3983,7 @@ public function setPaymentAuthExpiration($paymentAuthExpiration) } /** - * Set QuoteAddressId - * - * @return $this + * @inheritdoc */ public function setQuoteAddressId($id) { @@ -4145,9 +3991,7 @@ public function setQuoteAddressId($id) } /** - * Set QuoteId - * - * @return $this + * @inheritdoc */ public function setQuoteId($id) { @@ -4155,9 +3999,7 @@ public function setQuoteId($id) } /** - * Set AdjustmentNegative - * - * @return $this + * @inheritdoc */ public function setAdjustmentNegative($adjustmentNegative) { @@ -4165,9 +4007,7 @@ public function setAdjustmentNegative($adjustmentNegative) } /** - * Set AdjustmentPositive - * - * @return $this + * @inheritdoc */ public function setAdjustmentPositive($adjustmentPositive) { @@ -4175,9 +4015,7 @@ public function setAdjustmentPositive($adjustmentPositive) } /** - * Set BaseAdjustmentNegative - * - * @return $this + * @inheritdoc */ public function setBaseAdjustmentNegative($baseAdjustmentNegative) { @@ -4185,9 +4023,7 @@ public function setBaseAdjustmentNegative($baseAdjustmentNegative) } /** - * Set BaseAdjustmentPositive - * - * @return $this + * @inheritdoc */ public function setBaseAdjustmentPositive($baseAdjustmentPositive) { @@ -4195,9 +4031,7 @@ public function setBaseAdjustmentPositive($baseAdjustmentPositive) } /** - * Set BaseShippingDiscountAmount - * - * @return $this + * @inheritdoc */ public function setBaseShippingDiscountAmount($amount) { @@ -4205,9 +4039,7 @@ public function setBaseShippingDiscountAmount($amount) } /** - * Set BaseSubtotalInclTax - * - * @return $this + * @inheritdoc */ public function setBaseSubtotalInclTax($amount) { @@ -4215,9 +4047,7 @@ public function setBaseSubtotalInclTax($amount) } /** - * Set BaseTotalDue - * - * @return $this + * @inheritdoc */ public function setBaseTotalDue($baseTotalDue) { @@ -4225,9 +4055,7 @@ public function setBaseTotalDue($baseTotalDue) } /** - * Set PaymentAuthorizationAmount - * - * @return $this + * @inheritdoc */ public function setPaymentAuthorizationAmount($amount) { @@ -4235,9 +4063,7 @@ public function setPaymentAuthorizationAmount($amount) } /** - * Set ShippingDiscountAmount - * - * @return $this + * @inheritdoc */ public function setShippingDiscountAmount($amount) { @@ -4245,9 +4071,7 @@ public function setShippingDiscountAmount($amount) } /** - * Set SubtotalInclTax - * - * @return $this + * @inheritdoc */ public function setSubtotalInclTax($amount) { @@ -4255,9 +4079,7 @@ public function setSubtotalInclTax($amount) } /** - * Set TotalDue - * - * @return $this + * @inheritdoc */ public function setTotalDue($totalDue) { @@ -4265,9 +4087,7 @@ public function setTotalDue($totalDue) } /** - * Set Weight - * - * @return $this + * @inheritdoc */ public function setWeight($weight) { @@ -4275,9 +4095,7 @@ public function setWeight($weight) } /** - * Set CustomerDob - * - * @return $this + * @inheritdoc */ public function setCustomerDob($customerDob) { @@ -4285,9 +4103,7 @@ public function setCustomerDob($customerDob) } /** - * Set IncrementId - * - * @return $this + * @inheritdoc */ public function setIncrementId($id) { @@ -4295,9 +4111,7 @@ public function setIncrementId($id) } /** - * Set AppliedRuleIds - * - * @return $this + * @inheritdoc */ public function setAppliedRuleIds($appliedRuleIds) { @@ -4305,9 +4119,7 @@ public function setAppliedRuleIds($appliedRuleIds) } /** - * Set BaseCurrencyCode - * - * @return $this + * @inheritdoc */ public function setBaseCurrencyCode($code) { @@ -4315,9 +4127,7 @@ public function setBaseCurrencyCode($code) } /** - * Set CustomerEmail - * - * @return $this + * @inheritdoc */ public function setCustomerEmail($customerEmail) { @@ -4325,9 +4135,7 @@ public function setCustomerEmail($customerEmail) } /** - * Set CustomerFirstname - * - * @return $this + * @inheritdoc */ public function setCustomerFirstname($customerFirstname) { @@ -4335,9 +4143,7 @@ public function setCustomerFirstname($customerFirstname) } /** - * Set CustomerLastname - * - * @return $this + * @inheritdoc */ public function setCustomerLastname($customerLastname) { @@ -4345,9 +4151,7 @@ public function setCustomerLastname($customerLastname) } /** - * Set CustomerMiddlename - * - * @return $this + * @inheritdoc */ public function setCustomerMiddlename($customerMiddlename) { @@ -4355,9 +4159,7 @@ public function setCustomerMiddlename($customerMiddlename) } /** - * Set CustomerPrefix - * - * @return $this + * @inheritdoc */ public function setCustomerPrefix($customerPrefix) { @@ -4365,9 +4167,7 @@ public function setCustomerPrefix($customerPrefix) } /** - * Set CustomerSuffix - * - * @return $this + * @inheritdoc */ public function setCustomerSuffix($customerSuffix) { @@ -4375,9 +4175,7 @@ public function setCustomerSuffix($customerSuffix) } /** - * Set CustomerTaxvat - * - * @return $this + * @inheritdoc */ public function setCustomerTaxvat($customerTaxvat) { @@ -4385,9 +4183,7 @@ public function setCustomerTaxvat($customerTaxvat) } /** - * Set DiscountDescription - * - * @return $this + * @inheritdoc */ public function setDiscountDescription($description) { @@ -4395,9 +4191,7 @@ public function setDiscountDescription($description) } /** - * Set ExtCustomerId - * - * @return $this + * @inheritdoc */ public function setExtCustomerId($id) { @@ -4405,9 +4199,7 @@ public function setExtCustomerId($id) } /** - * Set ExtOrderId - * - * @return $this + * @inheritdoc */ public function setExtOrderId($id) { @@ -4415,9 +4207,7 @@ public function setExtOrderId($id) } /** - * Set GlobalCurrencyCode - * - * @return $this + * @inheritdoc */ public function setGlobalCurrencyCode($code) { @@ -4425,9 +4215,7 @@ public function setGlobalCurrencyCode($code) } /** - * Set HoldBeforeState - * - * @return $this + * @inheritdoc */ public function setHoldBeforeState($holdBeforeState) { @@ -4435,9 +4223,7 @@ public function setHoldBeforeState($holdBeforeState) } /** - * Set HoldBeforeStatus - * - * @return $this + * @inheritdoc */ public function setHoldBeforeStatus($holdBeforeStatus) { @@ -4445,9 +4231,7 @@ public function setHoldBeforeStatus($holdBeforeStatus) } /** - * Set OrderCurrencyCode - * - * @return $this + * @inheritdoc */ public function setOrderCurrencyCode($code) { @@ -4455,9 +4239,7 @@ public function setOrderCurrencyCode($code) } /** - * Set OriginalIncrementId - * - * @return $this + * @inheritdoc */ public function setOriginalIncrementId($id) { @@ -4465,9 +4247,7 @@ public function setOriginalIncrementId($id) } /** - * Set RelationChildId - * - * @return $this + * @inheritdoc */ public function setRelationChildId($id) { @@ -4475,9 +4255,7 @@ public function setRelationChildId($id) } /** - * Set RelationChildRealId - * - * @return $this + * @inheritdoc */ public function setRelationChildRealId($realId) { @@ -4485,9 +4263,7 @@ public function setRelationChildRealId($realId) } /** - * Set RelationParentId - * - * @return $this + * @inheritdoc */ public function setRelationParentId($id) { @@ -4495,9 +4271,7 @@ public function setRelationParentId($id) } /** - * Set RelationParentRealId - * - * @return $this + * @inheritdoc */ public function setRelationParentRealId($realId) { @@ -4505,9 +4279,7 @@ public function setRelationParentRealId($realId) } /** - * Set RemoteIp - * - * @return $this + * @inheritdoc */ public function setRemoteIp($remoteIp) { @@ -4515,9 +4287,7 @@ public function setRemoteIp($remoteIp) } /** - * Set StoreCurrencyCode - * - * @return $this + * @inheritdoc */ public function setStoreCurrencyCode($code) { @@ -4525,9 +4295,7 @@ public function setStoreCurrencyCode($code) } /** - * Set StoreName - * - * @return $this + * @inheritdoc */ public function setStoreName($storeName) { @@ -4535,9 +4303,7 @@ public function setStoreName($storeName) } /** - * Set XForwardedFor - * - * @return $this + * @inheritdoc */ public function setXForwardedFor($xForwardedFor) { @@ -4545,9 +4311,7 @@ public function setXForwardedFor($xForwardedFor) } /** - * Set CustomerNote - * - * @return $this + * @inheritdoc */ public function setCustomerNote($customerNote) { @@ -4555,9 +4319,7 @@ public function setCustomerNote($customerNote) } /** - * Set UpdatedAt - * - * @return $this + * @inheritdoc */ public function setUpdatedAt($timestamp) { @@ -4565,9 +4327,7 @@ public function setUpdatedAt($timestamp) } /** - * Set TotalItemCount - * - * @return $this + * @inheritdoc */ public function setTotalItemCount($totalItemCount) { @@ -4575,9 +4335,7 @@ public function setTotalItemCount($totalItemCount) } /** - * Set CustomerGender - * - * @return $this + * @inheritdoc */ public function setCustomerGender($customerGender) { @@ -4585,9 +4343,7 @@ public function setCustomerGender($customerGender) } /** - * Set DiscountTaxCompensationAmount - * - * @return $this + * @inheritdoc */ public function setDiscountTaxCompensationAmount($amount) { @@ -4595,9 +4351,7 @@ public function setDiscountTaxCompensationAmount($amount) } /** - * Set BaseDiscountTaxCompensationAmount - * - * @return $this + * @inheritdoc */ public function setBaseDiscountTaxCompensationAmount($amount) { @@ -4605,9 +4359,7 @@ public function setBaseDiscountTaxCompensationAmount($amount) } /** - * Set ShippingDiscountTaxCompensationAmount - * - * @return $this + * @inheritdoc */ public function setShippingDiscountTaxCompensationAmount($amount) { @@ -4615,9 +4367,7 @@ public function setShippingDiscountTaxCompensationAmount($amount) } /** - * Set BaseShippingDiscountTaxCompensationAmnt - * - * @return $this + * @inheritdoc */ public function setBaseShippingDiscountTaxCompensationAmnt($amnt) { @@ -4625,9 +4375,7 @@ public function setBaseShippingDiscountTaxCompensationAmnt($amnt) } /** - * Set DiscountTaxCompensationInvoiced - * - * @return $this + * @inheritdoc */ public function setDiscountTaxCompensationInvoiced($discountTaxCompensationInvoiced) { @@ -4635,9 +4383,7 @@ public function setDiscountTaxCompensationInvoiced($discountTaxCompensationInvoi } /** - * Set BaseDiscountTaxCompensationInvoiced - * - * @return $this + * @inheritdoc */ public function setBaseDiscountTaxCompensationInvoiced($baseDiscountTaxCompensationInvoiced) { @@ -4648,9 +4394,7 @@ public function setBaseDiscountTaxCompensationInvoiced($baseDiscountTaxCompensat } /** - * Set DiscountTaxCompensationRefunded - * - * @return $this + * @inheritdoc */ public function setDiscountTaxCompensationRefunded($discountTaxCompensationRefunded) { @@ -4661,9 +4405,7 @@ public function setDiscountTaxCompensationRefunded($discountTaxCompensationRefun } /** - * Set BaseDiscountTaxCompensationRefunded - * - * @return $this + * @inheritdoc */ public function setBaseDiscountTaxCompensationRefunded($baseDiscountTaxCompensationRefunded) { @@ -4674,9 +4416,7 @@ public function setBaseDiscountTaxCompensationRefunded($baseDiscountTaxCompensat } /** - * Set ShippingInclTax - * - * @return $this + * @inheritdoc */ public function setShippingInclTax($amount) { diff --git a/app/code/Magento/Sales/Model/Order/Item.php b/app/code/Magento/Sales/Model/Order/Item.php index 423d4b8d09d..cc8bb7aae78 100644 --- a/app/code/Magento/Sales/Model/Order/Item.php +++ b/app/code/Magento/Sales/Model/Order/Item.php @@ -651,7 +651,7 @@ public function isDummy($shipment = false) } /** - * Returns formatted buy request. + * Return formatted buy request. * * This object is holding request received from product view page with keys and options for configured product. * @@ -703,7 +703,7 @@ public function getStore() //@codeCoverageIgnoreStart /** - * Returns additional_data + * Return additional_data * * @return string|null */ @@ -713,7 +713,7 @@ public function getAdditionalData() } /** - * Returns amount_refunded + * Return amount_refunded * * @return float|null */ @@ -723,7 +723,7 @@ public function getAmountRefunded() } /** - * Returns applied_rule_ids + * Return applied_rule_ids * * @return string|null */ @@ -733,7 +733,7 @@ public function getAppliedRuleIds() } /** - * Returns base_amount_refunded + * Return base_amount_refunded * * @return float|null */ @@ -743,7 +743,7 @@ public function getBaseAmountRefunded() } /** - * Returns base_cost + * Return base_cost * * @return float|null */ @@ -753,7 +753,7 @@ public function getBaseCost() } /** - * Returns base_discount_amount + * Return base_discount_amount * * @return float|null */ @@ -763,7 +763,7 @@ public function getBaseDiscountAmount() } /** - * Returns base_discount_invoiced + * Return base_discount_invoiced * * @return float|null */ @@ -773,7 +773,7 @@ public function getBaseDiscountInvoiced() } /** - * Returns base_discount_refunded + * Return base_discount_refunded * * @return float|null */ @@ -783,7 +783,7 @@ public function getBaseDiscountRefunded() } /** - * Returns base_discount_tax_compensation_amount + * Return base_discount_tax_compensation_amount * * @return float|null */ @@ -793,7 +793,7 @@ public function getBaseDiscountTaxCompensationAmount() } /** - * Returns base_discount_tax_compensation_invoiced + * Return base_discount_tax_compensation_invoiced * * @return float|null */ @@ -803,7 +803,7 @@ public function getBaseDiscountTaxCompensationInvoiced() } /** - * Returns base_discount_tax_compensation_refunded + * Return base_discount_tax_compensation_refunded * * @return float|null */ @@ -813,7 +813,7 @@ public function getBaseDiscountTaxCompensationRefunded() } /** - * Returns base_original_price + * Return base_original_price * * @return float|null */ @@ -823,7 +823,7 @@ public function getBaseOriginalPrice() } /** - * Returns base_price + * Return base_price * * @return float|null */ @@ -833,7 +833,7 @@ public function getBasePrice() } /** - * Returns base_price_incl_tax + * Return base_price_incl_tax * * @return float|null */ @@ -843,7 +843,7 @@ public function getBasePriceInclTax() } /** - * Returns base_row_invoiced + * Return base_row_invoiced * * @return float|null */ @@ -853,7 +853,7 @@ public function getBaseRowInvoiced() } /** - * Returns base_row_total + * Return base_row_total * * @return float|null */ @@ -863,7 +863,7 @@ public function getBaseRowTotal() } /** - * Returns base_row_total_incl_tax + * Return base_row_total_incl_tax * * @return float|null */ @@ -873,7 +873,7 @@ public function getBaseRowTotalInclTax() } /** - * Returns base_tax_amount + * Return base_tax_amount * * @return float|null */ @@ -883,7 +883,7 @@ public function getBaseTaxAmount() } /** - * Returns base_tax_before_discount + * Return base_tax_before_discount * * @return float|null */ @@ -893,7 +893,7 @@ public function getBaseTaxBeforeDiscount() } /** - * Returns base_tax_invoiced + * Return base_tax_invoiced * * @return float|null */ @@ -903,7 +903,7 @@ public function getBaseTaxInvoiced() } /** - * Returns base_tax_refunded + * Return base_tax_refunded * * @return float|null */ @@ -913,7 +913,7 @@ public function getBaseTaxRefunded() } /** - * Returns base_weee_tax_applied_amount + * Return base_weee_tax_applied_amount * * @return float|null */ @@ -923,7 +923,7 @@ public function getBaseWeeeTaxAppliedAmount() } /** - * Returns base_weee_tax_applied_row_amnt + * Return base_weee_tax_applied_row_amnt * * @return float|null */ @@ -933,7 +933,7 @@ public function getBaseWeeeTaxAppliedRowAmnt() } /** - * Returns base_weee_tax_disposition + * Return base_weee_tax_disposition * * @return float|null */ @@ -943,7 +943,7 @@ public function getBaseWeeeTaxDisposition() } /** - * Returns base_weee_tax_row_disposition + * Return base_weee_tax_row_disposition * * @return float|null */ @@ -953,7 +953,7 @@ public function getBaseWeeeTaxRowDisposition() } /** - * Returns created_at + * Return created_at * * @return string|null */ @@ -971,7 +971,7 @@ public function setCreatedAt($createdAt) } /** - * Returns description + * Return description * * @return string|null */ @@ -981,7 +981,7 @@ public function getDescription() } /** - * Returns discount_amount + * Return discount_amount * * @return float|null */ @@ -991,7 +991,7 @@ public function getDiscountAmount() } /** - * Returns discount_invoiced + * Return discount_invoiced * * @return float|null */ @@ -1001,7 +1001,7 @@ public function getDiscountInvoiced() } /** - * Returns discount_percent + * Return discount_percent * * @return float|null */ @@ -1011,7 +1011,7 @@ public function getDiscountPercent() } /** - * Returns discount_refunded + * Return discount_refunded * * @return float|null */ @@ -1021,7 +1021,7 @@ public function getDiscountRefunded() } /** - * Returns event_id + * Return event_id * * @return int|null */ @@ -1031,7 +1031,7 @@ public function getEventId() } /** - * Returns ext_order_item_id + * Return ext_order_item_id * * @return string|null */ @@ -1041,7 +1041,7 @@ public function getExtOrderItemId() } /** - * Returns free_shipping + * Return free_shipping * * @return int|null */ @@ -1051,7 +1051,7 @@ public function getFreeShipping() } /** - * Returns gw_base_price + * Return gw_base_price * * @return float|null */ @@ -1061,7 +1061,7 @@ public function getGwBasePrice() } /** - * Returns gw_base_price_invoiced + * Return gw_base_price_invoiced * * @return float|null */ @@ -1071,7 +1071,7 @@ public function getGwBasePriceInvoiced() } /** - * Returns gw_base_price_refunded + * Return gw_base_price_refunded * * @return float|null */ @@ -1081,7 +1081,7 @@ public function getGwBasePriceRefunded() } /** - * Returns gw_base_tax_amount + * Return gw_base_tax_amount * * @return float|null */ @@ -1091,7 +1091,7 @@ public function getGwBaseTaxAmount() } /** - * Returns gw_base_tax_amount_invoiced + * Return gw_base_tax_amount_invoiced * * @return float|null */ @@ -1101,7 +1101,7 @@ public function getGwBaseTaxAmountInvoiced() } /** - * Returns gw_base_tax_amount_refunded + * Return gw_base_tax_amount_refunded * * @return float|null */ @@ -1111,7 +1111,7 @@ public function getGwBaseTaxAmountRefunded() } /** - * Returns gw_id + * Return gw_id * * @return int|null */ @@ -1121,7 +1121,7 @@ public function getGwId() } /** - * Returns gw_price + * Return gw_price * * @return float|null */ @@ -1131,7 +1131,7 @@ public function getGwPrice() } /** - * Returns gw_price_invoiced + * Return gw_price_invoiced * * @return float|null */ @@ -1141,7 +1141,7 @@ public function getGwPriceInvoiced() } /** - * Returns gw_price_refunded + * Return gw_price_refunded * * @return float|null */ @@ -1151,7 +1151,7 @@ public function getGwPriceRefunded() } /** - * Returns gw_tax_amount + * Return gw_tax_amount * * @return float|null */ @@ -1161,7 +1161,7 @@ public function getGwTaxAmount() } /** - * Returns gw_tax_amount_invoiced + * Return gw_tax_amount_invoiced * * @return float|null */ @@ -1171,7 +1171,7 @@ public function getGwTaxAmountInvoiced() } /** - * Returns gw_tax_amount_refunded + * Return gw_tax_amount_refunded * * @return float|null */ @@ -1181,7 +1181,7 @@ public function getGwTaxAmountRefunded() } /** - * Returns discount_tax_compensation_amount + * Return discount_tax_compensation_amount * * @return float|null */ @@ -1191,7 +1191,7 @@ public function getDiscountTaxCompensationAmount() } /** - * Returns discount_tax_compensation_canceled + * Return discount_tax_compensation_canceled * * @return float|null */ @@ -1201,7 +1201,7 @@ public function getDiscountTaxCompensationCanceled() } /** - * Returns discount_tax_compensation_invoiced + * Return discount_tax_compensation_invoiced * * @return float|null */ @@ -1211,7 +1211,7 @@ public function getDiscountTaxCompensationInvoiced() } /** - * Returns discount_tax_compensation_refunded + * Return discount_tax_compensation_refunded * * @return float|null */ @@ -1221,7 +1221,7 @@ public function getDiscountTaxCompensationRefunded() } /** - * Returns is_qty_decimal + * Return is_qty_decimal * * @return int|null */ @@ -1231,7 +1231,7 @@ public function getIsQtyDecimal() } /** - * Returns is_virtual + * Return is_virtual * * @return int|null */ @@ -1241,7 +1241,7 @@ public function getIsVirtual() } /** - * Returns item_id + * Return item_id * * @return int|null */ @@ -1251,7 +1251,7 @@ public function getItemId() } /** - * Returns locked_do_invoice + * Return locked_do_invoice * * @return int|null */ @@ -1261,7 +1261,7 @@ public function getLockedDoInvoice() } /** - * Returns locked_do_ship + * Return locked_do_ship * * @return int|null */ @@ -1271,7 +1271,7 @@ public function getLockedDoShip() } /** - * Returns name + * Return name * * @return string|null */ @@ -1281,7 +1281,7 @@ public function getName() } /** - * Returns no_discount + * Return no_discount * * @return int|null */ @@ -1291,7 +1291,7 @@ public function getNoDiscount() } /** - * Returns order_id + * Return order_id * * @return int|null */ @@ -1301,7 +1301,7 @@ public function getOrderId() } /** - * Returns parent_item_id + * Return parent_item_id * * @return int|null */ @@ -1311,7 +1311,7 @@ public function getParentItemId() } /** - * Returns price + * Return price * * @return float|null */ @@ -1321,7 +1321,7 @@ public function getPrice() } /** - * Returns price_incl_tax + * Return price_incl_tax * * @return float|null */ @@ -1331,7 +1331,7 @@ public function getPriceInclTax() } /** - * Returns product_id + * Return product_id * * @return int|null */ @@ -1341,7 +1341,7 @@ public function getProductId() } /** - * Returns product_type + * Return product_type * * @return string|null */ @@ -1351,7 +1351,7 @@ public function getProductType() } /** - * Returns qty_backordered + * Return qty_backordered * * @return float|null */ @@ -1361,7 +1361,7 @@ public function getQtyBackordered() } /** - * Returns qty_canceled + * Return qty_canceled * * @return float|null */ @@ -1371,7 +1371,7 @@ public function getQtyCanceled() } /** - * Returns qty_invoiced + * Return qty_invoiced * * @return float|null */ @@ -1381,7 +1381,7 @@ public function getQtyInvoiced() } /** - * Returns qty_ordered + * Return qty_ordered * * @return float|null */ @@ -1391,7 +1391,7 @@ public function getQtyOrdered() } /** - * Returns qty_refunded + * Return qty_refunded * * @return float|null */ @@ -1401,7 +1401,7 @@ public function getQtyRefunded() } /** - * Returns qty_returned + * Return qty_returned * * @return float|null */ @@ -1411,7 +1411,7 @@ public function getQtyReturned() } /** - * Returns qty_shipped + * Return qty_shipped * * @return float|null */ @@ -1421,7 +1421,7 @@ public function getQtyShipped() } /** - * Returns quote_item_id + * Return quote_item_id * * @return int|null */ @@ -1431,7 +1431,7 @@ public function getQuoteItemId() } /** - * Returns row_invoiced + * Return row_invoiced * * @return float|null */ @@ -1441,7 +1441,7 @@ public function getRowInvoiced() } /** - * Returns row_total + * Return row_total * * @return float|null */ @@ -1451,7 +1451,7 @@ public function getRowTotal() } /** - * Returns row_total_incl_tax + * Return row_total_incl_tax * * @return float|null */ @@ -1461,7 +1461,7 @@ public function getRowTotalInclTax() } /** - * Returns row_weight + * Return row_weight * * @return float|null */ @@ -1471,7 +1471,7 @@ public function getRowWeight() } /** - * Returns sku + * Return sku * * @return string */ @@ -1481,7 +1481,7 @@ public function getSku() } /** - * Returns store_id + * Return store_id * * @return int|null */ @@ -1491,7 +1491,7 @@ public function getStoreId() } /** - * Returns tax_amount + * Return tax_amount * * @return float|null */ @@ -1501,7 +1501,7 @@ public function getTaxAmount() } /** - * Returns tax_before_discount + * Return tax_before_discount * * @return float|null */ @@ -1511,7 +1511,7 @@ public function getTaxBeforeDiscount() } /** - * Returns tax_canceled + * Return tax_canceled * * @return float|null */ @@ -1521,7 +1521,7 @@ public function getTaxCanceled() } /** - * Returns tax_invoiced + * Return tax_invoiced * * @return float|null */ @@ -1531,7 +1531,7 @@ public function getTaxInvoiced() } /** - * Returns tax_percent + * Return tax_percent * * @return float|null */ @@ -1541,7 +1541,7 @@ public function getTaxPercent() } /** - * Returns tax_refunded + * Return tax_refunded * * @return float|null */ @@ -1551,7 +1551,7 @@ public function getTaxRefunded() } /** - * Returns updated_at + * Return updated_at * * @return string|null */ @@ -1561,7 +1561,7 @@ public function getUpdatedAt() } /** - * Returns weee_tax_applied + * Return weee_tax_applied * * @return string|null */ @@ -1571,7 +1571,7 @@ public function getWeeeTaxApplied() } /** - * Returns weee_tax_applied_amount + * Return weee_tax_applied_amount * * @return float|null */ @@ -1581,7 +1581,7 @@ public function getWeeeTaxAppliedAmount() } /** - * Returns weee_tax_applied_row_amount + * Return weee_tax_applied_row_amount * * @return float|null */ @@ -1591,7 +1591,7 @@ public function getWeeeTaxAppliedRowAmount() } /** - * Returns weee_tax_disposition + * Return weee_tax_disposition * * @return float|null */ @@ -1601,7 +1601,7 @@ public function getWeeeTaxDisposition() } /** - * Returns weee_tax_row_disposition + * Return weee_tax_row_disposition * * @return float|null */ @@ -1611,7 +1611,7 @@ public function getWeeeTaxRowDisposition() } /** - * Returns weight + * Return weight * * @return float|null */ From d0840536ed651a94bc684489a57207ce34048545 Mon Sep 17 00:00:00 2001 From: Max Lesechko <mlesechko@magento.com> Date: Mon, 17 Sep 2018 16:04:01 -0500 Subject: [PATCH 26/44] MAGETWO-94819: Swatch validation breaks the whole attribute form --- .../Controller/Adminhtml/Product/Attribute/Save.php | 2 +- .../Controller/Adminhtml/Product/Attribute/Validate.php | 2 +- .../Mftf/Test/AdminEditTextEditorProductAttributeTest.xml | 7 +++---- .../Controller/Adminhtml/Product/Attribute/SaveTest.php | 6 +++--- .../Adminhtml/Product/Attribute/ValidateTest.php | 8 ++++---- 5 files changed, 12 insertions(+), 13 deletions(-) diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Save.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Save.php index e32d84b393a..e730381b0ea 100644 --- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Save.php +++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Save.php @@ -140,7 +140,7 @@ public function execute() { try { $optionData = $this->optionsDataSerializer - ->unserialize($this->getRequest()->getParam('serialized_options')); + ->unserialize($this->getRequest()->getParam('serialized_options', '[]')); } catch (\InvalidArgumentException $e) { $message = __("The attribute couldn't be saved due to an error. Verify your information and try again. " . "If the error persists, please try again later."); diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Validate.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Validate.php index 34dcf6639f9..16449762b4a 100644 --- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Validate.php +++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Validate.php @@ -83,7 +83,7 @@ public function execute() $response->setError(false); try { $optionsData = $this->optionsDataSerializer - ->unserialize($this->getRequest()->getParam('serialized_options')); + ->unserialize($this->getRequest()->getParam('serialized_options', '[]')); } catch (\InvalidArgumentException $e) { $message = __("The attribute couldn't be validated due to an error. Verify your information and try again. " . "If the error persists, please try again later."); diff --git a/app/code/Magento/Catalog/Test/Mftf/Test/AdminEditTextEditorProductAttributeTest.xml b/app/code/Magento/Catalog/Test/Mftf/Test/AdminEditTextEditorProductAttributeTest.xml index 7603400ba8d..e914b8c96d0 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Test/AdminEditTextEditorProductAttributeTest.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Test/AdminEditTextEditorProductAttributeTest.xml @@ -26,10 +26,9 @@ <requiredEntity createDataKey="myProductAttributeCreation"/> </createData> </before> - <amOnPage url="{{AdminProductAttributeGridPage.url}}" stepKey="navigateToProductAttributeGrid1"/> - <waitForPageLoad stepKey="waitForPageLoad1"/> - <click selector="{{AdminProductAttributeGridSection.AttributeCode($$myProductAttributeCreation.attribute_code$$)}}" stepKey="navigateToAttributeEditPage1" /> - <waitForPageLoad stepKey="waitForPageLoad2" /> + <actionGroup ref="navigateToCreatedProductAttribute" stepKey="navigateToAttribute"> + <argument name="ProductAttribute" value="productAttributeWysiwyg"/> + </actionGroup> <seeOptionIsSelected selector="{{AttributePropertiesSection.InputType}}" userInput="Text Editor" stepKey="seeTextEditorSelected" /> <see selector="{{AttributePropertiesSection.InputType}}" userInput="Text Area" stepKey="seeTextArea1" /> <selectOption selector="{{AttributePropertiesSection.InputType}}" userInput="Text Area" stepKey="selectTextArea" /> diff --git a/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Attribute/SaveTest.php b/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Attribute/SaveTest.php index b9b1aeb9157..f34a70260a2 100644 --- a/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Attribute/SaveTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Attribute/SaveTest.php @@ -180,7 +180,7 @@ public function testExecuteWithEmptyData() ->method('getParam') ->willReturnMap([ ['isAjax', null, null], - ['serialized_options', null, ''], + ['serialized_options', '[]', ''], ]); $this->optionsDataSerializerMock ->expects($this->once()) @@ -211,7 +211,7 @@ public function testExecute() ->method('getParam') ->willReturnMap([ ['isAjax', null, null], - ['serialized_options', null, ''], + ['serialized_options', '[]', ''], ]); $this->optionsDataSerializerMock ->expects($this->once()) @@ -271,7 +271,7 @@ public function testExecuteWithOptionsDataError() ->method('getParam') ->willReturnMap([ ['isAjax', null, true], - ['serialized_options', null, $serializedOptions], + ['serialized_options', '[]', $serializedOptions], ]); $this->optionsDataSerializerMock ->expects($this->once()) diff --git a/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Attribute/ValidateTest.php b/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Attribute/ValidateTest.php index e9fc8bf3362..17af610fed7 100644 --- a/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Attribute/ValidateTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Attribute/ValidateTest.php @@ -130,7 +130,7 @@ public function testExecute() ['frontend_label', null, 'test_frontend_label'], ['attribute_code', null, 'test_attribute_code'], ['new_attribute_set_name', null, 'test_attribute_set_name'], - ['serialized_options', null, $serializedOptions], + ['serialized_options', '[]', $serializedOptions], ]); $this->objectManagerMock->expects($this->exactly(2)) ->method('create') @@ -181,7 +181,7 @@ public function testUniqueValidation(array $options, $isError) ['attribute_code', null, "test_attribute_code"], ['new_attribute_set_name', null, 'test_attribute_set_name'], ['message_key', null, Validate::DEFAULT_MESSAGE_KEY], - ['serialized_options', null, $serializedOptions], + ['serialized_options', '[]', $serializedOptions], ]); $this->optionsDataSerializerMock @@ -316,7 +316,7 @@ public function testEmptyOption(array $options, $result) ['attribute_code', null, "test_attribute_code"], ['new_attribute_set_name', null, 'test_attribute_set_name'], ['message_key', Validate::DEFAULT_MESSAGE_KEY, 'message'], - ['serialized_options', null, $serializedOptions], + ['serialized_options', '[]', $serializedOptions], ]); $this->optionsDataSerializerMock @@ -428,7 +428,7 @@ public function testExecuteWithOptionsDataError() ['attribute_code', null, 'test_attribute_code'], ['new_attribute_set_name', null, 'test_attribute_set_name'], ['message_key', Validate::DEFAULT_MESSAGE_KEY, 'message'], - ['serialized_options', null, $serializedOptions], + ['serialized_options', '[]', $serializedOptions], ]); $this->optionsDataSerializerMock From d1cbcc0e238fe7328c1af2b504908ec6473a1435 Mon Sep 17 00:00:00 2001 From: Max Lesechko <mlesechko@magento.com> Date: Mon, 17 Sep 2018 16:42:37 -0500 Subject: [PATCH 27/44] MAGETWO-94819: Swatch validation breaks the whole attribute form -- fix merge conflict --- .../Adminhtml/Product/Attribute/Validate.php | 5 ++++- .../Adminhtml/Product/AttributeTest.php | 20 +++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Validate.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Validate.php index 16449762b4a..d9627ddd147 100644 --- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Validate.php +++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Validate.php @@ -8,15 +8,18 @@ namespace Magento\Catalog\Controller\Adminhtml\Product\Attribute; use Magento\Catalog\Model\Product\Attribute\Option\OptionsDataSerializer; +use Magento\Framework\App\Action\HttpGetActionInterface; +use Magento\Framework\App\Action\HttpPostActionInterface as HttpPostActionInterface; use Magento\Framework\App\ObjectManager; use Magento\Framework\DataObject; +use Magento\Catalog\Controller\Adminhtml\Product\Attribute as AttributeAction; /** * Product attribute validate controller. * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ -class Validate extends \Magento\Catalog\Controller\Adminhtml\Product\Attribute +class Validate extends AttributeAction implements HttpGetActionInterface, HttpPostActionInterface { const DEFAULT_MESSAGE_KEY = 'message'; diff --git a/dev/tests/integration/testsuite/Magento/Swatches/Controller/Adminhtml/Product/AttributeTest.php b/dev/tests/integration/testsuite/Magento/Swatches/Controller/Adminhtml/Product/AttributeTest.php index 1a0073b154f..36e216ab4e5 100644 --- a/dev/tests/integration/testsuite/Magento/Swatches/Controller/Adminhtml/Product/AttributeTest.php +++ b/dev/tests/integration/testsuite/Magento/Swatches/Controller/Adminhtml/Product/AttributeTest.php @@ -7,6 +7,8 @@ namespace Magento\Swatches\Controller\Adminhtml\Product; +use Magento\Framework\App\Request\Http as HttpRequest; +use Magento\Framework\Data\Form\FormKey; use Magento\Framework\Exception\LocalizedException; /** @@ -17,6 +19,21 @@ */ class AttributeTest extends \Magento\TestFramework\TestCase\AbstractBackendController { + /** + * @var FormKey + */ + private $formKey; + + /** + * @inheritDoc + */ + protected function setUp() + { + parent::setUp(); + + $this->formKey = $this->_objectManager->get(FormKey::class); + } + /** * Generate random hex color. * @@ -116,6 +133,7 @@ private function getAttributePreset() : array { return [ 'form_key' => 'XxtpPYjm2YPYUlAt', + 'serialized_options' => '[]', 'frontend_label' => [ 0 => 'asdasd', 1 => '', @@ -178,7 +196,9 @@ public function testLargeOptionsDataSet( int $expectedOptionsCount, array $expectedLabels ) : void { + $this->getRequest()->setMethod(HttpRequest::METHOD_POST); $this->getRequest()->setPostValue($attributeData); + $this->getRequest()->setPostValue('form_key', $this->formKey->getFormKey()); $this->dispatch('backend/catalog/product_attribute/save'); $entityTypeId = $this->_objectManager->create( \Magento\Eav\Model\Entity::class From b33c4b2ccfb71a4ed126749698a530330fa8aab8 Mon Sep 17 00:00:00 2001 From: Max Lesechko <mlesechko@magento.com> Date: Tue, 18 Sep 2018 13:56:47 -0500 Subject: [PATCH 28/44] MAGETWO-94819: Swatch validation breaks the whole attribute form --- .../Adminhtml/Product/Attribute/Save.php | 16 +++--- .../Adminhtml/Product/Attribute/Validate.php | 16 +++--- .../Option/OptionsDataSerializer.php | 50 ----------------- .../Adminhtml/Product/Attribute/SaveTest.php | 16 +++--- .../Product/Attribute/ValidateTest.php | 16 +++--- .../Serialize/Serializer/FormData.php | 53 +++++++++++++++++++ 6 files changed, 85 insertions(+), 82 deletions(-) delete mode 100644 app/code/Magento/Catalog/Model/Product/Attribute/Option/OptionsDataSerializer.php create mode 100644 lib/internal/Magento/Framework/Serialize/Serializer/FormData.php diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Save.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Save.php index bf60381a8a4..435fdb0b413 100644 --- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Save.php +++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Save.php @@ -14,7 +14,7 @@ use Magento\Catalog\Controller\Adminhtml\Product\Attribute; use Magento\Catalog\Helper\Product; use Magento\Catalog\Model\Product\Attribute\Frontend\Inputtype\Presentation; -use Magento\Catalog\Model\Product\Attribute\Option\OptionsDataSerializer; +use Magento\Framework\Serialize\Serializer\FormData; use Magento\Catalog\Model\Product\AttributeSet\BuildFactory; use Magento\Catalog\Model\ResourceModel\Eav\AttributeFactory; use Magento\Eav\Model\Adminhtml\System\Config\Source\Inputtype\Validator; @@ -80,9 +80,9 @@ class Save extends Attribute implements HttpPostActionInterface private $presentation; /** - * @var OptionsDataSerializer|null + * @var FormData|null */ - private $optionsDataSerializer; + private $dataSerializer; /** * @param Context $context @@ -97,7 +97,7 @@ class Save extends Attribute implements HttpPostActionInterface * @param Product $productHelper * @param LayoutFactory $layoutFactory * @param Presentation|null $presentation - * @param OptionsDataSerializer|null $optionsDataSerializer + * @param FormData|null $dataSerializer * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( @@ -113,7 +113,7 @@ public function __construct( Product $productHelper, LayoutFactory $layoutFactory, Presentation $presentation = null, - OptionsDataSerializer $optionsDataSerializer = null + FormData $dataSerializer = null ) { parent::__construct($context, $attributeLabelCache, $coreRegistry, $resultPageFactory); $this->buildFactory = $buildFactory; @@ -124,8 +124,8 @@ public function __construct( $this->groupCollectionFactory = $groupCollectionFactory; $this->layoutFactory = $layoutFactory; $this->presentation = $presentation ?: ObjectManager::getInstance()->get(Presentation::class); - $this->optionsDataSerializer = $optionsDataSerializer - ?: ObjectManager::getInstance()->get(OptionsDataSerializer::class); + $this->dataSerializer = $dataSerializer + ?: ObjectManager::getInstance()->get(FormData::class); } /** @@ -140,7 +140,7 @@ public function __construct( public function execute() { try { - $optionData = $this->optionsDataSerializer + $optionData = $this->dataSerializer ->unserialize($this->getRequest()->getParam('serialized_options', '[]')); } catch (\InvalidArgumentException $e) { $message = __("The attribute couldn't be saved due to an error. Verify your information and try again. " diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Validate.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Validate.php index d9627ddd147..4e33fc737f0 100644 --- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Validate.php +++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Validate.php @@ -7,7 +7,7 @@ namespace Magento\Catalog\Controller\Adminhtml\Product\Attribute; -use Magento\Catalog\Model\Product\Attribute\Option\OptionsDataSerializer; +use Magento\Framework\Serialize\Serializer\FormData; use Magento\Framework\App\Action\HttpGetActionInterface; use Magento\Framework\App\Action\HttpPostActionInterface as HttpPostActionInterface; use Magento\Framework\App\ObjectManager; @@ -39,9 +39,9 @@ class Validate extends AttributeAction implements HttpGetActionInterface, HttpPo private $multipleAttributeList; /** - * @var OptionsDataSerializer|null + * @var FormData|null */ - private $optionsDataSerializer; + private $dataSerializer; /** * Constructor @@ -53,7 +53,7 @@ class Validate extends AttributeAction implements HttpGetActionInterface, HttpPo * @param \Magento\Framework\Controller\Result\JsonFactory $resultJsonFactory * @param \Magento\Framework\View\LayoutFactory $layoutFactory * @param array $multipleAttributeList - * @param OptionsDataSerializer|null $optionsDataSerializer + * @param FormData|null $dataSerializer */ public function __construct( \Magento\Backend\App\Action\Context $context, @@ -63,14 +63,14 @@ public function __construct( \Magento\Framework\Controller\Result\JsonFactory $resultJsonFactory, \Magento\Framework\View\LayoutFactory $layoutFactory, array $multipleAttributeList = [], - OptionsDataSerializer $optionsDataSerializer = null + FormData $dataSerializer = null ) { parent::__construct($context, $attributeLabelCache, $coreRegistry, $resultPageFactory); $this->resultJsonFactory = $resultJsonFactory; $this->layoutFactory = $layoutFactory; $this->multipleAttributeList = $multipleAttributeList; - $this->optionsDataSerializer = $optionsDataSerializer ?: ObjectManager::getInstance() - ->get(OptionsDataSerializer::class); + $this->dataSerializer = $dataSerializer ?: ObjectManager::getInstance() + ->get(FormData::class); } /** @@ -85,7 +85,7 @@ public function execute() $response = new DataObject(); $response->setError(false); try { - $optionsData = $this->optionsDataSerializer + $optionsData = $this->dataSerializer ->unserialize($this->getRequest()->getParam('serialized_options', '[]')); } catch (\InvalidArgumentException $e) { $message = __("The attribute couldn't be validated due to an error. Verify your information and try again. " diff --git a/app/code/Magento/Catalog/Model/Product/Attribute/Option/OptionsDataSerializer.php b/app/code/Magento/Catalog/Model/Product/Attribute/Option/OptionsDataSerializer.php deleted file mode 100644 index 8fe02a9123b..00000000000 --- a/app/code/Magento/Catalog/Model/Product/Attribute/Option/OptionsDataSerializer.php +++ /dev/null @@ -1,50 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ - -declare(strict_types=1); - -namespace Magento\Catalog\Model\Product\Attribute\Option; - -use Magento\Framework\Serialize\SerializerInterface; - -/** - * Attribute options data serializer. - */ -class OptionsDataSerializer -{ - /** - * @var SerializerInterface - */ - private $serializer; - - /** - * @param SerializerInterface $serializer - */ - public function __construct(SerializerInterface $serializer) - { - $this->serializer = $serializer; - } - - /** - * Provides attribute options data from the serialized data. - * - * @param string $serializedOptions - * @return array - */ - public function unserialize(string $serializedOptions): array - { - $optionsData = []; - $encodedOptions = $this->serializer->unserialize($serializedOptions); - - foreach ($encodedOptions as $encodedOption) { - $decodedOptionData = []; - parse_str($encodedOption, $decodedOptionData); - $optionsData = array_replace_recursive($optionsData, $decodedOptionData); - } - - return $optionsData; - } -} diff --git a/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Attribute/SaveTest.php b/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Attribute/SaveTest.php index f34a70260a2..e73f3527517 100644 --- a/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Attribute/SaveTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Attribute/SaveTest.php @@ -7,7 +7,7 @@ use Magento\Catalog\Api\Data\ProductAttributeInterface; use Magento\Catalog\Controller\Adminhtml\Product\Attribute\Save; -use Magento\Catalog\Model\Product\Attribute\Option\OptionsDataSerializer; +use Magento\Framework\Serialize\Serializer\FormData; use Magento\Catalog\Test\Unit\Controller\Adminhtml\Product\AttributeTest; use Magento\Catalog\Model\Product\AttributeSet\BuildFactory; use Magento\Catalog\Model\Product\AttributeSet\Build; @@ -85,9 +85,9 @@ class SaveTest extends AttributeTest protected $inputTypeValidatorMock; /** - * @var OptionsDataSerializer|\PHPUnit_Framework_MockObject_MockObject + * @var FormData|\PHPUnit_Framework_MockObject_MockObject */ - private $optionsDataSerializerMock; + private $dataSerializerMock; /** * @var ProductAttributeInterface|\PHPUnit_Framework_MockObject_MockObject @@ -135,7 +135,7 @@ protected function setUp() $this->inputTypeValidatorMock = $this->getMockBuilder(InputTypeValidator::class) ->disableOriginalConstructor() ->getMock(); - $this->optionsDataSerializerMock = $this->getMockBuilder(OptionsDataSerializer::class) + $this->dataSerializerMock = $this->getMockBuilder(FormData::class) ->disableOriginalConstructor() ->getMock(); $this->productAttributeMock = $this->getMockBuilder(ProductAttributeInterface::class) @@ -170,7 +170,7 @@ protected function getModel() 'validatorFactory' => $this->validatorFactoryMock, 'groupCollectionFactory' => $this->groupCollectionFactoryMock, 'layoutFactory' => $this->layoutFactoryMock, - 'optionsDataSerializer' => $this->optionsDataSerializerMock, + 'dataSerializer' => $this->dataSerializerMock, ]); } @@ -182,7 +182,7 @@ public function testExecuteWithEmptyData() ['isAjax', null, null], ['serialized_options', '[]', ''], ]); - $this->optionsDataSerializerMock + $this->dataSerializerMock ->expects($this->once()) ->method('unserialize') ->with('') @@ -213,7 +213,7 @@ public function testExecute() ['isAjax', null, null], ['serialized_options', '[]', ''], ]); - $this->optionsDataSerializerMock + $this->dataSerializerMock ->expects($this->once()) ->method('unserialize') ->with('') @@ -273,7 +273,7 @@ public function testExecuteWithOptionsDataError() ['isAjax', null, true], ['serialized_options', '[]', $serializedOptions], ]); - $this->optionsDataSerializerMock + $this->dataSerializerMock ->expects($this->once()) ->method('unserialize') ->with($serializedOptions) diff --git a/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Attribute/ValidateTest.php b/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Attribute/ValidateTest.php index 17af610fed7..666e6c1942c 100644 --- a/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Attribute/ValidateTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Attribute/ValidateTest.php @@ -6,7 +6,7 @@ namespace Magento\Catalog\Test\Unit\Controller\Adminhtml\Product\Attribute; use Magento\Catalog\Controller\Adminhtml\Product\Attribute\Validate; -use Magento\Catalog\Model\Product\Attribute\Option\OptionsDataSerializer; +use Magento\Framework\Serialize\Serializer\FormData; use Magento\Catalog\Model\ResourceModel\Eav\Attribute; use Magento\Catalog\Test\Unit\Controller\Adminhtml\Product\AttributeTest; use Magento\Eav\Model\Entity\Attribute\Set as AttributeSet; @@ -63,9 +63,9 @@ class ValidateTest extends AttributeTest protected $layoutMock; /** - * @var OptionsDataSerializer|\PHPUnit_Framework_MockObject_MockObject + * @var FormData|\PHPUnit_Framework_MockObject_MockObject */ - private $optionsDataSerializerMock; + private $dataSerializerMock; protected function setUp() { @@ -92,7 +92,7 @@ protected function setUp() ->getMock(); $this->layoutMock = $this->getMockBuilder(LayoutInterface::class) ->getMockForAbstractClass(); - $this->optionsDataSerializerMock = $this->getMockBuilder(OptionsDataSerializer::class) + $this->dataSerializerMock = $this->getMockBuilder(FormData::class) ->disableOriginalConstructor() ->getMock(); @@ -116,7 +116,7 @@ protected function getModel() 'resultJsonFactory' => $this->resultJsonFactoryMock, 'layoutFactory' => $this->layoutFactoryMock, 'multipleAttributeList' => ['select' => 'option'], - 'optionsDataSerializer' => $this->optionsDataSerializerMock, + 'dataSerializer' => $this->dataSerializerMock, ] ); } @@ -184,7 +184,7 @@ public function testUniqueValidation(array $options, $isError) ['serialized_options', '[]', $serializedOptions], ]); - $this->optionsDataSerializerMock + $this->dataSerializerMock ->expects($this->once()) ->method('unserialize') ->with($serializedOptions) @@ -319,7 +319,7 @@ public function testEmptyOption(array $options, $result) ['serialized_options', '[]', $serializedOptions], ]); - $this->optionsDataSerializerMock + $this->dataSerializerMock ->expects($this->once()) ->method('unserialize') ->with($serializedOptions) @@ -431,7 +431,7 @@ public function testExecuteWithOptionsDataError() ['serialized_options', '[]', $serializedOptions], ]); - $this->optionsDataSerializerMock + $this->dataSerializerMock ->expects($this->once()) ->method('unserialize') ->with($serializedOptions) diff --git a/lib/internal/Magento/Framework/Serialize/Serializer/FormData.php b/lib/internal/Magento/Framework/Serialize/Serializer/FormData.php new file mode 100644 index 00000000000..a945822d92f --- /dev/null +++ b/lib/internal/Magento/Framework/Serialize/Serializer/FormData.php @@ -0,0 +1,53 @@ +<?php +/** + * Copyright © Magento, Inc. All rights reserved. + * See COPYING.txt for license details. + */ + +declare(strict_types=1); + +namespace Magento\Framework\Serialize\Serializer; + +/** + * Class for processing of serialized form data. + */ +class FormData +{ + /** + * @var Json + */ + private $serializer; + + /** + * @param Json $serializer + */ + public function __construct(Json $serializer) + { + $this->serializer = $serializer; + } + + /** + * Provides form data from the serialized data. + * + * @param string $serializedData + * @return array + * @throws \InvalidArgumentException + */ + public function unserialize(string $serializedData): array + { + $encodedFields = $this->serializer->unserialize($serializedData); + + if (!is_array($encodedFields)) { + throw new \InvalidArgumentException('Unable to unserialize value.'); + } + + $formData = []; + foreach ($encodedFields as $item) { + $decodedFieldData = []; + parse_str($item, $decodedFieldData); + $formData = array_replace_recursive($formData, $decodedFieldData); + } + + return $formData; + } +} From 9cc36ea63c739048e9e55513784bf3aabcba0a45 Mon Sep 17 00:00:00 2001 From: Max Lesechko <mlesechko@magento.com> Date: Tue, 18 Sep 2018 16:33:23 -0500 Subject: [PATCH 29/44] MAGETWO-94819: Swatch validation breaks the whole attribute form --- .../Test/Mftf/Section/AdminCreateProductAttributeSection.xml | 1 + .../Test/AdminCreateVisualSwatchWithNonValidOptionsTest.xml | 5 +++++ .../Catalog/Controller/Adminhtml/Product/AttributeTest.php | 1 - .../Swatches/Controller/Adminhtml/Product/AttributeTest.php | 1 - 4 files changed, 6 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Catalog/Test/Mftf/Section/AdminCreateProductAttributeSection.xml b/app/code/Magento/Catalog/Test/Mftf/Section/AdminCreateProductAttributeSection.xml index a497233afbd..17778c76da9 100644 --- a/app/code/Magento/Catalog/Test/Mftf/Section/AdminCreateProductAttributeSection.xml +++ b/app/code/Magento/Catalog/Test/Mftf/Section/AdminCreateProductAttributeSection.xml @@ -24,6 +24,7 @@ <element name="useInLayeredNavigation" type="select" selector="#is_filterable"/> </section> <section name="StorefrontPropertiesSection"> + <element name="PageTitle" type="text" selector="//span[text()='Storefront Properties']" /> <element name="StoreFrontPropertiesTab" selector="#product_attribute_tabs_front" type="button"/> <element name="EnableWYSIWYG" type="select" selector="#enabled"/> <element name="useForPromoRuleConditions" type="select" selector="#is_used_for_promo_rules"/> diff --git a/app/code/Magento/Swatches/Test/Mftf/Test/AdminCreateVisualSwatchWithNonValidOptionsTest.xml b/app/code/Magento/Swatches/Test/Mftf/Test/AdminCreateVisualSwatchWithNonValidOptionsTest.xml index 1e9ce849db1..50dcfbf3da0 100644 --- a/app/code/Magento/Swatches/Test/Mftf/Test/AdminCreateVisualSwatchWithNonValidOptionsTest.xml +++ b/app/code/Magento/Swatches/Test/Mftf/Test/AdminCreateVisualSwatchWithNonValidOptionsTest.xml @@ -66,6 +66,11 @@ <fillField selector="{{AdminManageSwatchSection.adminInputByIndex('0')}}" userInput="red" stepKey="fillAdmin1"/> + <!-- Go to Storefront Properties tab --> + <scrollToTopOfPage stepKey="scrollToTop"/> + <click selector="{{StorefrontPropertiesSection.StoreFrontPropertiesTab}}" stepKey="goToStorefrontPropertiesTab"/> + <waitForElementVisible selector="{{StorefrontPropertiesSection.PageTitle}}" stepKey="waitTabLoad"/> + <!-- Save the new product attribute --> <click selector="{{AttributePropertiesSection.Save}}" stepKey="clickSave2"/> <waitForElementVisible selector="{{AdminProductMessagesSection.successMessage}}" diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/AttributeTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/AttributeTest.php index 5a1dcae6cb0..1f70ad0f7df 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/AttributeTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Controller/Adminhtml/Product/AttributeTest.php @@ -392,7 +392,6 @@ protected function _getAttributeData() 'used_for_sort_by' => '0', 'apply_to' => ['simple'], 'frontend_label' => [\Magento\Store\Model\Store::DEFAULT_STORE_ID => 'string to translate'], - 'serialized_options' => '[]', ]; } } diff --git a/dev/tests/integration/testsuite/Magento/Swatches/Controller/Adminhtml/Product/AttributeTest.php b/dev/tests/integration/testsuite/Magento/Swatches/Controller/Adminhtml/Product/AttributeTest.php index 36e216ab4e5..5b7a80bb38d 100644 --- a/dev/tests/integration/testsuite/Magento/Swatches/Controller/Adminhtml/Product/AttributeTest.php +++ b/dev/tests/integration/testsuite/Magento/Swatches/Controller/Adminhtml/Product/AttributeTest.php @@ -133,7 +133,6 @@ private function getAttributePreset() : array { return [ 'form_key' => 'XxtpPYjm2YPYUlAt', - 'serialized_options' => '[]', 'frontend_label' => [ 0 => 'asdasd', 1 => '', From 9793fb17167618d4f86316a2110cbd0f52e8ce15 Mon Sep 17 00:00:00 2001 From: roman <rleshchenko@magento.com> Date: Wed, 19 Sep 2018 14:43:08 +0300 Subject: [PATCH 30/44] MAGETWO-92195: Wrong order request flow --- .../Sales/Controller/Adminhtml/Order/MassHold.php | 3 ++- .../Sales/Controller/Adminhtml/Order/MassUnhold.php | 10 +++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Sales/Controller/Adminhtml/Order/MassHold.php b/app/code/Magento/Sales/Controller/Adminhtml/Order/MassHold.php index 241255f68e3..5c96fbbe9e2 100644 --- a/app/code/Magento/Sales/Controller/Adminhtml/Order/MassHold.php +++ b/app/code/Magento/Sales/Controller/Adminhtml/Order/MassHold.php @@ -5,6 +5,7 @@ */ namespace Magento\Sales\Controller\Adminhtml\Order; +use Magento\Framework\App\Action\HttpPostActionInterface; use Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection; use Magento\Backend\App\Action\Context; use Magento\Ui\Component\MassAction\Filter; @@ -14,7 +15,7 @@ /** * Class MassHold */ -class MassHold extends \Magento\Sales\Controller\Adminhtml\Order\AbstractMassAction +class MassHold extends \Magento\Sales\Controller\Adminhtml\Order\AbstractMassAction implements HttpPostActionInterface { /** * Authorization level of a basic admin session diff --git a/app/code/Magento/Sales/Controller/Adminhtml/Order/MassUnhold.php b/app/code/Magento/Sales/Controller/Adminhtml/Order/MassUnhold.php index 5e8ea9c4ad0..bd377e40f18 100644 --- a/app/code/Magento/Sales/Controller/Adminhtml/Order/MassUnhold.php +++ b/app/code/Magento/Sales/Controller/Adminhtml/Order/MassUnhold.php @@ -5,13 +5,19 @@ */ namespace Magento\Sales\Controller\Adminhtml\Order; +use Magento\Framework\App\Action\HttpPostActionInterface; use Magento\Framework\Model\ResourceModel\Db\Collection\AbstractCollection; use Magento\Backend\App\Action\Context; use Magento\Ui\Component\MassAction\Filter; use Magento\Sales\Model\ResourceModel\Order\CollectionFactory; use Magento\Sales\Api\OrderManagementInterface; -class MassUnhold extends AbstractMassAction +/** + * Class MassUnhold + * + * @package Magento\Sales\Controller\Adminhtml\Order + */ +class MassUnhold extends AbstractMassAction implements HttpPostActionInterface { /** * Authorization level of a basic admin session @@ -24,6 +30,8 @@ class MassUnhold extends AbstractMassAction private $orderManagement; /** + * Class constructor + * * @param Context $context * @param Filter $filter * @param CollectionFactory $collectionFactory From c450f44eeb530881115d63857f9d7e6af6f97158 Mon Sep 17 00:00:00 2001 From: roman <rleshchenko@magento.com> Date: Wed, 19 Sep 2018 14:46:20 +0300 Subject: [PATCH 31/44] MAGETWO-92195: Wrong order request flow --- .../Adminhtml/Order/MassCancelTest.php | 294 ------------------ .../Adminhtml/Order/MassHoldTest.php | 262 ---------------- .../Adminhtml/Order/MassUnholdTest.php | 261 ---------------- 3 files changed, 817 deletions(-) delete mode 100644 app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/MassCancelTest.php delete mode 100644 app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/MassHoldTest.php delete mode 100644 app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/MassUnholdTest.php diff --git a/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/MassCancelTest.php b/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/MassCancelTest.php deleted file mode 100644 index 38449c56866..00000000000 --- a/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/MassCancelTest.php +++ /dev/null @@ -1,294 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ - -namespace Magento\Sales\Test\Unit\Controller\Adminhtml\Order; - -use Magento\Framework\App\Action\Context; -use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; - -/** - * Class MassCancelTest - * @SuppressWarnings(PHPMD.CouplingBetweenObjects) - */ -class MassCancelTest extends \PHPUnit\Framework\TestCase -{ - /** - * @var \Magento\Sales\Controller\Adminhtml\Order\MassCancel - */ - protected $massAction; - - /** - * @var Context|\PHPUnit_Framework_MockObject_MockObject - */ - protected $contextMock; - - /** - * @var \Magento\Backend\Model\View\Result\Redirect|\PHPUnit_Framework_MockObject_MockObject - */ - protected $resultRedirectMock; - - /** - * @var \Magento\Framework\App\Request\Http|\PHPUnit_Framework_MockObject_MockObject - */ - protected $requestMock; - - /** - * @var \Magento\Framework\App\ResponseInterface|\PHPUnit_Framework_MockObject_MockObject - */ - protected $responseMock; - - /** - * @var \Magento\Framework\Message\Manager|\PHPUnit_Framework_MockObject_MockObject - */ - protected $messageManagerMock; - - /** - * @var \Magento\Framework\ObjectManager\ObjectManager|\PHPUnit_Framework_MockObject_MockObject - */ - protected $objectManagerMock; - - /** - * @var \Magento\Backend\Model\Session|\PHPUnit_Framework_MockObject_MockObject - */ - protected $sessionMock; - - /** - * @var \Magento\Framework\App\ActionFlag|\PHPUnit_Framework_MockObject_MockObject - */ - protected $actionFlagMock; - - /** - * @var \Magento\Backend\Helper\Data|\PHPUnit_Framework_MockObject_MockObject - */ - protected $helperMock; - - /** - * @var \Magento\Sales\Model\Order|\PHPUnit_Framework_MockObject_MockObject - */ - protected $orderMock; - - /** - * @var \Magento\Sales\Model\ResourceModel\Order\Collection|\PHPUnit_Framework_MockObject_MockObject - */ - protected $orderCollectionMock; - - /** - * @var \Magento\Sales\Model\ResourceModel\Order\CollectionFactory|\PHPUnit_Framework_MockObject_MockObject - */ - protected $orderCollectionFactoryMock; - - /** - * @var \Magento\Ui\Component\MassAction\Filter|\PHPUnit_Framework_MockObject_MockObject - */ - protected $filterMock; - - /** - * @var \PHPUnit_Framework_MockObject_MockObject - */ - private $orderManagementMock; - - /** - * Test setup - */ - protected function setUp() - { - $objectManagerHelper = new ObjectManagerHelper($this); - $this->contextMock = $this->createMock(\Magento\Backend\App\Action\Context::class); - $this->messageManagerMock = $this->createMock(\Magento\Framework\Message\Manager::class); - $this->responseMock = $this->createMock(\Magento\Framework\App\ResponseInterface::class); - $this->requestMock = $this->createMock(\Magento\Framework\App\Request\Http::class); - $this->objectManagerMock = $this->createMock(\Magento\Framework\ObjectManager\ObjectManager::class); - - $resultRedirectFactory = $this->createMock(\Magento\Backend\Model\View\Result\RedirectFactory::class); - - $this->orderCollectionMock = $this->getMockBuilder(\Magento\Sales\Model\ResourceModel\Order\Collection::class) - ->disableOriginalConstructor() - ->getMock(); - - $resourceCollection = \Magento\Sales\Model\ResourceModel\Order\CollectionFactory::class; - $this->orderCollectionFactoryMock = $this->getMockBuilder($resourceCollection) - ->disableOriginalConstructor() - ->setMethods(['create']) - ->getMock(); - - $this->sessionMock = $this->createPartialMock(\Magento\Backend\Model\Session::class, ['setIsUrlNotice']); - $this->actionFlagMock = $this->createPartialMock(\Magento\Framework\App\ActionFlag::class, ['get', 'set']); - $this->helperMock = $this->createPartialMock(\Magento\Backend\Helper\Data::class, ['getUrl']); - $this->resultRedirectMock = $this->createMock(\Magento\Backend\Model\View\Result\Redirect::class); - $resultRedirectFactory->expects($this->any())->method('create')->willReturn($this->resultRedirectMock); - - $redirectMock = $this->getMockBuilder(\Magento\Backend\Model\View\Result\Redirect::class) - ->disableOriginalConstructor() - ->getMock(); - - $resultFactoryMock = $this->getMockBuilder(\Magento\Framework\Controller\ResultFactory::class) - ->disableOriginalConstructor() - ->getMock(); - $resultFactoryMock->expects($this->any()) - ->method('create') - ->with(\Magento\Framework\Controller\ResultFactory::TYPE_REDIRECT) - ->willReturn($redirectMock); - - $this->contextMock->expects($this->once())->method('getMessageManager')->willReturn($this->messageManagerMock); - $this->contextMock->expects($this->once())->method('getRequest')->willReturn($this->requestMock); - $this->contextMock->expects($this->once())->method('getResponse')->willReturn($this->responseMock); - $this->contextMock->expects($this->once())->method('getObjectManager')->willReturn($this->objectManagerMock); - $this->contextMock->expects($this->once())->method('getSession')->willReturn($this->sessionMock); - $this->contextMock->expects($this->once())->method('getActionFlag')->willReturn($this->actionFlagMock); - $this->contextMock->expects($this->once())->method('getHelper')->willReturn($this->helperMock); - $this->contextMock->expects($this->once()) - ->method('getResultRedirectFactory') - ->willReturn($resultRedirectFactory); - $this->contextMock->expects($this->any()) - ->method('getResultFactory') - ->willReturn($resultFactoryMock); - $this->filterMock = $this->createMock(\Magento\Ui\Component\MassAction\Filter::class); - $this->filterMock->expects($this->once()) - ->method('getCollection') - ->with($this->orderCollectionMock) - ->willReturn($this->orderCollectionMock); - $this->orderCollectionFactoryMock->expects($this->once()) - ->method('create') - ->willReturn($this->orderCollectionMock); - $this->orderManagementMock = $this->createMock(\Magento\Sales\Api\OrderManagementInterface::class); - - $this->massAction = $objectManagerHelper->getObject( - \Magento\Sales\Controller\Adminhtml\Order\MassCancel::class, - [ - 'context' => $this->contextMock, - 'filter' => $this->filterMock, - 'collectionFactory' => $this->orderCollectionFactoryMock, - 'orderManagement' => $this->orderManagementMock - ] - ); - } - - /** - * Test for selected orders - * Two orders, only $order1 can be canceled - */ - public function testExecuteCanCancelOneOrder() - { - $order1id = 100; - $order2id = 200; - - $order1 = $this->getMockBuilder(\Magento\Sales\Model\Order::class) - ->disableOriginalConstructor() - ->getMock(); - $order2 = $this->getMockBuilder(\Magento\Sales\Model\Order::class) - ->disableOriginalConstructor() - ->getMock(); - $orders = [$order1, $order2]; - $countOrders = count($orders); - - $this->orderCollectionMock->expects($this->any()) - ->method('getItems') - ->willReturn($orders); - - $order1->expects($this->once()) - ->method('getEntityId') - ->willReturn($order1id); - - $order2->expects($this->once()) - ->method('getEntityId') - ->willReturn($order2id); - - $this->orderCollectionMock->expects($this->once()) - ->method('count') - ->willReturn($countOrders); - - $this->orderManagementMock->expects($this->at(0))->method('cancel')->with($order1id)->willReturn(true); - $this->orderManagementMock->expects($this->at(1))->method('cancel')->with($order2id)->willReturn(false); - - $this->messageManagerMock->expects($this->once()) - ->method('addErrorMessage') - ->with('1 order(s) cannot be canceled.'); - - $this->messageManagerMock->expects($this->once()) - ->method('addSuccessMessage') - ->with('We canceled 1 order(s).'); - - $this->resultRedirectMock->expects($this->once()) - ->method('setPath') - ->with('sales/*/') - ->willReturnSelf(); - - $this->massAction->execute(); - } - - /** - * Test for excluded orders - * Two orders could't be canceled - */ - public function testExcludedCannotCancelOrders() - { - $order1 = $this->getMockBuilder(\Magento\Sales\Model\Order::class) - ->disableOriginalConstructor() - ->getMock(); - $order2 = $this->getMockBuilder(\Magento\Sales\Model\Order::class) - ->disableOriginalConstructor() - ->getMock(); - - $orders = [$order1, $order2]; - $countOrders = count($orders); - - $order1->expects($this->once()) - ->method('getEntityId') - ->willReturn(100); - - $order2->expects($this->once()) - ->method('getEntityId') - ->willReturn(200); - - $this->orderCollectionMock->expects($this->any()) - ->method('getItems') - ->willReturn([$order1, $order2]); - - $this->orderCollectionMock->expects($this->once()) - ->method('count') - ->willReturn($countOrders); - - $this->orderManagementMock->expects($this->atLeastOnce())->method('cancel')->willReturn(false); - - $this->messageManagerMock->expects($this->once()) - ->method('addErrorMessage') - ->with('You cannot cancel the order(s).'); - - $this->resultRedirectMock->expects($this->once()) - ->method('setPath') - ->with('sales/*/') - ->willReturnSelf(); - - $this->massAction->execute(); - } - - /** - * Order throws exception while canceling - */ - public function testException() - { - $exception = new \Exception('Can not cancel'); - - $order1 = $this->getMockBuilder(\Magento\Sales\Model\Order::class) - ->disableOriginalConstructor() - ->getMock(); - $this->orderCollectionMock->expects($this->any()) - ->method('getItems') - ->willReturn([$order1]); - - $order1->expects($this->once()) - ->method('getEntityId') - ->willReturn(100); - - $this->orderManagementMock->expects($this->atLeastOnce())->method('cancel')->willThrowException($exception); - - $this->messageManagerMock->expects($this->once()) - ->method('addErrorMessage') - ->with('Can not cancel'); - - $this->massAction->execute(); - } -} diff --git a/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/MassHoldTest.php b/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/MassHoldTest.php deleted file mode 100644 index bfd1d1e825f..00000000000 --- a/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/MassHoldTest.php +++ /dev/null @@ -1,262 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ - -namespace Magento\Sales\Test\Unit\Controller\Adminhtml\Order; - -use Magento\Framework\App\Action\Context; -use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; - -/** - * Class MassHoldTest - * @SuppressWarnings(PHPMD.CouplingBetweenObjects) - */ -class MassHoldTest extends \PHPUnit\Framework\TestCase -{ - /** - * @var \Magento\Sales\Controller\Adminhtml\Order\MassHold - */ - protected $massAction; - - /** - * @var Context|\PHPUnit_Framework_MockObject_MockObject - */ - protected $contextMock; - - /** - * @var \Magento\Backend\Model\View\Result\Redirect|\PHPUnit_Framework_MockObject_MockObject - */ - protected $resultRedirectMock; - - /** - * @var \Magento\Framework\App\Request\Http|\PHPUnit_Framework_MockObject_MockObject - */ - protected $requestMock; - - /** - * @var \Magento\Framework\App\ResponseInterface|\PHPUnit_Framework_MockObject_MockObject - */ - protected $responseMock; - - /** - * @var \Magento\Framework\Message\Manager|\PHPUnit_Framework_MockObject_MockObject - */ - protected $messageManagerMock; - - /** - * @var \Magento\Framework\ObjectManager\ObjectManager|\PHPUnit_Framework_MockObject_MockObject - */ - protected $objectManagerMock; - - /** - * @var \Magento\Backend\Model\Session|\PHPUnit_Framework_MockObject_MockObject - */ - protected $sessionMock; - - /** - * @var \Magento\Framework\App\ActionFlag|\PHPUnit_Framework_MockObject_MockObject - */ - protected $actionFlagMock; - - /** - * @var \Magento\Backend\Helper\Data|\PHPUnit_Framework_MockObject_MockObject - */ - protected $helperMock; - - /** - * @var \Magento\Sales\Model\Order|\PHPUnit_Framework_MockObject_MockObject - */ - protected $orderMock; - - /** - * @var \Magento\Sales\Model\ResourceModel\Order\Collection|\PHPUnit_Framework_MockObject_MockObject - */ - protected $orderCollectionMock; - - /** - * @var \Magento\Sales\Model\ResourceModel\Order\CollectionFactory|\PHPUnit_Framework_MockObject_MockObject - */ - protected $orderCollectionFactoryMock; - - /** - * @var \Magento\Ui\Component\MassAction\Filter|\PHPUnit_Framework_MockObject_MockObject - */ - protected $filterMock; - - /** - * @var \Magento\Sales\Api\OrderManagementInterface|\PHPUnit_Framework_MockObject_MockObject - */ - protected $orderManagementMock; - - /** - * Test setup - */ - protected function setUp() - { - $objectManagerHelper = new ObjectManagerHelper($this); - $this->orderManagementMock = $this->getMockBuilder(\Magento\Sales\Api\OrderManagementInterface::class) - ->getMockForAbstractClass(); - $this->contextMock = $this->createMock(\Magento\Backend\App\Action\Context::class); - $resultRedirectFactory = $this->createMock(\Magento\Backend\Model\View\Result\RedirectFactory::class); - $this->responseMock = $this->createMock(\Magento\Framework\App\ResponseInterface::class); - $this->requestMock = $this->getMockBuilder(\Magento\Framework\App\Request\Http::class) - ->disableOriginalConstructor()->getMock(); - $this->objectManagerMock = $this->createPartialMock( - \Magento\Framework\ObjectManager\ObjectManager::class, - ['create'] - ); - $this->messageManagerMock = $this->createMock(\Magento\Framework\Message\Manager::class); - $this->orderCollectionMock = $this->getMockBuilder(\Magento\Sales\Model\ResourceModel\Order\Collection::class) - ->disableOriginalConstructor() - ->getMock(); - $orderCollection = \Magento\Sales\Model\ResourceModel\Order\CollectionFactory::class; - $this->orderCollectionFactoryMock = $this->getMockBuilder($orderCollection) - ->disableOriginalConstructor() - ->setMethods(['create']) - ->getMock(); - $redirectMock = $this->getMockBuilder(\Magento\Backend\Model\View\Result\Redirect::class) - ->disableOriginalConstructor() - ->getMock(); - - $resultFactoryMock = $this->getMockBuilder(\Magento\Framework\Controller\ResultFactory::class) - ->disableOriginalConstructor() - ->getMock(); - $resultFactoryMock->expects($this->any()) - ->method('create') - ->with(\Magento\Framework\Controller\ResultFactory::TYPE_REDIRECT) - ->willReturn($redirectMock); - - $this->sessionMock = $this->createPartialMock(\Magento\Backend\Model\Session::class, ['setIsUrlNotice']); - $this->actionFlagMock = $this->createPartialMock(\Magento\Framework\App\ActionFlag::class, ['get', 'set']); - $this->helperMock = $this->createPartialMock(\Magento\Backend\Helper\Data::class, ['getUrl']); - $this->resultRedirectMock = $this->createMock(\Magento\Backend\Model\View\Result\Redirect::class); - $resultRedirectFactory->expects($this->any())->method('create')->willReturn($this->resultRedirectMock); - - $this->contextMock->expects($this->once())->method('getMessageManager')->willReturn($this->messageManagerMock); - $this->contextMock->expects($this->once())->method('getRequest')->willReturn($this->requestMock); - $this->contextMock->expects($this->once())->method('getResponse')->willReturn($this->responseMock); - $this->contextMock->expects($this->once())->method('getObjectManager')->willReturn($this->objectManagerMock); - $this->contextMock->expects($this->once())->method('getSession')->willReturn($this->sessionMock); - $this->contextMock->expects($this->once())->method('getActionFlag')->willReturn($this->actionFlagMock); - $this->contextMock->expects($this->once())->method('getHelper')->willReturn($this->helperMock); - $this->contextMock - ->expects($this->once()) - ->method('getResultRedirectFactory') - ->willReturn($resultRedirectFactory); - $this->contextMock->expects($this->any()) - ->method('getResultFactory') - ->willReturn($resultFactoryMock); - - $this->filterMock = $this->createMock(\Magento\Ui\Component\MassAction\Filter::class); - $this->filterMock->expects($this->once()) - ->method('getCollection') - ->with($this->orderCollectionMock) - ->willReturn($this->orderCollectionMock); - $this->orderCollectionFactoryMock->expects($this->once()) - ->method('create') - ->willReturn($this->orderCollectionMock); - - $this->massAction = $objectManagerHelper->getObject( - \Magento\Sales\Controller\Adminhtml\Order\MassHold::class, - [ - 'context' => $this->contextMock, - 'filter' => $this->filterMock, - 'collectionFactory' => $this->orderCollectionFactoryMock, - 'orderManagement' => $this->orderManagementMock - ] - ); - } - - /** - * @throws \Magento\Framework\Exception\LocalizedException - */ - public function testExecuteOneOrderPutOnHold() - { - $order1 = $this->getMockBuilder(\Magento\Sales\Model\Order::class) - ->disableOriginalConstructor() - ->getMock(); - $order2 = $this->getMockBuilder(\Magento\Sales\Model\Order::class) - ->disableOriginalConstructor() - ->getMock(); - - $orders = [$order1, $order2]; - $countOrders = count($orders); - - $this->orderCollectionMock->expects($this->any()) - ->method('getItems') - ->willReturn($orders); - - $order1->expects($this->once()) - ->method('canHold') - ->willReturn(true); - $this->orderManagementMock->expects($this->once()) - ->method('hold'); - $this->orderCollectionMock->expects($this->once()) - ->method('count') - ->willReturn($countOrders); - - $order2->expects($this->once()) - ->method('canHold') - ->willReturn(false); - - $this->messageManagerMock->expects($this->once()) - ->method('addErrorMessage') - ->with('1 order(s) were not put on hold.'); - - $this->messageManagerMock->expects($this->once()) - ->method('addSuccessMessage') - ->with('You have put 1 order(s) on hold.'); - - $this->resultRedirectMock->expects($this->once()) - ->method('setPath') - ->with('sales/*/') - ->willReturnSelf(); - - $this->massAction->execute(); - } - - /** - * @throws \Magento\Framework\Exception\LocalizedException - */ - public function testExecuteNoOrdersPutOnHold() - { - $order1 = $this->getMockBuilder(\Magento\Sales\Model\Order::class) - ->disableOriginalConstructor() - ->getMock(); - $order2 = $this->getMockBuilder(\Magento\Sales\Model\Order::class) - ->disableOriginalConstructor() - ->getMock(); - - $orders = [$order1, $order2]; - $countOrders = count($orders); - - $this->orderCollectionMock->expects($this->any()) - ->method('getItems') - ->willReturn($orders); - - $order1->expects($this->once()) - ->method('canHold') - ->willReturn(false); - - $this->orderCollectionMock->expects($this->once()) - ->method('count') - ->willReturn($countOrders); - - $order2->expects($this->once()) - ->method('canHold') - ->willReturn(false); - - $this->messageManagerMock->expects($this->once()) - ->method('addErrorMessage') - ->with('No order(s) were put on hold.'); - - $this->resultRedirectMock->expects($this->once()) - ->method('setPath') - ->with('sales/*/') - ->willReturnSelf(); - - $this->massAction->execute(); - } -} diff --git a/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/MassUnholdTest.php b/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/MassUnholdTest.php deleted file mode 100644 index 56473ec948f..00000000000 --- a/app/code/Magento/Sales/Test/Unit/Controller/Adminhtml/Order/MassUnholdTest.php +++ /dev/null @@ -1,261 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ - -namespace Magento\Sales\Test\Unit\Controller\Adminhtml\Order; - -use Magento\Framework\App\Action\Context; -use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; - -/** - * Class MassHoldTest - * @SuppressWarnings(PHPMD.CouplingBetweenObjects) - */ -class MassUnholdTest extends \PHPUnit\Framework\TestCase -{ - /** - * @var \Magento\Sales\Controller\Adminhtml\Order\MassUnhold - */ - protected $massAction; - - /** - * @var Context|\PHPUnit_Framework_MockObject_MockObject - */ - protected $contextMock; - - /** - * @var \Magento\Backend\Model\View\Result\Redirect|\PHPUnit_Framework_MockObject_MockObject - */ - protected $resultRedirectMock; - - /** - * @var \Magento\Framework\App\Request\Http|\PHPUnit_Framework_MockObject_MockObject - */ - protected $requestMock; - - /** - * @var \Magento\Framework\App\ResponseInterface|\PHPUnit_Framework_MockObject_MockObject - */ - protected $responseMock; - - /** - * @var \Magento\Framework\Message\Manager|\PHPUnit_Framework_MockObject_MockObject - */ - protected $messageManagerMock; - - /** - * @var \Magento\Framework\ObjectManager\ObjectManager|\PHPUnit_Framework_MockObject_MockObject - */ - protected $objectManagerMock; - - /** - * @var \Magento\Backend\Model\Session|\PHPUnit_Framework_MockObject_MockObject - */ - protected $sessionMock; - - /** - * @var \Magento\Framework\App\ActionFlag|\PHPUnit_Framework_MockObject_MockObject - */ - protected $actionFlagMock; - - /** - * @var \Magento\Backend\Helper\Data|\PHPUnit_Framework_MockObject_MockObject - */ - protected $helperMock; - - /** - * @var \Magento\Sales\Model\Order|\PHPUnit_Framework_MockObject_MockObject - */ - protected $orderMock; - - /** - * @var \Magento\Sales\Model\ResourceModel\Order\Collection|\PHPUnit_Framework_MockObject_MockObject - */ - protected $orderCollectionMock; - - /** - * @var \Magento\Sales\Model\ResourceModel\Order\CollectionFactory|\PHPUnit_Framework_MockObject_MockObject - */ - protected $orderCollectionFactoryMock; - - /** - * @var \Magento\Ui\Component\MassAction\Filter|\PHPUnit_Framework_MockObject_MockObject - */ - protected $filterMock; - - /** - * @var \PHPUnit_Framework_MockObject_MockObject - */ - private $orderManagementMock; - - /** - * Test setup - */ - protected function setUp() - { - $objectManagerHelper = new ObjectManagerHelper($this); - $this->contextMock = $this->createMock(\Magento\Backend\App\Action\Context::class); - $resultRedirectFactory = $this->createMock(\Magento\Backend\Model\View\Result\RedirectFactory::class); - $this->responseMock = $this->createMock(\Magento\Framework\App\ResponseInterface::class); - $this->requestMock = $this->getMockBuilder(\Magento\Framework\App\Request\Http::class) - ->disableOriginalConstructor()->getMock(); - $this->objectManagerMock = $this->createMock(\Magento\Framework\ObjectManager\ObjectManager::class); - $this->messageManagerMock = $this->createMock(\Magento\Framework\Message\Manager::class); - - $this->orderCollectionMock = $this->getMockBuilder(\Magento\Sales\Model\ResourceModel\Order\Collection::class) - ->disableOriginalConstructor() - ->getMock(); - $orderCollection = \Magento\Sales\Model\ResourceModel\Order\CollectionFactory::class; - $this->orderCollectionFactoryMock = $this->getMockBuilder($orderCollection) - ->disableOriginalConstructor() - ->setMethods(['create']) - ->getMock(); - $this->sessionMock = $this->createPartialMock(\Magento\Backend\Model\Session::class, ['setIsUrlNotice']); - $this->actionFlagMock = $this->createPartialMock(\Magento\Framework\App\ActionFlag::class, ['get', 'set']); - $this->helperMock = $this->createPartialMock(\Magento\Backend\Helper\Data::class, ['getUrl']); - $this->resultRedirectMock = $this->createMock(\Magento\Backend\Model\View\Result\Redirect::class); - $resultRedirectFactory->expects($this->any())->method('create')->willReturn($this->resultRedirectMock); - - $redirectMock = $this->getMockBuilder(\Magento\Backend\Model\View\Result\Redirect::class) - ->disableOriginalConstructor() - ->getMock(); - - $resultFactoryMock = $this->getMockBuilder(\Magento\Framework\Controller\ResultFactory::class) - ->disableOriginalConstructor() - ->getMock(); - $resultFactoryMock->expects($this->any()) - ->method('create') - ->with(\Magento\Framework\Controller\ResultFactory::TYPE_REDIRECT) - ->willReturn($redirectMock); - - $this->contextMock->expects($this->once())->method('getMessageManager')->willReturn($this->messageManagerMock); - $this->contextMock->expects($this->once())->method('getRequest')->willReturn($this->requestMock); - $this->contextMock->expects($this->once())->method('getResponse')->willReturn($this->responseMock); - $this->contextMock->expects($this->once())->method('getObjectManager')->willReturn($this->objectManagerMock); - $this->contextMock->expects($this->once())->method('getSession')->willReturn($this->sessionMock); - $this->contextMock->expects($this->once())->method('getActionFlag')->willReturn($this->actionFlagMock); - $this->contextMock->expects($this->once())->method('getHelper')->willReturn($this->helperMock); - $this->contextMock - ->expects($this->once()) - ->method('getResultRedirectFactory') - ->willReturn($resultRedirectFactory); - $this->contextMock->expects($this->any()) - ->method('getResultFactory') - ->willReturn($resultFactoryMock); - - $this->filterMock = $this->createMock(\Magento\Ui\Component\MassAction\Filter::class); - $this->filterMock->expects($this->once()) - ->method('getCollection') - ->with($this->orderCollectionMock) - ->willReturn($this->orderCollectionMock); - $this->orderCollectionFactoryMock->expects($this->once()) - ->method('create') - ->willReturn($this->orderCollectionMock); - - $this->orderManagementMock = $this->createMock(\Magento\Sales\Api\OrderManagementInterface::class); - - $this->massAction = $objectManagerHelper->getObject( - \Magento\Sales\Controller\Adminhtml\Order\MassUnhold::class, - [ - 'context' => $this->contextMock, - 'filter' => $this->filterMock, - 'collectionFactory' => $this->orderCollectionFactoryMock, - 'orderManagement' => $this->orderManagementMock - ] - ); - } - - /** - * @throws \Magento\Framework\Exception\LocalizedException - */ - public function testExecuteOneOrdersReleasedFromHold() - { - $order1 = $this->getMockBuilder(\Magento\Sales\Model\Order::class) - ->disableOriginalConstructor() - ->getMock(); - $order2 = $this->getMockBuilder(\Magento\Sales\Model\Order::class) - ->disableOriginalConstructor() - ->getMock(); - - $orders = [$order1, $order2]; - - $this->orderCollectionMock->expects($this->any()) - ->method('getItems') - ->willReturn($orders); - - $order1->expects($this->once()) - ->method('canUnhold') - ->willReturn(true); - $order1->expects($this->once()) - ->method('getEntityId'); - - $this->orderCollectionMock->expects($this->once()) - ->method('count') - ->willReturn(count($orders)); - - $order2->expects($this->once()) - ->method('canUnhold') - ->willReturn(false); - - $this->orderManagementMock->expects($this->atLeastOnce())->method('unHold')->willReturn(true); - - $this->messageManagerMock->expects($this->once()) - ->method('addErrorMessage') - ->with('1 order(s) were not released from on hold status.'); - - $this->messageManagerMock->expects($this->once()) - ->method('addSuccessMessage') - ->with('1 order(s) have been released from on hold status.'); - - $this->resultRedirectMock->expects($this->once()) - ->method('setPath') - ->with('sales/*/') - ->willReturnSelf(); - - $this->massAction->execute(); - } - - /** - * @throws \Magento\Framework\Exception\LocalizedException - */ - public function testExecuteNoReleasedOrderFromHold() - { - $order1 = $this->getMockBuilder(\Magento\Sales\Model\Order::class) - ->disableOriginalConstructor() - ->getMock(); - $order2 = $this->getMockBuilder(\Magento\Sales\Model\Order::class) - ->disableOriginalConstructor() - ->getMock(); - - $orders = [$order1, $order2]; - - $this->orderCollectionMock->expects($this->any()) - ->method('getItems') - ->willReturn($orders); - - $order1->expects($this->once()) - ->method('canUnhold') - ->willReturn(false); - - $this->orderCollectionMock->expects($this->once()) - ->method('count') - ->willReturn(count($orders)); - - $order2->expects($this->once()) - ->method('canUnhold') - ->willReturn(false); - - $this->messageManagerMock->expects($this->once()) - ->method('addErrorMessage') - ->with('No order(s) were released from on hold status.'); - - $this->resultRedirectMock->expects($this->once()) - ->method('setPath') - ->with('sales/*/') - ->willReturnSelf(); - - $this->massAction->execute(); - } -} From c8f3f1751656d930517188edf7c2117e951046d9 Mon Sep 17 00:00:00 2001 From: Max Lesechko <mlesechko@magento.com> Date: Thu, 20 Sep 2018 16:53:25 -0500 Subject: [PATCH 32/44] MAGETWO-94819: Swatch validation breaks the whole attribute form --- .../Controller/Adminhtml/Product/Attribute/Save.php | 12 ++++++------ .../Adminhtml/Product/Attribute/Validate.php | 10 +++++----- .../Adminhtml/Product/Attribute/SaveTest.php | 12 ++++++------ .../Adminhtml/Product/Attribute/ValidateTest.php | 12 ++++++------ 4 files changed, 23 insertions(+), 23 deletions(-) diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Save.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Save.php index 435fdb0b413..985d812fc74 100644 --- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Save.php +++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Save.php @@ -82,7 +82,7 @@ class Save extends Attribute implements HttpPostActionInterface /** * @var FormData|null */ - private $dataSerializer; + private $formDataSerializer; /** * @param Context $context @@ -97,7 +97,7 @@ class Save extends Attribute implements HttpPostActionInterface * @param Product $productHelper * @param LayoutFactory $layoutFactory * @param Presentation|null $presentation - * @param FormData|null $dataSerializer + * @param FormData|null $formDataSerializer * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( @@ -113,7 +113,7 @@ public function __construct( Product $productHelper, LayoutFactory $layoutFactory, Presentation $presentation = null, - FormData $dataSerializer = null + FormData $formDataSerializer = null ) { parent::__construct($context, $attributeLabelCache, $coreRegistry, $resultPageFactory); $this->buildFactory = $buildFactory; @@ -124,7 +124,7 @@ public function __construct( $this->groupCollectionFactory = $groupCollectionFactory; $this->layoutFactory = $layoutFactory; $this->presentation = $presentation ?: ObjectManager::getInstance()->get(Presentation::class); - $this->dataSerializer = $dataSerializer + $this->formDataSerializer = $formDataSerializer ?: ObjectManager::getInstance()->get(FormData::class); } @@ -140,7 +140,7 @@ public function __construct( public function execute() { try { - $optionData = $this->dataSerializer + $optionData = $this->formDataSerializer ->unserialize($this->getRequest()->getParam('serialized_options', '[]')); } catch (\InvalidArgumentException $e) { $message = __("The attribute couldn't be saved due to an error. Verify your information and try again. " @@ -150,7 +150,7 @@ public function execute() } $data = $this->getRequest()->getPostValue(); - $data = array_merge_recursive( + $data = array_replace_recursive( $data, $optionData ); diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Validate.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Validate.php index 4e33fc737f0..8a9d0c9b612 100644 --- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Validate.php +++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Attribute/Validate.php @@ -41,7 +41,7 @@ class Validate extends AttributeAction implements HttpGetActionInterface, HttpPo /** * @var FormData|null */ - private $dataSerializer; + private $formDataSerializer; /** * Constructor @@ -53,7 +53,7 @@ class Validate extends AttributeAction implements HttpGetActionInterface, HttpPo * @param \Magento\Framework\Controller\Result\JsonFactory $resultJsonFactory * @param \Magento\Framework\View\LayoutFactory $layoutFactory * @param array $multipleAttributeList - * @param FormData|null $dataSerializer + * @param FormData|null $formDataSerializer */ public function __construct( \Magento\Backend\App\Action\Context $context, @@ -63,13 +63,13 @@ public function __construct( \Magento\Framework\Controller\Result\JsonFactory $resultJsonFactory, \Magento\Framework\View\LayoutFactory $layoutFactory, array $multipleAttributeList = [], - FormData $dataSerializer = null + FormData $formDataSerializer = null ) { parent::__construct($context, $attributeLabelCache, $coreRegistry, $resultPageFactory); $this->resultJsonFactory = $resultJsonFactory; $this->layoutFactory = $layoutFactory; $this->multipleAttributeList = $multipleAttributeList; - $this->dataSerializer = $dataSerializer ?: ObjectManager::getInstance() + $this->formDataSerializer = $formDataSerializer ?: ObjectManager::getInstance() ->get(FormData::class); } @@ -85,7 +85,7 @@ public function execute() $response = new DataObject(); $response->setError(false); try { - $optionsData = $this->dataSerializer + $optionsData = $this->formDataSerializer ->unserialize($this->getRequest()->getParam('serialized_options', '[]')); } catch (\InvalidArgumentException $e) { $message = __("The attribute couldn't be validated due to an error. Verify your information and try again. " diff --git a/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Attribute/SaveTest.php b/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Attribute/SaveTest.php index e73f3527517..ced65b2d2e1 100644 --- a/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Attribute/SaveTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Attribute/SaveTest.php @@ -87,7 +87,7 @@ class SaveTest extends AttributeTest /** * @var FormData|\PHPUnit_Framework_MockObject_MockObject */ - private $dataSerializerMock; + private $formDataSerializerMock; /** * @var ProductAttributeInterface|\PHPUnit_Framework_MockObject_MockObject @@ -135,7 +135,7 @@ protected function setUp() $this->inputTypeValidatorMock = $this->getMockBuilder(InputTypeValidator::class) ->disableOriginalConstructor() ->getMock(); - $this->dataSerializerMock = $this->getMockBuilder(FormData::class) + $this->formDataSerializerMock = $this->getMockBuilder(FormData::class) ->disableOriginalConstructor() ->getMock(); $this->productAttributeMock = $this->getMockBuilder(ProductAttributeInterface::class) @@ -170,7 +170,7 @@ protected function getModel() 'validatorFactory' => $this->validatorFactoryMock, 'groupCollectionFactory' => $this->groupCollectionFactoryMock, 'layoutFactory' => $this->layoutFactoryMock, - 'dataSerializer' => $this->dataSerializerMock, + 'formDataSerializer' => $this->formDataSerializerMock, ]); } @@ -182,7 +182,7 @@ public function testExecuteWithEmptyData() ['isAjax', null, null], ['serialized_options', '[]', ''], ]); - $this->dataSerializerMock + $this->formDataSerializerMock ->expects($this->once()) ->method('unserialize') ->with('') @@ -213,7 +213,7 @@ public function testExecute() ['isAjax', null, null], ['serialized_options', '[]', ''], ]); - $this->dataSerializerMock + $this->formDataSerializerMock ->expects($this->once()) ->method('unserialize') ->with('') @@ -273,7 +273,7 @@ public function testExecuteWithOptionsDataError() ['isAjax', null, true], ['serialized_options', '[]', $serializedOptions], ]); - $this->dataSerializerMock + $this->formDataSerializerMock ->expects($this->once()) ->method('unserialize') ->with($serializedOptions) diff --git a/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Attribute/ValidateTest.php b/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Attribute/ValidateTest.php index 666e6c1942c..c6210f93e12 100644 --- a/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Attribute/ValidateTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Attribute/ValidateTest.php @@ -65,7 +65,7 @@ class ValidateTest extends AttributeTest /** * @var FormData|\PHPUnit_Framework_MockObject_MockObject */ - private $dataSerializerMock; + private $formDataSerializerMock; protected function setUp() { @@ -92,7 +92,7 @@ protected function setUp() ->getMock(); $this->layoutMock = $this->getMockBuilder(LayoutInterface::class) ->getMockForAbstractClass(); - $this->dataSerializerMock = $this->getMockBuilder(FormData::class) + $this->formDataSerializerMock = $this->getMockBuilder(FormData::class) ->disableOriginalConstructor() ->getMock(); @@ -116,7 +116,7 @@ protected function getModel() 'resultJsonFactory' => $this->resultJsonFactoryMock, 'layoutFactory' => $this->layoutFactoryMock, 'multipleAttributeList' => ['select' => 'option'], - 'dataSerializer' => $this->dataSerializerMock, + 'formDataSerializer' => $this->formDataSerializerMock, ] ); } @@ -184,7 +184,7 @@ public function testUniqueValidation(array $options, $isError) ['serialized_options', '[]', $serializedOptions], ]); - $this->dataSerializerMock + $this->formDataSerializerMock ->expects($this->once()) ->method('unserialize') ->with($serializedOptions) @@ -319,7 +319,7 @@ public function testEmptyOption(array $options, $result) ['serialized_options', '[]', $serializedOptions], ]); - $this->dataSerializerMock + $this->formDataSerializerMock ->expects($this->once()) ->method('unserialize') ->with($serializedOptions) @@ -431,7 +431,7 @@ public function testExecuteWithOptionsDataError() ['serialized_options', '[]', $serializedOptions], ]); - $this->dataSerializerMock + $this->formDataSerializerMock ->expects($this->once()) ->method('unserialize') ->with($serializedOptions) From 60f33baab9a476c4320f17b80e1e1df74543ac9f Mon Sep 17 00:00:00 2001 From: roman <rleshchenko@magento.com> Date: Fri, 21 Sep 2018 14:54:58 +0300 Subject: [PATCH 33/44] MAGETWO-92195: Wrong order request flow --- .../Magento/Sales/Controller/Adminhtml/Order/MassUnhold.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Sales/Controller/Adminhtml/Order/MassUnhold.php b/app/code/Magento/Sales/Controller/Adminhtml/Order/MassUnhold.php index bd377e40f18..e862710379a 100644 --- a/app/code/Magento/Sales/Controller/Adminhtml/Order/MassUnhold.php +++ b/app/code/Magento/Sales/Controller/Adminhtml/Order/MassUnhold.php @@ -13,7 +13,7 @@ use Magento\Sales\Api\OrderManagementInterface; /** - * Class MassUnhold + * Class MassUnhold, change status for select orders * * @package Magento\Sales\Controller\Adminhtml\Order */ From cdc0fd39bac4218fe16eecb34ee7ffa407ac94ca Mon Sep 17 00:00:00 2001 From: roman <rleshchenko@magento.com> Date: Fri, 21 Sep 2018 15:58:18 +0300 Subject: [PATCH 34/44] MAGETWO-70943: Incorrect reset password flow --- .../Api/AccountManagementInterface.php | 11 ++- .../Controller/Account/CreatePassword.php | 21 +++-- .../Controller/Account/ResetPasswordPost.php | 39 +++++---- .../Customer/Model/AccountManagement.php | 83 +++++++++++++++++-- .../email/password_reset_confirmation.html | 3 +- .../form/resetforgottenpassword.phtml | 2 +- .../Customer/Controller/AccountTest.php | 12 +-- .../Customer/Model/AccountManagementTest.php | 58 ++++++++++++- .../Magento/Framework/Math/Random.php | 68 +++++---------- 9 files changed, 202 insertions(+), 95 deletions(-) diff --git a/app/code/Magento/Customer/Api/AccountManagementInterface.php b/app/code/Magento/Customer/Api/AccountManagementInterface.php index d2f9fb7ebc4..10fc2349968 100644 --- a/app/code/Magento/Customer/Api/AccountManagementInterface.php +++ b/app/code/Magento/Customer/Api/AccountManagementInterface.php @@ -7,6 +7,8 @@ namespace Magento\Customer\Api; +use Magento\Framework\Exception\InputException; + /** * Interface for managing customers accounts. * @api @@ -144,19 +146,24 @@ public function initiatePasswordReset($email, $template, $websiteId = null); /** * Reset customer password. * - * @param string $email + * @param string $email If empty value given then the customer + * will be matched by the RP token. * @param string $resetToken * @param string $newPassword + * * @return bool true on success * @throws \Magento\Framework\Exception\LocalizedException + * @throws InputException */ public function resetPassword($email, $resetToken, $newPassword); /** * Check if password reset token is valid. * - * @param int $customerId + * @param int $customerId If null is given then a customer + * will be matched by the RP token. * @param string $resetPasswordLinkToken + * * @return bool True if the token is valid * @throws \Magento\Framework\Exception\State\InputMismatchException If token is mismatched * @throws \Magento\Framework\Exception\State\ExpiredException If token is expired diff --git a/app/code/Magento/Customer/Controller/Account/CreatePassword.php b/app/code/Magento/Customer/Controller/Account/CreatePassword.php index fb2e3dd4290..124ac912a7c 100644 --- a/app/code/Magento/Customer/Controller/Account/CreatePassword.php +++ b/app/code/Magento/Customer/Controller/Account/CreatePassword.php @@ -1,6 +1,5 @@ <?php /** - * * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ @@ -8,10 +7,16 @@ use Magento\Customer\Api\AccountManagementInterface; use Magento\Customer\Model\Session; +use Magento\Framework\App\Action\HttpGetActionInterface; use Magento\Framework\View\Result\PageFactory; use Magento\Framework\App\Action\Context; -class CreatePassword extends \Magento\Customer\Controller\AbstractAccount +/** + * Class CreatePassword + * + * @package Magento\Customer\Controller\Account + */ +class CreatePassword extends \Magento\Customer\Controller\AbstractAccount implements HttpGetActionInterface { /** * @var \Magento\Customer\Api\AccountManagementInterface @@ -54,27 +59,27 @@ public function __construct( public function execute() { $resetPasswordToken = (string)$this->getRequest()->getParam('token'); - $customerId = (int)$this->getRequest()->getParam('id'); - $isDirectLink = $resetPasswordToken != '' && $customerId != 0; + $isDirectLink = $resetPasswordToken != ''; if (!$isDirectLink) { $resetPasswordToken = (string)$this->session->getRpToken(); - $customerId = (int)$this->session->getRpCustomerId(); } try { - $this->accountManagement->validateResetPasswordLinkToken($customerId, $resetPasswordToken); + $this->accountManagement->validateResetPasswordLinkToken(null, $resetPasswordToken); if ($isDirectLink) { $this->session->setRpToken($resetPasswordToken); - $this->session->setRpCustomerId($customerId); $resultRedirect = $this->resultRedirectFactory->create(); $resultRedirect->setPath('*/*/createpassword'); + return $resultRedirect; } else { /** @var \Magento\Framework\View\Result\Page $resultPage */ $resultPage = $this->resultPageFactory->create(); - $resultPage->getLayout()->getBlock('resetPassword')->setCustomerId($customerId) + $resultPage->getLayout() + ->getBlock('resetPassword') ->setResetPasswordLinkToken($resetPasswordToken); + return $resultPage; } } catch (\Exception $exception) { diff --git a/app/code/Magento/Customer/Controller/Account/ResetPasswordPost.php b/app/code/Magento/Customer/Controller/Account/ResetPasswordPost.php index 3de44e35d24..27a00f86dd9 100644 --- a/app/code/Magento/Customer/Controller/Account/ResetPasswordPost.php +++ b/app/code/Magento/Customer/Controller/Account/ResetPasswordPost.php @@ -1,6 +1,5 @@ <?php /** - * * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ @@ -10,11 +9,16 @@ use Magento\Customer\Api\CustomerRepositoryInterface; use Magento\Customer\Model\Session; use Magento\Framework\App\Action\Context; +use Magento\Framework\App\Action\HttpPostActionInterface; use Magento\Framework\Exception\InputException; use Magento\Customer\Model\Customer\CredentialsValidator; -use Magento\Framework\App\ObjectManager; -class ResetPasswordPost extends \Magento\Customer\Controller\AbstractAccount +/** + * Class ResetPasswordPost + * + * @package Magento\Customer\Controller\Account + */ +class ResetPasswordPost extends \Magento\Customer\Controller\AbstractAccount implements HttpPostActionInterface { /** * @var \Magento\Customer\Api\AccountManagementInterface @@ -31,17 +35,14 @@ class ResetPasswordPost extends \Magento\Customer\Controller\AbstractAccount */ protected $session; - /** - * @var CredentialsValidator - */ - private $credentialsValidator; - /** * @param Context $context * @param Session $customerSession * @param AccountManagementInterface $accountManagement * @param CustomerRepositoryInterface $customerRepository * @param CredentialsValidator|null $credentialsValidator + * + * @SuppressWarnings(PHPMD.UnusedFormalParameter) */ public function __construct( Context $context, @@ -53,8 +54,6 @@ public function __construct( $this->session = $customerSession; $this->accountManagement = $accountManagement; $this->customerRepository = $customerRepository; - $this->credentialsValidator = $credentialsValidator ?: ObjectManager::getInstance() - ->get(CredentialsValidator::class); parent::__construct($context); } @@ -70,29 +69,32 @@ public function execute() /** @var \Magento\Framework\Controller\Result\Redirect $resultRedirect */ $resultRedirect = $this->resultRedirectFactory->create(); $resetPasswordToken = (string)$this->getRequest()->getQuery('token'); - $customerId = (int)$this->getRequest()->getQuery('id'); $password = (string)$this->getRequest()->getPost('password'); $passwordConfirmation = (string)$this->getRequest()->getPost('password_confirmation'); if ($password !== $passwordConfirmation) { $this->messageManager->addError(__("New Password and Confirm New Password values didn't match.")); - $resultRedirect->setPath('*/*/createPassword', ['id' => $customerId, 'token' => $resetPasswordToken]); + $resultRedirect->setPath('*/*/createPassword', ['token' => $resetPasswordToken]); + return $resultRedirect; } if (iconv_strlen($password) <= 0) { $this->messageManager->addError(__('Please enter a new password.')); - $resultRedirect->setPath('*/*/createPassword', ['id' => $customerId, 'token' => $resetPasswordToken]); + $resultRedirect->setPath('*/*/createPassword', ['token' => $resetPasswordToken]); + return $resultRedirect; } try { - $customerEmail = $this->customerRepository->getById($customerId)->getEmail(); - $this->credentialsValidator->checkPasswordDifferentFromEmail($customerEmail, $password); - $this->accountManagement->resetPassword($customerEmail, $resetPasswordToken, $password); + $this->accountManagement->resetPassword( + null, + $resetPasswordToken, + $password + ); $this->session->unsRpToken(); - $this->session->unsRpCustomerId(); $this->messageManager->addSuccess(__('You updated your password.')); $resultRedirect->setPath('*/*/login'); + return $resultRedirect; } catch (InputException $e) { $this->messageManager->addError($e->getMessage()); @@ -102,7 +104,8 @@ public function execute() } catch (\Exception $exception) { $this->messageManager->addError(__('Something went wrong while saving the new password.')); } - $resultRedirect->setPath('*/*/createPassword', ['id' => $customerId, 'token' => $resetPasswordToken]); + $resultRedirect->setPath('*/*/createPassword', ['token' => $resetPasswordToken]); + return $resultRedirect; } } diff --git a/app/code/Magento/Customer/Model/AccountManagement.php b/app/code/Magento/Customer/Model/AccountManagement.php index fe17adcb09c..52264c78b77 100644 --- a/app/code/Magento/Customer/Model/AccountManagement.php +++ b/app/code/Magento/Customer/Model/AccountManagement.php @@ -20,6 +20,7 @@ use Magento\Customer\Model\Metadata\Validator; use Magento\Eav\Model\Validator\Attribute\Backend; use Magento\Framework\Api\ExtensibleDataObjectConverter; +use Magento\Framework\Api\SearchCriteriaBuilder; use Magento\Framework\App\Area; use Magento\Framework\App\Config\ScopeConfigInterface; use Magento\Framework\App\ObjectManager; @@ -41,6 +42,7 @@ use Magento\Framework\Intl\DateTimeFactory; use Magento\Framework\Mail\Template\TransportBuilder; use Magento\Framework\Math\Random; +use Magento\Framework\Phrase; use Magento\Framework\Reflection\DataObjectProcessor; use Magento\Framework\Registry; use Magento\Framework\Stdlib\DateTime; @@ -326,6 +328,11 @@ class AccountManagement implements AccountManagementInterface */ private $accountConfirmation; + /** + * @var SearchCriteriaBuilder + */ + private $searchCriteriaBuilder; + /** * @param CustomerFactory $customerFactory * @param ManagerInterface $eventManager @@ -356,6 +363,7 @@ class AccountManagement implements AccountManagementInterface * @param SessionManagerInterface|null $sessionManager * @param SaveHandlerInterface|null $saveHandler * @param CollectionFactory|null $visitorCollectionFactory + * @param SearchCriteriaBuilder|null $searchCriteriaBuilder * @SuppressWarnings(PHPMD.ExcessiveParameterList) */ public function __construct( @@ -387,7 +395,8 @@ public function __construct( AccountConfirmation $accountConfirmation = null, SessionManagerInterface $sessionManager = null, SaveHandlerInterface $saveHandler = null, - CollectionFactory $visitorCollectionFactory = null + CollectionFactory $visitorCollectionFactory = null, + SearchCriteriaBuilder $searchCriteriaBuilder = null ) { $this->customerFactory = $customerFactory; $this->eventManager = $eventManager; @@ -423,6 +432,8 @@ public function __construct( ?: ObjectManager::getInstance()->get(SaveHandlerInterface::class); $this->visitorCollectionFactory = $visitorCollectionFactory ?: ObjectManager::getInstance()->get(CollectionFactory::class); + $this->searchCriteriaBuilder = $searchCriteriaBuilder + ?: ObjectManager::getInstance()->get(SearchCriteriaBuilder::class); } /** @@ -591,6 +602,43 @@ public function initiatePasswordReset($email, $template, $websiteId = null) return false; } + /** + * Match a customer by their RP token. + * + * @param string $rpToken + * @throws ExpiredException + * @throws NoSuchEntityException + * + * @return CustomerInterface + * @throws LocalizedException + */ + private function matchCustomerByRpToken(string $rpToken): CustomerInterface + { + $this->searchCriteriaBuilder->addFilter( + 'rp_token', + $rpToken + ); + $this->searchCriteriaBuilder->setPageSize(1); + $found = $this->customerRepository->getList( + $this->searchCriteriaBuilder->create() + ); + if ($found->getTotalCount() > 1) { + //Failed to generated unique RP token + throw new ExpiredException( + new Phrase('Reset password token expired.') + ); + } + if ($found->getTotalCount() === 0) { + //Customer with such token not found. + throw NoSuchEntityException::singleField( + 'rp_token', + $rpToken + ); + } + //Unique customer found. + return $found->getItems()[0]; + } + /** * Handle not supported template * @@ -613,18 +661,26 @@ private function handleUnknownTemplate($template) /** * @inheritdoc */ - public function resetPassword($email, $resetToken, $newPassword) + public function resetPassword(?string $email, string $resetToken, string $newPassword): bool { - $customer = $this->customerRepository->get($email); + if (!$email) { + $customer = $this->matchCustomerByRpToken($resetToken); + $email = $customer->getEmail(); + } else { + $customer = $this->customerRepository->get($email); + } //Validate Token and new password strength $this->validateResetPasswordToken($customer->getId(), $resetToken); + $this->credentialsValidator->checkPasswordDifferentFromEmail( + $email, + $newPassword + ); $this->checkPasswordStrength($newPassword); //Update secure data $customerSecure = $this->customerRegistry->retrieveSecureData($customer->getId()); $customerSecure->setRpToken(null); $customerSecure->setRpTokenCreatedAt(null); $customerSecure->setPasswordHash($this->createPasswordHash($newPassword)); - $this->getAuthentication()->unlock($customer->getId()); $this->sessionManager->destroy(); $this->destroyCustomerSessions($customer->getId()); $this->customerRepository->save($customer); @@ -955,6 +1011,8 @@ protected function createPasswordHash($password) } /** + * Returns eval validator + * * @return Backend */ private function getEavValidator() @@ -1033,10 +1091,11 @@ public function isCustomerInStore($customerWebsiteId, $storeId) * @throws \Magento\Framework\Exception\State\ExpiredException If token is expired * @throws \Magento\Framework\Exception\InputException If token or customer id is invalid * @throws \Magento\Framework\Exception\NoSuchEntityException If customer doesn't exist + * @throws LocalizedException */ - private function validateResetPasswordToken($customerId, $resetPasswordLinkToken) + private function validateResetPasswordToken(?int $customerId, ?string $resetPasswordLinkToken) : bool { - if (empty($customerId) || $customerId < 0) { + if ($customerId !== null && $customerId <= 0) { throw new InputException( __( 'Invalid value of "%value" provided for the %fieldName field.', @@ -1044,21 +1103,24 @@ private function validateResetPasswordToken($customerId, $resetPasswordLinkToken ) ); } + + if ($customerId === null) { + //Looking for the customer. + $customerId = $this->matchCustomerByRpToken($resetPasswordLinkToken) + ->getId(); + } if (!is_string($resetPasswordLinkToken) || empty($resetPasswordLinkToken)) { $params = ['fieldName' => 'resetPasswordLinkToken']; throw new InputException(__('"%fieldName" is required. Enter and try again.', $params)); } - $customerSecureData = $this->customerRegistry->retrieveSecureData($customerId); $rpToken = $customerSecureData->getRpToken(); $rpTokenCreatedAt = $customerSecureData->getRpTokenCreatedAt(); - if (!Security::compareStrings($rpToken, $resetPasswordLinkToken)) { throw new InputMismatchException(__('The password token is mismatched. Reset and try again.')); } elseif ($this->isResetPasswordLinkTokenExpired($rpToken, $rpTokenCreatedAt)) { throw new ExpiredException(__('The password token is expired. Reset and try again.')); } - return true; } @@ -1141,6 +1203,7 @@ protected function sendPasswordResetNotificationEmail($customer) * @param int|string|null $defaultStoreId * @return int * @deprecated 100.1.0 + * @throws LocalizedException */ protected function getWebsiteStoreId($customer, $defaultStoreId = null) { @@ -1153,6 +1216,8 @@ protected function getWebsiteStoreId($customer, $defaultStoreId = null) } /** + * Return array with template types + * * @return array * @deprecated 100.1.0 */ diff --git a/app/code/Magento/Customer/view/frontend/email/password_reset_confirmation.html b/app/code/Magento/Customer/view/frontend/email/password_reset_confirmation.html index 6c17762a882..f33350ea482 100644 --- a/app/code/Magento/Customer/view/frontend/email/password_reset_confirmation.html +++ b/app/code/Magento/Customer/view/frontend/email/password_reset_confirmation.html @@ -21,7 +21,8 @@ <table class="inner-wrapper" border="0" cellspacing="0" cellpadding="0" align="center"> <tr> <td align="center"> - <a href="{{var this.getUrl($store,'customer/account/createPassword/',[_query:[id:$customer.id,token:$customer.rp_token],_nosid:1])}}" target="_blank">{{trans "Set a New Password"}}</a> + <a href="{{var this.getUrl($store,'customer/account/createPassword/',[_query:[token:$customer.rp_token],_nosid:1])}}" target="_blank">{{trans "Set a New Password"}}</a> + </td> </tr> </table> diff --git a/app/code/Magento/Customer/view/frontend/templates/form/resetforgottenpassword.phtml b/app/code/Magento/Customer/view/frontend/templates/form/resetforgottenpassword.phtml index 15e570da04b..e79cea80ac8 100644 --- a/app/code/Magento/Customer/view/frontend/templates/form/resetforgottenpassword.phtml +++ b/app/code/Magento/Customer/view/frontend/templates/form/resetforgottenpassword.phtml @@ -8,7 +8,7 @@ /** @var \Magento\Customer\Block\Account\Resetpassword $block */ ?> -<form action="<?= $block->escapeUrl($block->getUrl('*/*/resetpasswordpost', ['_query' => ['id' => $block->getCustomerId(), 'token' => $block->getResetPasswordLinkToken()]])) ?>" +<form action="<?= $block->escapeUrl($block->getUrl('*/*/resetpasswordpost', ['_query' => ['token' => $block->getResetPasswordLinkToken()]])) ?>" method="post" <?php if ($block->isAutocompleteDisabled()) :?> autocomplete="off"<?php endif; ?> id="form-validate" diff --git a/dev/tests/integration/testsuite/Magento/Customer/Controller/AccountTest.php b/dev/tests/integration/testsuite/Magento/Customer/Controller/AccountTest.php index 921fa81fa6f..12855e457ef 100644 --- a/dev/tests/integration/testsuite/Magento/Customer/Controller/AccountTest.php +++ b/dev/tests/integration/testsuite/Magento/Customer/Controller/AccountTest.php @@ -130,7 +130,6 @@ public function testCreatepasswordActionWithDirectLink() $customer->save(); $this->getRequest()->setParam('token', $token); - $this->getRequest()->setParam('id', $customer->getId()); $this->dispatch('customer/account/createPassword'); @@ -138,12 +137,13 @@ public function testCreatepasswordActionWithDirectLink() $this->assertEquals(302, $response->getHttpResponseCode()); $text = $response->getBody(); $this->assertFalse((bool)preg_match('/' . $token . '/m', $text)); - $this->assertRedirect($this->stringContains('customer/account/createpassword')); + $this->assertRedirect( + $this->stringContains('customer/account/createpassword') + ); - /** @var \Magento\Customer\Model\Session $customer */ - $session = Bootstrap::getObjectManager()->get(\Magento\Customer\Model\Session::class); + /** @var Session $customer */ + $session = Bootstrap::getObjectManager()->get(Session::class); $this->assertEquals($token, $session->getRpToken()); - $this->assertEquals($customer->getId(), $session->getRpCustomerId()); $this->assertNotContains($token, $response->getHeader('Location')->getFieldValue()); } @@ -419,6 +419,7 @@ public function testResetPasswordPostNoTokenAction() $this->getRequest() ->setParam('id', 1) ->setParam('token', '8ed8677e6c79e68b94e61658bd756ea5') + ->setMethod('POST') ->setPostValue([ 'password' => 'new-password', 'password_confirmation' => 'new-password', @@ -441,6 +442,7 @@ public function testResetPasswordPostAction() $this->getRequest() ->setQueryValue('id', 1) ->setQueryValue('token', '8ed8677e6c79e68b94e61658bd756ea5') + ->setMethod('POST') ->setPostValue([ 'password' => 'new-Password1', 'password_confirmation' => 'new-Password1', diff --git a/dev/tests/integration/testsuite/Magento/Customer/Model/AccountManagementTest.php b/dev/tests/integration/testsuite/Magento/Customer/Model/AccountManagementTest.php index f5b6fdc93d3..4810b6c28ca 100644 --- a/dev/tests/integration/testsuite/Magento/Customer/Model/AccountManagementTest.php +++ b/dev/tests/integration/testsuite/Magento/Customer/Model/AccountManagementTest.php @@ -357,6 +357,29 @@ public function testValidateResetPasswordLinkTokenNull() } } + /** + * @magentoDataFixture Magento/Customer/_files/customer.php + */ + public function testValidateResetPasswordLinkTokenWithoutId() + { + $token = 'randomStr123'; + $this->setResetPasswordData($token, 'Y-m-d H:i:s'); + $this->assertTrue( + $this->accountManagement->validateResetPasswordLinkToken(null, $token) + ); + } + /** + * @magentoDataFixture Magento/Customer/_files/two_customers.php + * @expectedException \Magento\Framework\Exception\State\ExpiredException + */ + public function testValidateResetPasswordLinkTokenAmbiguous() + { + $token = 'randomStr123'; + $this->setResetPasswordData($token, 'Y-m-d H:i:s', 1); + $this->setResetPasswordData($token, 'Y-m-d H:i:s', 2); + $this->accountManagement->validateResetPasswordLinkToken(null, $token); + } + /** * @magentoAppArea frontend * @magentoDataFixture Magento/Customer/_files/customer.php @@ -512,6 +535,31 @@ public function testResetPasswordTokenInvalidUserEmail() } } + /** + * @magentoDataFixture Magento/Customer/_files/customer.php + */ + public function testResetPasswordWithoutEmail() + { + $resetToken = 'lsdj579slkj5987slkj595lkj'; + $password = 'new_Password123'; + $this->setResetPasswordData($resetToken, 'Y-m-d H:i:s'); + $this->assertTrue( + $this->accountManagement->resetPassword(null, $resetToken, $password) + ); + } + /** + * @magentoDataFixture Magento/Customer/_files/two_customers.php + * @expectedException \Magento\Framework\Exception\State\ExpiredException + */ + public function testResetPasswordAmbiguousToken() + { + $resetToken = 'lsdj579slkj5987slkj595lkj'; + $password = 'new_Password123'; + $this->setResetPasswordData($resetToken, 'Y-m-d H:i:s', 1); + $this->setResetPasswordData($resetToken, 'Y-m-d H:i:s', 2); + $this->accountManagement->resetPassword(null, $resetToken, $password); + } + /** * @magentoAppArea frontend * @magentoAppIsolation enabled @@ -960,10 +1008,14 @@ public function testGetDefaultAddressesForNonExistentAddress() * * @param $resetToken * @param $date + * @param int $customerIdFromFixture Which customer to use. + * @throws \Exception */ - protected function setResetPasswordData($resetToken, $date) - { - $customerIdFromFixture = 1; + protected function setResetPasswordData( + $resetToken, + $date, + int $customerIdFromFixture = 1 + ) { /** @var \Magento\Customer\Model\Customer $customerModel */ $customerModel = $this->objectManager->create(\Magento\Customer\Model\Customer::class); $customerModel->load($customerIdFromFixture); diff --git a/lib/internal/Magento/Framework/Math/Random.php b/lib/internal/Magento/Framework/Math/Random.php index 7cb70c9a822..c2059e1935a 100644 --- a/lib/internal/Magento/Framework/Math/Random.php +++ b/lib/internal/Magento/Framework/Math/Random.php @@ -5,6 +5,9 @@ */ namespace Magento\Framework\Math; +use Magento\Framework\Exception\LocalizedException; +use Magento\Framework\Phrase; + /** * Random data generator * @@ -24,41 +27,24 @@ class Random /**#@-*/ /** - * Get random string + * Get random string. * * @param int $length * @param null|string $chars + * * @return string - * @throws \Magento\Framework\Exception\LocalizedException + * @throws LocalizedException */ public function getRandomString($length, $chars = null) { $str = ''; if (null === $chars) { - $chars = self::CHARS_LOWERS . self::CHARS_UPPERS . self::CHARS_DIGITS; + $chars = self::CHARS_LOWERS.self::CHARS_UPPERS.self::CHARS_DIGITS; } - if (function_exists('openssl_random_pseudo_bytes')) { - // use openssl lib if it is installed - for ($i = 0, $lc = strlen($chars) - 1; $i < $length; $i++) { - $bytes = openssl_random_pseudo_bytes(PHP_INT_SIZE); - $hex = bin2hex($bytes); // hex() doubles the length of the string - $rand = abs(hexdec($hex) % $lc); // random integer from 0 to $lc - $str .= $chars[$rand]; // random character in $chars - } - } elseif ($fp = @fopen('/dev/urandom', 'rb')) { - // attempt to use /dev/urandom if it exists but openssl isn't available - for ($i = 0, $lc = strlen($chars) - 1; $i < $length; $i++) { - $bytes = @fread($fp, PHP_INT_SIZE); - $hex = bin2hex($bytes); // hex() doubles the length of the string - $rand = abs(hexdec($hex) % $lc); // random integer from 0 to $lc - $str .= $chars[$rand]; // random character in $chars - } - fclose($fp); - } else { - throw new \Magento\Framework\Exception\LocalizedException( - new \Magento\Framework\Phrase("Please make sure you have 'openssl' extension installed") - ); + $charsMaxKey = mb_strlen($chars) - 1; + for ($i = 0; $i < $length; $i++) { + $str .= $chars[self::getRandomNumber(0, $charsMaxKey)]; } return $str; @@ -67,47 +53,33 @@ public function getRandomString($length, $chars = null) /** * Return a random number in the specified range * - * @param $min [optional] - * @param $max [optional] - * @return int A random integer value between min (or 0) and max - * @throws \Magento\Framework\Exception\LocalizedException + * @param int $min + * @param int $max + * @return int A random integer value between min (or 0) and max + * @throws LocalizedException */ public static function getRandomNumber($min = 0, $max = null) { if (null === $max) { $max = mt_getrandmax(); } - $range = $max - $min + 1; - $offset = 0; - if (function_exists('openssl_random_pseudo_bytes')) { - // use openssl lib if it is installed - $bytes = openssl_random_pseudo_bytes(PHP_INT_SIZE); - $hex = bin2hex($bytes); // hex() doubles the length of the string - $offset = abs(hexdec($hex) % $range); // random integer from 0 to $range - } elseif ($fp = @fopen('/dev/urandom', 'rb')) { - // attempt to use /dev/urandom if it exists but openssl isn't available - $bytes = @fread($fp, PHP_INT_SIZE); - $hex = bin2hex($bytes); // hex() doubles the length of the string - $offset = abs(hexdec($hex) % $range); // random integer from 0 to $range - fclose($fp); - } else { - throw new \Magento\Framework\Exception\LocalizedException( - new \Magento\Framework\Phrase("Please make sure you have 'openssl' extension installed") - ); + if ($max < $min) { + throw new LocalizedException(new Phrase('Invalid range given.')); } - return $min + $offset; // random integer from $min to $max + return random_int($min, $max); } /** - * Generate a hash from unique ID + * Generate a hash from unique ID. * * @param string $prefix * @return string + * @throws LocalizedException */ public function getUniqueHash($prefix = '') { - return $prefix . md5(uniqid(microtime() . self::getRandomNumber(), true)); + return $prefix . $this->getRandomString(32); } } From 822de9dfbd4683ae7591779ac19a495b92118167 Mon Sep 17 00:00:00 2001 From: roman <rleshchenko@magento.com> Date: Fri, 21 Sep 2018 15:59:25 +0300 Subject: [PATCH 35/44] MAGETWO-70943: Incorrect reset password flow --- .../Controller/Account/CreatePasswordTest.php | 233 -- .../Account/ResetPasswordPostTest.php | 379 --- .../Test/Unit/Model/AccountManagementTest.php | 2057 ----------------- 3 files changed, 2669 deletions(-) delete mode 100644 app/code/Magento/Customer/Test/Unit/Controller/Account/CreatePasswordTest.php delete mode 100644 app/code/Magento/Customer/Test/Unit/Controller/Account/ResetPasswordPostTest.php delete mode 100644 app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php diff --git a/app/code/Magento/Customer/Test/Unit/Controller/Account/CreatePasswordTest.php b/app/code/Magento/Customer/Test/Unit/Controller/Account/CreatePasswordTest.php deleted file mode 100644 index 77f41024ba0..00000000000 --- a/app/code/Magento/Customer/Test/Unit/Controller/Account/CreatePasswordTest.php +++ /dev/null @@ -1,233 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Customer\Test\Unit\Controller\Account; - -use Magento\Framework\Controller\Result\Redirect; -use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; - -/** - * @SuppressWarnings(PHPMD.CouplingBetweenObjects) - */ -class CreatePasswordTest extends \PHPUnit\Framework\TestCase -{ - /** @var \Magento\Customer\Controller\Account\CreatePassword */ - protected $model; - - /** @var ObjectManagerHelper */ - protected $objectManagerHelper; - - /** @var \Magento\Customer\Model\Session|\PHPUnit_Framework_MockObject_MockObject */ - protected $sessionMock; - - /** @var \Magento\Framework\View\Result\PageFactory|\PHPUnit_Framework_MockObject_MockObject */ - protected $pageFactoryMock; - - /** @var \Magento\Customer\Api\AccountManagementInterface|\PHPUnit_Framework_MockObject_MockObject */ - protected $accountManagementMock; - - /** @var \Magento\Framework\App\RequestInterface|\PHPUnit_Framework_MockObject_MockObject */ - protected $requestMock; - - /** @var \Magento\Framework\Controller\Result\RedirectFactory|\PHPUnit_Framework_MockObject_MockObject */ - protected $redirectFactoryMock; - - /** @var \Magento\Framework\Message\ManagerInterface|\PHPUnit_Framework_MockObject_MockObject */ - protected $messageManagerMock; - - protected function setUp() - { - $this->sessionMock = $this->getMockBuilder(\Magento\Customer\Model\Session::class) - ->disableOriginalConstructor() - ->setMethods(['setRpToken', 'setRpCustomerId', 'getRpToken', 'getRpCustomerId']) - ->getMock(); - $this->pageFactoryMock = $this->getMockBuilder(\Magento\Framework\View\Result\PageFactory::class) - ->disableOriginalConstructor() - ->getMock(); - $this->accountManagementMock = $this->getMockBuilder(\Magento\Customer\Api\AccountManagementInterface::class) - ->getMockForAbstractClass(); - $this->requestMock = $this->getMockBuilder(\Magento\Framework\App\RequestInterface::class) - ->getMockForAbstractClass(); - $this->redirectFactoryMock = $this->getMockBuilder(\Magento\Framework\Controller\Result\RedirectFactory::class) - ->disableOriginalConstructor() - ->getMock(); - $this->messageManagerMock = $this->getMockBuilder(\Magento\Framework\Message\ManagerInterface::class) - ->getMockForAbstractClass(); - - $this->objectManagerHelper = new ObjectManagerHelper($this); - $this->model = $this->objectManagerHelper->getObject( - \Magento\Customer\Controller\Account\CreatePassword::class, - [ - 'customerSession' => $this->sessionMock, - 'resultPageFactory' => $this->pageFactoryMock, - 'accountManagement' => $this->accountManagementMock, - 'request' => $this->requestMock, - 'resultRedirectFactory' => $this->redirectFactoryMock, - 'messageManager' => $this->messageManagerMock, - ] - ); - } - - public function testExecuteWithLink() - { - $token = 'token'; - $customerId = '11'; - - $this->requestMock->expects($this->exactly(2)) - ->method('getParam') - ->willReturnMap( - [ - ['token', null, $token], - ['id', null, $customerId], - ] - ); - - $this->accountManagementMock->expects($this->once()) - ->method('validateResetPasswordLinkToken') - ->with($customerId, $token) - ->willReturn(true); - - $this->sessionMock->expects($this->once()) - ->method('setRpToken') - ->with($token); - $this->sessionMock->expects($this->once()) - ->method('setRpCustomerId') - ->with($customerId); - - /** @var Redirect|\PHPUnit_Framework_MockObject_MockObject $redirectMock */ - $redirectMock = $this->getMockBuilder(\Magento\Framework\Controller\Result\Redirect::class) - ->disableOriginalConstructor() - ->getMock(); - - $this->redirectFactoryMock->expects($this->once()) - ->method('create') - ->with([]) - ->willReturn($redirectMock); - - $redirectMock->expects($this->once()) - ->method('setPath') - ->with('*/*/createpassword', []) - ->willReturnSelf(); - - $this->assertEquals($redirectMock, $this->model->execute()); - } - - public function testExecuteWithSession() - { - $token = 'token'; - $customerId = '11'; - - $this->requestMock->expects($this->exactly(2)) - ->method('getParam') - ->willReturnMap( - [ - ['token', null, null], - ['id', null, $customerId], - ] - ); - - $this->sessionMock->expects($this->once()) - ->method('getRpToken') - ->willReturn($token); - $this->sessionMock->expects($this->once()) - ->method('getRpCustomerId') - ->willReturn($customerId); - - $this->accountManagementMock->expects($this->once()) - ->method('validateResetPasswordLinkToken') - ->with($customerId, $token) - ->willReturn(true); - - /** @var \Magento\Framework\View\Result\Page|\PHPUnit_Framework_MockObject_MockObject $pageMock */ - $pageMock = $this->getMockBuilder(\Magento\Framework\View\Result\Page::class) - ->disableOriginalConstructor() - ->getMock(); - - $this->pageFactoryMock->expects($this->once()) - ->method('create') - ->with(false, []) - ->willReturn($pageMock); - - /** @var \Magento\Framework\View\Layout|\PHPUnit_Framework_MockObject_MockObject $layoutMock */ - $layoutMock = $this->getMockBuilder(\Magento\Framework\View\Layout::class) - ->disableOriginalConstructor() - ->getMock(); - - $pageMock->expects($this->once()) - ->method('getLayout') - ->willReturn($layoutMock); - - /** @var \Magento\Customer\Block\Account\Resetpassword|\PHPUnit_Framework_MockObject_MockObject $layoutMock */ - $blockMock = $this->getMockBuilder(\Magento\Customer\Block\Account\Resetpassword::class) - ->disableOriginalConstructor() - ->setMethods(['setCustomerId', 'setResetPasswordLinkToken']) - ->getMock(); - - $layoutMock->expects($this->once()) - ->method('getBlock') - ->with('resetPassword') - ->willReturn($blockMock); - - $blockMock->expects($this->once()) - ->method('setCustomerId') - ->with($customerId) - ->willReturnSelf(); - $blockMock->expects($this->once()) - ->method('setResetPasswordLinkToken') - ->with($token) - ->willReturnSelf(); - - $this->assertEquals($pageMock, $this->model->execute()); - } - - public function testExecuteWithException() - { - $token = 'token'; - $customerId = '11'; - - $this->requestMock->expects($this->exactly(2)) - ->method('getParam') - ->willReturnMap( - [ - ['token', null, $token], - ['id', null, null], - ] - ); - - $this->sessionMock->expects($this->once()) - ->method('getRpToken') - ->willReturn($token); - $this->sessionMock->expects($this->once()) - ->method('getRpCustomerId') - ->willReturn($customerId); - - $this->accountManagementMock->expects($this->once()) - ->method('validateResetPasswordLinkToken') - ->with($customerId, $token) - ->willThrowException(new \Exception('Exception.')); - - $this->messageManagerMock->expects($this->once()) - ->method('addError') - ->with(__('Your password reset link has expired.')) - ->willReturnSelf(); - - /** @var Redirect|\PHPUnit_Framework_MockObject_MockObject $redirectMock */ - $redirectMock = $this->getMockBuilder(\Magento\Framework\Controller\Result\Redirect::class) - ->disableOriginalConstructor() - ->getMock(); - - $this->redirectFactoryMock->expects($this->once()) - ->method('create') - ->with([]) - ->willReturn($redirectMock); - - $redirectMock->expects($this->once()) - ->method('setPath') - ->with('*/*/forgotpassword', []) - ->willReturnSelf(); - - $this->assertEquals($redirectMock, $this->model->execute()); - } -} diff --git a/app/code/Magento/Customer/Test/Unit/Controller/Account/ResetPasswordPostTest.php b/app/code/Magento/Customer/Test/Unit/Controller/Account/ResetPasswordPostTest.php deleted file mode 100644 index b79ad008e5e..00000000000 --- a/app/code/Magento/Customer/Test/Unit/Controller/Account/ResetPasswordPostTest.php +++ /dev/null @@ -1,379 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\Customer\Test\Unit\Controller\Account; - -use Magento\Framework\Controller\Result\Redirect; -use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; - -/** - * @SuppressWarnings(PHPMD.CouplingBetweenObjects) - */ -class ResetPasswordPostTest extends \PHPUnit\Framework\TestCase -{ - /** @var \Magento\Customer\Controller\Account\ResetPasswordPost */ - protected $model; - - /** @var ObjectManagerHelper */ - protected $objectManagerHelper; - - /** @var \Magento\Customer\Model\Session|\PHPUnit_Framework_MockObject_MockObject */ - protected $sessionMock; - - /** @var \Magento\Framework\View\Result\PageFactory|\PHPUnit_Framework_MockObject_MockObject */ - protected $pageFactoryMock; - - /** @var \Magento\Customer\Api\AccountManagementInterface|\PHPUnit_Framework_MockObject_MockObject */ - protected $accountManagementMock; - - /** @var \Magento\Customer\Api\CustomerRepositoryInterface|\PHPUnit_Framework_MockObject_MockObject */ - protected $customerRepositoryMock; - - /** @var \Magento\Framework\App\RequestInterface|\PHPUnit_Framework_MockObject_MockObject */ - protected $requestMock; - - /** @var \Magento\Framework\Controller\Result\RedirectFactory|\PHPUnit_Framework_MockObject_MockObject */ - protected $redirectFactoryMock; - - /** @var \Magento\Framework\Message\ManagerInterface|\PHPUnit_Framework_MockObject_MockObject */ - protected $messageManagerMock; - - protected function setUp() - { - $this->sessionMock = $this->getMockBuilder(\Magento\Customer\Model\Session::class) - ->disableOriginalConstructor() - ->setMethods(['unsRpToken', 'unsRpCustomerId']) - ->getMock(); - $this->pageFactoryMock = $this->getMockBuilder(\Magento\Framework\View\Result\PageFactory::class) - ->disableOriginalConstructor() - ->getMock(); - $this->accountManagementMock = $this->getMockBuilder(\Magento\Customer\Api\AccountManagementInterface::class) - ->getMockForAbstractClass(); - $this->customerRepositoryMock = $this->getMockBuilder(\Magento\Customer\Api\CustomerRepositoryInterface::class) - ->getMockForAbstractClass(); - $this->requestMock = $this->getMockBuilder(\Magento\Framework\App\RequestInterface::class) - ->setMethods(['getQuery', 'getPost']) - ->getMockForAbstractClass(); - $this->redirectFactoryMock = $this->getMockBuilder(\Magento\Framework\Controller\Result\RedirectFactory::class) - ->disableOriginalConstructor() - ->getMock(); - $this->messageManagerMock = $this->getMockBuilder(\Magento\Framework\Message\ManagerInterface::class) - ->getMockForAbstractClass(); - - $this->objectManagerHelper = new ObjectManagerHelper($this); - $this->model = $this->objectManagerHelper->getObject( - \Magento\Customer\Controller\Account\ResetPasswordPost::class, - [ - 'customerSession' => $this->sessionMock, - 'resultPageFactory' => $this->pageFactoryMock, - 'accountManagement' => $this->accountManagementMock, - 'customerRepository' => $this->customerRepositoryMock, - 'request' => $this->requestMock, - 'resultRedirectFactory' => $this->redirectFactoryMock, - 'messageManager' => $this->messageManagerMock, - ] - ); - } - - public function testExecute() - { - $token = 'token'; - $customerId = '11'; - $password = 'password'; - $passwordConfirmation = 'password'; - $email = 'email@email.com'; - - $this->requestMock->expects($this->exactly(2)) - ->method('getQuery') - ->willReturnMap( - [ - ['token', $token], - ['id', $customerId], - ] - ); - $this->requestMock->expects($this->exactly(2)) - ->method('getPost') - ->willReturnMap( - [ - ['password', $password], - ['password_confirmation', $passwordConfirmation], - ] - ); - - /** @var \Magento\Customer\Api\Data\CustomerInterface|\PHPUnit_Framework_MockObject_MockObject $customerMock */ - $customerMock = $this->getMockBuilder(\Magento\Customer\Api\Data\CustomerInterface::class) - ->getMockForAbstractClass(); - - $this->customerRepositoryMock->expects($this->once()) - ->method('getById') - ->with($customerId) - ->willReturn($customerMock); - - $customerMock->expects($this->once()) - ->method('getEmail') - ->willReturn($email); - - $this->accountManagementMock->expects($this->once()) - ->method('resetPassword') - ->with($email, $token, $password) - ->willReturn(true); - - $this->sessionMock->expects($this->once()) - ->method('unsRpToken'); - $this->sessionMock->expects($this->once()) - ->method('unsRpCustomerId'); - - $this->messageManagerMock->expects($this->once()) - ->method('addSuccess') - ->with(__('You updated your password.')) - ->willReturnSelf(); - - /** @var Redirect|\PHPUnit_Framework_MockObject_MockObject $redirectMock */ - $redirectMock = $this->getMockBuilder(\Magento\Framework\Controller\Result\Redirect::class) - ->disableOriginalConstructor() - ->getMock(); - - $this->redirectFactoryMock->expects($this->once()) - ->method('create') - ->with([]) - ->willReturn($redirectMock); - - $redirectMock->expects($this->once()) - ->method('setPath') - ->with('*/*/login', []) - ->willReturnSelf(); - - $this->assertEquals($redirectMock, $this->model->execute()); - } - - public function testExecuteWithException() - { - $token = 'token'; - $customerId = '11'; - $password = 'password'; - $passwordConfirmation = 'password'; - $email = 'email@email.com'; - - $this->requestMock->expects($this->exactly(2)) - ->method('getQuery') - ->willReturnMap( - [ - ['token', $token], - ['id', $customerId], - ] - ); - $this->requestMock->expects($this->exactly(2)) - ->method('getPost') - ->willReturnMap( - [ - ['password', $password], - ['password_confirmation', $passwordConfirmation], - ] - ); - - /** @var \Magento\Customer\Api\Data\CustomerInterface|\PHPUnit_Framework_MockObject_MockObject $customerMock */ - $customerMock = $this->getMockBuilder(\Magento\Customer\Api\Data\CustomerInterface::class) - ->getMockForAbstractClass(); - - $this->customerRepositoryMock->expects($this->once()) - ->method('getById') - ->with($customerId) - ->willReturn($customerMock); - - $customerMock->expects($this->once()) - ->method('getEmail') - ->willReturn($email); - - $this->accountManagementMock->expects($this->once()) - ->method('resetPassword') - ->with($email, $token, $password) - ->willThrowException(new \Exception('Exception.')); - - $this->messageManagerMock->expects($this->once()) - ->method('addError') - ->with(__('Something went wrong while saving the new password.')) - ->willReturnSelf(); - - /** @var Redirect|\PHPUnit_Framework_MockObject_MockObject $redirectMock */ - $redirectMock = $this->getMockBuilder(\Magento\Framework\Controller\Result\Redirect::class) - ->disableOriginalConstructor() - ->getMock(); - - $this->redirectFactoryMock->expects($this->once()) - ->method('create') - ->with([]) - ->willReturn($redirectMock); - - $redirectMock->expects($this->once()) - ->method('setPath') - ->with('*/*/createPassword', ['id' => $customerId, 'token' => $token]) - ->willReturnSelf(); - - $this->assertEquals($redirectMock, $this->model->execute()); - } - - /** - * Test for InputException - */ - public function testExecuteWithInputException() - { - $token = 'token'; - $customerId = '11'; - $password = 'password'; - $passwordConfirmation = 'password'; - $email = 'email@email.com'; - - $this->requestMock->expects($this->exactly(2)) - ->method('getQuery') - ->willReturnMap( - [ - ['token', $token], - ['id', $customerId], - ] - ); - $this->requestMock->expects($this->exactly(2)) - ->method('getPost') - ->willReturnMap( - [ - ['password', $password], - ['password_confirmation', $passwordConfirmation], - ] - ); - - /** @var \Magento\Customer\Api\Data\CustomerInterface|\PHPUnit_Framework_MockObject_MockObject $customerMock */ - $customerMock = $this->getMockBuilder(\Magento\Customer\Api\Data\CustomerInterface::class) - ->getMockForAbstractClass(); - - $this->customerRepositoryMock->expects($this->once()) - ->method('getById') - ->with($customerId) - ->willReturn($customerMock); - - $customerMock->expects($this->once()) - ->method('getEmail') - ->willReturn($email); - - $this->accountManagementMock->expects($this->once()) - ->method('resetPassword') - ->with($email, $token, $password) - ->willThrowException(new \Magento\Framework\Exception\InputException(__('InputException.'))); - - $this->messageManagerMock->expects($this->once()) - ->method('addError') - ->with(__('InputException.')) - ->willReturnSelf(); - - /** @var Redirect|\PHPUnit_Framework_MockObject_MockObject $redirectMock */ - $redirectMock = $this->getMockBuilder(\Magento\Framework\Controller\Result\Redirect::class) - ->disableOriginalConstructor() - ->getMock(); - - $this->redirectFactoryMock->expects($this->once()) - ->method('create') - ->with([]) - ->willReturn($redirectMock); - - $redirectMock->expects($this->once()) - ->method('setPath') - ->with('*/*/createPassword', ['id' => $customerId, 'token' => $token]) - ->willReturnSelf(); - - $this->assertEquals($redirectMock, $this->model->execute()); - } - - public function testExecuteWithWrongConfirmation() - { - $token = 'token'; - $customerId = '11'; - $password = 'password'; - $passwordConfirmation = 'wrong_password'; - - $this->requestMock->expects($this->exactly(2)) - ->method('getQuery') - ->willReturnMap( - [ - ['token', $token], - ['id', $customerId], - ] - ); - $this->requestMock->expects($this->exactly(2)) - ->method('getPost') - ->willReturnMap( - [ - ['password', $password], - ['password_confirmation', $passwordConfirmation], - ] - ); - - $this->messageManagerMock->expects($this->once()) - ->method('addError') - ->with(__('New Password and Confirm New Password values didn\'t match.')) - ->willReturnSelf(); - - /** @var Redirect|\PHPUnit_Framework_MockObject_MockObject $redirectMock */ - $redirectMock = $this->getMockBuilder(\Magento\Framework\Controller\Result\Redirect::class) - ->disableOriginalConstructor() - ->getMock(); - - $this->redirectFactoryMock->expects($this->once()) - ->method('create') - ->with([]) - ->willReturn($redirectMock); - - $redirectMock->expects($this->once()) - ->method('setPath') - ->with('*/*/createPassword', ['id' => $customerId, 'token' => $token]) - ->willReturnSelf(); - - $this->assertEquals($redirectMock, $this->model->execute()); - } - - public function testExecuteWithEmptyPassword() - { - $token = 'token'; - $customerId = '11'; - $password = ''; - $passwordConfirmation = ''; - - $this->requestMock->expects($this->exactly(2)) - ->method('getQuery') - ->willReturnMap( - [ - ['token', $token], - ['id', $customerId], - ] - ); - $this->requestMock->expects($this->exactly(2)) - ->method('getPost') - ->willReturnMap( - [ - ['password', $password], - ['password_confirmation', $passwordConfirmation], - ] - ); - - $this->messageManagerMock->expects($this->once()) - ->method('addError') - ->with(__('Please enter a new password.')) - ->willReturnSelf(); - - /** @var Redirect|\PHPUnit_Framework_MockObject_MockObject $redirectMock */ - $redirectMock = $this->getMockBuilder(\Magento\Framework\Controller\Result\Redirect::class) - ->disableOriginalConstructor() - ->getMock(); - - $this->redirectFactoryMock->expects($this->once()) - ->method('create') - ->with([]) - ->willReturn($redirectMock); - - $redirectMock->expects($this->once()) - ->method('setPath') - ->with('*/*/createPassword', ['id' => $customerId, 'token' => $token]) - ->willReturnSelf(); - - $this->assertEquals($redirectMock, $this->model->execute()); - } -} diff --git a/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php b/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php deleted file mode 100644 index aad20f757e9..00000000000 --- a/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php +++ /dev/null @@ -1,2057 +0,0 @@ -<?php -/** - * Copyright © Magento, Inc. All rights reserved. - * See COPYING.txt for license details. - */ - -namespace Magento\Customer\Test\Unit\Model; - -use Magento\Customer\Model\AccountManagement; -use Magento\Customer\Model\AccountConfirmation; -use Magento\Customer\Model\AuthenticationInterface; -use Magento\Customer\Model\EmailNotificationInterface; -use Magento\Framework\App\Area; -use Magento\Framework\Exception\NoSuchEntityException; -use Magento\Framework\Intl\DateTimeFactory; -use Magento\Framework\TestFramework\Unit\Helper\ObjectManager as ObjectManagerHelper; -use Magento\Store\Model\ScopeInterface; - -/** - * @SuppressWarnings(PHPMD.TooManyFields) - * @SuppressWarnings(PHPMD.CouplingBetweenObjects) - */ -class AccountManagementTest extends \PHPUnit\Framework\TestCase -{ - /** @var AccountManagement */ - protected $accountManagement; - - /** @var ObjectManagerHelper */ - protected $objectManagerHelper; - - /** @var \Magento\Customer\Model\CustomerFactory|\PHPUnit_Framework_MockObject_MockObject */ - protected $customerFactory; - - /** @var \Magento\Framework\Event\ManagerInterface|\PHPUnit_Framework_MockObject_MockObject */ - protected $manager; - - /** @var \Magento\Store\Model\StoreManagerInterface|\PHPUnit_Framework_MockObject_MockObject */ - protected $storeManager; - - /** @var \Magento\Framework\Math\Random|\PHPUnit_Framework_MockObject_MockObject */ - protected $random; - - /** @var \Magento\Customer\Model\Metadata\Validator|\PHPUnit_Framework_MockObject_MockObject */ - protected $validator; - - /** @var \Magento\Customer\Api\Data\ValidationResultsInterfaceFactory|\PHPUnit_Framework_MockObject_MockObject */ - protected $validationResultsInterfaceFactory; - - /** @var \Magento\Customer\Api\AddressRepositoryInterface|\PHPUnit_Framework_MockObject_MockObject */ - protected $addressRepository; - - /** @var \Magento\Customer\Api\CustomerMetadataInterface|\PHPUnit_Framework_MockObject_MockObject */ - protected $customerMetadata; - - /** @var \Magento\Customer\Model\CustomerRegistry|\PHPUnit_Framework_MockObject_MockObject */ - protected $customerRegistry; - - /** @var \Psr\Log\LoggerInterface|\PHPUnit_Framework_MockObject_MockObject */ - protected $logger; - - /** @var \Magento\Framework\Encryption\EncryptorInterface|\PHPUnit_Framework_MockObject_MockObject */ - protected $encryptor; - - /** @var \Magento\Customer\Model\Config\Share|\PHPUnit_Framework_MockObject_MockObject */ - protected $share; - - /** @var \Magento\Framework\Stdlib\StringUtils|\PHPUnit_Framework_MockObject_MockObject */ - protected $string; - - /** @var \Magento\Customer\Api\CustomerRepositoryInterface|\PHPUnit_Framework_MockObject_MockObject */ - protected $customerRepository; - - /** @var \Magento\Framework\App\Config\ScopeConfigInterface|\PHPUnit_Framework_MockObject_MockObject */ - protected $scopeConfig; - - /** @var \Magento\Framework\Mail\Template\TransportBuilder|\PHPUnit_Framework_MockObject_MockObject */ - protected $transportBuilder; - - /** @var \Magento\Framework\Reflection\DataObjectProcessor|\PHPUnit_Framework_MockObject_MockObject */ - protected $dataObjectProcessor; - - /** @var \Magento\Framework\Registry|\PHPUnit_Framework_MockObject_MockObject */ - protected $registry; - - /** @var \Magento\Customer\Helper\View|\PHPUnit_Framework_MockObject_MockObject */ - protected $customerViewHelper; - - /** @var \Magento\Framework\Stdlib\DateTime|\PHPUnit_Framework_MockObject_MockObject */ - protected $dateTime; - - /** @var \Magento\Customer\Model\Customer|\PHPUnit_Framework_MockObject_MockObject */ - protected $customer; - - /** @var \Magento\Framework\DataObjectFactory|\PHPUnit_Framework_MockObject_MockObject */ - protected $objectFactory; - - /** @var \Magento\Framework\Api\ExtensibleDataObjectConverter|\PHPUnit_Framework_MockObject_MockObject */ - protected $extensibleDataObjectConverter; - - /** - * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Store\Model\Store - */ - protected $store; - - /** - * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Customer\Model\Data\CustomerSecure - */ - protected $customerSecure; - - /** - * @var AuthenticationInterface |\PHPUnit_Framework_MockObject_MockObject - */ - protected $authenticationMock; - - /** - * @var EmailNotificationInterface |\PHPUnit_Framework_MockObject_MockObject - */ - protected $emailNotificationMock; - - /** - * @var DateTimeFactory|\PHPUnit_Framework_MockObject_MockObject - */ - private $dateTimeFactory; - - /** - * @var AccountConfirmation|\PHPUnit_Framework_MockObject_MockObject - */ - private $accountConfirmation; - - /** - * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Framework\Session\SessionManagerInterface - */ - private $sessionManager; - - /** - * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Customer\Model\ResourceModel\Visitor\CollectionFactory - */ - private $visitorCollectionFactory; - - /** - * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Framework\Session\SaveHandlerInterface - */ - private $saveHandler; - - /** - * @SuppressWarnings(PHPMD.ExcessiveMethodLength) - */ - protected function setUp() - { - $this->customerFactory = $this->createPartialMock(\Magento\Customer\Model\CustomerFactory::class, ['create']); - $this->manager = $this->createMock(\Magento\Framework\Event\ManagerInterface::class); - $this->store = $this->getMockBuilder(\Magento\Store\Model\Store::class) - ->disableOriginalConstructor() - ->getMock(); - $this->storeManager = $this->createMock(\Magento\Store\Model\StoreManagerInterface::class); - $this->random = $this->createMock(\Magento\Framework\Math\Random::class); - $this->validator = $this->createMock(\Magento\Customer\Model\Metadata\Validator::class); - $this->validationResultsInterfaceFactory = $this->createMock( - \Magento\Customer\Api\Data\ValidationResultsInterfaceFactory::class - ); - $this->addressRepository = $this->createMock(\Magento\Customer\Api\AddressRepositoryInterface::class); - $this->customerMetadata = $this->createMock(\Magento\Customer\Api\CustomerMetadataInterface::class); - $this->customerRegistry = $this->createMock(\Magento\Customer\Model\CustomerRegistry::class); - $this->logger = $this->createMock(\Psr\Log\LoggerInterface::class); - $this->encryptor = $this->createMock(\Magento\Framework\Encryption\EncryptorInterface::class); - $this->share = $this->createMock(\Magento\Customer\Model\Config\Share::class); - $this->string = $this->createMock(\Magento\Framework\Stdlib\StringUtils::class); - $this->customerRepository = $this->createMock(\Magento\Customer\Api\CustomerRepositoryInterface::class); - $this->scopeConfig = $this->getMockBuilder(\Magento\Framework\App\Config\ScopeConfigInterface::class) - ->disableOriginalConstructor() - ->getMock(); - $this->transportBuilder = $this->createMock(\Magento\Framework\Mail\Template\TransportBuilder::class); - $this->dataObjectProcessor = $this->createMock(\Magento\Framework\Reflection\DataObjectProcessor::class); - $this->registry = $this->createMock(\Magento\Framework\Registry::class); - $this->customerViewHelper = $this->createMock(\Magento\Customer\Helper\View::class); - $this->dateTime = $this->createMock(\Magento\Framework\Stdlib\DateTime::class); - $this->customer = $this->createMock(\Magento\Customer\Model\Customer::class); - $this->objectFactory = $this->createMock(\Magento\Framework\DataObjectFactory::class); - $this->extensibleDataObjectConverter = $this->createMock( - \Magento\Framework\Api\ExtensibleDataObjectConverter::class - ); - $this->authenticationMock = $this->getMockBuilder(AuthenticationInterface::class) - ->disableOriginalConstructor() - ->getMock(); - $this->emailNotificationMock = $this->getMockBuilder(EmailNotificationInterface::class) - ->disableOriginalConstructor() - ->getMock(); - - $this->customerSecure = $this->getMockBuilder(\Magento\Customer\Model\Data\CustomerSecure::class) - ->setMethods(['setRpToken', 'addData', 'setRpTokenCreatedAt', 'setData']) - ->disableOriginalConstructor() - ->getMock(); - - $this->dateTimeFactory = $this->createMock(DateTimeFactory::class); - $this->accountConfirmation = $this->createMock(AccountConfirmation::class); - - $this->visitorCollectionFactory = $this->getMockBuilder( - \Magento\Customer\Model\ResourceModel\Visitor\CollectionFactory::class - ) - ->disableOriginalConstructor() - ->setMethods(['create']) - ->getMock(); - $this->sessionManager = $this->getMockBuilder(\Magento\Framework\Session\SessionManagerInterface::class) - ->disableOriginalConstructor() - ->getMock(); - $this->saveHandler = $this->getMockBuilder(\Magento\Framework\Session\SaveHandlerInterface::class) - ->disableOriginalConstructor() - ->getMock(); - - $this->objectManagerHelper = new ObjectManagerHelper($this); - $this->accountManagement = $this->objectManagerHelper->getObject( - \Magento\Customer\Model\AccountManagement::class, - [ - 'customerFactory' => $this->customerFactory, - 'eventManager' => $this->manager, - 'storeManager' => $this->storeManager, - 'mathRandom' => $this->random, - 'validator' => $this->validator, - 'validationResultsDataFactory' => $this->validationResultsInterfaceFactory, - 'addressRepository' => $this->addressRepository, - 'customerMetadataService' => $this->customerMetadata, - 'customerRegistry' => $this->customerRegistry, - 'logger' => $this->logger, - 'encryptor' => $this->encryptor, - 'configShare' => $this->share, - 'stringHelper' => $this->string, - 'customerRepository' => $this->customerRepository, - 'scopeConfig' => $this->scopeConfig, - 'transportBuilder' => $this->transportBuilder, - 'dataProcessor' => $this->dataObjectProcessor, - 'registry' => $this->registry, - 'customerViewHelper' => $this->customerViewHelper, - 'dateTime' => $this->dateTime, - 'customerModel' => $this->customer, - 'objectFactory' => $this->objectFactory, - 'extensibleDataObjectConverter' => $this->extensibleDataObjectConverter, - 'dateTimeFactory' => $this->dateTimeFactory, - 'accountConfirmation' => $this->accountConfirmation, - 'sessionManager' => $this->sessionManager, - 'saveHandler' => $this->saveHandler, - 'visitorCollectionFactory' => $this->visitorCollectionFactory, - ] - ); - $this->objectManagerHelper->setBackwardCompatibleProperty( - $this->accountManagement, - 'authentication', - $this->authenticationMock - ); - $this->objectManagerHelper->setBackwardCompatibleProperty( - $this->accountManagement, - 'emailNotification', - $this->emailNotificationMock - ); - } - - /** - * @expectedException \Magento\Framework\Exception\InputException - */ - public function testCreateAccountWithPasswordHashWithExistingCustomer() - { - $websiteId = 1; - $storeId = 1; - $customerId = 1; - $customerEmail = 'email@email.com'; - $hash = '4nj54lkj5jfi03j49f8bgujfgsd'; - - $website = $this->getMockBuilder(\Magento\Store\Model\Website::class)->disableOriginalConstructor()->getMock(); - $website->expects($this->once()) - ->method('getStoreIds') - ->willReturn([1, 2, 3]); - $customer = $this->getMockBuilder(\Magento\Customer\Api\Data\CustomerInterface::class)->getMock(); - $customer->expects($this->once()) - ->method('getId') - ->willReturn($customerId); - $customer->expects($this->once()) - ->method('getEmail') - ->willReturn($customerEmail); - $customer->expects($this->once()) - ->method('getWebsiteId') - ->willReturn($websiteId); - $customer->expects($this->atLeastOnce()) - ->method('getStoreId') - ->willReturn($storeId); - $this->customerRepository - ->expects($this->once()) - ->method('get') - ->with($customerEmail) - ->willReturn($customer); - $this->share - ->expects($this->once()) - ->method('isWebsiteScope') - ->willReturn(true); - $this->storeManager - ->expects($this->once()) - ->method('getWebsite') - ->with($websiteId) - ->willReturn($website); - $this->accountManagement->createAccountWithPasswordHash($customer, $hash); - } - - /** - * @expectedException \Magento\Framework\Exception\State\InputMismatchException - */ - public function testCreateAccountWithPasswordHashWithCustomerWithoutStoreId() - { - $websiteId = 1; - $storeId = null; - $defaultStoreId = 1; - $customerId = 1; - $customerEmail = 'email@email.com'; - $hash = '4nj54lkj5jfi03j49f8bgujfgsd'; - - $address = $this->getMockBuilder(\Magento\Customer\Api\Data\AddressInterface::class) - ->disableOriginalConstructor() - ->getMock(); - $store = $this->getMockBuilder(\Magento\Store\Model\Store::class)->disableOriginalConstructor()->getMock(); - $store->expects($this->once()) - ->method('getId') - ->willReturn($defaultStoreId); - $website = $this->getMockBuilder(\Magento\Store\Model\Website::class)->disableOriginalConstructor()->getMock(); - $website->expects($this->atLeastOnce()) - ->method('getStoreIds') - ->willReturn([1, 2, 3]); - $website->expects($this->once()) - ->method('getDefaultStore') - ->willReturn($store); - $customer = $this->getMockBuilder(\Magento\Customer\Api\Data\CustomerInterface::class)->getMock(); - $customer->expects($this->atLeastOnce()) - ->method('getId') - ->willReturn($customerId); - $customer->expects($this->once()) - ->method('getEmail') - ->willReturn($customerEmail); - $customer->expects($this->atLeastOnce()) - ->method('getWebsiteId') - ->willReturn($websiteId); - $customer->expects($this->atLeastOnce()) - ->method('getStoreId') - ->willReturn($storeId); - $customer->expects($this->once()) - ->method('setStoreId') - ->with($defaultStoreId); - $customer - ->expects($this->once()) - ->method('getAddresses') - ->willReturn([$address]); - $customer - ->expects($this->once()) - ->method('setAddresses') - ->with(null); - $this->customerRepository - ->expects($this->once()) - ->method('get') - ->with($customerEmail) - ->willReturn($customer); - $this->share - ->expects($this->atLeastOnce()) - ->method('isWebsiteScope') - ->willReturn(true); - $this->storeManager - ->expects($this->atLeastOnce()) - ->method('getWebsite') - ->with($websiteId) - ->willReturn($website); - $exception = new \Magento\Framework\Exception\AlreadyExistsException( - new \Magento\Framework\Phrase('Exception message') - ); - $this->customerRepository - ->expects($this->once()) - ->method('save') - ->with($customer, $hash) - ->willThrowException($exception); - - $this->accountManagement->createAccountWithPasswordHash($customer, $hash); - } - - /** - * @expectedException \Magento\Framework\Exception\LocalizedException - */ - public function testCreateAccountWithPasswordHashWithLocalizedException() - { - $websiteId = 1; - $storeId = null; - $defaultStoreId = 1; - $customerId = 1; - $customerEmail = 'email@email.com'; - $hash = '4nj54lkj5jfi03j49f8bgujfgsd'; - - $address = $this->getMockBuilder(\Magento\Customer\Api\Data\AddressInterface::class) - ->disableOriginalConstructor() - ->getMock(); - $store = $this->getMockBuilder(\Magento\Store\Model\Store::class)->disableOriginalConstructor()->getMock(); - $store->expects($this->once()) - ->method('getId') - ->willReturn($defaultStoreId); - $website = $this->getMockBuilder(\Magento\Store\Model\Website::class)->disableOriginalConstructor()->getMock(); - $website->expects($this->once()) - ->method('getStoreIds') - ->willReturn([1, 2, 3]); - $website->expects($this->once()) - ->method('getDefaultStore') - ->willReturn($store); - $customer = $this->getMockBuilder(\Magento\Customer\Api\Data\CustomerInterface::class)->getMock(); - $customer->expects($this->atLeastOnce()) - ->method('getId') - ->willReturn($customerId); - $customer->expects($this->once()) - ->method('getEmail') - ->willReturn($customerEmail); - $customer->expects($this->atLeastOnce()) - ->method('getWebsiteId') - ->willReturn($websiteId); - $customer->expects($this->atLeastOnce()) - ->method('getStoreId') - ->willReturn($storeId); - $customer->expects($this->once()) - ->method('setStoreId') - ->with($defaultStoreId); - $customer - ->expects($this->once()) - ->method('getAddresses') - ->willReturn([$address]); - $customer - ->expects($this->once()) - ->method('setAddresses') - ->with(null); - $this->customerRepository - ->expects($this->once()) - ->method('get') - ->with($customerEmail) - ->willReturn($customer); - $this->share - ->expects($this->once()) - ->method('isWebsiteScope') - ->willReturn(true); - $this->storeManager - ->expects($this->atLeastOnce()) - ->method('getWebsite') - ->with($websiteId) - ->willReturn($website); - $exception = new \Magento\Framework\Exception\LocalizedException( - new \Magento\Framework\Phrase('Exception message') - ); - $this->customerRepository - ->expects($this->once()) - ->method('save') - ->with($customer, $hash) - ->willThrowException($exception); - - $this->accountManagement->createAccountWithPasswordHash($customer, $hash); - } - - /** - * @expectedException \Magento\Framework\Exception\LocalizedException - */ - public function testCreateAccountWithPasswordHashWithAddressException() - { - $websiteId = 1; - $storeId = null; - $defaultStoreId = 1; - $customerId = 1; - $customerEmail = 'email@email.com'; - $hash = '4nj54lkj5jfi03j49f8bgujfgsd'; - - $address = $this->getMockBuilder(\Magento\Customer\Api\Data\AddressInterface::class) - ->disableOriginalConstructor() - ->getMock(); - $address->expects($this->once()) - ->method('setCustomerId') - ->with($customerId); - $store = $this->getMockBuilder(\Magento\Store\Model\Store::class)->disableOriginalConstructor()->getMock(); - $store->expects($this->once()) - ->method('getId') - ->willReturn($defaultStoreId); - $website = $this->getMockBuilder(\Magento\Store\Model\Website::class)->disableOriginalConstructor()->getMock(); - $website->expects($this->once()) - ->method('getStoreIds') - ->willReturn([1, 2, 3]); - $website->expects($this->once()) - ->method('getDefaultStore') - ->willReturn($store); - $customer = $this->getMockBuilder(\Magento\Customer\Api\Data\CustomerInterface::class)->getMock(); - $customer->expects($this->atLeastOnce()) - ->method('getId') - ->willReturn($customerId); - $customer->expects($this->once()) - ->method('getEmail') - ->willReturn($customerEmail); - $customer->expects($this->atLeastOnce()) - ->method('getWebsiteId') - ->willReturn($websiteId); - $customer->expects($this->atLeastOnce()) - ->method('getStoreId') - ->willReturn($storeId); - $customer->expects($this->once()) - ->method('setStoreId') - ->with($defaultStoreId); - $customer - ->expects($this->once()) - ->method('getAddresses') - ->willReturn([$address]); - $customer - ->expects($this->once()) - ->method('setAddresses') - ->with(null); - $this->customerRepository - ->expects($this->once()) - ->method('get') - ->with($customerEmail) - ->willReturn($customer); - $this->share - ->expects($this->once()) - ->method('isWebsiteScope') - ->willReturn(true); - $this->storeManager - ->expects($this->atLeastOnce()) - ->method('getWebsite') - ->with($websiteId) - ->willReturn($website); - $this->customerRepository - ->expects($this->once()) - ->method('save') - ->with($customer, $hash) - ->willReturn($customer); - $exception = new \Magento\Framework\Exception\InputException( - new \Magento\Framework\Phrase('Exception message') - ); - $this->addressRepository - ->expects($this->atLeastOnce()) - ->method('save') - ->with($address) - ->willThrowException($exception); - $this->customerRepository - ->expects($this->once()) - ->method('delete') - ->with($customer); - - $this->accountManagement->createAccountWithPasswordHash($customer, $hash); - } - - /** - * @expectedException \Magento\Framework\Exception\LocalizedException - */ - public function testCreateAccountWithPasswordHashWithNewCustomerAndLocalizedException() - { - $storeId = 1; - $storeName = 'store_name'; - $websiteId = 1; - $hash = '4nj54lkj5jfi03j49f8bgujfgsd'; - - $customerMock = $this->getMockBuilder(\Magento\Customer\Api\Data\CustomerInterface::class) - ->getMockForAbstractClass(); - - $customerMock->expects($this->atLeastOnce()) - ->method('getId') - ->willReturn(null); - $customerMock->expects($this->atLeastOnce()) - ->method('getStoreId') - ->willReturn($storeId); - $customerMock->expects($this->atLeastOnce()) - ->method('getWebsiteId') - ->willReturn($websiteId); - $customerMock->expects($this->once()) - ->method('setCreatedIn') - ->with($storeName) - ->willReturnSelf(); - $customerMock->expects($this->once()) - ->method('getAddresses') - ->willReturn([]); - $customerMock->expects($this->once()) - ->method('setAddresses') - ->with(null) - ->willReturnSelf(); - $this->share - ->expects($this->once()) - ->method('isWebsiteScope') - ->willReturn(true); - $website = $this->getMockBuilder(\Magento\Store\Model\Website::class)->disableOriginalConstructor()->getMock(); - $website->expects($this->once()) - ->method('getStoreIds') - ->willReturn([1, 2, 3]); - $this->storeManager - ->expects($this->atLeastOnce()) - ->method('getWebsite') - ->with($websiteId) - ->willReturn($website); - - $storeMock = $this->getMockBuilder(\Magento\Store\Model\Store::class) - ->disableOriginalConstructor() - ->getMock(); - - $storeMock->expects($this->once()) - ->method('getName') - ->willReturn($storeName); - - $this->storeManager->expects($this->exactly(1)) - ->method('getStore') - ->with($storeId) - ->willReturn($storeMock); - $exception = new \Magento\Framework\Exception\LocalizedException( - new \Magento\Framework\Phrase('Exception message') - ); - $this->customerRepository - ->expects($this->once()) - ->method('save') - ->with($customerMock, $hash) - ->willThrowException($exception); - - $this->accountManagement->createAccountWithPasswordHash($customerMock, $hash); - } - - /** - * @SuppressWarnings(PHPMD.ExcessiveMethodLength) - */ - public function testCreateAccountWithoutPassword() - { - $websiteId = 1; - $storeId = null; - $defaultStoreId = 1; - $customerId = 1; - $customerEmail = 'email@email.com'; - $newLinkToken = '2jh43j5h2345jh23lh452h345hfuzasd96ofu'; - - $datetime = $this->prepareDateTimeFactory(); - - $address = $this->getMockBuilder(\Magento\Customer\Api\Data\AddressInterface::class) - ->disableOriginalConstructor() - ->getMock(); - $address->expects($this->once()) - ->method('setCustomerId') - ->with($customerId); - $store = $this->getMockBuilder(\Magento\Store\Model\Store::class)->disableOriginalConstructor()->getMock(); - $store->expects($this->once()) - ->method('getId') - ->willReturn($defaultStoreId); - $website = $this->getMockBuilder(\Magento\Store\Model\Website::class)->disableOriginalConstructor()->getMock(); - $website->expects($this->atLeastOnce()) - ->method('getStoreIds') - ->willReturn([1, 2, 3]); - $website->expects($this->once()) - ->method('getDefaultStore') - ->willReturn($store); - $customer = $this->getMockBuilder(\Magento\Customer\Api\Data\CustomerInterface::class)->getMock(); - $customer->expects($this->atLeastOnce()) - ->method('getId') - ->willReturn($customerId); - $customer->expects($this->atLeastOnce()) - ->method('getEmail') - ->willReturn($customerEmail); - $customer->expects($this->atLeastOnce()) - ->method('getWebsiteId') - ->willReturn($websiteId); - $customer->expects($this->atLeastOnce()) - ->method('getStoreId') - ->willReturn($storeId); - $customer->expects($this->once()) - ->method('setStoreId') - ->with($defaultStoreId); - $customer->expects($this->once()) - ->method('getAddresses') - ->willReturn([$address]); - $customer->expects($this->once()) - ->method('setAddresses') - ->with(null); - $this->customerRepository - ->expects($this->once()) - ->method('get') - ->with($customerEmail) - ->willReturn($customer); - $this->share->expects($this->once()) - ->method('isWebsiteScope') - ->willReturn(true); - $this->storeManager->expects($this->atLeastOnce()) - ->method('getWebsite') - ->with($websiteId) - ->willReturn($website); - $this->customerRepository->expects($this->atLeastOnce()) - ->method('save') - ->willReturn($customer); - $this->addressRepository->expects($this->atLeastOnce()) - ->method('save') - ->with($address); - $this->customerRepository->expects($this->once()) - ->method('getById') - ->with($customerId) - ->willReturn($customer); - $this->random->expects($this->once()) - ->method('getUniqueHash') - ->willReturn($newLinkToken); - $customerSecure = $this->getMockBuilder(\Magento\Customer\Model\Data\CustomerSecure::class) - ->setMethods(['setRpToken', 'setRpTokenCreatedAt', 'getPasswordHash']) - ->disableOriginalConstructor() - ->getMock(); - $customerSecure->expects($this->any()) - ->method('setRpToken') - ->with($newLinkToken); - $customerSecure->expects($this->any()) - ->method('setRpTokenCreatedAt') - ->with($datetime) - ->willReturnSelf(); - $customerSecure->expects($this->any()) - ->method('getPasswordHash') - ->willReturn(null); - $this->customerRegistry->expects($this->atLeastOnce()) - ->method('retrieveSecureData') - ->willReturn($customerSecure); - $this->emailNotificationMock->expects($this->once()) - ->method('newAccount') - ->willReturnSelf(); - - $this->accountManagement->createAccount($customer); - } - - /** - * Data provider for testCreateAccountWithPasswordInputException test - * - * @return array - */ - public function dataProviderCheckPasswordStrength() - { - return [ - [ - 'testNumber' => 1, - 'password' => 'qwer', - 'minPasswordLength' => 5, - 'minCharacterSetsNum' => 1, - ], - [ - 'testNumber' => 2, - 'password' => 'wrfewqedf1', - 'minPasswordLength' => 5, - 'minCharacterSetsNum' => 3, - ], - ]; - } - - /** - * @param int $testNumber - * @param string $password - * @param int $minPasswordLength - * @param int $minCharacterSetsNum - * @dataProvider dataProviderCheckPasswordStrength - */ - public function testCreateAccountWithPasswordInputException( - $testNumber, - $password, - $minPasswordLength, - $minCharacterSetsNum - ) { - $this->scopeConfig->expects($this->any()) - ->method('getValue') - ->will( - $this->returnValueMap( - [ - [ - AccountManagement::XML_PATH_MINIMUM_PASSWORD_LENGTH, - 'default', - null, - $minPasswordLength, - ], - [ - AccountManagement::XML_PATH_REQUIRED_CHARACTER_CLASSES_NUMBER, - 'default', - null, - $minCharacterSetsNum, - ], - ] - ) - ); - - $this->string->expects($this->any()) - ->method('strlen') - ->with($password) - ->willReturn(iconv_strlen($password, 'UTF-8')); - - if ($testNumber == 1) { - $this->expectException(\Magento\Framework\Exception\InputException::class); - $this->expectExceptionMessage('The password needs at least ' . $minPasswordLength . ' characters. ' - . 'Create a new password and try again.'); - } - - if ($testNumber == 2) { - $this->expectException(\Magento\Framework\Exception\InputException::class); - $this->expectExceptionMessage('Minimum of different classes of characters in password is ' . - $minCharacterSetsNum . '. Classes of characters: Lower Case, Upper Case, Digits, Special Characters.'); - } - - $customer = $this->getMockBuilder(\Magento\Customer\Api\Data\CustomerInterface::class)->getMock(); - $this->accountManagement->createAccount($customer, $password); - } - - /** - * @throws \Magento\Framework\Exception\LocalizedException - */ - public function testCreateAccountInputExceptionExtraLongPassword() - { - $password = '257*chars*************************************************************************************' - . '****************************************************************************************************' - . '***************************************************************'; - - $this->string->expects($this->any()) - ->method('strlen') - ->with($password) - ->willReturn(iconv_strlen($password, 'UTF-8')); - - $this->expectException(\Magento\Framework\Exception\InputException::class); - $this->expectExceptionMessage('Please enter a password with at most 256 characters.'); - - $customer = $this->getMockBuilder(\Magento\Customer\Api\Data\CustomerInterface::class)->getMock(); - $this->accountManagement->createAccount($customer, $password); - } - - /** - * @SuppressWarnings(PHPMD.ExcessiveMethodLength) - */ - public function testCreateAccountWithPassword() - { - $websiteId = 1; - $storeId = null; - $defaultStoreId = 1; - $customerId = 1; - $customerEmail = 'email@email.com'; - $hash = '4nj54lkj5jfi03j49f8bgujfgsd'; - $newLinkToken = '2jh43j5h2345jh23lh452h345hfuzasd96ofu'; - $templateIdentifier = 'Template Identifier'; - $sender = 'Sender'; - $password = 'wrfewqedf1'; - $minPasswordLength = 5; - $minCharacterSetsNum = 2; - - $datetime = $this->prepareDateTimeFactory(); - - $this->scopeConfig->expects($this->any()) - ->method('getValue') - ->willReturnMap( - [ - [ - AccountManagement::XML_PATH_MINIMUM_PASSWORD_LENGTH, - 'default', - null, - $minPasswordLength, - ], - [ - AccountManagement::XML_PATH_REQUIRED_CHARACTER_CLASSES_NUMBER, - 'default', - null, - $minCharacterSetsNum, - ], - [ - AccountManagement::XML_PATH_REGISTER_EMAIL_TEMPLATE, - ScopeInterface::SCOPE_STORE, - $defaultStoreId, - $templateIdentifier, - ], - [ - AccountManagement::XML_PATH_REGISTER_EMAIL_IDENTITY, - ScopeInterface::SCOPE_STORE, - 1, - $sender, - ], - ] - ); - $this->string->expects($this->any()) - ->method('strlen') - ->with($password) - ->willReturn(iconv_strlen($password, 'UTF-8')); - $this->encryptor->expects($this->once()) - ->method('getHash') - ->with($password, true) - ->willReturn($hash); - $address = $this->getMockBuilder(\Magento\Customer\Api\Data\AddressInterface::class) - ->disableOriginalConstructor() - ->getMock(); - $address->expects($this->once()) - ->method('setCustomerId') - ->with($customerId); - $store = $this->getMockBuilder(\Magento\Store\Model\Store::class)->disableOriginalConstructor()->getMock(); - $store->expects($this->once()) - ->method('getId') - ->willReturn($defaultStoreId); - $website = $this->getMockBuilder(\Magento\Store\Model\Website::class)->disableOriginalConstructor()->getMock(); - $website->expects($this->atLeastOnce()) - ->method('getStoreIds') - ->willReturn([1, 2, 3]); - $website->expects($this->once()) - ->method('getDefaultStore') - ->willReturn($store); - $customer = $this->getMockBuilder(\Magento\Customer\Api\Data\CustomerInterface::class)->getMock(); - $customer->expects($this->atLeastOnce()) - ->method('getId') - ->willReturn($customerId); - $customer->expects($this->atLeastOnce()) - ->method('getEmail') - ->willReturn($customerEmail); - $customer->expects($this->atLeastOnce()) - ->method('getWebsiteId') - ->willReturn($websiteId); - $customer->expects($this->atLeastOnce()) - ->method('getStoreId') - ->willReturn($storeId); - $customer->expects($this->once()) - ->method('setStoreId') - ->with($defaultStoreId); - $customer->expects($this->once()) - ->method('getAddresses') - ->willReturn([$address]); - $customer->expects($this->once()) - ->method('setAddresses') - ->with(null); - $this->customerRepository - ->expects($this->once()) - ->method('get') - ->with($customerEmail) - ->willReturn($customer); - $this->share->expects($this->once()) - ->method('isWebsiteScope') - ->willReturn(true); - $this->storeManager->expects($this->atLeastOnce()) - ->method('getWebsite') - ->with($websiteId) - ->willReturn($website); - $this->customerRepository->expects($this->atLeastOnce()) - ->method('save') - ->willReturn($customer); - $this->addressRepository->expects($this->atLeastOnce()) - ->method('save') - ->with($address); - $this->customerRepository->expects($this->once()) - ->method('getById') - ->with($customerId) - ->willReturn($customer); - $this->random->expects($this->once()) - ->method('getUniqueHash') - ->willReturn($newLinkToken); - $customerSecure = $this->getMockBuilder(\Magento\Customer\Model\Data\CustomerSecure::class) - ->setMethods(['setRpToken', 'setRpTokenCreatedAt', 'getPasswordHash']) - ->disableOriginalConstructor() - ->getMock(); - $customerSecure->expects($this->any()) - ->method('setRpToken') - ->with($newLinkToken); - $customerSecure->expects($this->any()) - ->method('setRpTokenCreatedAt') - ->with($datetime) - ->willReturnSelf(); - $customerSecure->expects($this->any()) - ->method('getPasswordHash') - ->willReturn($hash); - $this->customerRegistry->expects($this->atLeastOnce()) - ->method('retrieveSecureData') - ->willReturn($customerSecure); - $this->emailNotificationMock->expects($this->once()) - ->method('newAccount') - ->willReturnSelf(); - - $this->accountManagement->createAccount($customer, $password); - } - - /** - * @SuppressWarnings(PHPMD.ExcessiveMethodLength) - */ - public function testSendPasswordReminderEmail() - { - $customerId = 1; - $customerStoreId = 2; - $customerEmail = 'email@email.com'; - $customerData = ['key' => 'value']; - $customerName = 'Customer Name'; - $templateIdentifier = 'Template Identifier'; - $sender = 'Sender'; - - $customer = $this->getMockBuilder(\Magento\Customer\Api\Data\CustomerInterface::class) - ->getMock(); - $customer->expects($this->any()) - ->method('getStoreId') - ->willReturn($customerStoreId); - $customer->expects($this->any()) - ->method('getId') - ->willReturn($customerId); - $customer->expects($this->any()) - ->method('getEmail') - ->willReturn($customerEmail); - - $this->store->expects($this->any()) - ->method('getId') - ->willReturn($customerStoreId); - - $this->storeManager->expects($this->at(0)) - ->method('getStore') - ->willReturn($this->store); - - $this->storeManager->expects($this->at(1)) - ->method('getStore') - ->with($customerStoreId) - ->willReturn($this->store); - - $this->customerRegistry->expects($this->once()) - ->method('retrieveSecureData') - ->with($customerId) - ->willReturn($this->customerSecure); - - $this->dataObjectProcessor->expects($this->once()) - ->method('buildOutputDataArray') - ->with($customer, \Magento\Customer\Api\Data\CustomerInterface::class) - ->willReturn($customerData); - - $this->customerViewHelper->expects($this->any()) - ->method('getCustomerName') - ->with($customer) - ->willReturn($customerName); - - $this->customerSecure->expects($this->once()) - ->method('addData') - ->with($customerData) - ->willReturnSelf(); - $this->customerSecure->expects($this->once()) - ->method('setData') - ->with('name', $customerName) - ->willReturnSelf(); - - $this->scopeConfig->expects($this->at(0)) - ->method('getValue') - ->with(AccountManagement::XML_PATH_REMIND_EMAIL_TEMPLATE, ScopeInterface::SCOPE_STORE, $customerStoreId) - ->willReturn($templateIdentifier); - $this->scopeConfig->expects($this->at(1)) - ->method('getValue') - ->with(AccountManagement::XML_PATH_FORGOT_EMAIL_IDENTITY, ScopeInterface::SCOPE_STORE, $customerStoreId) - ->willReturn($sender); - - $transport = $this->getMockBuilder(\Magento\Framework\Mail\TransportInterface::class) - ->getMock(); - - $this->transportBuilder->expects($this->once()) - ->method('setTemplateIdentifier') - ->with($templateIdentifier) - ->willReturnSelf(); - $this->transportBuilder->expects($this->once()) - ->method('setTemplateOptions') - ->with(['area' => Area::AREA_FRONTEND, 'store' => $customerStoreId]) - ->willReturnSelf(); - $this->transportBuilder->expects($this->once()) - ->method('setTemplateVars') - ->with(['customer' => $this->customerSecure, 'store' => $this->store]) - ->willReturnSelf(); - $this->transportBuilder->expects($this->once()) - ->method('setFrom') - ->with($sender) - ->willReturnSelf(); - $this->transportBuilder->expects($this->once()) - ->method('addTo') - ->with($customerEmail, $customerName) - ->willReturnSelf(); - $this->transportBuilder->expects($this->once()) - ->method('getTransport') - ->willReturn($transport); - - $transport->expects($this->once()) - ->method('sendMessage'); - - $this->assertEquals($this->accountManagement, $this->accountManagement->sendPasswordReminderEmail($customer)); - } - - /** - * @param string $email - * @param string $templateIdentifier - * @param string $sender - * @param int $storeId - * @param int $customerId - * @param string $hash - */ - protected function prepareInitiatePasswordReset($email, $templateIdentifier, $sender, $storeId, $customerId, $hash) - { - $websiteId = 1; - - $datetime = $this->prepareDateTimeFactory(); - - $customerData = ['key' => 'value']; - $customerName = 'Customer Name'; - - $this->store->expects($this->once()) - ->method('getWebsiteId') - ->willReturn($websiteId); - $this->store->expects($this->any()) - ->method('getId') - ->willReturn($storeId); - - $this->storeManager->expects($this->any()) - ->method('getStore') - ->willReturn($this->store); - - $customer = $this->getMockBuilder(\Magento\Customer\Api\Data\CustomerInterface::class) - ->getMock(); - $customer->expects($this->any()) - ->method('getEmail') - ->willReturn($email); - $customer->expects($this->any()) - ->method('getId') - ->willReturn($customerId); - $customer->expects($this->any()) - ->method('getStoreId') - ->willReturn($storeId); - - $this->customerRepository->expects($this->once()) - ->method('get') - ->with($email, $websiteId) - ->willReturn($customer); - $this->customerRepository->expects($this->once()) - ->method('save') - ->with($customer) - ->willReturnSelf(); - - $this->random->expects($this->once()) - ->method('getUniqueHash') - ->willReturn($hash); - - $this->customerViewHelper->expects($this->any()) - ->method('getCustomerName') - ->with($customer) - ->willReturn($customerName); - - $this->customerSecure->expects($this->any()) - ->method('setRpToken') - ->with($hash) - ->willReturnSelf(); - $this->customerSecure->expects($this->any()) - ->method('setRpTokenCreatedAt') - ->with($datetime) - ->willReturnSelf(); - $this->customerSecure->expects($this->any()) - ->method('addData') - ->with($customerData) - ->willReturnSelf(); - $this->customerSecure->expects($this->any()) - ->method('setData') - ->with('name', $customerName) - ->willReturnSelf(); - - $this->customerRegistry->expects($this->any()) - ->method('retrieveSecureData') - ->with($customerId) - ->willReturn($this->customerSecure); - - $this->dataObjectProcessor->expects($this->any()) - ->method('buildOutputDataArray') - ->with($customer, \Magento\Customer\Api\Data\CustomerInterface::class) - ->willReturn($customerData); - - $this->prepareEmailSend($email, $templateIdentifier, $sender, $storeId, $customerName); - } - - /** - * @param string $email - * @param int $templateIdentifier - * @param string $sender - * @param int $storeId - * @param string $customerName - */ - protected function prepareEmailSend($email, $templateIdentifier, $sender, $storeId, $customerName) - { - $transport = $this->getMockBuilder(\Magento\Framework\Mail\TransportInterface::class) - ->getMock(); - - $this->transportBuilder->expects($this->any()) - ->method('setTemplateIdentifier') - ->with($templateIdentifier) - ->willReturnSelf(); - $this->transportBuilder->expects($this->any()) - ->method('setTemplateOptions') - ->with(['area' => Area::AREA_FRONTEND, 'store' => $storeId]) - ->willReturnSelf(); - $this->transportBuilder->expects($this->any()) - ->method('setTemplateVars') - ->with(['customer' => $this->customerSecure, 'store' => $this->store]) - ->willReturnSelf(); - $this->transportBuilder->expects($this->any()) - ->method('setFrom') - ->with($sender) - ->willReturnSelf(); - $this->transportBuilder->expects($this->any()) - ->method('addTo') - ->with($email, $customerName) - ->willReturnSelf(); - $this->transportBuilder->expects($this->any()) - ->method('getTransport') - ->willReturn($transport); - - $transport->expects($this->any()) - ->method('sendMessage'); - } - - /** - * @throws \Magento\Framework\Exception\LocalizedException - */ - public function testInitiatePasswordResetEmailReminder() - { - $customerId = 1; - - $email = 'test@example.com'; - $template = AccountManagement::EMAIL_REMINDER; - $templateIdentifier = 'Template Identifier'; - $sender = 'Sender'; - - $storeId = 1; - - mt_srand(mt_rand() + (100000000 * (float)microtime()) % PHP_INT_MAX); - $hash = md5(uniqid(microtime() . mt_rand(0, mt_getrandmax()), true)); - - $this->emailNotificationMock->expects($this->once()) - ->method('passwordReminder') - ->willReturnSelf(); - - $this->prepareInitiatePasswordReset($email, $templateIdentifier, $sender, $storeId, $customerId, $hash); - - $this->assertTrue($this->accountManagement->initiatePasswordReset($email, $template)); - } - - /** - * @throws \Magento\Framework\Exception\LocalizedException - */ - public function testInitiatePasswordResetEmailReset() - { - $storeId = 1; - $customerId = 1; - - $email = 'test@example.com'; - $template = AccountManagement::EMAIL_RESET; - $templateIdentifier = 'Template Identifier'; - $sender = 'Sender'; - - mt_srand(mt_rand() + (100000000 * (float)microtime()) % PHP_INT_MAX); - $hash = md5(uniqid(microtime() . mt_rand(0, mt_getrandmax()), true)); - - $this->emailNotificationMock->expects($this->once()) - ->method('passwordResetConfirmation') - ->willReturnSelf(); - - $this->prepareInitiatePasswordReset($email, $templateIdentifier, $sender, $storeId, $customerId, $hash); - - $this->assertTrue($this->accountManagement->initiatePasswordReset($email, $template)); - } - - /** - * @throws \Magento\Framework\Exception\LocalizedException - */ - public function testInitiatePasswordResetNoTemplate() - { - $storeId = 1; - $customerId = 1; - - $email = 'test@example.com'; - $template = null; - $templateIdentifier = 'Template Identifier'; - $sender = 'Sender'; - - mt_srand(mt_rand() + (100000000 * (float)microtime()) % PHP_INT_MAX); - $hash = md5(uniqid(microtime() . mt_rand(0, mt_getrandmax()), true)); - - $this->prepareInitiatePasswordReset($email, $templateIdentifier, $sender, $storeId, $customerId, $hash); - - $this->expectException(\Magento\Framework\Exception\InputException::class); - $this->expectExceptionMessage( - 'Invalid value of "" provided for the template field. Possible values: email_reminder or email_reset.' - ); - $this->accountManagement->initiatePasswordReset($email, $template); - } - - /** - * @expectedException \Magento\Framework\Exception\InputException - * @expectedExceptionMessage Invalid value of "" provided for the customerId field - */ - public function testValidateResetPasswordTokenBadCustomerId() - { - $this->accountManagement->validateResetPasswordLinkToken(null, ''); - } - - /** - * @expectedException \Magento\Framework\Exception\InputException - * @expectedExceptionMessage "resetPasswordLinkToken" is required. Enter and try again. - */ - public function testValidateResetPasswordTokenBadResetPasswordLinkToken() - { - $this->accountManagement->validateResetPasswordLinkToken(22, null); - } - - /** - * @expectedException \Magento\Framework\Exception\State\InputMismatchException - * @expectedExceptionMessage The password token is mismatched. Reset and try again. - */ - public function testValidateResetPasswordTokenTokenMismatch() - { - $this->customerRegistry->expects($this->atLeastOnce()) - ->method('retrieveSecureData') - ->willReturn($this->customerSecure); - - $this->accountManagement->validateResetPasswordLinkToken(22, 'newStringToken'); - } - - /** - * @expectedException \Magento\Framework\Exception\State\ExpiredException - * @expectedExceptionMessage The password token is expired. Reset and try again. - */ - public function testValidateResetPasswordTokenTokenExpired() - { - $this->reInitModel(); - $this->customerRegistry->expects($this->atLeastOnce()) - ->method('retrieveSecureData') - ->willReturn($this->customerSecure); - - $this->accountManagement->validateResetPasswordLinkToken(22, 'newStringToken'); - } - - /** - * return bool - */ - public function testValidateResetPasswordToken() - { - $this->reInitModel(); - - $this->customer - ->expects($this->once()) - ->method('getResetPasswordLinkExpirationPeriod') - ->willReturn(100000); - - $this->customerRegistry->expects($this->atLeastOnce()) - ->method('retrieveSecureData') - ->willReturn($this->customerSecure); - - $this->assertTrue($this->accountManagement->validateResetPasswordLinkToken(22, 'newStringToken')); - } - - /** - * reInit $this->accountManagement object - */ - private function reInitModel() - { - $this->customerSecure = $this->getMockBuilder(\Magento\Customer\Model\Data\CustomerSecure::class) - ->disableOriginalConstructor() - ->setMethods( - [ - 'getRpToken', - 'getRpTokenCreatedAt', - 'getPasswordHash', - 'setPasswordHash', - 'setRpToken', - 'setRpTokenCreatedAt', - ] - ) - ->getMock(); - $this->customerSecure->expects($this->any()) - ->method('getRpToken') - ->willReturn('newStringToken'); - $pastDateTime = '2016-10-25 00:00:00'; - $this->customerSecure->expects($this->any()) - ->method('getRpTokenCreatedAt') - ->willReturn($pastDateTime); - $this->customer = $this->getMockBuilder(\Magento\Customer\Model\Customer::class) - ->disableOriginalConstructor() - ->setMethods(['getResetPasswordLinkExpirationPeriod']) - ->getMock(); - - $this->prepareDateTimeFactory(); - $this->sessionManager = $this->getMockBuilder(\Magento\Framework\Session\SessionManagerInterface::class) - ->disableOriginalConstructor() - ->getMockForAbstractClass(); - $this->visitorCollectionFactory = $this->getMockBuilder( - \Magento\Customer\Model\ResourceModel\Visitor\CollectionFactory::class - ) - ->disableOriginalConstructor() - ->setMethods(['create']) - ->getMock(); - $this->saveHandler = $this->getMockBuilder(\Magento\Framework\Session\SaveHandlerInterface::class) - ->disableOriginalConstructor() - ->setMethods(['destroy']) - ->getMockForAbstractClass(); - - $dateTime = '2017-10-25 18:57:08'; - $timestamp = '1508983028'; - $dateTimeMock = $this->getMockBuilder(\DateTime::class) - ->disableOriginalConstructor() - ->setMethods(['format', 'getTimestamp', 'setTimestamp']) - ->getMock(); - - $dateTimeMock->expects($this->any()) - ->method('format') - ->with(\Magento\Framework\Stdlib\DateTime::DATETIME_PHP_FORMAT) - ->willReturn($dateTime); - $dateTimeMock->expects($this->any()) - ->method('getTimestamp') - ->willReturn($timestamp); - $dateTimeMock->expects($this->any()) - ->method('setTimestamp') - ->willReturnSelf(); - $dateTimeFactory = $this->getMockBuilder(DateTimeFactory::class) - ->disableOriginalConstructor() - ->setMethods(['create']) - ->getMock(); - $dateTimeFactory->expects($this->any())->method('create')->willReturn($dateTimeMock); - - $this->objectManagerHelper = new ObjectManagerHelper($this); - $this->accountManagement = $this->objectManagerHelper->getObject( - \Magento\Customer\Model\AccountManagement::class, - [ - 'customerFactory' => $this->customerFactory, - 'customerRegistry' => $this->customerRegistry, - 'customerRepository' => $this->customerRepository, - 'customerModel' => $this->customer, - 'dateTimeFactory' => $dateTimeFactory, - 'stringHelper' => $this->string, - 'scopeConfig' => $this->scopeConfig, - 'sessionManager' => $this->sessionManager, - 'visitorCollectionFactory' => $this->visitorCollectionFactory, - 'saveHandler' => $this->saveHandler, - 'encryptor' => $this->encryptor, - 'dataProcessor' => $this->dataObjectProcessor, - 'storeManager' => $this->storeManager, - 'transportBuilder' => $this->transportBuilder, - ] - ); - $this->objectManagerHelper->setBackwardCompatibleProperty( - $this->accountManagement, - 'authentication', - $this->authenticationMock - ); - } - - /** - * @return void - */ - public function testChangePassword() - { - $customerId = 7; - $email = 'test@example.com'; - $currentPassword = '1234567'; - $newPassword = 'abcdefg'; - $passwordHash = '1a2b3f4c'; - - $this->reInitModel(); - $customer = $this->getMockBuilder(\Magento\Customer\Api\Data\CustomerInterface::class) - ->getMock(); - $customer->expects($this->any()) - ->method('getId') - ->willReturn($customerId); - - $this->customerRepository - ->expects($this->once()) - ->method('get') - ->with($email) - ->willReturn($customer); - - $this->authenticationMock->expects($this->once()) - ->method('authenticate'); - - $this->customerSecure->expects($this->once()) - ->method('setRpToken') - ->with(null); - $this->customerSecure->expects($this->once()) - ->method('setRpTokenCreatedAt') - ->willReturnSelf(); - $this->customerSecure->expects($this->any()) - ->method('getPasswordHash') - ->willReturn($passwordHash); - - $this->customerRegistry->expects($this->any()) - ->method('retrieveSecureData') - ->with($customerId) - ->willReturn($this->customerSecure); - - $this->scopeConfig->expects($this->any()) - ->method('getValue') - ->willReturnMap( - [ - [ - AccountManagement::XML_PATH_MINIMUM_PASSWORD_LENGTH, - 'default', - null, - 7, - ], - [ - AccountManagement::XML_PATH_REQUIRED_CHARACTER_CLASSES_NUMBER, - 'default', - null, - 1, - ], - ] - ); - $this->string->expects($this->any()) - ->method('strlen') - ->with($newPassword) - ->willReturn(7); - - $this->customerRepository - ->expects($this->once()) - ->method('save') - ->with($customer); - - $this->sessionManager->expects($this->atLeastOnce())->method('getSessionId'); - - $visitor = $this->getMockBuilder(\Magento\Customer\Model\Visitor::class) - ->disableOriginalConstructor() - ->setMethods(['getSessionId']) - ->getMock(); - $visitor->expects($this->atLeastOnce())->method('getSessionId') - ->willReturnOnConsecutiveCalls('session_id_1', 'session_id_2'); - $visitorCollection = $this->getMockBuilder( - \Magento\Customer\Model\ResourceModel\Visitor\CollectionFactory::class - ) - ->disableOriginalConstructor()->setMethods(['addFieldToFilter', 'getItems'])->getMock(); - $visitorCollection->expects($this->atLeastOnce())->method('addFieldToFilter')->willReturnSelf(); - $visitorCollection->expects($this->atLeastOnce())->method('getItems')->willReturn([$visitor, $visitor]); - $this->visitorCollectionFactory->expects($this->atLeastOnce())->method('create') - ->willReturn($visitorCollection); - $this->saveHandler->expects($this->atLeastOnce())->method('destroy') - ->withConsecutive( - ['session_id_1'], - ['session_id_2'] - ); - - $this->assertTrue($this->accountManagement->changePassword($email, $currentPassword, $newPassword)); - } - - /** - * @throws \Magento\Framework\Exception\LocalizedException - */ - public function testResetPassword() - { - $customerEmail = 'customer@example.com'; - $customerId = '1'; - $resetToken = 'newStringToken'; - $newPassword = 'new_password'; - - $this->reInitModel(); - $customer = $this->getMockBuilder(\Magento\Customer\Api\Data\CustomerInterface::class)->getMock(); - $customer->expects($this->any())->method('getId')->willReturn($customerId); - $this->customerRepository->expects($this->atLeastOnce())->method('get')->with($customerEmail) - ->willReturn($customer); - $this->customer->expects($this->atLeastOnce())->method('getResetPasswordLinkExpirationPeriod') - ->willReturn(100000); - $this->string->expects($this->any())->method('strlen')->willReturnCallback( - function ($string) { - return strlen($string); - } - ); - $this->customerRegistry->expects($this->atLeastOnce())->method('retrieveSecureData') - ->willReturn($this->customerSecure); - - $this->customerSecure->expects($this->once())->method('setRpToken')->with(null); - $this->customerSecure->expects($this->once())->method('setRpTokenCreatedAt')->with(null); - $this->customerSecure->expects($this->any())->method('setPasswordHash')->willReturn(null); - - $this->sessionManager->expects($this->atLeastOnce())->method('destroy'); - $this->sessionManager->expects($this->atLeastOnce())->method('getSessionId'); - $visitor = $this->getMockBuilder(\Magento\Customer\Model\Visitor::class) - ->disableOriginalConstructor() - ->setMethods(['getSessionId']) - ->getMock(); - $visitor->expects($this->atLeastOnce())->method('getSessionId') - ->willReturnOnConsecutiveCalls('session_id_1', 'session_id_2'); - $visitorCollection = $this->getMockBuilder( - \Magento\Customer\Model\ResourceModel\Visitor\CollectionFactory::class - ) - ->disableOriginalConstructor()->setMethods(['addFieldToFilter', 'getItems'])->getMock(); - $visitorCollection->expects($this->atLeastOnce())->method('addFieldToFilter')->willReturnSelf(); - $visitorCollection->expects($this->atLeastOnce())->method('getItems')->willReturn([$visitor, $visitor]); - $this->visitorCollectionFactory->expects($this->atLeastOnce())->method('create') - ->willReturn($visitorCollection); - $this->saveHandler->expects($this->atLeastOnce())->method('destroy') - ->withConsecutive( - ['session_id_1'], - ['session_id_2'] - ); - $this->assertTrue($this->accountManagement->resetPassword($customerEmail, $resetToken, $newPassword)); - } - - /** - * @return void - */ - public function testChangePasswordException() - { - $email = 'test@example.com'; - $currentPassword = '1234567'; - $newPassword = 'abcdefg'; - - $exception = new NoSuchEntityException( - new \Magento\Framework\Phrase('Exception message') - ); - $this->customerRepository - ->expects($this->once()) - ->method('get') - ->with($email) - ->willThrowException($exception); - - $this->expectException(\Magento\Framework\Exception\InvalidEmailOrPasswordException::class); - $this->expectExceptionMessage('Invalid login or password.'); - - $this->accountManagement->changePassword($email, $currentPassword, $newPassword); - } - - /** - * @return void - */ - public function testAuthenticate() - { - $username = 'login'; - $password = '1234567'; - $passwordHash = '1a2b3f4c'; - - $customerData = $this->getMockBuilder(\Magento\Customer\Api\Data\CustomerInterface::class) - ->getMock(); - - $customerModel = $this->getMockBuilder(\Magento\Customer\Model\Customer::class) - ->disableOriginalConstructor() - ->getMock(); - $customerModel->expects($this->once()) - ->method('updateData') - ->willReturn($customerModel); - - $this->customerRepository - ->expects($this->once()) - ->method('get') - ->with($username) - ->willReturn($customerData); - - $this->authenticationMock->expects($this->once()) - ->method('authenticate'); - - $customerSecure = $this->getMockBuilder(\Magento\Customer\Model\Data\CustomerSecure::class) - ->setMethods(['getPasswordHash']) - ->disableOriginalConstructor() - ->getMock(); - $customerSecure->expects($this->any()) - ->method('getPasswordHash') - ->willReturn($passwordHash); - - $this->customerRegistry->expects($this->any()) - ->method('retrieveSecureData') - ->willReturn($customerSecure); - - $this->customerFactory->expects($this->once()) - ->method('create') - ->willReturn($customerModel); - - $this->manager->expects($this->exactly(2)) - ->method('dispatch') - ->withConsecutive( - [ - 'customer_customer_authenticated', - ['model' => $customerModel, 'password' => $password], - ], - [ - 'customer_data_object_login', ['customer' => $customerData], - ] - ); - - $this->assertEquals($customerData, $this->accountManagement->authenticate($username, $password)); - } - - /** - * @param int $isConfirmationRequired - * @param string|null $confirmation - * @param string $expected - * @dataProvider dataProviderGetConfirmationStatus - */ - public function testGetConfirmationStatus( - $isConfirmationRequired, - $confirmation, - $expected - ) { - $websiteId = 1; - $customerId = 1; - $customerEmail = 'test1@example.com'; - - $customerMock = $this->getMockBuilder(\Magento\Customer\Api\Data\CustomerInterface::class) - ->disableOriginalConstructor() - ->getMock(); - $customerMock->expects($this->once()) - ->method('getId') - ->willReturn($customerId); - $customerMock->expects($this->any()) - ->method('getConfirmation') - ->willReturn($confirmation); - $customerMock->expects($this->once()) - ->method('getEmail') - ->willReturn($customerEmail); - $customerMock->expects($this->once()) - ->method('getWebsiteId') - ->willReturn($websiteId); - - $this->accountConfirmation->expects($this->once()) - ->method('isConfirmationRequired') - ->with($websiteId, $customerId, $customerEmail) - ->willReturn($isConfirmationRequired); - - $this->customerRepository->expects($this->once()) - ->method('getById') - ->with($customerId) - ->willReturn($customerMock); - - $this->assertEquals($expected, $this->accountManagement->getConfirmationStatus($customerId)); - } - - /** - * @return array - */ - public function dataProviderGetConfirmationStatus() - { - return [ - [0, null, AccountManagement::ACCOUNT_CONFIRMATION_NOT_REQUIRED], - [0, null, AccountManagement::ACCOUNT_CONFIRMATION_NOT_REQUIRED], - [0, null, AccountManagement::ACCOUNT_CONFIRMATION_NOT_REQUIRED], - [1, null, AccountManagement::ACCOUNT_CONFIRMED], - [1, 'test', AccountManagement::ACCOUNT_CONFIRMATION_REQUIRED], - ]; - } - - /** - * @expectedException \Magento\Framework\Exception\LocalizedException - */ - public function testCreateAccountWithPasswordHashForGuest() - { - $storeId = 1; - $storeName = 'store_name'; - $websiteId = 1; - $hash = '4nj54lkj5jfi03j49f8bgujfgsd'; - - $storeMock = $this->getMockBuilder(\Magento\Store\Model\Store::class) - ->disableOriginalConstructor() - ->getMock(); - $storeMock->expects($this->once()) - ->method('getId') - ->willReturn($storeId); - $storeMock->expects($this->once()) - ->method('getWebsiteId') - ->willReturn($websiteId); - $storeMock->expects($this->once()) - ->method('getName') - ->willReturn($storeName); - - $this->storeManager->expects($this->exactly(3)) - ->method('getStore') - ->willReturn($storeMock); - - $customerMock = $this->getMockBuilder(\Magento\Customer\Api\Data\CustomerInterface::class) - ->getMockForAbstractClass(); - $customerMock->expects($this->exactly(2)) - ->method('getId') - ->willReturn(null); - $customerMock->expects($this->exactly(3)) - ->method('getStoreId') - ->willReturn(null); - $customerMock->expects($this->exactly(3)) - ->method('getWebsiteId') - ->willReturn(null); - $customerMock->expects($this->once()) - ->method('setStoreId') - ->with($storeId) - ->willReturnSelf(); - $customerMock->expects($this->once()) - ->method('setWebsiteId') - ->with($websiteId) - ->willReturnSelf(); - $customerMock->expects($this->once()) - ->method('setCreatedIn') - ->with($storeName) - ->willReturnSelf(); - $customerMock->expects($this->once()) - ->method('getAddresses') - ->willReturn(null); - $customerMock->expects($this->once()) - ->method('setAddresses') - ->with(null) - ->willReturnSelf(); - - $this->customerRepository - ->expects($this->once()) - ->method('save') - ->with($customerMock, $hash) - ->willThrowException(new \Magento\Framework\Exception\LocalizedException(__('Exception message'))); - - $this->accountManagement->createAccountWithPasswordHash($customerMock, $hash); - } - - /** - * @SuppressWarnings(PHPMD.ExcessiveMethodLength) - */ - public function testCreateAccountWithPasswordHashWithCustomerAddresses() - { - $websiteId = 1; - $addressId = 2; - $customerId = null; - $storeId = 1; - $hash = '4nj54lkj5jfi03j49f8bgujfgsd'; - - $this->prepareDateTimeFactory(); - - //Handle store - $store = $this->getMockBuilder(\Magento\Store\Model\Store::class)->disableOriginalConstructor()->getMock(); - $store->expects($this->any()) - ->method('getWebsiteId') - ->willReturn($websiteId); - //Handle address - existing and non-existing. Non-Existing should return null when call getId method - $existingAddress = $this->getMockBuilder(\Magento\Customer\Api\Data\AddressInterface::class) - ->disableOriginalConstructor() - ->getMock(); - $nonExistingAddress = $this->getMockBuilder(\Magento\Customer\Api\Data\AddressInterface::class) - ->disableOriginalConstructor() - ->getMock(); - //Ensure that existing address is not in use - $this->addressRepository - ->expects($this->atLeastOnce()) - ->method("save") - ->withConsecutive( - [$this->logicalNot($this->identicalTo($existingAddress))], - [$this->identicalTo($nonExistingAddress)] - ); - - $existingAddress - ->expects($this->any()) - ->method("getId") - ->willReturn($addressId); - //Expects that id for existing address should be unset - $existingAddress - ->expects($this->once()) - ->method("setId") - ->with(null); - //Handle Customer calls - $customer = $this->getMockBuilder(\Magento\Customer\Api\Data\CustomerInterface::class)->getMock(); - $customer - ->expects($this->atLeastOnce()) - ->method('getWebsiteId') - ->willReturn($websiteId); - $customer - ->expects($this->atLeastOnce()) - ->method('getStoreId') - ->willReturn($storeId); - $customer - ->expects($this->any()) - ->method("getId") - ->willReturn($customerId); - //Return Customer from customer repository - $this->customerRepository - ->expects($this->atLeastOnce()) - ->method('save') - ->willReturn($customer); - $this->customerRepository - ->expects($this->once()) - ->method('getById') - ->with($customerId) - ->willReturn($customer); - $customerSecure = $this->getMockBuilder(\Magento\Customer\Model\Data\CustomerSecure::class) - ->setMethods(['setRpToken', 'setRpTokenCreatedAt', 'getPasswordHash']) - ->disableOriginalConstructor() - ->getMock(); - $customerSecure->expects($this->once()) - ->method('setRpToken') - ->with($hash); - - $customerSecure->expects($this->any()) - ->method('getPasswordHash') - ->willReturn($hash); - - $this->customerRegistry->expects($this->any()) - ->method('retrieveSecureData') - ->with($customerId) - ->willReturn($customerSecure); - - $this->random->expects($this->once()) - ->method('getUniqueHash') - ->willReturn($hash); - - $customer - ->expects($this->atLeastOnce()) - ->method('getAddresses') - ->willReturn([$existingAddress, $nonExistingAddress]); - - $this->storeManager - ->expects($this->atLeastOnce()) - ->method('getStore') - ->willReturn($store); - $this->share - ->expects($this->once()) - ->method('isWebsiteScope') - ->willReturn(true); - $website = $this->getMockBuilder(\Magento\Store\Model\Website::class)->disableOriginalConstructor()->getMock(); - $website->expects($this->once()) - ->method('getStoreIds') - ->willReturn([1, 2, 3]); - $this->storeManager - ->expects($this->atLeastOnce()) - ->method('getWebsite') - ->with($websiteId) - ->willReturn($website); - - $this->assertSame($customer, $this->accountManagement->createAccountWithPasswordHash($customer, $hash)); - } - - /** - * @return string - */ - private function prepareDateTimeFactory() - { - $dateTime = '2017-10-25 18:57:08'; - $timestamp = '1508983028'; - $dateTimeMock = $this->createMock(\DateTime::class); - $dateTimeMock->expects($this->any()) - ->method('format') - ->with(\Magento\Framework\Stdlib\DateTime::DATETIME_PHP_FORMAT) - ->willReturn($dateTime); - - $dateTimeMock - ->expects($this->any()) - ->method('getTimestamp') - ->willReturn($timestamp); - - $this->dateTimeFactory - ->expects($this->any()) - ->method('create') - ->willReturn($dateTimeMock); - - return $dateTime; - } - - /** - * @return void - */ - public function testCreateAccountUnexpectedValueException(): void - { - $websiteId = 1; - $storeId = null; - $defaultStoreId = 1; - $customerId = 1; - $customerEmail = 'email@email.com'; - $newLinkToken = '2jh43j5h2345jh23lh452h345hfuzasd96ofu'; - $exception = new \UnexpectedValueException('Template file was not found'); - - $datetime = $this->prepareDateTimeFactory(); - - $address = $this->createMock(\Magento\Customer\Api\Data\AddressInterface::class); - $address->expects($this->once()) - ->method('setCustomerId') - ->with($customerId); - $store = $this->createMock(\Magento\Store\Model\Store::class); - $store->expects($this->once()) - ->method('getId') - ->willReturn($defaultStoreId); - $website = $this->createMock(\Magento\Store\Model\Website::class); - $website->expects($this->atLeastOnce()) - ->method('getStoreIds') - ->willReturn([1, 2, 3]); - $website->expects($this->once()) - ->method('getDefaultStore') - ->willReturn($store); - $customer = $this->createMock(\Magento\Customer\Api\Data\CustomerInterface::class); - $customer->expects($this->atLeastOnce()) - ->method('getId') - ->willReturn($customerId); - $customer->expects($this->atLeastOnce()) - ->method('getEmail') - ->willReturn($customerEmail); - $customer->expects($this->atLeastOnce()) - ->method('getWebsiteId') - ->willReturn($websiteId); - $customer->expects($this->atLeastOnce()) - ->method('getStoreId') - ->willReturn($storeId); - $customer->expects($this->once()) - ->method('setStoreId') - ->with($defaultStoreId); - $customer->expects($this->once()) - ->method('getAddresses') - ->willReturn([$address]); - $customer->expects($this->once()) - ->method('setAddresses') - ->with(null); - $this->customerRepository->expects($this->once()) - ->method('get') - ->with($customerEmail) - ->willReturn($customer); - $this->share->expects($this->once()) - ->method('isWebsiteScope') - ->willReturn(true); - $this->storeManager->expects($this->atLeastOnce()) - ->method('getWebsite') - ->with($websiteId) - ->willReturn($website); - $this->customerRepository->expects($this->atLeastOnce()) - ->method('save') - ->willReturn($customer); - $this->addressRepository->expects($this->atLeastOnce()) - ->method('save') - ->with($address); - $this->customerRepository->expects($this->once()) - ->method('getById') - ->with($customerId) - ->willReturn($customer); - $this->random->expects($this->once()) - ->method('getUniqueHash') - ->willReturn($newLinkToken); - $customerSecure = $this->createPartialMock( - \Magento\Customer\Model\Data\CustomerSecure::class, - ['setRpToken', 'setRpTokenCreatedAt', 'getPasswordHash'] - ); - $customerSecure->expects($this->any()) - ->method('setRpToken') - ->with($newLinkToken); - $customerSecure->expects($this->any()) - ->method('setRpTokenCreatedAt') - ->with($datetime) - ->willReturnSelf(); - $customerSecure->expects($this->any()) - ->method('getPasswordHash') - ->willReturn(null); - $this->customerRegistry->expects($this->atLeastOnce()) - ->method('retrieveSecureData') - ->willReturn($customerSecure); - $this->emailNotificationMock->expects($this->once()) - ->method('newAccount') - ->willThrowException($exception); - $this->logger->expects($this->once())->method('error')->with($exception); - - $this->accountManagement->createAccount($customer); - } - - /** - * @expectedException \Magento\Framework\Exception\LocalizedException - */ - public function testCreateAccountWithStoreNotInWebsite() - { - $storeId = 1; - $websiteId = 1; - $hash = '4nj54lkj5jfi03j49f8bgujfgsd'; - $customerMock = $this->getMockBuilder(\Magento\Customer\Api\Data\CustomerInterface::class) - ->getMockForAbstractClass(); - $customerMock->expects($this->atLeastOnce()) - ->method('getId') - ->willReturn(null); - $customerMock->expects($this->atLeastOnce()) - ->method('getStoreId') - ->willReturn($storeId); - $customerMock->expects($this->atLeastOnce()) - ->method('getWebsiteId') - ->willReturn($websiteId); - $this->share - ->expects($this->once()) - ->method('isWebsiteScope') - ->willReturn(true); - $website = $this->getMockBuilder(\Magento\Store\Model\Website::class)->disableOriginalConstructor()->getMock(); - $website->expects($this->once()) - ->method('getStoreIds') - ->willReturn([2, 3]); - $this->storeManager - ->expects($this->atLeastOnce()) - ->method('getWebsite') - ->with($websiteId) - ->willReturn($website); - $this->accountManagement->createAccountWithPasswordHash($customerMock, $hash); - } -} From e41cd3a5aef2c0620f05b758dc6852ceb46785d8 Mon Sep 17 00:00:00 2001 From: roman <rleshchenko@magento.com> Date: Fri, 21 Sep 2018 16:09:39 +0300 Subject: [PATCH 36/44] MAGETWO-70943: Incorrect reset password flow --- app/code/Magento/Customer/Model/AccountManagement.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Customer/Model/AccountManagement.php b/app/code/Magento/Customer/Model/AccountManagement.php index 52264c78b77..6aee2894f49 100644 --- a/app/code/Magento/Customer/Model/AccountManagement.php +++ b/app/code/Magento/Customer/Model/AccountManagement.php @@ -661,7 +661,7 @@ private function handleUnknownTemplate($template) /** * @inheritdoc */ - public function resetPassword(?string $email, string $resetToken, string $newPassword): bool + public function resetPassword($email, $resetToken, $newPassword): bool { if (!$email) { $customer = $this->matchCustomerByRpToken($resetToken); From 073ca97b102143b1ea13bb4a910eb1d426ee78bb Mon Sep 17 00:00:00 2001 From: Roman Ganin <rganin@adobe.com> Date: Tue, 25 Sep 2018 16:37:26 -0500 Subject: [PATCH 37/44] MAGETWO-95035: Multi-master splitting works for the core tables (created through declarative schema) but not for tables created with setup scripts --- app/code/Magento/SalesRule/etc/db_schema.xml | 4 ++-- app/code/Magento/Tax/etc/db_schema.xml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/SalesRule/etc/db_schema.xml b/app/code/Magento/SalesRule/etc/db_schema.xml index 3d882ee2eae..cdbd50c3f34 100644 --- a/app/code/Magento/SalesRule/etc/db_schema.xml +++ b/app/code/Magento/SalesRule/etc/db_schema.xml @@ -198,7 +198,7 @@ <column name="attribute_id"/> </index> </table> - <table name="salesrule_coupon_aggregated" resource="default" engine="innodb" comment="Coupon Aggregated"> + <table name="salesrule_coupon_aggregated" resource="sales" engine="innodb" comment="Coupon Aggregated"> <column xsi:type="int" name="id" padding="10" unsigned="true" nullable="false" identity="true" comment="Id"/> <column xsi:type="date" name="period" nullable="false" comment="Period"/> <column xsi:type="smallint" name="store_id" padding="5" unsigned="true" nullable="true" identity="false" @@ -239,7 +239,7 @@ <column name="rule_name"/> </index> </table> - <table name="salesrule_coupon_aggregated_updated" resource="default" engine="innodb" + <table name="salesrule_coupon_aggregated_updated" resource="sales" engine="innodb" comment="Salesrule Coupon Aggregated Updated"> <column xsi:type="int" name="id" padding="10" unsigned="true" nullable="false" identity="true" comment="Id"/> <column xsi:type="date" name="period" nullable="false" comment="Period"/> diff --git a/app/code/Magento/Tax/etc/db_schema.xml b/app/code/Magento/Tax/etc/db_schema.xml index 6cc4041f75a..6e83a647919 100644 --- a/app/code/Magento/Tax/etc/db_schema.xml +++ b/app/code/Magento/Tax/etc/db_schema.xml @@ -139,7 +139,7 @@ <column name="store_id"/> </index> </table> - <table name="tax_order_aggregated_created" resource="default" engine="innodb" comment="Tax Order Aggregation"> + <table name="tax_order_aggregated_created" resource="sales" engine="innodb" comment="Tax Order Aggregation"> <column xsi:type="int" name="id" padding="10" unsigned="true" nullable="false" identity="true" comment="Id"/> <column xsi:type="date" name="period" comment="Period"/> <column xsi:type="smallint" name="store_id" padding="5" unsigned="true" nullable="true" identity="false" @@ -168,7 +168,7 @@ <column name="store_id"/> </index> </table> - <table name="tax_order_aggregated_updated" resource="default" engine="innodb" + <table name="tax_order_aggregated_updated" resource="sales" engine="innodb" comment="Tax Order Aggregated Updated"> <column xsi:type="int" name="id" padding="10" unsigned="true" nullable="false" identity="true" comment="Id"/> <column xsi:type="date" name="period" comment="Period"/> From e2370ace78e463a9ae128e4f75b05993f261c25c Mon Sep 17 00:00:00 2001 From: Cristian Partica <cpartica@magento.com> Date: Wed, 26 Sep 2018 11:01:03 -0500 Subject: [PATCH 38/44] MAGETWO-94819: Swatch validation breaks the whole attribute form - add jquery form validation event to restore options container --- app/code/Magento/Catalog/view/adminhtml/web/js/options.js | 2 +- .../Swatches/view/adminhtml/web/js/product-attributes.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Catalog/view/adminhtml/web/js/options.js b/app/code/Magento/Catalog/view/adminhtml/web/js/options.js index 7c359936704..1ec47f14fee 100644 --- a/app/code/Magento/Catalog/view/adminhtml/web/js/options.js +++ b/app/code/Magento/Catalog/view/adminhtml/web/js/options.js @@ -210,7 +210,7 @@ define([ } tableBody = optionContainer.detach(); }); - editForm.on('afterValidate.error', function () { + editForm.on('afterValidate.error highlight.validate', function () { if (optionPanel.hasClass(activePanelClass)) { optionPanel.find('table').append(tableBody); jQuery('input[name="serialized_options"]').remove(); diff --git a/app/code/Magento/Swatches/view/adminhtml/web/js/product-attributes.js b/app/code/Magento/Swatches/view/adminhtml/web/js/product-attributes.js index d0eacc94e2c..1dc833d5901 100644 --- a/app/code/Magento/Swatches/view/adminhtml/web/js/product-attributes.js +++ b/app/code/Magento/Swatches/view/adminhtml/web/js/product-attributes.js @@ -463,7 +463,7 @@ define([ tableBody = optionContainer.detach(); }); - editForm.on('afterValidate.error', function () { + editForm.on('afterValidate.error highlight.validate', function () { if (activePanel.hasClass(activePanelClass)) { activePanel.find('table').append(tableBody); $('input[name="serialized_options"]').remove(); From b76a01a15360dbd8f5b3c284fd32098d7d298200 Mon Sep 17 00:00:00 2001 From: Cristian Partica <cpartica@magento.com> Date: Mon, 17 Sep 2018 16:53:28 -0500 Subject: [PATCH 39/44] MAGETWO-60034: Cannot ship remaining items in an order for several of one product if credit memo is made for some - fix functional tests --- ...OrderCancelMassActionPartialFailMessage.php} | 17 +++++++++++++---- .../Test/TestCase/MassOrdersUpdateTest.xml | 12 ++++++------ 2 files changed, 19 insertions(+), 10 deletions(-) rename dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/{AssertOrderCancelMassActionFailMessage.php => AssertOrderCancelMassActionPartialFailMessage.php} (60%) diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertOrderCancelMassActionFailMessage.php b/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertOrderCancelMassActionPartialFailMessage.php similarity index 60% rename from dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertOrderCancelMassActionFailMessage.php rename to dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertOrderCancelMassActionPartialFailMessage.php index fffb0746d49..6aed5cd39aa 100644 --- a/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertOrderCancelMassActionFailMessage.php +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/Constraint/AssertOrderCancelMassActionPartialFailMessage.php @@ -10,15 +10,20 @@ use Magento\Mtf\Constraint\AbstractConstraint; /** - * Class AssertOrderCancelMassActionFailMessage + * Class AssertOrderCancelAndSuccessMassActionFailMessage * Assert cancel fail message is displayed on order index page */ -class AssertOrderCancelMassActionFailMessage extends AbstractConstraint +class AssertOrderCancelMassActionPartialFailMessage extends AbstractConstraint { + /** + * Message displayed after cancel order from archive + */ + const SUCCESS_MESSAGE = 'We canceled 1 order(s).'; + /** * Text value to be checked */ - const FAIL_CANCEL_MESSAGE = 'You cannot cancel the order(s).'; + const FAIL_CANCEL_MESSAGE = '1 order(s) cannot be canceled.'; /** * Assert cancel fail message is displayed on order index page @@ -32,6 +37,10 @@ public function processAssert(OrderIndex $orderIndex) self::FAIL_CANCEL_MESSAGE, $orderIndex->getMessagesBlock()->getErrorMessage() ); + \PHPUnit\Framework\Assert::assertEquals( + self::SUCCESS_MESSAGE, + $orderIndex->getMessagesBlock()->getSuccessMessage() + ); } /** @@ -41,6 +50,6 @@ public function processAssert(OrderIndex $orderIndex) */ public function toString() { - return 'Cancel fail message is displayed on order index page.'; + return 'Cancel and success fail message is displayed on order index page.'; } } diff --git a/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/MassOrdersUpdateTest.xml b/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/MassOrdersUpdateTest.xml index e6ab0ff5026..31d5c30d25f 100644 --- a/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/MassOrdersUpdateTest.xml +++ b/dev/tests/functional/tests/app/Magento/Sales/Test/TestCase/MassOrdersUpdateTest.xml @@ -18,12 +18,12 @@ <constraint name="Magento\Sales\Test\Constraint\AssertOrdersInOrdersGrid" /> </variation> <variation name="MassOrdersUpdateTestVariation2"> - <data name="description" xsi:type="string">try to cancel orders in status Complete, Closed</data> + <data name="description" xsi:type="string">try to cancel orders in status Complete, Canceled</data> <data name="steps" xsi:type="string">invoice, shipment|invoice, credit memo</data> <data name="action" xsi:type="string">Cancel</data> <data name="ordersCount" xsi:type="string">2</data> - <data name="resultStatuses" xsi:type="string">Complete,Processing</data> - <constraint name="Magento\Sales\Test\Constraint\AssertOrderCancelMassActionFailMessage" /> + <data name="resultStatuses" xsi:type="string">Complete,Canceled</data> + <constraint name="Magento\Sales\Test\Constraint\AssertOrderCancelMassActionPartialFailMessage" /> <constraint name="Magento\Sales\Test\Constraint\AssertOrdersInOrdersGrid" /> </variation> <variation name="MassOrdersUpdateTestVariation3"> @@ -31,8 +31,8 @@ <data name="steps" xsi:type="string">invoice|invoice, credit memo</data> <data name="action" xsi:type="string">Cancel</data> <data name="ordersCount" xsi:type="string">2</data> - <data name="resultStatuses" xsi:type="string">Processing,Closed</data> - <constraint name="Magento\Sales\Test\Constraint\AssertOrderCancelMassActionFailMessage" /> + <data name="resultStatuses" xsi:type="string">Processing,Canceled</data> + <constraint name="Magento\Sales\Test\Constraint\AssertOrderCancelMassActionPartialFailMessage" /> <constraint name="Magento\Sales\Test\Constraint\AssertOrdersInOrdersGrid" /> </variation> <variation name="MassOrdersUpdateTestVariation4"> @@ -55,7 +55,7 @@ <constraint name="Magento\Sales\Test\Constraint\AssertOrdersInOrdersGrid" /> </variation> <variation name="MassOrdersUpdateTestVariation6"> - <data name="description" xsi:type="string">Release order in statuse On Hold</data> + <data name="description" xsi:type="string">Release order in status On Hold</data> <data name="steps" xsi:type="string">on hold</data> <data name="action" xsi:type="string">Unhold</data> <data name="ordersCount" xsi:type="string">1</data> From c4c8af6b221a84e5f389a95a29bc60af4fc3ae44 Mon Sep 17 00:00:00 2001 From: roman <rleshchenko@magento.com> Date: Fri, 28 Sep 2018 18:27:01 +0300 Subject: [PATCH 40/44] MAGETWO-70943: Incorrect reset password flow --- app/code/Magento/Customer/Model/AccountManagement.php | 4 ++-- .../view/frontend/email/password_reset_confirmation.html | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Customer/Model/AccountManagement.php b/app/code/Magento/Customer/Model/AccountManagement.php index 6aee2894f49..06c1f41c388 100644 --- a/app/code/Magento/Customer/Model/AccountManagement.php +++ b/app/code/Magento/Customer/Model/AccountManagement.php @@ -661,7 +661,7 @@ private function handleUnknownTemplate($template) /** * @inheritdoc */ - public function resetPassword($email, $resetToken, $newPassword): bool + public function resetPassword($email, $resetToken, $newPassword) { if (!$email) { $customer = $this->matchCustomerByRpToken($resetToken); @@ -1093,7 +1093,7 @@ public function isCustomerInStore($customerWebsiteId, $storeId) * @throws \Magento\Framework\Exception\NoSuchEntityException If customer doesn't exist * @throws LocalizedException */ - private function validateResetPasswordToken(?int $customerId, ?string $resetPasswordLinkToken) : bool + private function validateResetPasswordToken($customerId, $resetPasswordLinkToken) { if ($customerId !== null && $customerId <= 0) { throw new InputException( diff --git a/app/code/Magento/Customer/view/frontend/email/password_reset_confirmation.html b/app/code/Magento/Customer/view/frontend/email/password_reset_confirmation.html index f33350ea482..59e7f16adfd 100644 --- a/app/code/Magento/Customer/view/frontend/email/password_reset_confirmation.html +++ b/app/code/Magento/Customer/view/frontend/email/password_reset_confirmation.html @@ -22,7 +22,6 @@ <tr> <td align="center"> <a href="{{var this.getUrl($store,'customer/account/createPassword/',[_query:[token:$customer.rp_token],_nosid:1])}}" target="_blank">{{trans "Set a New Password"}}</a> - </td> </tr> </table> From 706fd1b965e1a04a6f7109b3300b24bddeccb19c Mon Sep 17 00:00:00 2001 From: Deepty Thampy <dthampy@adobe.com> Date: Fri, 28 Sep 2018 17:03:01 -0500 Subject: [PATCH 41/44] MAGETWO-60034: Cannot ship remaining items in an order for several of one product if credit memo is made for some - updated test --- .../Mftf/Test/AdminAbleToShipPartiallyInvoicedItemsTest.xml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminAbleToShipPartiallyInvoicedItemsTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminAbleToShipPartiallyInvoicedItemsTest.xml index 3fdbb3eae0b..66316d0af8b 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminAbleToShipPartiallyInvoicedItemsTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminAbleToShipPartiallyInvoicedItemsTest.xml @@ -64,6 +64,7 @@ <!--Submit Order and verify information--> <click selector="{{AdminOrderFormActionSection.SubmitOrder}}" stepKey="clickSubmitOrder" after="seeCorrectGrandTotal"/> + <waitForLoadingMaskToDisappear stepKey="waitForLoadingMaskTodisappear"/> <waitForPageLoad stepKey="waitForOrderToProcess"/> <seeInCurrentUrl url="{{AdminOrderDetailsPage.url}}" stepKey="seeViewOrderPage" after="clickSubmitOrder"/> <see selector="{{AdminOrderDetailsMessagesSection.successMessage}}" userInput="You created the order." stepKey="seeSuccessMessage" after="seeViewOrderPage"/> @@ -122,7 +123,8 @@ <!--Update Qty of items to be refunded and submit refund--> <scrollTo selector="{{AdminCreditMemoItemsSection.itemQtyToRefund('1')}}" stepKey="scrollToItemsToRefund"/> <fillField selector="{{AdminCreditMemoItemsSection.itemQtyToRefund('1')}}" userInput="5" stepKey="fillQtyOfItemsToRefund" after="scrollToItemsToRefund"/> - <click selector="{{AdminCreditMemoItemsSection.updateQty}}" stepKey="updateRefundQty"/> + + <!--<click selector="{{AdminCreditMemoItemsSection.updateQty}}" stepKey="updateRefundQty"/>--> <waitForLoadingMaskToDisappear stepKey="waitForRefundQtyToUpdate"/> <waitForElementVisible selector="{{AdminCreditMemoTotalSection.submitRefundOffline}}" stepKey="seeSubmitRefundBtn"/> <click selector="{{AdminCreditMemoTotalSection.submitRefundOffline}}" stepKey="submitRefundOffline"/> From 0c42ce29764cd1198a2d84ac0509891b7801934e Mon Sep 17 00:00:00 2001 From: Deepty Thampy <dthampy@adobe.com> Date: Mon, 1 Oct 2018 17:31:28 -0500 Subject: [PATCH 42/44] MAGETWO-60034: Cannot ship remaining items in an order for several of one product if credit memo is made for some - updated test to comment out a step to fillField --- .../Mftf/Test/AdminAbleToShipPartiallyInvoicedItemsTest.xml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Sales/Test/Mftf/Test/AdminAbleToShipPartiallyInvoicedItemsTest.xml b/app/code/Magento/Sales/Test/Mftf/Test/AdminAbleToShipPartiallyInvoicedItemsTest.xml index 66316d0af8b..e4fd894f608 100644 --- a/app/code/Magento/Sales/Test/Mftf/Test/AdminAbleToShipPartiallyInvoicedItemsTest.xml +++ b/app/code/Magento/Sales/Test/Mftf/Test/AdminAbleToShipPartiallyInvoicedItemsTest.xml @@ -120,10 +120,9 @@ <click selector="{{AdminOrderDetailsMainActionsSection.creditMemo}}" stepKey="clickCreateCreditMemo" after="createCreditMemoComment"/> <see selector="{{AdminHeaderSection.pageTitle}}" userInput="New Memo" stepKey="seeNewMemoInPageTitle"/> - <!--Update Qty of items to be refunded and submit refund--> + <!--Submit refund--> <scrollTo selector="{{AdminCreditMemoItemsSection.itemQtyToRefund('1')}}" stepKey="scrollToItemsToRefund"/> - <fillField selector="{{AdminCreditMemoItemsSection.itemQtyToRefund('1')}}" userInput="5" stepKey="fillQtyOfItemsToRefund" after="scrollToItemsToRefund"/> - + <!--<fillField selector="{{AdminCreditMemoItemsSection.itemQtyToRefund('1')}}" userInput="5" stepKey="fillQtyOfItemsToRefund" after="scrollToItemsToRefund"/>--> <!--<click selector="{{AdminCreditMemoItemsSection.updateQty}}" stepKey="updateRefundQty"/>--> <waitForLoadingMaskToDisappear stepKey="waitForRefundQtyToUpdate"/> <waitForElementVisible selector="{{AdminCreditMemoTotalSection.submitRefundOffline}}" stepKey="seeSubmitRefundBtn"/> From 1e3728050a4236827bf65a52fd1dfc8e759d1c59 Mon Sep 17 00:00:00 2001 From: Oleksandr Gorkun <ogorkun@magento.com> Date: Thu, 4 Oct 2018 10:24:24 +0300 Subject: [PATCH 43/44] MAGETWO-88654: Sales Rule Widget Label --- .../SalesRule/Block/Adminhtml/Promo/Widget/Chooser.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/SalesRule/Block/Adminhtml/Promo/Widget/Chooser.php b/app/code/Magento/SalesRule/Block/Adminhtml/Promo/Widget/Chooser.php index b4be904223a..901866d52f7 100644 --- a/app/code/Magento/SalesRule/Block/Adminhtml/Promo/Widget/Chooser.php +++ b/app/code/Magento/SalesRule/Block/Adminhtml/Promo/Widget/Chooser.php @@ -3,8 +3,12 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\SalesRule\Block\Adminhtml\Promo\Widget; +/** + * Widget that allows to select a sales rule. + */ class Chooser extends \Magento\Backend\Block\Widget\Grid\Extended { /** @@ -87,7 +91,7 @@ public function prepareElementHtml(\Magento\Framework\Data\Form\Element\Abstract if ($element->getValue()) { $rule = $this->ruleFactory->create()->load((int)$element->getValue()); if ($rule->getId()) { - $chooser->setLabel($rule->getName()); + $chooser->setLabel($this->escapeHtml($rule->getName())); } } From 420ab7ef10211a2e1664d55b8445f3c39659643c Mon Sep 17 00:00:00 2001 From: Dmytro Voskoboinikov <dvoskoboinikov@magento.com> Date: Thu, 4 Oct 2018 14:00:02 +0300 Subject: [PATCH 44/44] MAGETWO-91699: Displaying of error messages in a customer account is broken --- .../Customer/Controller/Account/EditPost.php | 17 +++++++++++++---- .../Magento/Customer/Controller/AccountTest.php | 6 +++--- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/app/code/Magento/Customer/Controller/Account/EditPost.php b/app/code/Magento/Customer/Controller/Account/EditPost.php index e3b3d834522..38bc52eac42 100644 --- a/app/code/Magento/Customer/Controller/Account/EditPost.php +++ b/app/code/Magento/Customer/Controller/Account/EditPost.php @@ -22,6 +22,7 @@ use Magento\Customer\Model\CustomerExtractor; use Magento\Customer\Model\Session; use Magento\Framework\App\Action\Context; +use Magento\Framework\Escaper; use Magento\Framework\Exception\InputException; use Magento\Framework\Exception\InvalidEmailOrPasswordException; use Magento\Framework\Exception\State\UserLockedException; @@ -79,6 +80,11 @@ class EditPost extends AbstractAccount implements CsrfAwareActionInterface, Http */ private $customerMapper; + /** + * @var Escaper + */ + private $escaper; + /** * @param Context $context * @param Session $customerSession @@ -86,6 +92,7 @@ class EditPost extends AbstractAccount implements CsrfAwareActionInterface, Http * @param CustomerRepositoryInterface $customerRepository * @param Validator $formKeyValidator * @param CustomerExtractor $customerExtractor + * @param Escaper|null $escaper */ public function __construct( Context $context, @@ -93,7 +100,8 @@ public function __construct( AccountManagementInterface $customerAccountManagement, CustomerRepositoryInterface $customerRepository, Validator $formKeyValidator, - CustomerExtractor $customerExtractor + CustomerExtractor $customerExtractor, + ?Escaper $escaper = null ) { parent::__construct($context); $this->session = $customerSession; @@ -101,6 +109,7 @@ public function __construct( $this->customerRepository = $customerRepository; $this->formKeyValidator = $formKeyValidator; $this->customerExtractor = $customerExtractor; + $this->escaper = $escaper ?: ObjectManager::getInstance()->get(Escaper::class); } /** @@ -196,7 +205,7 @@ public function execute() $this->messageManager->addSuccess(__('You saved the account information.')); return $resultRedirect->setPath('customer/account'); } catch (InvalidEmailOrPasswordException $e) { - $this->messageManager->addError($e->getMessage()); + $this->messageManager->addErrorMessage($this->escaper->escapeHtml($e->getMessage())); } catch (UserLockedException $e) { $message = __( 'The account sign-in was incorrect or your account is disabled temporarily. ' @@ -207,9 +216,9 @@ public function execute() $this->messageManager->addError($message); return $resultRedirect->setPath('customer/account/login'); } catch (InputException $e) { - $this->messageManager->addError($e->getMessage()); + $this->messageManager->addErrorMessage($this->escaper->escapeHtml($e->getMessage())); foreach ($e->getErrors() as $error) { - $this->messageManager->addError($error->getMessage()); + $this->messageManager->addErrorMessage($this->escaper->escapeHtml($error->getMessage())); } } catch (\Magento\Framework\Exception\LocalizedException $e) { $this->messageManager->addError($e->getMessage()); diff --git a/dev/tests/integration/testsuite/Magento/Customer/Controller/AccountTest.php b/dev/tests/integration/testsuite/Magento/Customer/Controller/AccountTest.php index 921fa81fa6f..eb06d8d5d66 100644 --- a/dev/tests/integration/testsuite/Magento/Customer/Controller/AccountTest.php +++ b/dev/tests/integration/testsuite/Magento/Customer/Controller/AccountTest.php @@ -606,7 +606,7 @@ public function testMissingDataEditPostAction() $this->assertRedirect($this->stringContains('customer/account/edit/')); $this->assertSessionMessages( - $this->equalTo(['"Email" is not a valid email address.']), + $this->equalTo(['"Email" is not a valid email address.']), MessageInterface::TYPE_ERROR ); } @@ -637,7 +637,7 @@ public function testWrongPasswordEditPostAction() $this->assertRedirect($this->stringContains('customer/account/edit/')); // Not sure if its the most secure message. Not changing the behavior for now in the new AccountManagement APIs. $this->assertSessionMessages( - $this->equalTo(["The password doesn't match this account. Verify the password and try again."]), + $this->equalTo(["The password doesn't match this account. Verify the password and try again."]), MessageInterface::TYPE_ERROR ); } @@ -665,7 +665,7 @@ public function testWrongConfirmationEditPostAction() $this->assertRedirect($this->stringContains('customer/account/edit/')); $this->assertSessionMessages( - $this->equalTo(['Password confirmation doesn\'t match entered password.']), + $this->equalTo(['Password confirmation doesn't match entered password.']), MessageInterface::TYPE_ERROR ); }