- {newsletterEnabled ? (
+ {!optinEnabled ? (
<>
diff --git a/assets/js/src/newsletter_block/editor.scss b/assets/js/src/marketing_optin_block/editor.scss
similarity index 100%
rename from assets/js/src/newsletter_block/editor.scss
rename to assets/js/src/marketing_optin_block/editor.scss
diff --git a/assets/js/src/newsletter_block/frontend.tsx b/assets/js/src/marketing_optin_block/frontend.tsx
similarity index 100%
rename from assets/js/src/newsletter_block/frontend.tsx
rename to assets/js/src/marketing_optin_block/frontend.tsx
diff --git a/assets/js/src/newsletter_block/index.tsx b/assets/js/src/marketing_optin_block/index.tsx
similarity index 100%
rename from assets/js/src/newsletter_block/index.tsx
rename to assets/js/src/marketing_optin_block/index.tsx
diff --git a/assets/js/src/newsletter_block/attributes.js b/assets/js/src/newsletter_block/attributes.js
deleted file mode 100644
index 508d8e98d3..0000000000
--- a/assets/js/src/newsletter_block/attributes.js
+++ /dev/null
@@ -1,12 +0,0 @@
-/**
- * External dependencies
- */
-import { getSetting } from "@woocommerce/settings";
-
-const { newsletterDefaultText } = getSetting("mailpoet_data");
-export default {
- text: {
- type: "string",
- default: newsletterDefaultText,
- },
-};
diff --git a/assets/js/src/newsletter_block/block.tsx b/assets/js/src/newsletter_block/block.tsx
deleted file mode 100644
index a89adbd794..0000000000
--- a/assets/js/src/newsletter_block/block.tsx
+++ /dev/null
@@ -1,33 +0,0 @@
-/**
- * External dependencies
- */
-import React from 'react';
-import { CheckboxControl } from '@woocommerce/blocks-checkout';
-import { useState, useEffect } from '@wordpress/element';
-import { getSetting } from '@woocommerce/settings';
-
-const { newsletterEnabled, newsletterDefaultText } = getSetting('mailpoet_data');
-
-const Block = ({ text, checkoutExtensionData }) => {
- const [checked, setChecked] = useState(false);
- const { setExtensionData } = checkoutExtensionData || {};
- useEffect(() => {
- if (newsletterEnabled && setExtensionData) {
- setExtensionData('mailpoet', 'optin', checked);
- }
- }, [checked, setExtensionData]);
-
- if (!newsletterEnabled) {
- return null;
- }
-
- return (
-
- );
-};
-
-export default Block;
diff --git a/assets/js/src/newsletter_block/style.scss b/assets/js/src/newsletter_block/style.scss
deleted file mode 100644
index 67ce83e4d0..0000000000
--- a/assets/js/src/newsletter_block/style.scss
+++ /dev/null
@@ -1,3 +0,0 @@
-body {
- background: red;
-}
diff --git a/lib/Config/Initializer.php b/lib/Config/Initializer.php
index 9f0d6fe780..a3bb0284ad 100644
--- a/lib/Config/Initializer.php
+++ b/lib/Config/Initializer.php
@@ -6,8 +6,8 @@ use MailPoet\API\JSON\API;
use MailPoet\AutomaticEmails\AutomaticEmails;
use MailPoet\Cron\CronTrigger;
use MailPoet\InvalidStateException;
-use MailPoet\PostEditorBlocks\NewsletterBlock;
use MailPoet\PostEditorBlocks\PostEditorBlock;
+use MailPoet\PostEditorBlocks\WooCommerceBlocksIntegration;
use MailPoet\Router;
use MailPoet\Settings\SettingsController;
use MailPoet\Util\ConflictResolver;
@@ -72,8 +72,8 @@ class Initializer {
/** @var \MailPoet\PostEditorBlocks\PostEditorBlock */
private $postEditorBlock;
- /** @var \MailPoet\PostEditorBlocks\NewsletterBlock */
- private $newsletterBlock;
+ /** @var \MailPoet\PostEditorBlocks\WooCommerceBlocksIntegration */
+ private $woocommerceBlocksIntegration;
/** @var Localizer */
private $localizer;
@@ -99,7 +99,7 @@ class Initializer {
DatabaseInitializer $databaseInitializer,
WCTransactionalEmails $wcTransactionalEmails,
PostEditorBlock $postEditorBlock,
- NewsletterBlock $newsletterBlock,
+ WooCommerceBlocksIntegration $woocommerceBlocksIntegration,
WooCommerceHelper $wcHelper,
Localizer $localizer,
AssetsLoader $assetsLoader
@@ -120,7 +120,7 @@ class Initializer {
$this->wcTransactionalEmails = $wcTransactionalEmails;
$this->wcHelper = $wcHelper;
$this->postEditorBlock = $postEditorBlock;
- $this->newsletterBlock = $newsletterBlock;
+ $this->woocommerceBlocksIntegration = $woocommerceBlocksIntegration;
$this->localizer = $localizer;
$this->assetsLoader = $assetsLoader;
}
@@ -236,8 +236,8 @@ class Initializer {
$this->setupPermanentNotices();
$this->setupAutomaticEmails();
+ $this->setupWoocommerceBlocksIntegration();
$this->postEditorBlock->init();
- $this->newsletterBlock->init();
WPFunctions::get()->doAction('mailpoet_initialized', MAILPOET_VERSION);
} catch (InvalidStateException $e) {
@@ -389,4 +389,12 @@ class Initializer {
$this->wcTransactionalEmails->useTemplateForWoocommerceEmails();
}
}
+
+ private function setupWoocommerceBlocksIntegration() {
+ $wcEnabled = $this->wcHelper->isWooCommerceActive();
+ $wcBlocksEnabled = $this->wcHelper->isWooCommerceBlocksActive( '6.3.0-dev' );
+ if ($wcEnabled && $wcBlocksEnabled) {
+ $this->woocommerceBlocksIntegration->init();
+ }
+ }
}
diff --git a/lib/DI/ContainerConfigurator.php b/lib/DI/ContainerConfigurator.php
index 1bd5464ea3..ff8e72b1f1 100644
--- a/lib/DI/ContainerConfigurator.php
+++ b/lib/DI/ContainerConfigurator.php
@@ -135,7 +135,7 @@ class ContainerConfigurator implements IContainerConfigurator {
->setFactory([new Reference(\MailPoet\Doctrine\Validator\ValidatorFactory::class), 'createValidator']);
$container->autowire(\MailPoet\PostEditorBlocks\PostEditorBlock::class);
$container->autowire(\MailPoet\PostEditorBlocks\SubscriptionFormBlock::class);
- $container->autowire(\MailPoet\PostEditorBlocks\NewsletterBlock::class);
+ $container->autowire(\MailPoet\PostEditorBlocks\WooCommerceBlocksIntegration::class);
// Cron
$container->autowire(\MailPoet\Cron\CronHelper::class)->setPublic(true);
$container->autowire(\MailPoet\Cron\CronTrigger::class)->setPublic(true);
diff --git a/lib/PostEditorBlocks/MarketingOptinBlock.php b/lib/PostEditorBlocks/MarketingOptinBlock.php
new file mode 100644
index 0000000000..70d332c386
--- /dev/null
+++ b/lib/PostEditorBlocks/MarketingOptinBlock.php
@@ -0,0 +1,83 @@
+options = $options;
+ }
+
+ /**
+ * The name of the integration.
+ *
+ * @return string
+ */
+ public function get_name() { // phpcs:ignore
+ return 'mailpoet';
+ }
+
+ /**
+ * Register block scripts and assets.
+ */
+ public function initialize() {
+ $script_asset_path = Env::$assetsUrl . '/dist/js/marketing_optin_block/marketing-optin-block-frontend.asset.php';
+ $script_asset = file_exists($script_asset_path)
+ ? require $script_asset_path
+ : [
+ 'dependencies' => [],
+ 'version' => Env::$version,
+ ];
+ wp_register_script(
+ 'mailpoet-marketing-optin-block-frontend',
+ Env::$assetsUrl . '/dist/js/marketing_optin_block/marketing-optin-block-frontend.js',
+ $script_asset['dependencies'],
+ $script_asset['version'],
+ true
+ );
+ wp_set_script_translations(
+ 'mailpoet-marketing-optin-block-frontend',
+ 'mailpoet',
+ Env::$languagesPath
+ );
+ }
+
+ /**
+ * Returns an array of script handles to enqueue in the frontend context.
+ *
+ * @return string[]
+ */
+ public function get_script_handles() { // phpcs:ignore
+ return ['mailpoet-marketing-optin-block-frontend'];
+ }
+
+ /**
+ * Returns an array of script handles to enqueue in the editor context.
+ *
+ * @return string[]
+ */
+ public function get_editor_script_handles() { // phpcs:ignore
+ return [];
+ }
+
+ /**
+ * An array of key, value pairs of data made available to the block on the client side.
+ *
+ * @return array
+ */
+ public function get_script_data() { // phpcs:ignore
+ return $this->options;
+ }
+}
diff --git a/lib/PostEditorBlocks/NewsletterBlock.php b/lib/PostEditorBlocks/NewsletterBlock.php
deleted file mode 100644
index 26665798fd..0000000000
--- a/lib/PostEditorBlocks/NewsletterBlock.php
+++ /dev/null
@@ -1,93 +0,0 @@
-wp = $wp;
- $this->settings = $settings;
- }
-
- public function init() {
- $this->wp->registerBlockType( Env::$assetsPath . '/js/src/newsletter_block' );
- $this->wp->addFilter(
- '__experimental_woocommerce_blocks_add_data_attributes_to_block',
- [$this, 'addDataAttributesToBlock']
- );
- $this->wp->addAction(
- '__experimental_woocommerce_blocks_checkout_update_order_from_request',
- [$this, 'process_checkout_block_optin']
- );
- $this->addScriptData();
- $this->extendRestApi();
- }
-
- public function addDataAttributesToBlock( array $blocks ) {
- $blocks[] = 'mailpoet/newsletter-block';
- return $blocks;
- }
-
- public function addScriptData() {
- $data_registry = Package::container()->get(
- AssetDataRegistry::class
- );
- $data_registry->add( 'mailpoet_data', array(
- 'newsletterDefaultText' => $this->settings->get('woocommerce.optin_on_checkout.message', ''),
- 'newsletterEnabled' => $this->settings->get('woocommerce.optin_on_checkout.enabled', false),
- ) );
- }
-
- public function extendRestApi() {
- $extend = Package::container()->get(
- ExtendRestApi::class
- );
- $extend->register_endpoint_data(
- array(
- 'endpoint' => CheckoutSchema::IDENTIFIER,
- 'namespace' => 'mailpoet',
- 'schema_callback' => function() {
- return array(
- 'newsletter-opt-in' => array(
- 'description' => __( 'Subscribe to newsletter opt-in.', 'woo-gutenberg-products-block' ),
- 'type' => 'boolean',
- ),
- );
- },
- )
- );
- }
-
- public function process_checkout_block_optin( \WC_Order $order, array $request ) {
- if ( ! $this->settings->get('woocommerce.optin_on_checkout.enabled', false) ) {
- return;
- }
-
- if ( ! $order ) {
- return;
- }
-
- if ( ! isset( $request['extensions']['mailpoet'][ 'optin' ] ) ) {
- return;
- }
-
- // @todo do optin
- }
-}
diff --git a/lib/PostEditorBlocks/WooCommerceBlocksIntegration.php b/lib/PostEditorBlocks/WooCommerceBlocksIntegration.php
new file mode 100644
index 0000000000..ee4182191e
--- /dev/null
+++ b/lib/PostEditorBlocks/WooCommerceBlocksIntegration.php
@@ -0,0 +1,109 @@
+wp = $wp;
+ $this->settings = $settings;
+ $this->woocommerceSubscription = $woocommerceSubscription;
+ }
+
+ public function init() {
+ $this->wp->addAction(
+ 'woocommerce_blocks_checkout_block_registration',
+ [$this, 'registerCheckoutFrontendBlocks']
+ );
+ $this->wp->addAction(
+ '__experimental_woocommerce_blocks_checkout_update_order_from_request',
+ [$this, 'processCheckoutBlockOptin'],
+ 10,
+ 2
+ );
+ $this->wp->addFilter(
+ '__experimental_woocommerce_blocks_add_data_attributes_to_block',
+ [$this, 'addDataAttributesToBlock']
+ );
+ $this->wp->registerBlockType(Env::$assetsPath . '/js/src/marketing_optin_block');
+ $this->extendRestApi();
+ }
+
+ /**
+ * Load blocks in frontend with Checkout.
+ */
+ public function registerCheckoutFrontendBlocks($integration_registry) {
+ $integration_registry->register(new MarketingOptinBlock([
+ 'defaultText' => $this->settings->get('woocommerce.optin_on_checkout.message', ''),
+ 'optinEnabled' => $this->settings->get('woocommerce.optin_on_checkout.enabled', false),
+ 'defaultStatus' => $this->woocommerceSubscription->isCurrentUserSubscribed(),
+ ]));
+ }
+
+ public function addDataAttributesToBlock(array $blocks) {
+ $blocks[] = 'mailpoet/marketing-optin-block';
+ return $blocks;
+ }
+
+ public function extendRestApi() {
+ $extend = Package::container()->get(ExtendRestApi::class);
+ $extend->register_endpoint_data(
+ [
+ 'endpoint' => CheckoutSchema::IDENTIFIER,
+ 'namespace' => 'mailpoet',
+ 'schema_callback' => function () {
+ return [
+ 'optin' => [
+ 'description' => __('Subscribe to marketing opt-in.', 'mailpoet'),
+ 'type' => 'boolean',
+ ],
+ ];
+ },
+ ]
+ );
+ }
+
+ public function processCheckoutBlockOptin(\WC_Order $order, $request) {
+ if (!$this->settings->get('woocommerce.optin_on_checkout.enabled', false)) {
+ return;
+ }
+
+ if (!$order || !$order->get_billing_email()) {
+ return;
+ }
+
+ if (!isset($request['extensions']['mailpoet']['optin'])) {
+ return;
+ }
+
+ // See Subscription::subscribeOnCheckout
+ $subscriber = Subscriber::where('email', $order->get_billing_email())
+ ->where('is_woocommerce_user', 1)
+ ->findOne();
+
+ if (!$subscriber) {
+ return null;
+ }
+
+ $this->woocommerceSubscription->handleSubscriberOptin($subscriber, (bool)$request['extensions']['mailpoet']['optin']);
+ }
+}
diff --git a/lib/WooCommerce/Helper.php b/lib/WooCommerce/Helper.php
index f7a2404ab7..02211c25b7 100644
--- a/lib/WooCommerce/Helper.php
+++ b/lib/WooCommerce/Helper.php
@@ -7,6 +7,16 @@ class Helper {
return class_exists('WooCommerce');
}
+ public function isWooCommerceBlocksActive($min_version = '') {
+ if (!class_exists('\Automattic\WooCommerce\Blocks\Package')) {
+ return false;
+ }
+ if ($min_version) {
+ return version_compare(\Automattic\WooCommerce\Blocks\Package::get_version(), $min_version, '>=');
+ }
+ return true;
+ }
+
public function WC() {
return WC();
}
@@ -53,10 +63,10 @@ class Helper {
public function getOrdersCountCreatedBefore($dateTime) {
global $wpdb;
- $result = $wpdb->get_var( "
+ $result = $wpdb->get_var("
SELECT DISTINCT count(p.ID) FROM {$wpdb->prefix}posts as p
WHERE p.post_type = 'shop_order' AND p.post_date < '{$dateTime}'
- " );
+ ");
return (int)$result;
}
diff --git a/lib/WooCommerce/Subscription.php b/lib/WooCommerce/Subscription.php
index 0a245295e4..5b0926ee8c 100644
--- a/lib/WooCommerce/Subscription.php
+++ b/lib/WooCommerce/Subscription.php
@@ -116,7 +116,7 @@ class Subscription {
return str_replace('type="text', 'type="hidden"', $field);
}
- private function isCurrentUserSubscribed() {
+ public function isCurrentUserSubscribed() {
$subscriber = $this->subscribersRepository->getCurrentWPUser();
if (!$subscriber instanceof SubscriberEntity) {
return false;
@@ -148,44 +148,59 @@ class Subscription {
$subscriber = Subscriber::where('email', $data['billing_email'])
->where('is_woocommerce_user', 1)
->findOne();
+
if (!$subscriber) {
// no subscriber: WooCommerce sync didn't work
return null;
}
- $checkoutOptinEnabled = (bool)$this->settings->get(self::OPTIN_ENABLED_SETTING_NAME);
+ $checkoutOptinEnabled = (bool)$this->settings->get( self::OPTIN_ENABLED_SETTING_NAME );
+ $checkoutOptin = ! empty( $_POST[self::CHECKOUT_OPTIN_INPUT_NAME] );
+
+ return $this->handleSubscriberOptin( $subscriber, $checkoutOptinEnabled && $checkoutOptin );
+ }
+
+ /**
+ * Subscribe or unsubscribe a subscriber.
+ *
+ * @param Subscriber $subscriber Subscriber object
+ * @param bool $optin Opting in or opting out.
+ */
+ public function handleSubscriberOptin( Subscriber $subscriber, $optin = true ) {
$wcSegment = Segment::getWooCommerceSegment();
$moreSegmentsToSubscribe = (array)$this->settings->get(self::OPTIN_SEGMENTS_SETTING_NAME, []);
- if (!$checkoutOptinEnabled || empty($_POST[self::CHECKOUT_OPTIN_INPUT_NAME])) {
+ $signupConfirmation = $this->settings->get('signup_confirmation');
+
+ if ( ! $optin ) {
// Opt-in is disabled or checkbox is unchecked
SubscriberSegment::unsubscribeFromSegments(
$subscriber,
[$wcSegment->id]
);
- if ($checkoutOptinEnabled) {
- $this->updateSubscriberStatus($subscriber);
- }
+ $this->updateSubscriberStatus($subscriber);
+
return false;
}
- $subscriber->source = Source::WOOCOMMERCE_CHECKOUT;
- $signupConfirmation = $this->settings->get('signup_confirmation');
- // checkbox is checked
- if (
- ($subscriber->status === Subscriber::STATUS_SUBSCRIBED)
- || ((bool)$signupConfirmation['enabled'] === false)
- ) {
- $this->subscribe($subscriber);
- } else {
- $this->requireSubscriptionConfirmation($subscriber);
+ if ( $optin ) {
+ $subscriber->source = Source::WOOCOMMERCE_CHECKOUT;
+
+ if (
+ ($subscriber->status === Subscriber::STATUS_SUBSCRIBED)
+ || ((bool)$signupConfirmation['enabled'] === false)
+ ) {
+ $this->subscribe($subscriber);
+ } else {
+ $this->requireSubscriptionConfirmation($subscriber);
+ }
+
+ SubscriberSegment::subscribeToSegments(
+ $subscriber,
+ array_merge([$wcSegment->id], $moreSegmentsToSubscribe)
+ );
+
+ return true;
}
-
- SubscriberSegment::subscribeToSegments(
- $subscriber,
- array_merge([$wcSegment->id], $moreSegmentsToSubscribe)
- );
-
- return true;
}
private function subscribe(Subscriber $subscriber) {
diff --git a/webpack.config.js b/webpack.config.js
index 0e1898158c..403a4d0d4d 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -408,58 +408,58 @@ const postEditorBlock = {
},
};
-const requestToExternal = ( request ) => {
- // The following default externals are bundled for compatibility with older versions of WP
- // Note CSS for specific components is bundled via admin/assets/src/index.scss
- // WP 5.4 is the min version for ,
- const bundled = [
- '@wordpress/compose',
- '@wordpress/components',
- '@wordpress/warning',
- '@wordpress/primitives',
- ];
- if ( bundled.includes( request ) ) {
- return false;
- }
+const requestToExternal = (request) => {
+ // The following default externals are bundled for compatibility with older versions of WP
+ // Note CSS for specific components is bundled via admin/assets/src/index.scss
+ // WP 5.4 is the min version for ,
+ const bundled = [
+ "@wordpress/compose",
+ "@wordpress/components",
+ "@wordpress/warning",
+ "@wordpress/primitives",
+ ];
+ if (bundled.includes(request)) {
+ return false;
+ }
- const wcDepMap = {
- '@woocommerce/settings': [ 'wc', 'wcSettings' ],
- '@woocommerce/blocks-checkout': [ 'wc', 'blocksCheckout' ],
- };
- if ( wcDepMap[ request ] ) {
- return wcDepMap[ request ];
- }
+ const wcDepMap = {
+ "@woocommerce/settings": ["wc", "wcSettings"],
+ "@woocommerce/blocks-checkout": ["wc", "blocksCheckout"],
+ };
+ if (wcDepMap[request]) {
+ return wcDepMap[request];
+ }
};
-const requestToHandle = ( request ) => {
- const wcHandleMap = {
- '@woocommerce/settings': 'wc-settings',
- '@woocommerce/blocks-checkout': 'wc-blocks-checkout',
- };
- if ( wcHandleMap[ request ] ) {
- return wcHandleMap[ request ];
- }
+const requestToHandle = (request) => {
+ const wcHandleMap = {
+ "@woocommerce/settings": "wc-settings",
+ "@woocommerce/blocks-checkout": "wc-blocks-checkout",
+ };
+ if (wcHandleMap[request]) {
+ return wcHandleMap[request];
+ }
};
-// Newsletter config
-const newsletterBlock = {
+// Marketing Optin config
+const marketingOptinBlock = {
...wpScriptConfig,
- name: "newsletter_block",
+ name: "marketing_optin_block",
entry: {
- newsletter_block: path.resolve(
+ "marketing-optin-block": path.resolve(
process.cwd(),
- "assets/js/src/newsletter_block",
+ "assets/js/src/marketing_optin_block",
"index.tsx"
),
- newsletter_block_frontend: path.resolve(
+ "marketing-optin-block-frontend": path.resolve(
process.cwd(),
- "assets/js/src/newsletter_block",
+ "assets/js/src/marketing_optin_block",
"frontend.tsx"
),
},
output: {
filename: "[name].js",
- path: path.resolve(process.cwd(), "assets/dist/js/newsletter_block"),
+ path: path.resolve(process.cwd(), "assets/dist/js/marketing_optin_block"),
},
module: {
...wpScriptConfig.module,
@@ -469,24 +469,22 @@ const newsletterBlock = {
test: /\.(t|j)sx?$/,
exclude: /node_modules/,
use: {
- loader: 'babel-loader?cacheDirectory',
+ loader: "babel-loader?cacheDirectory",
options: {
- presets: [ '@wordpress/babel-preset-default' ],
+ presets: ["@wordpress/babel-preset-default"],
plugins: [
+ require.resolve("@babel/plugin-proposal-class-properties"),
require.resolve(
- '@babel/plugin-proposal-class-properties'
+ "@babel/plugin-proposal-nullish-coalescing-operator"
),
- require.resolve(
- '@babel/plugin-proposal-nullish-coalescing-operator'
- ),
- ].filter( Boolean ),
+ ].filter(Boolean),
},
},
},
],
},
resolve: {
- extensions: [ '.js', '.jsx', '.ts', '.tsx' ],
+ extensions: [".js", ".jsx", ".ts", ".tsx"],
},
plugins: [
...wpScriptConfig.plugins.filter(
@@ -524,5 +522,5 @@ module.exports = [
}
return Object.assign({}, baseConfig, config);
}),
- newsletterBlock,
-];
\ No newline at end of file
+ marketingOptinBlock,
+];