Skip to content

Commit

Permalink
Merge pull request #427 from magento-folks/grouped_product
Browse files Browse the repository at this point in the history
[Folks] Grouped product + bugs
  • Loading branch information
irenelagno committed Mar 21, 2016
2 parents e7bc266 + 7117256 commit b3a13b8
Show file tree
Hide file tree
Showing 16 changed files with 384 additions and 69 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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\Model\Product\Link\Resolver as LinkResolver;
use Magento\Framework\App\ObjectManager;

/**
* Class Helper
Expand Down Expand Up @@ -56,6 +58,11 @@ class Helper
*/
protected $productLinks;

/**
* @var LinkResolver
*/
private $linkResolver;

/**
* @param \Magento\Framework\App\RequestInterface $request
* @param \Magento\Store\Model\StoreManagerInterface $storeManager
Expand Down Expand Up @@ -194,6 +201,18 @@ public function initialize(\Magento\Catalog\Model\Product $product)
return $product;
}

/**
* @deprecated
* @return LinkResolver
*/
private function getLinkResolver()
{
if (!is_object($this->linkResolver)) {
$this->linkResolver = ObjectManager::getInstance()->get(LinkResolver::class);
}
return $this->linkResolver;
}

/**
* Setting product links
*
Expand All @@ -203,7 +222,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([]);

Expand Down
49 changes: 49 additions & 0 deletions app/code/Magento/Catalog/Model/Product/Link/Converter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?php
/**
* Copyright © 2016 Magento. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\Catalog\Model\Product\Link;

/**
* Class Converter
*/
class Converter
{
/**
* Convert product links info to array indexed by sku
*
* @param \Magento\Catalog\Model\Product[] $products
* @return array
*/
protected function indexBySku(array $products)
{
$converted = [];
foreach($products as $product) {
$converted[$product->getSku()] = $product;
}
return $converted;
}

/**
* @param \Magento\Catalog\Model\Product $entity
* @return array
*/
public function convertLinksToGroupedArray($entity)
{
$basicData = $entity->getProductLinks();
$associatedProducts = $entity->getTypeInstance()->getAssociatedProducts($entity);
$associatedProducts = $this->indexBySku($associatedProducts);

/** @var \Magento\Catalog\Api\Data\ProductLinkInterface $link */
foreach ($basicData as $link) {
$info = $link->getData();
if ($link->getLinkType() == 'associated') {
$info['id'] = $associatedProducts[$link->getLinkedProductSku()]->getId();
}
$info = array_merge($info, $link->getExtensionAttributes()->__toArray());
$linksAsArray[$link->getLinkType()][] = $info;
}
return $linksAsArray;
}
}
50 changes: 50 additions & 0 deletions app/code/Magento/Catalog/Model/Product/Link/Resolver.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<?php
/**
* Copyright © 2016 Magento. All rights reserved.
* See COPYING.txt for license details.
*/
namespace Magento\Catalog\Model\Product\Link;

class Resolver
{
/**
* @var \Magento\Framework\App\RequestInterface
*/
protected $request;

/**
* @var null|array
*/
protected $links = null;

public function __construct(
\Magento\Framework\App\RequestInterface $request
) {
$this->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;
}
}
2 changes: 1 addition & 1 deletion app/code/Magento/Catalog/Model/ProductLink/Repository.php
Original file line number Diff line number Diff line change
Expand Up @@ -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()
)
Expand Down
2 changes: 2 additions & 0 deletions app/code/Magento/Catalog/Model/ProductRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -544,6 +544,8 @@ public function delete(\Magento\Catalog\Api\Data\ProductInterface $product)
unset($this->instances[$product->getSku()]);
unset($this->instancesById[$product->getId()]);
$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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,11 @@ class HelperTest extends \PHPUnit_Framework_TestCase
*/
protected $customOptionMock;

/**
* @var \PHPUnit_Framework_MockObject_MockObject
*/
protected $linkResolverMock;

/**
* @var ProductLinks
*/
Expand Down Expand Up @@ -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);
}

/**
Expand Down Expand Up @@ -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'])
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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()
{
Expand Down
11 changes: 7 additions & 4 deletions app/code/Magento/Checkout/CustomerData/Cart.php
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
107 changes: 106 additions & 1 deletion app/code/Magento/Checkout/Test/Unit/CustomerData/CartTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -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]))
Expand Down Expand Up @@ -170,4 +170,109 @@ public function testGetSectionData()
];
$this->assertEquals($expectedResult, $this->model->getSectionData());
}

/**
* @SuppressWarnings(PHPMD.ExcessiveMethodLength)
*/
public function testGetSectionDataWithCompositeProduct()
{
$summaryQty = 100;
$subtotalValue = 200;
$productId = 10;
$storeId = 20;

$productRewrite = [$productId => ['rewrite' => 'product']];
$itemData = ['item' => 'data'];
$shortcutButtonsHtml = '<span>Buttons</span>';
$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' => '<span>Buttons</span>',
'isGuestCheckoutAllowed' => 1
];
$this->assertEquals($expectedResult, $this->model->getSectionData());
}
}
Loading

0 comments on commit b3a13b8

Please sign in to comment.