Skip to content

Commit

Permalink
Q1-657: Display the PayPal Checkout button in the PDP and in search r…
Browse files Browse the repository at this point in the history
…esults. (#6)

* Q1-657: Display the PayPal Checkout button in the PDP and in search results.

* Make PayPal Checkout button in the PDP configurable

* Make PayPal Checkout button in the PDP configurable

* Make PayPal Checkout button in the PDP configurable
  • Loading branch information
p-bystritsky authored Dec 8, 2023
1 parent ac3c8f0 commit 57c7836
Show file tree
Hide file tree
Showing 16 changed files with 539 additions and 9 deletions.
71 changes: 71 additions & 0 deletions Block/System/Config/Form/Field/Status.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<?php

declare(strict_types=1);

namespace Bold\CheckoutFlowPaypal\Block\System\Config\Form\Field;

use Bold\Checkout\Block\System\Config\Form\Field;
use Bold\CheckoutFlowPaypal\Model\Config as PayPalConfig;
use Magento\Backend\Block\Template\Context;
use Magento\Config\Model\Config;
use Magento\Framework\Data\Form\Element\AbstractElement;
use Magento\Store\Model\StoreManagerInterface;

/**
* Bold PayPal Flow status field.
*/
class Status extends Field
{
protected $unsetScope = true;

/**
* @var Config
*/
private $config;

/**
* @var PayPalConfig
*/
private $payPalConfig;

/**
* @var StoreManagerInterface
*/
private $storeManager;

/**
* @param Context $context
* @param Config $config
* @param PayPalConfig $payPalConfig
* @param StoreManagerInterface $storeManager
* @param array $data
*/
public function __construct(
Context $context,
Config $config,
PayPalConfig $payPalConfig,
StoreManagerInterface $storeManager,
array $data = []
) {
parent::__construct($context, $data);
$this->config = $config;
$this->payPalConfig = $payPalConfig;
$this->storeManager = $storeManager;
}

/**
* @inheritDoc
*/
protected function _renderValue(AbstractElement $element)
{
$websiteId = (int)$this->config->getWebsite() ?: (int)$this->storeManager->getWebsite(true)->getId();
$status = $this->payPalConfig->getIsPaypalFlowEnabled($websiteId);
$statusText = $status ? __('PayPal Checkout Flow is enabled') : __('PayPal Checkout Flow is disabled');
$class = $status ? 'enabled' : 'disabled';
$element->setText(
sprintf('<strong class=\'%s\'>%s</strong>', $class, $statusText)
);

return parent::_renderValue($element);
}
}
2 changes: 1 addition & 1 deletion Block/System/Config/Form/Field/Toggle.php
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ public function getButtonHtml()
*/
private function getLabel(): string
{
return $this->isEnabled() ? 'Disable' : 'Enable';
return $this->isEnabled() ? 'Disable PayPal Checkout Flow' : 'Enable PayPal Checkout Flow';
}

/**
Expand Down
48 changes: 44 additions & 4 deletions Model/Config.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ class Config
{
private const PATH_TYPE = 'checkout/bold_checkout_base/type';
private const PATH_IS_PAYPAL_FLOW_ENABLED = 'checkout/bold_checkout_paypal/is_enabled';
private const PATH_IS_INSTANT_ON_PRODUCT_PAGE_ENABLED = 'checkout/bold_checkout_paypal/is_instant_product';
private const PATH_IS_INSTANT_ENABLED_FOR = 'checkout/bold_checkout_paypal/instant_for';
private const PATH_PAYPAL_FLOW_ID = 'checkout/bold_checkout_paypal/flow_id';

/**
Expand Down Expand Up @@ -47,10 +49,10 @@ class Config
* @param TypeListInterface $cacheTypeList
*/
public function __construct(
ScopeConfigInterface $scopeConfig,
ScopeConfigInterface $scopeConfig,
ConfigManagementInterface $configManagement,
WriterInterface $configWriter,
TypeListInterface $cacheTypeList
WriterInterface $configWriter,
TypeListInterface $cacheTypeList
) {
$this->scopeConfig = $scopeConfig;
$this->configManagement = $configManagement;
Expand All @@ -65,7 +67,8 @@ public function __construct(
* @return bool
* @throws LocalizedException
*/
public function getIsPaypalFlowEnabled(int $websiteId): bool {
public function getIsPaypalFlowEnabled(int $websiteId): bool
{
return $this->configManagement->isSetFlag(
self::PATH_IS_PAYPAL_FLOW_ENABLED,
$websiteId
Expand Down Expand Up @@ -123,4 +126,41 @@ public function setCheckoutTypeParallel(int $websiteId): void
$this->cacheTypeList->cleanType('config');
$this->scopeConfig->clean();
}

/**
* Get if the Instant Checkout button is enabled on Product page.
*
* @param int $websiteId
* @return bool
* @throws LocalizedException
*/
public function isProductPageInstantCheckoutEnabled(int $websiteId): bool
{
return $this->configManagement->isSetFlag(
self::PATH_IS_INSTANT_ON_PRODUCT_PAGE_ENABLED,
$websiteId
);
}

/**
* Get if the Instant Checkout button is enabled for Product type.
*
* @param int $websiteId
* @param string $productType
* @return bool
* @throws LocalizedException
*/
public function isProductPageInstantCheckoutEnabledForType(int $websiteId, string $productType): bool
{
return in_array(
$productType,
explode(
',',
$this->configManagement->getValue(
self::PATH_IS_INSTANT_ENABLED_FOR,
$websiteId
)
)
);
}
}
46 changes: 46 additions & 0 deletions Model/Config/Backend/InvalidateBlockBackend.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?php

declare(strict_types=1);

namespace Bold\CheckoutFlowPaypal\Model\Config\Backend;

use Magento\Config\Model\ResourceModel\Config\Data;
use Magento\Config\Model\ResourceModel\Config\Data\Collection\Proxy;
use Magento\Framework\App\Cache\Type\Block;
use Magento\Framework\App\Cache\TypeListInterface;
use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Framework\App\Config\Value;
use Magento\Framework\Model\Context;
use Magento\Framework\Registry;
use Magento\PageCache\Model\Cache\Type;

/**
* Backend model for cache invalidation after PayPal configuration change.
*/
class InvalidateBlockBackend extends Value
{
public function __construct(
Context $context,
Registry $registry,
ScopeConfigInterface $config,
TypeListInterface $cacheTypeList,
Data $resource,
Proxy $resourceCollection,
array $data = []
) {
parent::__construct($context, $registry, $config, $cacheTypeList, $resource, $resourceCollection, $data);
}

/**
* @inheritDoc
*/
public function afterSave()
{
if ($this->isValueChanged()) {
$this->cacheTypeList->invalidate(Block::TYPE_IDENTIFIER);
$this->cacheTypeList->invalidate(Type::TYPE_IDENTIFIER);
}

return parent::afterSave();
}
}
54 changes: 54 additions & 0 deletions Model/Config/Source/ProductTypeSource.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<?php

declare(strict_types=1);

namespace Bold\CheckoutFlowPaypal\Model\Config\Source;

use Magento\Bundle\Model\Product\Type as BundleType;
use Magento\Catalog\Model\Product\Type;
use Magento\ConfigurableProduct\Model\Product\Type\Configurable as ConfigurableType;
use Magento\Downloadable\Model\Product\Type as DownloadableType;
use Magento\GiftCard\Model\Catalog\Product\Type\Giftcard as GiftcardType;
use Magento\GroupedProduct\Model\Product\Type\Grouped as GroupedType;

/**
* Field source for product type multiselect.
*/
class ProductTypeSource implements \Magento\Framework\Option\ArrayInterface
{
/**
* @var array
*/
private $additionalProductTypes;

/**
* @param array $additionalProductTypes
*/
public function __construct(array $additionalProductTypes = [])
{
$this->additionalProductTypes = $additionalProductTypes;
}

/**
* @inheritDoc
*/
public function toOptionArray()
{
$result = [
['value' => Type::TYPE_SIMPLE, 'label' => __('Simple Products')],
['value' => Type::TYPE_VIRTUAL, 'label' => __('Virtual Products')],
['value' => DownloadableType::TYPE_DOWNLOADABLE, 'label' => __('Downloadable Products')],
['value' => GroupedType::TYPE_CODE, 'label' => __('Grouped Products')],
['value' => ConfigurableType::TYPE_CODE, 'label' => __('Configurable Products')],
['value' => BundleType::TYPE_CODE, 'label' => __('Bundle Products')],
];
if (class_exists(GiftcardType::class)) {
$result[] = ['value' => GiftcardType::TYPE_GIFTCARD, 'label' => __('Gift Cards')];
}
foreach ($this->additionalProductTypes as $typeValue => $typeLabel) {
$result[] = ['value' => $typeValue, 'label' => __($typeLabel)];
}

return $result;
}
}
129 changes: 129 additions & 0 deletions ViewModel/Instant.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
<?php

declare(strict_types=1);

namespace Bold\CheckoutFlowPaypal\ViewModel;

use Bold\Checkout\Block\Onepage\Button;
use Bold\CheckoutFlowPaypal\Model\Config;
use Magento\Catalog\Block\Product\View;
use Magento\Framework\App\RequestInterface;
use Magento\Framework\Exception\LocalizedException;
use Magento\Framework\UrlInterface;
use Magento\Framework\View\Asset\Repository;
use Magento\Framework\View\Element\Block\ArgumentInterface;
use Magento\Store\Model\StoreManagerInterface;

/**
* View Model for Instant Checkout button.
*/
class Instant implements ArgumentInterface
{
const PRODUCT_FORM_SELECTOR = '#product_addtocart_form';

/**
* @var Config
*/
private $config;

/**
* @var StoreManagerInterface
*/
private $storeManager;

/**
* @var RequestInterface
*/
private $request;

/**
* @var UrlInterface
*/
private $url;

/**
* @var Repository
*/
private $assetRepository;

/**
* @var View
*/
private $view;

/**
* @param Config $config
* @param StoreManagerInterface $storeManager
* @param RequestInterface $request
* @param UrlInterface $url
* @param Repository $assetRepository
* @param View $view
*/
public function __construct(
Config $config,
StoreManagerInterface $storeManager,
RequestInterface $request,
UrlInterface $url,
Repository $assetRepository,
View $view
) {
$this->config = $config;
$this->storeManager = $storeManager;
$this->request = $request;
$this->url = $url;
$this->assetRepository = $assetRepository;
$this->view = $view;
}

/**
* Render Instant Checkout button on Product page.
*
* @return bool
* @throws LocalizedException
*/
public function enabledOnProductPage(): bool
{
$websiteId = (int)$this->storeManager->getWebsite()->getId();
$productType = $this->view->getProduct()->getTypeId();

return $this->config->getIsPaypalFlowEnabled($websiteId)
&& $this->config->isProductPageInstantCheckoutEnabled($websiteId)
&& $this->config->isProductPageInstantCheckoutEnabledForType($websiteId, $productType);
}

/**
* Get parallel checkout url.
*
* @return string
*/
public function getCheckoutUrl(): string
{
return $this->url->getUrl(
'checkout',
[
'_secure' => $this->request->isSecure(),
Button::KEY_PARALLEL => true,
]
);
}

/**
* Get Product form selector.
*
* @return string
*/
public function getProductFormSelector(): string
{
return self::PRODUCT_FORM_SELECTOR;
}

/**
* Get ULR for loader image.
*
* @return string
*/
public function getLoaderIcon(): string
{
return $this->assetRepository->getUrl('images/loader-2.gif');
}
}
Loading

0 comments on commit 57c7836

Please sign in to comment.