-
Notifications
You must be signed in to change notification settings - Fork 22
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: Add subscription functionality on grouped products.
Refs: #207
- Loading branch information
1 parent
5b035ef
commit 5f31561
Showing
9 changed files
with
471 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Swarming\SubscribePro\Block\Product; | ||
|
||
use Magento\Framework\Exception\NoSuchEntityException; | ||
use SubscribePro\Exception\HttpException; | ||
use SubscribePro\Exception\InvalidArgumentException; | ||
use SubscribePro\Service\Product\ProductInterface as ProductInterfaceAlias; | ||
use Swarming\SubscribePro\Helper\Product; | ||
|
||
class Grouped extends Subscription | ||
{ | ||
private $helper; | ||
public function __construct( | ||
\Magento\Catalog\Block\Product\Context $context, | ||
\Swarming\SubscribePro\Model\Config\SubscriptionDiscount $subscriptionDiscountConfig, | ||
\Swarming\SubscribePro\Platform\Manager\Product $platformProductManager, | ||
\Magento\Tax\Api\TaxCalculationInterface $taxCalculation, | ||
\Swarming\SubscribePro\Ui\ConfigProvider\PriceConfig $priceConfigProvider, | ||
\Magento\Framework\Pricing\PriceCurrencyInterface $priceCurrency, | ||
\Swarming\SubscribePro\Helper\Product $productHelper, | ||
\Magento\Checkout\Model\Cart $cart, | ||
\Swarming\SubscribePro\Helper\QuoteItem $quoteItemHelper, | ||
\Psr\Log\LoggerInterface $logger, | ||
Product $helper, | ||
array $data = [] | ||
) { | ||
$this->helper = $helper; | ||
parent::__construct( | ||
$context, | ||
$subscriptionDiscountConfig, | ||
$platformProductManager, | ||
$taxCalculation, | ||
$priceConfigProvider, | ||
$priceCurrency, | ||
$productHelper, | ||
$cart, | ||
$quoteItemHelper, | ||
$logger, | ||
$data | ||
); | ||
} | ||
|
||
/** | ||
* @return void | ||
* @throws NoSuchEntityException | ||
*/ | ||
protected function initJsLayout(): void | ||
{ | ||
try { | ||
$platformProduct = $this->getPlatformProduct()->toArray(); | ||
} catch (InvalidArgumentException|HttpException $e) { | ||
$this->logger->debug('Could not load product from Subscribe Pro platform.'); | ||
$this->logger->info($e->getMessage()); | ||
$platformProduct = []; | ||
} | ||
|
||
$data = [ | ||
'components' => [ | ||
'subscription-container-' . $this->getProduct()->getId() => [ | ||
'component' => 'Swarming_SubscribePro/js/view/product/grouped-subscription', | ||
'config' => [ | ||
'oneTimePurchaseOption' => ProductInterfaceAlias::SO_ONETIME_PURCHASE, | ||
'subscriptionOption' => ProductInterfaceAlias::SO_SUBSCRIPTION, | ||
'subscriptionOnlyMode' => ProductInterfaceAlias::SOM_SUBSCRIPTION_ONLY, | ||
'subscriptionAndOneTimePurchaseMode' => ProductInterfaceAlias::SOM_SUBSCRIPTION_AND_ONETIME_PURCHASE, | ||
'product' => $platformProduct, | ||
'product_id' => $this->getProduct()->getId(), | ||
'priceConfig' => $this->priceConfigProvider->getConfig(), | ||
'template' => 'Swarming_SubscribePro/product/grouped-subscription', | ||
'priceBoxSelector' => '.price-box', | ||
'messages' => [ | ||
'component' => 'Magento_Ui/js/view/messages', | ||
'displayArea' => 'messages', | ||
], | ||
] | ||
] | ||
] | ||
]; | ||
|
||
$jsLayout = array_replace_recursive($this->jsLayout, $data); | ||
if ($this->isPriceHidden()) { | ||
$class = 'Swarming_SubscribePro/js/view/product/subscription-msrp'; | ||
$jsLayout['components']['subscription-container-' . $this->getProduct()->getId()]['component'] = $class; | ||
$jsLayout['components']['subscription-container-' . $this->getProduct()->getId()]['config']['msrpPrice'] = $this->getMsrpPrice(); | ||
} | ||
|
||
$this->jsLayout = $jsLayout; | ||
} | ||
|
||
/** | ||
* @param $item | ||
* @return bool | ||
*/ | ||
public function isSubscriptionEnabled($item): bool | ||
{ | ||
return $this->helper->isSubscriptionEnabled($item); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,85 @@ | ||
<?php | ||
|
||
declare(strict_types=1); | ||
|
||
namespace Swarming\SubscribePro\Model\Product\Type; | ||
|
||
use Magento\Framework\DataObject; | ||
use Magento\Framework\Phrase; | ||
|
||
class Grouped extends \Magento\GroupedProduct\Model\Product\Type\Grouped | ||
{ | ||
/** | ||
* @param DataObject $buyRequest | ||
* @param $product | ||
* @param $processMode | ||
* @return Phrase|array|string | ||
*/ | ||
protected function _prepareProduct(DataObject $buyRequest, $product, $processMode): Phrase|array|string | ||
{ | ||
$products = []; | ||
$associatedProductsInfo = []; | ||
$isStrictProcessMode = $this->_isStrictProcessMode($processMode); | ||
$subscriptionConfig = $buyRequest->getData('subscription_option'); | ||
$productsInfo = $this->getProductInfo($buyRequest, $product, $isStrictProcessMode); | ||
if (is_string($productsInfo)) { | ||
return $productsInfo; | ||
} | ||
$associatedProducts = !$isStrictProcessMode || !empty($productsInfo) | ||
? $this->getAssociatedProducts($product) | ||
: false; | ||
|
||
foreach ($associatedProducts as $subProduct) { | ||
$qty = $productsInfo[$subProduct->getId()]; | ||
if (!is_numeric($qty) || empty($qty)) { | ||
continue; | ||
} | ||
|
||
$_result = $subProduct->getTypeInstance()->_prepareProduct($buyRequest, $subProduct, $processMode); | ||
|
||
if (is_string($_result)) { | ||
return $_result; | ||
} elseif (!isset($_result[0])) { | ||
return __('Cannot process the item.')->render(); | ||
} | ||
|
||
if ($isStrictProcessMode) { | ||
$subscription = []; | ||
if (isset($subscriptionConfig[$subProduct->getId()])) { | ||
$subscription = $subscriptionConfig[$subProduct->getId()]; | ||
} | ||
$_result[0]->setCartQty($qty); | ||
$_result[0]->addCustomOption('product_type', self::TYPE_CODE, $product); | ||
$_result[0]->addCustomOption( | ||
'info_buyRequest', | ||
$this->serializer->serialize( | ||
[ | ||
'super_product_config' => [ | ||
'product_type' => self::TYPE_CODE, | ||
'product_id' => $product->getId(), | ||
], | ||
'subscription_option' => $subscription | ||
] | ||
) | ||
); | ||
$products[] = $_result[0]; | ||
} else { | ||
$associatedProductsInfo[] = [$subProduct->getId() => $qty]; | ||
$product->addCustomOption('associated_product_' . $subProduct->getId(), $qty); | ||
} | ||
} | ||
|
||
if (!$isStrictProcessMode || count($associatedProductsInfo)) { | ||
$product->addCustomOption('product_type', self::TYPE_CODE, $product); | ||
$product->addCustomOption('info_buyRequest', $this->serializer->serialize($buyRequest->getData())); | ||
|
||
$products[] = $product; | ||
} | ||
|
||
if (count($products)) { | ||
return $products; | ||
} | ||
|
||
return __('Please specify the quantity of product(s).')->render(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
<?php | ||
namespace Swarming\SubscribePro\ViewModel; | ||
|
||
use Magento\Framework\View\Element\Block\ArgumentInterface; | ||
use Swarming\SubscribePro\Helper\Product; | ||
|
||
class Grouped implements ArgumentInterface | ||
{ | ||
/** | ||
* @var Product | ||
*/ | ||
private Product $helper; | ||
|
||
/** | ||
* @param Product $helper | ||
*/ | ||
public function __construct( | ||
Product $helper | ||
) { | ||
$this->helper = $helper; | ||
} | ||
|
||
/** | ||
* @param $item | ||
* @return bool | ||
*/ | ||
public function isSubscriptionEnabled($item): bool | ||
{ | ||
return $this->helper->isSubscriptionEnabled($item); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
12 changes: 12 additions & 0 deletions
12
view/frontend/layout/catalog_product_view_type_grouped.xml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
<?xml version="1.0"?> | ||
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd"> | ||
<body> | ||
<referenceBlock name="product.info.grouped" template="Swarming_SubscribePro::product/view/type/grouped.phtml"> | ||
<arguments> | ||
<argument name="view_model" xsi:type="object">Swarming\SubscribePro\ViewModel\Grouped</argument> | ||
</arguments> | ||
<block class="Swarming\SubscribePro\Block\Product\Grouped" name="product.info.subscription.options.grouped" as="product_info_subscription_options_grouped" template="Swarming_SubscribePro::product/grouped-subscription.phtml"> | ||
</block> | ||
</referenceBlock> | ||
</body> | ||
</page> |
20 changes: 20 additions & 0 deletions
20
view/frontend/templates/product/grouped-subscription.phtml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
<?php | ||
/** | ||
* @var $block \Swarming\SubscribePro\Block\Product\Grouped | ||
*/ | ||
|
||
?> | ||
|
||
<div class="subscription-container" data-bind="scope: 'subscription-container-<?= (int)$block->getProduct()->getId() ?>'"> | ||
<!-- ko template: getTemplate() --><!-- /ko --> | ||
</div> | ||
|
||
<script type="text/x-magento-init"> | ||
{ | ||
"*": { | ||
"Magento_Ui/js/core/app": <?= $block->getJsLayout() ?> | ||
} | ||
} | ||
</script> | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
<?php | ||
/** | ||
* Grouped product data template | ||
* | ||
* @var $block \Magento\Catalog\Block\Product\View\BaseImage | ||
* @var $block \Swarming\SubscribePro\Model\Product\Type\Grouped | ||
* @var \Swarming\SubscribePro\ViewModel\Grouped $viewModel | ||
*/ | ||
?> | ||
<?php $viewModel = $block->getData('view_model'); ?> | ||
<?php $block->setPreconfiguredValue(); ?> | ||
<?php $_product = $block->getProduct(); ?> | ||
<?php $_associatedProducts = $block->getAssociatedProducts($_product); ?> | ||
<?php $_hasAssociatedProducts = count($_associatedProducts) > 0; ?> | ||
|
||
<div class="table-wrapper grouped"> | ||
<table class="table data grouped" | ||
id="super-product-table" | ||
data-mage-init='{ "Magento_GroupedProduct/js/product-ids-resolver": {} }'> | ||
<caption class="table-caption"><?= $block->escapeHtml(__('Grouped product items')) ?></caption> | ||
<thead> | ||
<tr> | ||
<th class="col item" scope="col"><?= $block->escapeHtml(__('Product Name')) ?></th> | ||
<?php if ($_product->isSaleable()) : ?> | ||
<th class="col qty" scope="col"><?= $block->escapeHtml(__('Qty')) ?></th> | ||
<?php endif; ?> | ||
</tr> | ||
</thead> | ||
|
||
<?php if ($_hasAssociatedProducts) : ?> | ||
<tbody> | ||
<?php foreach ($_associatedProducts as $_item) : ?> | ||
<tr> | ||
<td data-th="<?= $block->escapeHtml(__('Product Name')) ?>" class="col item"> | ||
<strong class="product-item-name"><?= $block->escapeHtml($_item->getName()) ?></strong> | ||
<?php if ($block->getCanShowProductPrice($_product)) : ?> | ||
<?php if ($block->getCanShowProductPrice($_item)) : ?> | ||
<?= /* @noEscape */ $block->getProductPrice($_item) ?> | ||
<?php endif; ?> | ||
<?php endif; ?> | ||
<?php if ($viewModel->isSubscriptionEnabled($_item)): ?> | ||
<div data-id="<?= $_item->getId()?>"> | ||
<?php echo $block->getChildBlock('product_info_subscription_options_grouped')->setProduct($_item)->toHtml()?> | ||
</div> | ||
<?php endif; ?> | ||
</td> | ||
|
||
<?php if ($_product->isSaleable()) : ?> | ||
<td data-th="<?= $block->escapeHtml(__('Qty')) ?>" class="col qty"> | ||
<?php if ($_item->isSaleable()) : ?> | ||
<div class="control qty"> | ||
<input type="number" | ||
name="super_group[<?= $block->escapeHtmlAttr($_item->getId()) ?>]" | ||
data-selector="super_group[<?= $block->escapeHtmlAttr($_item->getId()) ?>]" | ||
value="<?= $block->escapeHtmlAttr($_item->getQty() * 1) ?>" | ||
title="<?= $block->escapeHtmlAttr(__('Qty')) ?>" | ||
class="input-text qty" | ||
data-validate="{'validate-grouped-qty':'#super-product-table'}" | ||
data-errors-message-box="#validation-message-box"/> | ||
</div> | ||
<?php else : ?> | ||
<div class="stock unavailable" title="<?= $block->escapeHtmlAttr(__('Availability')) ?>"> | ||
<span><?= $block->escapeHtml(__('Out of stock')) ?></span> | ||
</div> | ||
<?php endif; ?> | ||
</td> | ||
<?php endif; ?> | ||
</tr> | ||
<?php if ($block->getCanShowProductPrice($_product) | ||
&& $block->getCanShowProductPrice($_item) | ||
&& trim($block->getProductPriceHtml( | ||
$_item, | ||
\Magento\Catalog\Pricing\Price\TierPrice::PRICE_CODE | ||
))) : ?> | ||
<tr class="row-tier-price"> | ||
<td colspan="2"> | ||
<?= $block->getProductPriceHtml( | ||
$_item, | ||
\Magento\Catalog\Pricing\Price\TierPrice::PRICE_CODE | ||
) ?> | ||
</td> | ||
</tr> | ||
<?php endif; ?> | ||
<?php endforeach; ?> | ||
</tbody> | ||
<?php else : ?> | ||
<tbody> | ||
<tr> | ||
<td class="unavailable" | ||
colspan="<?php if ($_product->isSaleable()) : ?>4<?php else : ?>3<?php endif; ?>"> | ||
<?= $block->escapeHtml(__('No options of this product are available.')) ?> | ||
</td> | ||
</tr> | ||
</tbody> | ||
<?php endif; ?> | ||
</table> | ||
</div> | ||
<div id="validation-message-box"></div> |
Oops, something went wrong.