From 33ffcd3080955ec5f121ad0ef480f0f1626866f9 Mon Sep 17 00:00:00 2001 From: Stanislav Idolov Date: Wed, 2 Mar 2016 16:47:29 +0200 Subject: [PATCH 01/14] MAGETWO-49756: Groupped Product ui configuration --- .../Product/Form/Modifier/Grouped.php | 67 ++++++++++++++----- 1 file changed, 51 insertions(+), 16 deletions(-) diff --git a/app/code/Magento/GroupedProduct/Ui/DataProvider/Product/Form/Modifier/Grouped.php b/app/code/Magento/GroupedProduct/Ui/DataProvider/Product/Form/Modifier/Grouped.php index aee2965ba8e05..d59e4410f1444 100644 --- a/app/code/Magento/GroupedProduct/Ui/DataProvider/Product/Form/Modifier/Grouped.php +++ b/app/code/Magento/GroupedProduct/Ui/DataProvider/Product/Form/Modifier/Grouped.php @@ -71,6 +71,16 @@ class Grouped extends AbstractModifier */ protected $localeCurrency; + /** + * @var array + */ + protected $uiComponentsConfig = [ + 'button_set' => 'grouped_products_button_set', + 'modal' => 'grouped_products_modal', + 'listing' => 'grouped_product_listing', + 'form' => 'product_form', + ]; + /** * @var string */ @@ -95,6 +105,7 @@ class Grouped extends AbstractModifier * @param Status $status * @param AttributeSetRepositoryInterface $attributeSetRepository * @param CurrencyInterface $localeCurrency + * @param array $uiComponentsConfig */ public function __construct( LocatorInterface $locator, @@ -104,7 +115,8 @@ public function __construct( ImageHelper $imageHelper, Status $status, AttributeSetRepositoryInterface $attributeSetRepository, - CurrencyInterface $localeCurrency + CurrencyInterface $localeCurrency, + array $uiComponentsConfig = [] ) { $this->locator = $locator; $this->urlBuilder = $urlBuilder; @@ -114,6 +126,7 @@ public function __construct( $this->attributeSetRepository = $attributeSetRepository; $this->status = $status; $this->localeCurrency = $localeCurrency; + $this->uiComponentsConfig = array_replace_recursive($this->uiComponentsConfig, $uiComponentsConfig); } /** @@ -246,8 +259,8 @@ protected function modifyQtyAndStockStatus(array $meta) protected function getChildren() { $children = [ - 'grouped_products_button_set' => $this->getButtonSet(), - 'grouped_products_modal' => $this->getModal(), + $this->uiComponentsConfig['button_set'] => $this->getButtonSet(), + $this->uiComponentsConfig['modal'] => $this->getModal(), self::LINK_TYPE => $this->getGrid(), ]; return $children; @@ -266,7 +279,11 @@ protected function getModal() 'config' => [ 'componentType' => Modal::NAME, 'dataScope' => '', - 'provider' => 'product_form.product_form_data_source', + 'provider' => + $this->uiComponentsConfig['form'] + . '.' + . $this->uiComponentsConfig['form'] + . '_data_source', 'options' => [ 'title' => __('Add Products to Group'), 'buttons' => [ @@ -280,7 +297,7 @@ protected function getModal() 'class' => 'action-primary', 'actions' => [ [ - 'targetName' => 'index = grouped_product_listing', + 'targetName' => 'index = ' . $this->uiComponentsConfig['listing'], 'actionName' => 'save' ], 'closeModal' @@ -291,7 +308,7 @@ protected function getModal() ], ], ], - 'children' => ['grouped_product_listing' => $this->getListing()], + 'children' => [$this->uiComponentsConfig['listing'] => $this->getListing()], ]; } @@ -308,13 +325,25 @@ protected function getListing() 'config' => [ 'autoRender' => false, 'componentType' => 'insertListing', - 'dataScope' => 'grouped_product_listing', - 'externalProvider' => 'grouped_product_listing.grouped_product_listing_data_source', - 'selectionsProvider' => 'grouped_product_listing.grouped_product_listing.product_columns.ids', - 'ns' => 'grouped_product_listing', + 'dataScope' => $this->uiComponentsConfig['listing'], + 'externalProvider' => + $this->uiComponentsConfig['listing'] + . '.' + . $this->uiComponentsConfig['listing'] + . '_data_source', + 'selectionsProvider' => + $this->uiComponentsConfig['listing'] + . '.' + . $this->uiComponentsConfig['listing'] + . '.product_columns.ids', + 'ns' => $this->uiComponentsConfig['listing'], 'render_url' => $this->urlBuilder->getUrl('mui/index/render'), 'realTimeLink' => true, - 'provider' => 'product_form.product_form_data_source', + 'provider' => + $this->uiComponentsConfig['form'] + . '.' + . $this->uiComponentsConfig['form'] + . '_data_source', 'dataLinks' => ['imports' => false, 'exports' => true], 'behaviourType' => 'simple', 'externalFilterMode' => true, @@ -365,16 +394,22 @@ protected function getButtonSet() 'actions' => [ [ 'targetName' => - 'product_form.product_form.' + $this->uiComponentsConfig['form'] . '.' . $this->uiComponentsConfig['form'] + . '.' . static::GROUP_GROUPED - . '.grouped_products_modal', + . '.' + . $this->uiComponentsConfig['modal'], 'actionName' => 'openModal', ], [ 'targetName' => - 'product_form.product_form.' + $this->uiComponentsConfig['form'] . '.' . $this->uiComponentsConfig['form'] + . '.' . static::GROUP_GROUPED - . '.grouped_products_modal.grouped_product_listing', + . '.' + . $this->uiComponentsConfig['modal'] + . '.' + . $this->uiComponentsConfig['listing'], 'actionName' => 'render', ], ], @@ -409,7 +444,7 @@ protected function getGrid() 'itemTemplate' => 'record', 'dataScope' => 'data.links', 'deleteButtonLabel' => __('Remove'), - 'dataProvider' => 'grouped_product_listing', + 'dataProvider' => $this->uiComponentsConfig['listing'], 'map' => [ 'id' => 'entity_id', 'name' => 'name', From 8e0c8a67653cbd92df3c65f1cc3d96c8313df72e Mon Sep 17 00:00:00 2001 From: Stanislav Idolov Date: Thu, 10 Mar 2016 16:27:16 +0200 Subject: [PATCH 02/14] MAGETWO-50025: Extention attributes errors for CartItemInterface #3640 --- app/code/Magento/Quote/Model/Cart/Totals/ItemConverter.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/code/Magento/Quote/Model/Cart/Totals/ItemConverter.php b/app/code/Magento/Quote/Model/Cart/Totals/ItemConverter.php index 2b4792d2e44a2..16f76e1d18496 100644 --- a/app/code/Magento/Quote/Model/Cart/Totals/ItemConverter.php +++ b/app/code/Magento/Quote/Model/Cart/Totals/ItemConverter.php @@ -8,6 +8,7 @@ use Magento\Catalog\Helper\Product\ConfigurationPool; use Magento\Framework\Event\ManagerInterface as EventManager; use Magento\Framework\Api\DataObjectHelper; +use Magento\Framework\Api\ExtensibleDataInterface; /** * Cart item totals converter. @@ -68,6 +69,8 @@ public function modelToDataObject($item) $this->eventManager->dispatch('items_additional_data', ['item' => $item]); $items = $item->toArray(); $items['options'] = $this->getFormattedOptionValue($item); + unset($items[ExtensibleDataInterface::EXTENSION_ATTRIBUTES_KEY]); + $itemsData = $this->totalsItemFactory->create(); $this->dataObjectHelper->populateWithArray( $itemsData, From 0218b3ded770fe99dc06c7ff15d3fe003f80dcd5 Mon Sep 17 00:00:00 2001 From: Stanislav Idolov Date: Fri, 11 Mar 2016 10:00:18 +0200 Subject: [PATCH 03/14] MAGETWO-50285: Gift options *.less file is not properly packaged in the composer package --- .../web/css/source/_module.less | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 app/design/adminhtml/Magento/backend/Magento_GiftRegistry/web/css/source/_module.less diff --git a/app/design/adminhtml/Magento/backend/Magento_GiftRegistry/web/css/source/_module.less b/app/design/adminhtml/Magento/backend/Magento_GiftRegistry/web/css/source/_module.less new file mode 100644 index 0000000000000..83999a521950a --- /dev/null +++ b/app/design/adminhtml/Magento/backend/Magento_GiftRegistry/web/css/source/_module.less @@ -0,0 +1,41 @@ +// /** +// * Copyright © 2015 Magento. All rights reserved. +// * See COPYING.txt for license details. +// */ + +// +// Gift Registry styles +// _____________________________________________ + +.media-width(@extremum, @break) when (@extremum = 'min') and (@break = @screen__m) { + + .gift-registry-info { + float: left; + #mix-grid .width(6,12); + } + + .gift-registry-address { + float: right; + #mix-grid .width(6,12); + } +} + +.form-sharing-info { + .admin__legend { + &:extend(.abs-clearfix all); + border-bottom: 1px solid @color-gray80; + margin-bottom: 1.7rem; + padding: 1.4rem 0 .5rem; + span { + &:extend(h2); + float: left; + margin: 0; + } + } + + .sharing-info-textarea { + display: block; + height: 50px; + margin-bottom: @indent__m; + } +} From 2ccb65095716964a61c4f58c1d3c0421fccb9599 Mon Sep 17 00:00:00 2001 From: Iryna Lagno Date: Mon, 14 Mar 2016 12:10:14 +0200 Subject: [PATCH 04/14] MAGETWO-50354: Catch validation exception in the Product Repository --- app/code/Magento/Catalog/Model/ProductRepository.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Catalog/Model/ProductRepository.php b/app/code/Magento/Catalog/Model/ProductRepository.php index 9f1087544ae23..5ecde911d9840 100644 --- a/app/code/Magento/Catalog/Model/ProductRepository.php +++ b/app/code/Magento/Catalog/Model/ProductRepository.php @@ -15,6 +15,8 @@ use Magento\Framework\Exception\InputException; use Magento\Framework\Exception\NoSuchEntityException; use Magento\Framework\Exception\StateException; +use Magento\Framework\Exception\CouldNotSaveException; +use Magento\Framework\Exception\ValidatorException; /** * @SuppressWarnings(PHPMD.CouplingBetweenObjects) @@ -515,8 +517,10 @@ public function save(\Magento\Catalog\Api\Data\ProductInterface $product, $saveO $product->getData($exception->getAttributeCode()), $exception ); + } catch (ValidatorException $e) { + throw new CouldNotSaveException(__($e->getMessage())); } catch (\Exception $e) { - throw new \Magento\Framework\Exception\CouldNotSaveException(__('Unable to save product')); + throw new CouldNotSaveException(__('Unable to save product')); } unset($this->instances[$product->getSku()]); unset($this->instancesById[$product->getId()]); @@ -532,6 +536,8 @@ public function delete(\Magento\Catalog\Api\Data\ProductInterface $product) $productId = $product->getId(); try { $this->resourceModel->delete($product); + } catch (ValidatorException $e) { + throw new CouldNotSaveException(__($e->getMessage())); } catch (\Exception $e) { throw new \Magento\Framework\Exception\StateException( __('Unable to remove product %1', $sku) From ef5a410557d61dbfd896904c3f7accb820daaeb1 Mon Sep 17 00:00:00 2001 From: Stanislav Idolov Date: Mon, 14 Mar 2016 17:06:09 +0200 Subject: [PATCH 05/14] MAGETWO-49374: Impossible use \Magento\Quote\Api\Data\CartInterface::KEY_ID in FilterBuilder --- app/code/Magento/Quote/Api/Data/CartInterface.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/code/Magento/Quote/Api/Data/CartInterface.php b/app/code/Magento/Quote/Api/Data/CartInterface.php index 17489d01d4edf..dce47320608ae 100644 --- a/app/code/Magento/Quote/Api/Data/CartInterface.php +++ b/app/code/Magento/Quote/Api/Data/CartInterface.php @@ -16,6 +16,8 @@ interface CartInterface extends \Magento\Framework\Api\ExtensibleDataInterface */ const KEY_ID = 'id'; + const KEY_ENTITY_ID = 'entity_id'; + const KEY_CREATED_AT = 'created_at'; const KEY_UPDATED_AT = 'updated_at'; From 520f76d054a3fd1bda57144e17e58e116361a6d5 Mon Sep 17 00:00:00 2001 From: Stanislav Idolov Date: Thu, 17 Mar 2016 10:10:02 +0200 Subject: [PATCH 06/14] MAGETWO-50368: Grouped product items not visible individually are absent in mini cart #3728 --- .../Magento/Checkout/CustomerData/Cart.php | 11 +- .../Test/Unit/CustomerData/CartTest.php | 105 +++++++++++++++++- 2 files changed, 111 insertions(+), 5 deletions(-) diff --git a/app/code/Magento/Checkout/CustomerData/Cart.php b/app/code/Magento/Checkout/CustomerData/Cart.php index 9782c438a11b5..a06f04817476e 100644 --- a/app/code/Magento/Checkout/CustomerData/Cart.php +++ b/app/code/Magento/Checkout/CustomerData/Cart.php @@ -150,12 +150,15 @@ protected function getRecentItems() foreach (array_reverse($this->getAllQuoteItems()) as $item) { /* @var $item \Magento\Quote\Model\Quote\Item */ if (!$item->getProduct()->isVisibleInSiteVisibility()) { - $productId = $item->getProduct()->getId(); - $products = $this->catalogUrl->getRewriteByProductStore([$productId => $item->getStoreId()]); - if (!isset($products[$productId])) { + $product = $item->getOptionByCode('product_type') !== null + ? $item->getOptionByCode('product_type')->getProduct() + : $item->getProduct(); + + $products = $this->catalogUrl->getRewriteByProductStore([$product->getId() => $item->getStoreId()]); + if (!isset($products[$product->getId()])) { continue; } - $urlDataObject = new \Magento\Framework\DataObject($products[$productId]); + $urlDataObject = new \Magento\Framework\DataObject($products[$product->getId()]); $item->getProduct()->setUrlDataObject($urlDataObject); } $items[] = $this->itemPoolInterface->getItemData($item); diff --git a/app/code/Magento/Checkout/Test/Unit/CustomerData/CartTest.php b/app/code/Magento/Checkout/Test/Unit/CustomerData/CartTest.php index 4c85bd10abdfa..3612120276b75 100644 --- a/app/code/Magento/Checkout/Test/Unit/CustomerData/CartTest.php +++ b/app/code/Magento/Checkout/Test/Unit/CustomerData/CartTest.php @@ -130,7 +130,7 @@ public function testGetSectionData() $quoteItemMock->expects($this->once())->method('getStoreId')->willReturn($storeId); $productMock->expects($this->once())->method('isVisibleInSiteVisibility')->willReturn(false); - $productMock->expects($this->once())->method('getId')->willReturn($productId); + $productMock->expects($this->exactly(3))->method('getId')->willReturn($productId); $productMock->expects($this->once()) ->method('setUrlDataObject') ->with(new \Magento\Framework\DataObject($productRewrite[$productId])) @@ -170,4 +170,107 @@ public function testGetSectionData() ]; $this->assertEquals($expectedResult, $this->model->getSectionData()); } + + public function testGetSectionDataWithCompositeProduct() + { + $summaryQty = 100; + $subtotalValue = 200; + $productId = 10; + $storeId = 20; + + $productRewrite = [$productId => ['rewrite' => 'product']]; + $itemData = ['item' => 'data']; + $shortcutButtonsHtml = 'Buttons'; + $subtotalMock = $this->getMock('\Magento\Framework\DataObject', ['getValue'], [], '', false); + $subtotalMock->expects($this->once())->method('getValue')->willReturn($subtotalValue); + $totals = ['subtotal' => $subtotalMock]; + + $quoteMock = $this->getMock( + '\Magento\Quote\Model\Quote', + ['getTotals', 'getHasError', 'getAllVisibleItems'], + [], + '', + false + ); + $quoteItemMock = $this->getMock( + '\Magento\Quote\Model\Quote\Item', + ['getProduct', 'getOptionByCode', 'getStoreId'], + [], + '', + false + ); + + $this->checkoutSessionMock->expects($this->exactly(2))->method('getQuote')->willReturn($quoteMock); + $quoteMock->expects($this->once())->method('getTotals')->willReturn($totals); + $quoteMock->expects($this->once())->method('getHasError')->willReturn(false); + + $this->checkoutCartMock->expects($this->once())->method('getSummaryQty')->willReturn($summaryQty); + $this->checkoutHelperMock->expects($this->once()) + ->method('formatPrice') + ->with($subtotalValue) + ->willReturn($subtotalValue); + $this->checkoutHelperMock->expects($this->once())->method('canOnepageCheckout')->willReturn(true); + + + $quoteMock->expects($this->once())->method('getAllVisibleItems')->willReturn([$quoteItemMock]); + + $productMock = $this->getMock( + '\Magento\Catalog\Model\Product', + ['isVisibleInSiteVisibility', 'getId', 'setUrlDataObject'], + [], + '', + false + ); + + $optionsMock = $this->getMock('\Magento\Quote\Model\Quote\Item\Option', [], [], '', false); + $optionsMock->expects($this->once())->method('getProduct')->willReturn($productMock); + + $quoteItemMock->expects($this->exactly(2))->method('getProduct')->willReturn($productMock); + $quoteItemMock->expects($this->exactly(2)) + ->method('getOptionByCode') + ->with('product_type') + ->willReturn($optionsMock); + $quoteItemMock->expects($this->once())->method('getStoreId')->willReturn($storeId); + + $productMock->expects($this->once())->method('isVisibleInSiteVisibility')->willReturn(false); + $productMock->expects($this->exactly(3))->method('getId')->willReturn($productId); + $productMock->expects($this->once()) + ->method('setUrlDataObject') + ->with(new \Magento\Framework\DataObject($productRewrite[$productId])) + ->willReturnSelf(); + + $this->catalogUrlMock->expects($this->once()) + ->method('getRewriteByProductStore') + ->with([$productId => $storeId]) + ->willReturn($productRewrite); + + $shortcutButtonsMock = $this->getMock('\Magento\Catalog\Block\ShortcutButtons', [], [], '', false); + $this->layoutMock->expects($this->once()) + ->method('createBlock') + ->with('Magento\Catalog\Block\ShortcutButtons') + ->willReturn($shortcutButtonsMock); + + $shortcutButtonsMock->expects($this->once())->method('toHtml')->willReturn($shortcutButtonsHtml); + $this->checkoutHelperMock->expects($this->once()) + ->method('isAllowedGuestCheckout') + ->with($quoteMock) + ->willReturn(true); + + $this->itemPoolInterfaceMock->expects($this->once()) + ->method('getItemData') + ->with($quoteItemMock) + ->willReturn($itemData); + + $expectedResult = [ + 'summary_count' => 100, + 'subtotal' => 200, + 'possible_onepage_checkout' => 1, + 'items' => [ + ['item' => 'data'] + ], + 'extra_actions' => 'Buttons', + 'isGuestCheckoutAllowed' => 1 + ]; + $this->assertEquals($expectedResult, $this->model->getSectionData()); + } } From 8c9f650c9d9a8a5d497380422ad7659386ce18c9 Mon Sep 17 00:00:00 2001 From: Serhiy Shkolyarenko Date: Thu, 17 Mar 2016 10:11:54 +0200 Subject: [PATCH 07/14] MAGETWO-50370: There is no ability to "Save as a new update" for grouped product fix for permanent campaigns --- .../Product/Initialization/Helper.php | 20 +++++++- .../Adminhtml/Product/Link/Resolver.php | 50 +++++++++++++++++++ .../Model/Product/Type/AbstractType.php | 11 ++++ .../Catalog/Model/ProductLink/Repository.php | 2 +- .../Model/Product/Type/Grouped.php | 8 +++ 5 files changed, 89 insertions(+), 2 deletions(-) create mode 100644 app/code/Magento/Catalog/Controller/Adminhtml/Product/Link/Resolver.php diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Initialization/Helper.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Initialization/Helper.php index 387c83f312b59..1f18da31a6f7a 100644 --- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Initialization/Helper.php +++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Initialization/Helper.php @@ -9,6 +9,8 @@ use Magento\Catalog\Api\Data\ProductLinkInterfaceFactory as ProductLinkFactory; use Magento\Catalog\Api\ProductRepositoryInterface\Proxy as ProductRepository; use Magento\Catalog\Model\Product\Initialization\Helper\ProductLinks; +use Magento\Catalog\Controller\Adminhtml\Product\Link\Resolver as LinkResolver; +use Magento\Framework\App\ObjectManager; /** * Class Helper @@ -56,6 +58,11 @@ class Helper */ protected $productLinks; + /** + * @var LinkResolver + */ + private $linkResolver; + /** * @param \Magento\Framework\App\RequestInterface $request * @param \Magento\Store\Model\StoreManagerInterface $storeManager @@ -194,6 +201,17 @@ public function initialize(\Magento\Catalog\Model\Product $product) return $product; } + /** + * @return LinkResolver + */ + protected function getLinkResolver() + { + if (!is_object($this->linkResolver)) { + $this->linkResolver = ObjectManager::getInstance()->get(LinkResolver::class); + } + return $this->linkResolver; + } + /** * Setting product links * @@ -203,7 +221,7 @@ public function initialize(\Magento\Catalog\Model\Product $product) */ protected function setProductLinks(\Magento\Catalog\Model\Product $product) { - $links = (array)$this->request->getParam('links', []); + $links = $this->getLinkResolver()->getLinks(); $product->setProductLinks([]); diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Link/Resolver.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Link/Resolver.php new file mode 100644 index 0000000000000..e2891f33d6ccc --- /dev/null +++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Link/Resolver.php @@ -0,0 +1,50 @@ +request = $request; + } + + + /** + * Get stored value. + * Fallback to request if none. + * + * @return array|null + */ + public function getLinks() + { + if (null === $this->links) { + $this->links = (array)$this->request->getParam('links', []); + } + return $this->links; + } + + /** + * Override link data from request + * + * @param array|null $links + */ + public function override($links) + { + $this->links = $links; + } +} diff --git a/app/code/Magento/Catalog/Model/Product/Type/AbstractType.php b/app/code/Magento/Catalog/Model/Product/Type/AbstractType.php index 343e6c194be4f..c37fa14cdcc9c 100644 --- a/app/code/Magento/Catalog/Model/Product/Type/AbstractType.php +++ b/app/code/Magento/Catalog/Model/Product/Type/AbstractType.php @@ -1081,4 +1081,15 @@ public function getAssociatedProducts($product) { return []; } + + /** + * Reset cache of associated products + * + * @param \Magento\Catalog\Model\Product\Type\AbstractType $product + * @return void + */ + public function clearAssociatedProductsCache($product) + { + return; + } } diff --git a/app/code/Magento/Catalog/Model/ProductLink/Repository.php b/app/code/Magento/Catalog/Model/ProductLink/Repository.php index 41a0d01e1add2..b874adb39be5c 100644 --- a/app/code/Magento/Catalog/Model/ProductLink/Repository.php +++ b/app/code/Magento/Catalog/Model/ProductLink/Repository.php @@ -214,7 +214,7 @@ public function delete(\Magento\Catalog\Api\Data\ProductLinkInterface $entity) if (!$linkId) { throw new NoSuchEntityException( __( - 'Product with SKU %1 is not linked to product with SKU %2', + 'Product with SKU \'%1\' is not linked to product with SKU \'%2\'', $entity->getLinkedProductSku(), $entity->getSku() ) diff --git a/app/code/Magento/GroupedProduct/Model/Product/Type/Grouped.php b/app/code/Magento/GroupedProduct/Model/Product/Type/Grouped.php index 86a8743f63026..ef26f0072fb53 100644 --- a/app/code/Magento/GroupedProduct/Model/Product/Type/Grouped.php +++ b/app/code/Magento/GroupedProduct/Model/Product/Type/Grouped.php @@ -219,6 +219,14 @@ public function getAssociatedProducts($product) return $product->getData($this->_keyAssociatedProducts); } + /** + * {@inheritdoc} + */ + public function clearAssociatedProductsCache($product) + { + $product->unsetData($this->_keyAssociatedProducts); + } + /** * Add status filter to collection * From 8024119f0424fa792d2043db9cbfd520a3fee770 Mon Sep 17 00:00:00 2001 From: Stanislav Idolov Date: Thu, 17 Mar 2016 12:44:50 +0200 Subject: [PATCH 08/14] MAGETWO-50561: Item Level Gift Message can not be saved for guest #3804 --- .../frontend/web/js/action/gift-options.js | 37 +++++++++++------- .../view/frontend/web/js/model/url-builder.js | 39 ++++++------------- 2 files changed, 35 insertions(+), 41 deletions(-) diff --git a/app/code/Magento/GiftMessage/view/frontend/web/js/action/gift-options.js b/app/code/Magento/GiftMessage/view/frontend/web/js/action/gift-options.js index 29f9240dec25c..932d3970522d8 100644 --- a/app/code/Magento/GiftMessage/view/frontend/web/js/action/gift-options.js +++ b/app/code/Magento/GiftMessage/view/frontend/web/js/action/gift-options.js @@ -5,29 +5,40 @@ /*global define*/ define( [ - '../model/url-builder', + 'Magento_GiftMessage/js/model/url-builder', 'mage/storage', 'Magento_Ui/js/model/messageList', 'Magento_Checkout/js/model/error-processor', - 'mage/url' + 'mage/url', + 'Magento_Checkout/js/model/quote' ], - function(urlBuilder, storage, messageList, errorProcessor, url) { - "use strict"; - return function(giftMessage, remove) { - url.setBaseUrl(giftMessage.getConfigValue('baseUrl')); - var quoteId = giftMessage.getConfigValue('quoteId'); + function (urlBuilder, storage, messageList, errorProcessor, url, quote) { + 'use strict'; + + return function (giftMessage, remove) { var serviceUrl; + + url.setBaseUrl(giftMessage.getConfigValue('baseUrl')); + if (giftMessage.getConfigValue('isCustomerLoggedIn')) { serviceUrl = urlBuilder.createUrl('/carts/mine/gift-message', {}); + if (giftMessage.itemId != 'orderLevel') { - serviceUrl = urlBuilder.createUrl('/carts/mine/gift-message/:itemId', {itemId: giftMessage.itemId}); + serviceUrl = urlBuilder.createUrl('/carts/mine/gift-message/:itemId', { + itemId: giftMessage.itemId + }); } } else { - serviceUrl = urlBuilder.createUrl('/guest-carts/:cartId/gift-message', {cartId: quoteId}); + serviceUrl = urlBuilder.createUrl('/guest-carts/:cartId/gift-message', { + cartId: quote.getQuoteId() + }); + if (giftMessage.itemId != 'orderLevel') { serviceUrl = urlBuilder.createUrl( '/guest-carts/:cartId/gift-message/:itemId', - {cartId: quoteId, itemId: giftMessage.itemId} + { + cartId: quote.getQuoteId(), itemId: giftMessage.itemId + } ); } } @@ -39,16 +50,16 @@ define( gift_message: giftMessage.getSubmitParams(remove) }) ).done( - function(result) { + function (response) { giftMessage.reset(); - _.each(giftMessage.getAfterSubmitCallbacks(), function(callback) { + _.each(giftMessage.getAfterSubmitCallbacks(), function (callback) { if (_.isFunction(callback)) { callback(); } }); } ).fail( - function(response) { + function (response) { errorProcessor.process(response); } ); diff --git a/app/code/Magento/GiftMessage/view/frontend/web/js/model/url-builder.js b/app/code/Magento/GiftMessage/view/frontend/web/js/model/url-builder.js index ba62ba64f94d0..a40beadfbafae 100644 --- a/app/code/Magento/GiftMessage/view/frontend/web/js/model/url-builder.js +++ b/app/code/Magento/GiftMessage/view/frontend/web/js/model/url-builder.js @@ -3,36 +3,19 @@ * See COPYING.txt for license details. */ /*jshint browser:true jquery:true*/ -/*global alert*/ define( - ['jquery'], - function($) { - return { - method: "rest", - storeCode: window.giftOptionsConfig.storeCode, - version: 'V1', - serviceUrl: ':method/:storeCode/:version', + [ + 'jquery', + 'Magento_Checkout/js/model/url-builder' + ], + function ($, urlBuilder) { + 'use strict'; - createUrl: function(url, params) { - var completeUrl = this.serviceUrl + url; - return this.bindParams(completeUrl, params); - }, - bindParams: function(url, params) { - params.method = this.method; - params.storeCode = this.storeCode; - params.version = this.version; - - var urlParts = url.split("/"); - urlParts = urlParts.filter(Boolean); - - $.each(urlParts, function(key, part) { - part = part.replace(':', ''); - if (params[part] != undefined) { - urlParts[key] = params[part]; - } - }); - return urlParts.join('/'); + return $.extend( + urlBuilder, + { + storeCode: window.giftOptionsConfig.storeCode } - }; + ); } ); From f2e93eec5a6444f48207c997c6ae74e26d923dab Mon Sep 17 00:00:00 2001 From: Serhiy Shkolyarenko Date: Thu, 17 Mar 2016 15:05:46 +0200 Subject: [PATCH 09/14] MAGETWO-50370: There is no ability to "Save as a new update" for grouped product moved models --- .../Product/Initialization/Helper.php | 2 +- .../Catalog/Model/Product/Link/Converter.php | 49 +++++++++++++++++++ .../Product/Link/Resolver.php | 2 +- 3 files changed, 51 insertions(+), 2 deletions(-) create mode 100644 app/code/Magento/Catalog/Model/Product/Link/Converter.php rename app/code/Magento/Catalog/{Controller/Adminhtml => Model}/Product/Link/Resolver.php (93%) diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Initialization/Helper.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Initialization/Helper.php index 1f18da31a6f7a..56c2110ccaceb 100644 --- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Initialization/Helper.php +++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Initialization/Helper.php @@ -9,7 +9,7 @@ use Magento\Catalog\Api\Data\ProductLinkInterfaceFactory as ProductLinkFactory; use Magento\Catalog\Api\ProductRepositoryInterface\Proxy as ProductRepository; use Magento\Catalog\Model\Product\Initialization\Helper\ProductLinks; -use Magento\Catalog\Controller\Adminhtml\Product\Link\Resolver as LinkResolver; +use Magento\Catalog\Model\Product\Link\Resolver as LinkResolver; use Magento\Framework\App\ObjectManager; /** diff --git a/app/code/Magento/Catalog/Model/Product/Link/Converter.php b/app/code/Magento/Catalog/Model/Product/Link/Converter.php new file mode 100644 index 0000000000000..1e86d7f324181 --- /dev/null +++ b/app/code/Magento/Catalog/Model/Product/Link/Converter.php @@ -0,0 +1,49 @@ +getSku()] = $product; + } + return $converted; + } + + /** + * @param \Magento\Catalog\Model\Product $entity + * @return array + */ + public function convertLinksToGroupedArray($entity) + { + $basicData = $entity->getProductLinks(); + $additionalData = $entity->getTypeInstance()->getAssociatedProducts($entity); + $additionalData = $this->indexBySku($additionalData); + + /** @var \Magento\Catalog\Api\Data\ProductLinkInterface $link */ + foreach ($basicData as $link) { + $info = []; + $info['id'] = $additionalData[$link->getLinkedProductSku()]->getId(); + $info['sku'] = $link->getLinkedProductSku(); + $info['position'] = $link->getPosition(); + $info = array_merge($info, $link->getExtensionAttributes()->__toArray()); + $linksAsArray[$link->getLinkType()][] = $info; + } + return $linksAsArray; + } +} \ No newline at end of file diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Link/Resolver.php b/app/code/Magento/Catalog/Model/Product/Link/Resolver.php similarity index 93% rename from app/code/Magento/Catalog/Controller/Adminhtml/Product/Link/Resolver.php rename to app/code/Magento/Catalog/Model/Product/Link/Resolver.php index e2891f33d6ccc..ab5b01669265d 100644 --- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Link/Resolver.php +++ b/app/code/Magento/Catalog/Model/Product/Link/Resolver.php @@ -3,7 +3,7 @@ * Copyright © 2015 Magento. All rights reserved. * See COPYING.txt for license details. */ -namespace Magento\Catalog\Controller\Adminhtml\Product\Link; +namespace Magento\Catalog\Model\Product\Link; class Resolver { From c54ec9f039bf869afd969e8b0b714f15576d4832 Mon Sep 17 00:00:00 2001 From: Serhiy Shkolyarenko Date: Thu, 17 Mar 2016 17:01:51 +0200 Subject: [PATCH 10/14] MAGETWO-50370: There is no ability to "Save as a new update" for grouped product moved cache cleaning to resource model --- .../Adminhtml/Product/Initialization/Helper.php | 2 +- .../Catalog/Model/Product/Type/AbstractType.php | 11 ----------- .../GroupedProduct/Model/Product/Type/Grouped.php | 10 ++-------- 3 files changed, 3 insertions(+), 20 deletions(-) diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Initialization/Helper.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Initialization/Helper.php index 56c2110ccaceb..05156d7d7f00e 100644 --- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Initialization/Helper.php +++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Initialization/Helper.php @@ -204,7 +204,7 @@ public function initialize(\Magento\Catalog\Model\Product $product) /** * @return LinkResolver */ - protected function getLinkResolver() + private function getLinkResolver() { if (!is_object($this->linkResolver)) { $this->linkResolver = ObjectManager::getInstance()->get(LinkResolver::class); diff --git a/app/code/Magento/Catalog/Model/Product/Type/AbstractType.php b/app/code/Magento/Catalog/Model/Product/Type/AbstractType.php index c37fa14cdcc9c..343e6c194be4f 100644 --- a/app/code/Magento/Catalog/Model/Product/Type/AbstractType.php +++ b/app/code/Magento/Catalog/Model/Product/Type/AbstractType.php @@ -1081,15 +1081,4 @@ public function getAssociatedProducts($product) { return []; } - - /** - * Reset cache of associated products - * - * @param \Magento\Catalog\Model\Product\Type\AbstractType $product - * @return void - */ - public function clearAssociatedProductsCache($product) - { - return; - } } diff --git a/app/code/Magento/GroupedProduct/Model/Product/Type/Grouped.php b/app/code/Magento/GroupedProduct/Model/Product/Type/Grouped.php index ef26f0072fb53..79da4b5d17254 100644 --- a/app/code/Magento/GroupedProduct/Model/Product/Type/Grouped.php +++ b/app/code/Magento/GroupedProduct/Model/Product/Type/Grouped.php @@ -219,14 +219,6 @@ public function getAssociatedProducts($product) return $product->getData($this->_keyAssociatedProducts); } - /** - * {@inheritdoc} - */ - public function clearAssociatedProductsCache($product) - { - $product->unsetData($this->_keyAssociatedProducts); - } - /** * Add status filter to collection * @@ -472,6 +464,8 @@ public function deleteTypeSpecificData(\Magento\Catalog\Model\Product $product) */ public function beforeSave($product) { + //clear cached associated links + $product->unsetData($this->_keyAssociatedProducts); if ($product->hasData('product_options') && !empty($product->getData('product_options'))) { throw new \Exception('Custom options for grouped product type are not supported'); } From 95191b85232121c0fdcafc300abb9b1e4f2d8f64 Mon Sep 17 00:00:00 2001 From: Iryna Lagno Date: Fri, 18 Mar 2016 18:25:12 +0200 Subject: [PATCH 11/14] MAGETWO-50651: Pull request support --- app/code/Magento/Checkout/Test/Unit/CustomerData/CartTest.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Checkout/Test/Unit/CustomerData/CartTest.php b/app/code/Magento/Checkout/Test/Unit/CustomerData/CartTest.php index ffdd39cfde5d1..b13656dfae659 100644 --- a/app/code/Magento/Checkout/Test/Unit/CustomerData/CartTest.php +++ b/app/code/Magento/Checkout/Test/Unit/CustomerData/CartTest.php @@ -171,6 +171,9 @@ public function testGetSectionData() $this->assertEquals($expectedResult, $this->model->getSectionData()); } + /** + * @SuppressWarnings(PHPMD.ExcessiveMethodLength) + */ public function testGetSectionDataWithCompositeProduct() { $summaryQty = 100; @@ -211,7 +214,6 @@ public function testGetSectionDataWithCompositeProduct() ->willReturn($subtotalValue); $this->checkoutHelperMock->expects($this->once())->method('canOnepageCheckout')->willReturn(true); - $quoteMock->expects($this->once())->method('getAllVisibleItems')->willReturn([$quoteItemMock]); $productMock = $this->getMock( From 31a5f2eeb2baa5c45d7f9e6403fc42cba064c6d8 Mon Sep 17 00:00:00 2001 From: Serhiy Shkolyarenko Date: Sat, 19 Mar 2016 20:10:07 +0200 Subject: [PATCH 12/14] MAGETWO-50370: There is no ability to "Save as a new update" for grouped product fixed to be updated with mainline --- .../Product/Initialization/Helper.php | 1 + .../Catalog/Model/Product/Link/Converter.php | 14 ++++++++------ .../Product/Initialization/HelperTest.php | 18 ++++++++++++++---- .../Unit/Model/ProductLink/RepositoryTest.php | 2 +- 4 files changed, 24 insertions(+), 11 deletions(-) diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Initialization/Helper.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Initialization/Helper.php index 05156d7d7f00e..d69d59aea10e3 100644 --- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Initialization/Helper.php +++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Initialization/Helper.php @@ -202,6 +202,7 @@ public function initialize(\Magento\Catalog\Model\Product $product) } /** + * @deprecated * @return LinkResolver */ private function getLinkResolver() diff --git a/app/code/Magento/Catalog/Model/Product/Link/Converter.php b/app/code/Magento/Catalog/Model/Product/Link/Converter.php index 1e86d7f324181..b14fe1bcea2d7 100644 --- a/app/code/Magento/Catalog/Model/Product/Link/Converter.php +++ b/app/code/Magento/Catalog/Model/Product/Link/Converter.php @@ -32,15 +32,17 @@ protected function indexBySku(array $products) public function convertLinksToGroupedArray($entity) { $basicData = $entity->getProductLinks(); - $additionalData = $entity->getTypeInstance()->getAssociatedProducts($entity); - $additionalData = $this->indexBySku($additionalData); + $associatedProducts = $entity->getTypeInstance()->getAssociatedProducts($entity); + $associatedProducts = $this->indexBySku($associatedProducts); /** @var \Magento\Catalog\Api\Data\ProductLinkInterface $link */ foreach ($basicData as $link) { - $info = []; - $info['id'] = $additionalData[$link->getLinkedProductSku()]->getId(); - $info['sku'] = $link->getLinkedProductSku(); - $info['position'] = $link->getPosition(); + $info = $link->getData(); + if ($link->getLinkType() == 'associated') { + $info['id'] = $associatedProducts[$link->getLinkedProductSku()]->getId(); + } +// $info['sku'] = $link->getLinkedProductSku(); +// $info['position'] = $link->getPosition(); $info = array_merge($info, $link->getExtensionAttributes()->__toArray()); $linksAsArray[$link->getLinkType()][] = $info; } diff --git a/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Initialization/HelperTest.php b/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Initialization/HelperTest.php index e6937fd19ec0d..406557fca88ae 100644 --- a/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Initialization/HelperTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Controller/Adminhtml/Product/Initialization/HelperTest.php @@ -96,6 +96,11 @@ class HelperTest extends \PHPUnit_Framework_TestCase */ protected $customOptionMock; + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $linkResolverMock; + /** * @var ProductLinks */ @@ -175,6 +180,14 @@ protected function setUp() 'productLinkFactory' => $this->productLinkFactoryMock, 'productRepository' => $this->productRepositoryMock, ]); + + $this->linkResolverMock = $this->getMockBuilder(\Magento\Catalog\Model\Product\Link\Resolver::class) + ->disableOriginalConstructor() + ->getMock(); + $helperReflection = new \ReflectionClass(get_class($this->helper)); + $resolverProperty = $helperReflection->getProperty('linkResolver'); + $resolverProperty->setAccessible(true); + $resolverProperty->setValue($this->helper, $this->linkResolverMock); } /** @@ -248,10 +261,7 @@ public function testInitialize() ->method('getPost') ->with('use_default') ->willReturn($useDefaults); - $this->requestMock->expects($this->at(3)) - ->method('getPost') - ->with('options_use_default') - ->willReturn(true); + $this->linkResolverMock->expects($this->once())->method('getLinks')->willReturn([]); $this->stockFilterMock->expects($this->once()) ->method('filter') ->with(['stock_data']) diff --git a/app/code/Magento/Catalog/Test/Unit/Model/ProductLink/RepositoryTest.php b/app/code/Magento/Catalog/Test/Unit/Model/ProductLink/RepositoryTest.php index c4b773d53f08f..4ba0960fc21b3 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/ProductLink/RepositoryTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/ProductLink/RepositoryTest.php @@ -272,7 +272,7 @@ public function testDeleteWithInvalidDataException() /** * @expectedException \Magento\Framework\Exception\NoSuchEntityException - * @expectedExceptionMessage Product with SKU linkedProduct is not linked to product with SKU product + * @expectedExceptionMessage Product with SKU 'linkedProduct' is not linked to product with SKU 'product' */ public function testDeleteWithNoSuchEntityException() { From f7dde9f63b2d2956c63c5fd5d72809d1239c66a6 Mon Sep 17 00:00:00 2001 From: Serhiy Shkolyarenko Date: Sat, 19 Mar 2016 20:33:35 +0200 Subject: [PATCH 13/14] MAGETWO-50370: There is no ability to "Save as a new update" for grouped product --- app/code/Magento/Catalog/Model/Product/Link/Converter.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/code/Magento/Catalog/Model/Product/Link/Converter.php b/app/code/Magento/Catalog/Model/Product/Link/Converter.php index b14fe1bcea2d7..96c1afccad6a3 100644 --- a/app/code/Magento/Catalog/Model/Product/Link/Converter.php +++ b/app/code/Magento/Catalog/Model/Product/Link/Converter.php @@ -41,8 +41,6 @@ public function convertLinksToGroupedArray($entity) if ($link->getLinkType() == 'associated') { $info['id'] = $associatedProducts[$link->getLinkedProductSku()]->getId(); } -// $info['sku'] = $link->getLinkedProductSku(); -// $info['position'] = $link->getPosition(); $info = array_merge($info, $link->getExtensionAttributes()->__toArray()); $linksAsArray[$link->getLinkType()][] = $info; } From 41fedfe7fae1559d51a54adfc150f53aa0966b17 Mon Sep 17 00:00:00 2001 From: Serhiy Shkolyarenko Date: Sun, 20 Mar 2016 11:16:54 +0200 Subject: [PATCH 14/14] MAGETWO-50370: There is no ability to "Save as a new update" for grouped product test fixes --- app/code/Magento/Catalog/Model/Product/Link/Converter.php | 2 +- app/code/Magento/Catalog/Model/Product/Link/Resolver.php | 2 +- .../backend/Magento_GiftRegistry/web/css/source/_module.less | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Catalog/Model/Product/Link/Converter.php b/app/code/Magento/Catalog/Model/Product/Link/Converter.php index 96c1afccad6a3..7fa80daeb92db 100644 --- a/app/code/Magento/Catalog/Model/Product/Link/Converter.php +++ b/app/code/Magento/Catalog/Model/Product/Link/Converter.php @@ -1,6 +1,6 @@