diff --git a/Block/System/Config/Form/Field/Status.php b/Block/System/Config/Form/Field/Status.php
new file mode 100644
index 0000000..e510fb1
--- /dev/null
+++ b/Block/System/Config/Form/Field/Status.php
@@ -0,0 +1,71 @@
+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('%s', $class, $statusText)
+ );
+
+ return parent::_renderValue($element);
+ }
+}
diff --git a/Block/System/Config/Form/Field/Toggle.php b/Block/System/Config/Form/Field/Toggle.php
index b3535db..4294385 100644
--- a/Block/System/Config/Form/Field/Toggle.php
+++ b/Block/System/Config/Form/Field/Toggle.php
@@ -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';
}
/**
diff --git a/Model/Config.php b/Model/Config.php
index 6ca4aa1..d204e7e 100644
--- a/Model/Config.php
+++ b/Model/Config.php
@@ -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';
/**
@@ -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;
@@ -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
@@ -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
+ )
+ )
+ );
+ }
}
diff --git a/Model/Config/Backend/InvalidateBlockBackend.php b/Model/Config/Backend/InvalidateBlockBackend.php
new file mode 100644
index 0000000..c90b0bc
--- /dev/null
+++ b/Model/Config/Backend/InvalidateBlockBackend.php
@@ -0,0 +1,46 @@
+isValueChanged()) {
+ $this->cacheTypeList->invalidate(Block::TYPE_IDENTIFIER);
+ $this->cacheTypeList->invalidate(Type::TYPE_IDENTIFIER);
+ }
+
+ return parent::afterSave();
+ }
+}
diff --git a/Model/Config/Source/ProductTypeSource.php b/Model/Config/Source/ProductTypeSource.php
new file mode 100644
index 0000000..5741130
--- /dev/null
+++ b/Model/Config/Source/ProductTypeSource.php
@@ -0,0 +1,54 @@
+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;
+ }
+}
diff --git a/ViewModel/Instant.php b/ViewModel/Instant.php
new file mode 100644
index 0000000..2474a23
--- /dev/null
+++ b/ViewModel/Instant.php
@@ -0,0 +1,129 @@
+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');
+ }
+}
diff --git a/etc/adminhtml/system.xml b/etc/adminhtml/system.xml
index 7c69648..5295342 100644
--- a/etc/adminhtml/system.xml
+++ b/etc/adminhtml/system.xml
@@ -5,11 +5,14 @@
-
-
- Magento\Config\Model\Config\Source\Yesno
Bold\CheckoutFlowPaypal\Block\System\Config\Form\Field\Disabled
+
+
+
+ Bold\CheckoutFlowPaypal\Block\System\Config\Form\Field\Status
documentation.
@@ -17,8 +20,27 @@
Bold\CheckoutFlowPaypal\Block\System\Config\Form\Field\Toggle
+
+
+
+ Magento\Config\Model\Config\Source\Yesno
+ Bold\CheckoutFlowPaypal\Model\Config\Backend\InvalidateBlockBackend
-
+
+
+ 1
+
+
+
+
+ Bold\CheckoutFlowPaypal\Model\Config\Source\ProductTypeSource
+ Bold\CheckoutFlowPaypal\Model\Config\Backend\InvalidateBlockBackend
+
+ 1
+ 1
+
diff --git a/etc/config.xml b/etc/config.xml
index 6b43a0a..ca7f3ce 100644
--- a/etc/config.xml
+++ b/etc/config.xml
@@ -4,6 +4,8 @@
paypal_branded
+ 1
+ simple,virtual,downloadable,grouped,configurable,bundle,giftcard
diff --git a/view/adminhtml/layout/adminhtml_system_config_edit.xml b/view/adminhtml/layout/adminhtml_system_config_edit.xml
new file mode 100644
index 0000000..11b8d3b
--- /dev/null
+++ b/view/adminhtml/layout/adminhtml_system_config_edit.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
diff --git a/view/adminhtml/web/css/system-styles.less b/view/adminhtml/web/css/system-styles.less
new file mode 100644
index 0000000..0730d7b
--- /dev/null
+++ b/view/adminhtml/web/css/system-styles.less
@@ -0,0 +1,25 @@
+#checkout_bold_checkout_paypal_status {
+ padding-top: 0;
+
+ .enabled {
+ color: green;
+ display: flex;
+ font-size: 1em;
+
+ &:before {
+ content: url('../images/enabled.svg');
+ margin-right: 0.5em;
+ }
+ }
+
+ .disabled {
+ display: flex;
+ color: red;
+ font-size: 1em;
+
+ &:before {
+ content: url('../images/disabled.svg');
+ margin-right: 0.5em;
+ }
+ }
+}
diff --git a/view/adminhtml/web/images/disabled.svg b/view/adminhtml/web/images/disabled.svg
new file mode 100644
index 0000000..ac2520c
--- /dev/null
+++ b/view/adminhtml/web/images/disabled.svg
@@ -0,0 +1,10 @@
+
diff --git a/view/adminhtml/web/images/enabled.svg b/view/adminhtml/web/images/enabled.svg
new file mode 100644
index 0000000..86934ea
--- /dev/null
+++ b/view/adminhtml/web/images/enabled.svg
@@ -0,0 +1,10 @@
+
diff --git a/view/frontend/layout/catalog_product_view.xml b/view/frontend/layout/catalog_product_view.xml
new file mode 100644
index 0000000..1b144ef
--- /dev/null
+++ b/view/frontend/layout/catalog_product_view.xml
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+ Bold\CheckoutFlowPaypal\ViewModel\Instant
+
+
+
+
+
+
+ Bold\CheckoutFlowPaypal\ViewModel\Instant
+
+
+
+
+
diff --git a/view/frontend/layout/catalog_product_view_type_bundle.xml b/view/frontend/layout/catalog_product_view_type_bundle.xml
new file mode 100644
index 0000000..fd92b6f
--- /dev/null
+++ b/view/frontend/layout/catalog_product_view_type_bundle.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+ Bold\CheckoutFlowPaypal\ViewModel\Instant
+
+
+
+
+
+
diff --git a/view/frontend/templates/instant/product_button.phtml b/view/frontend/templates/instant/product_button.phtml
new file mode 100644
index 0000000..ee5d8de
--- /dev/null
+++ b/view/frontend/templates/instant/product_button.phtml
@@ -0,0 +1,27 @@
+getData('viewModel');
+?>
+
+enabledOnProductPage()): ?>
+
+
diff --git a/view/frontend/web/js/proceed-to-checkout.js b/view/frontend/web/js/proceed-to-checkout.js
new file mode 100644
index 0000000..2c7ae0f
--- /dev/null
+++ b/view/frontend/web/js/proceed-to-checkout.js
@@ -0,0 +1,40 @@
+define([
+ 'jquery',
+ 'Magento_Customer/js/model/authentication-popup',
+ 'Magento_Customer/js/customer-data'
+], function (
+ $,
+ authenticationPopup,
+ customerData
+) {
+ 'use strict';
+
+ return function (config, element) {
+ $(element).click(function (event) {
+ var cart = customerData.get('cart'),
+ customer = customerData.get('customer');
+ event.preventDefault();
+ event.stopImmediatePropagation();
+ if (!customer().firstname && cart().isGuestCheckoutAllowed === false) {
+ authenticationPopup.showModal();
+ return false;
+ }
+ $(element).attr('disabled', true);
+ const form = $(config.productFormSelector);
+ const loader = $('body').loader(
+ {
+ icon: config.loaderIcon
+ }
+ );
+ form.submit(() => {
+ location.href = config.checkoutUrl
+ });
+ if (form.validation('isValid')) {
+ loader.loader('show');
+ form.submit();
+ } else {
+ $(element).attr('disabled', false);
+ }
+ });
+ };
+});