From 6477944ab930f5f6688a1a290dc58ee958655d10 Mon Sep 17 00:00:00 2001 From: "Soare Robert Daniel (Mac 2023)" Date: Fri, 26 May 2023 16:59:44 +0300 Subject: [PATCH 01/13] feat: stripe checkout autoresponder --- inc/plugins/class-stripe-api.php | 18 +++ inc/render/class-stripe-checkout-block.php | 4 + plugins/otter-pro/inc/class-main.php | 1 + .../inc/plugins/class-stripe-pro-features.php | 117 ++++++++++++++++++ src/blocks/blocks/stripe-checkout/block.json | 5 +- .../blocks/stripe-checkout/inspector.js | 62 +++++++++- src/blocks/blocks/stripe-checkout/types.d.ts | 4 + src/pro/components/autoresponder/index.js | 36 ++++++ src/pro/plugins/form/index.js | 28 +---- src/pro/plugins/index.js | 1 + src/pro/plugins/stripe-checkout/index.js | 50 ++++++++ 11 files changed, 296 insertions(+), 30 deletions(-) create mode 100644 plugins/otter-pro/inc/plugins/class-stripe-pro-features.php create mode 100644 src/pro/components/autoresponder/index.js create mode 100644 src/pro/plugins/stripe-checkout/index.js diff --git a/inc/plugins/class-stripe-api.php b/inc/plugins/class-stripe-api.php index 0fe548016..2c6a3d66b 100644 --- a/inc/plugins/class-stripe-api.php +++ b/inc/plugins/class-stripe-api.php @@ -325,4 +325,22 @@ function( $item ) use ( $product ) { return $bool; } + + /** + * Get session email. + * + * @param string $session_id Stripe Session ID. + * + * @return bool|string + * @access public + */ + public function get_session_email( $session_id ) { + $session = $this->create_request( 'get_session', $session_id ); + + if ( empty( $session['customer_details']['email'] ) ) { + return false; + } + + return $session['customer_details']['email']; + } } diff --git a/inc/render/class-stripe-checkout-block.php b/inc/render/class-stripe-checkout-block.php index 4bc65eed2..81bedc1bb 100644 --- a/inc/render/class-stripe-checkout-block.php +++ b/inc/render/class-stripe-checkout-block.php @@ -39,6 +39,10 @@ public function render( $attributes ) { if ( false !== $status ) { if ( 'success' === $status ) { $message = isset( $attributes['successMessage'] ) ? wp_kses_post( $attributes['successMessage'] ) : __( 'Your payment was successful. If you have any questions, please email orders@example.com.', 'otter-blocks' ); + + if ( has_action( 'otter_blocks_stripe_checkout_success' ) ) { + do_action( 'otter_blocks_stripe_checkout_success', $attributes, $stripe, $session_id ); + } } else { $message = isset( $attributes['cancelMessage'] ) ? wp_kses_post( $attributes['cancelMessage'] ) : __( 'Your payment was unsuccessful. If you have any questions, please email orders@example.com.', 'otter-blocks' ); } diff --git a/plugins/otter-pro/inc/class-main.php b/plugins/otter-pro/inc/class-main.php index 0f24982d8..e0dd92499 100644 --- a/plugins/otter-pro/inc/class-main.php +++ b/plugins/otter-pro/inc/class-main.php @@ -67,6 +67,7 @@ public function autoload_classes( $classnames ) { '\ThemeIsle\OtterPro\Plugins\Posts_ACF_Integration', '\ThemeIsle\OtterPro\Plugins\Review_Woo_Integration', '\ThemeIsle\OtterPro\Plugins\WooCommerce_Builder', + '\ThemeIsle\OtterPro\Plugins\Stripe_Pro_Features', '\ThemeIsle\OtterPro\Server\Dashboard_Server', '\ThemeIsle\OtterPro\Server\Filter_Blocks_Server', '\ThemeIsle\OtterPro\Server\Live_Search_Server', diff --git a/plugins/otter-pro/inc/plugins/class-stripe-pro-features.php b/plugins/otter-pro/inc/plugins/class-stripe-pro-features.php new file mode 100644 index 000000000..767a865d4 --- /dev/null +++ b/plugins/otter-pro/inc/plugins/class-stripe-pro-features.php @@ -0,0 +1,117 @@ +get_session_email( $session_id ); + + if ( ! $email ) { + return; + } + + $to = $email; + $headers[] = 'Content-Type: text/html'; + $headers[] = 'From: ' . get_bloginfo( 'name', 'display' ); + $subject = isset( $attributes['autoresponder']['subject'] ) ? $attributes['autoresponder']['subject'] : __( 'Thank you for your purchase', 'otter-blocks' ); + $body = isset( $attributes['autoresponder']['body'] ) ? $attributes['autoresponder']['body'] : __( 'Thank you for choosing our online store for your recent purchase. We greatly appreciate your business and trust in our products.', 'otter-blocks' ); + + // phpcs:ignore + if ( wp_mail( $to, $subject, $body, $headers ) ) { + set_transient( $transient_key, true, 60 * 24 * 7 ); + } + } + + /** + * The instance method for the static class. + * Defines and returns the instance of the static class. + * + * @static + * @since 1.7.1 + * @access public + * @return Live_Search + */ + public static function instance() { + if ( is_null( self::$instance ) ) { + self::$instance = new self(); + self::$instance->init(); + } + + return self::$instance; + } + + /** + * Throw error on object clone + * + * The whole idea of the singleton design pattern is that there is a single + * object therefore, we don't want the object to be cloned. + * + * @access public + * @since 1.7.1 + * @return void + */ + public function __clone() { + // Cloning instances of the class is forbidden. + _doing_it_wrong( __FUNCTION__, esc_html__( 'Cheatin’ huh?', 'otter-blocks' ), '1.0.0' ); + } + + /** + * Disable unserializing of the class + * + * @access public + * @since 1.7.1 + * @return void + */ + public function __wakeup() { + // Unserializing instances of the class is forbidden. + _doing_it_wrong( __FUNCTION__, esc_html__( 'Cheatin’ huh?', 'otter-blocks' ), '1.0.0' ); + } +} diff --git a/src/blocks/blocks/stripe-checkout/block.json b/src/blocks/blocks/stripe-checkout/block.json index 417a44496..22b8fa080 100644 --- a/src/blocks/blocks/stripe-checkout/block.json +++ b/src/blocks/blocks/stripe-checkout/block.json @@ -19,6 +19,9 @@ }, "cancelMessage": { "type": "string" + }, + "autoresponder": { + "type": "object" } }, "supports": { @@ -26,4 +29,4 @@ }, "editorStyle": "otter-stripe-checkout-editor", "style": "otter-stripe-checkout-style" -} \ No newline at end of file +} diff --git a/src/blocks/blocks/stripe-checkout/inspector.js b/src/blocks/blocks/stripe-checkout/inspector.js index e5e8e341d..9bb90ac21 100644 --- a/src/blocks/blocks/stripe-checkout/inspector.js +++ b/src/blocks/blocks/stripe-checkout/inspector.js @@ -13,14 +13,63 @@ import { SelectControl, Spinner, TextControl, - TextareaControl + TextareaControl, + ExternalLink } from '@wordpress/components'; /** * Internal dependencies */ -import { ButtonToggleControl, RichTextEditor } from '../../components/index.js'; -import { useState } from '@wordpress/element'; +import { ButtonToggleControl, Notice, RichTextEditor } from '../../components/index.js'; +import { Fragment, useContext, useState } from '@wordpress/element'; +import { applyFilters } from '@wordpress/hooks'; +import { FormContext } from '../form/edit'; +import { setUtm } from '../../helpers/helper-functions'; + +const ProFeatures = () => { + return ( + + { ! Boolean( window.themeisleGutenberg?.hasPro ) && ( + + {}} + help={__( + 'Enter the subject of the autoresponder email.', + 'otter-blocks' + )} + /> + + {} } + help={ __( 'Enter the body of the autoresponder email.', 'otter-blocks' ) } + disabled + className="o-disabled" + /> + +
+ { __( 'Unlock this with Otter Pro.', 'otter-blocks' ) } } + variant="upsell" + /> +

{ __( 'Automatically send follow-up emails to your users with the Autoresponder feature.', 'otter-blocks' ) }

+
+
+ )} +
+ ); +}; const Inspector = ({ attributes, @@ -160,6 +209,13 @@ const Inspector = ({ { __( 'Save API Key', 'otter-blocks' ) } + + { applyFilters( + 'otter.stripe-checkout.inspector', + , + attributes, + setAttributes + ) } ); }; diff --git a/src/blocks/blocks/stripe-checkout/types.d.ts b/src/blocks/blocks/stripe-checkout/types.d.ts index 1150adde5..1bdd144cf 100644 --- a/src/blocks/blocks/stripe-checkout/types.d.ts +++ b/src/blocks/blocks/stripe-checkout/types.d.ts @@ -5,6 +5,10 @@ type Attributes = { price: string successMessage: string cancelMessage: string + autoresponder: { + subject: string + body: string + } } export type StripeCheckoutProps = BlockProps diff --git a/src/pro/components/autoresponder/index.js b/src/pro/components/autoresponder/index.js new file mode 100644 index 000000000..e4b16a55b --- /dev/null +++ b/src/pro/components/autoresponder/index.js @@ -0,0 +1,36 @@ +import { useState } from '@wordpress/element'; +import { Button, Modal } from '@wordpress/components'; +import { __ } from '@wordpress/i18n'; +import { RichTextEditor } from '../../../blocks/components'; + +const AutoresponderBodyModal = ({ value, onChange }) => { + const [ isOpen, setOpen ] = useState( false ); + + return ( + <> + { isOpen && ( + setOpen( false )} + shouldCloseOnClickOutside={ false } + > + + + ) } +
+ + + ); +}; + +export default AutoresponderBodyModal; diff --git a/src/pro/plugins/form/index.js b/src/pro/plugins/form/index.js index 8b7c23e26..b0d4accdc 100644 --- a/src/pro/plugins/form/index.js +++ b/src/pro/plugins/form/index.js @@ -21,40 +21,16 @@ import { Notice as OtterNotice } from '../../../blocks/components'; import { RichTextEditor } from '../../../blocks/components'; import { FieldInputWidth, HideFieldLabelToggle } from '../../../blocks/blocks/form/common'; import { setSavedState } from '../../../blocks/helpers/helper-functions'; +import AutoreponderBodyModal from '../../components/autoresponder/index.js'; // +-------------- Autoresponder --------------+ const AutoresponderBody = ({ formOptions, setFormOption }) => { - const [ isOpen, setOpen ] = useState( false ); const onChange = body => { setFormOption({ autoresponder: { ...formOptions.autoresponder, body }}); }; - return ( - <> - { isOpen && ( - setOpen( false )} - shouldCloseOnClickOutside={ false } - > - - - ) } -
- - - ); + return ; }; const helpMessages = { diff --git a/src/pro/plugins/index.js b/src/pro/plugins/index.js index e1dcb294a..b94b42409 100644 --- a/src/pro/plugins/index.js +++ b/src/pro/plugins/index.js @@ -14,3 +14,4 @@ import './wc-integration/index.js'; import './countdown/index'; import './live-search/index.js'; import './form/index.js'; +import './stripe-checkout/index.js'; diff --git a/src/pro/plugins/stripe-checkout/index.js b/src/pro/plugins/stripe-checkout/index.js new file mode 100644 index 000000000..aaa912580 --- /dev/null +++ b/src/pro/plugins/stripe-checkout/index.js @@ -0,0 +1,50 @@ +import { Fragment } from '@wordpress/element'; +import { Notice, Notice as OtterNotice } from '../../../blocks/components'; +import { __ } from '@wordpress/i18n'; +import { ExternalLink, PanelBody, TextareaControl, TextControl } from '@wordpress/components'; +import { setUtm } from '../../../blocks/helpers/helper-functions'; +import { addFilter } from '@wordpress/hooks'; +import AutoresponderBodyModal from '../../components/autoresponder/index.js'; + +const Autoresponder = ( Template, attributes, setAttributes ) => { + + if ( ! Boolean( window?.otterPro?.isActive ) ) { + return ( + + { Template } + + + ); + } + + return ( + + + setAttributes({ autoresponder: { ...attributes.autoresponder, subject }})} + help={__( + 'Enter the subject of the autoresponder email.', + 'otter-blocks' + )} + /> + + setAttributes({ autoresponder: { ...attributes.autoresponder, body }}) } /> + + + ); +}; + +addFilter( 'otter.stripe-checkout.inspector', 'themeisle-gutenberg/stripe-checkout-inspector', Autoresponder ); From 6a9d082efeda6fc096f18c52d22f31e8ee2c288f Mon Sep 17 00:00:00 2001 From: "Soare Robert Daniel (Mac 2023)" Date: Fri, 26 May 2023 17:17:55 +0300 Subject: [PATCH 02/13] chore: add toggle --- src/pro/plugins/stripe-checkout/index.js | 45 +++++++++++++++--------- 1 file changed, 29 insertions(+), 16 deletions(-) diff --git a/src/pro/plugins/stripe-checkout/index.js b/src/pro/plugins/stripe-checkout/index.js index aaa912580..1ad40195b 100644 --- a/src/pro/plugins/stripe-checkout/index.js +++ b/src/pro/plugins/stripe-checkout/index.js @@ -1,7 +1,7 @@ import { Fragment } from '@wordpress/element'; import { Notice, Notice as OtterNotice } from '../../../blocks/components'; import { __ } from '@wordpress/i18n'; -import { ExternalLink, PanelBody, TextareaControl, TextControl } from '@wordpress/components'; +import { ExternalLink, PanelBody, TextareaControl, TextControl, ToggleControl } from '@wordpress/components'; import { setUtm } from '../../../blocks/helpers/helper-functions'; import { addFilter } from '@wordpress/hooks'; import AutoresponderBodyModal from '../../components/autoresponder/index.js'; @@ -25,23 +25,36 @@ const Autoresponder = ( Template, attributes, setAttributes ) => { - setAttributes({ autoresponder: { ...attributes.autoresponder, subject }})} - help={__( - 'Enter the subject of the autoresponder email.', - 'otter-blocks' - )} + setAttributes({ autoresponder: value ? { subject: undefined, body: undefined } : undefined })} + help={ __( 'Enable autoresponder email to be sent to the customer after a successful purchase.', 'otter-blocks' ) } /> - setAttributes({ autoresponder: { ...attributes.autoresponder, body }}) } /> + { + attributes.autoresponder && ( + + setAttributes({ autoresponder: { ...attributes.autoresponder, subject }})} + help={__( + 'Enter the subject of the autoresponder email.', + 'otter-blocks' + )} + /> + + setAttributes({ autoresponder: { ...attributes.autoresponder, body }}) } /> + + ) + } ); From 6dd95ab31ce4ce3e64cd88243740106c966dde2c Mon Sep 17 00:00:00 2001 From: "Soare Robert Daniel (Mac 2023)" Date: Mon, 29 May 2023 15:22:48 +0300 Subject: [PATCH 03/13] chore: minor --- .../inc/plugins/class-stripe-pro-features.php | 1 - .../blocks/stripe-checkout/inspector.js | 86 +++++++++++-------- src/pro/plugins/stripe-checkout/index.js | 4 - 3 files changed, 50 insertions(+), 41 deletions(-) diff --git a/plugins/otter-pro/inc/plugins/class-stripe-pro-features.php b/plugins/otter-pro/inc/plugins/class-stripe-pro-features.php index 767a865d4..b6288d2d8 100644 --- a/plugins/otter-pro/inc/plugins/class-stripe-pro-features.php +++ b/plugins/otter-pro/inc/plugins/class-stripe-pro-features.php @@ -51,7 +51,6 @@ public function autoresponder( $attributes, $stripe, $session_id ) { if ( false !== $transient ) { return; } - $email = $stripe->get_session_email( $session_id ); if ( ! $email ) { diff --git a/src/blocks/blocks/stripe-checkout/inspector.js b/src/blocks/blocks/stripe-checkout/inspector.js index 9bb90ac21..f616ff008 100644 --- a/src/blocks/blocks/stripe-checkout/inspector.js +++ b/src/blocks/blocks/stripe-checkout/inspector.js @@ -20,7 +20,7 @@ import { /** * Internal dependencies */ -import { ButtonToggleControl, Notice, RichTextEditor } from '../../components/index.js'; +import { ButtonToggleControl, Notice as OtterNotice, Notice, RichTextEditor } from '../../components/index.js'; import { Fragment, useContext, useState } from '@wordpress/element'; import { applyFilters } from '@wordpress/hooks'; import { FormContext } from '../form/edit'; @@ -29,44 +29,58 @@ import { setUtm } from '../../helpers/helper-functions'; const ProFeatures = () => { return ( - { ! Boolean( window.themeisleGutenberg?.hasPro ) && ( - - {}} - help={__( - 'Enter the subject of the autoresponder email.', - 'otter-blocks' - )} - /> - {} } - help={ __( 'Enter the body of the autoresponder email.', 'otter-blocks' ) } - disabled - className="o-disabled" - /> + + {}} + help={__( + 'Enter the subject of the autoresponder email.', + 'otter-blocks' + )} + className="o-disabled" + /> + + {} } + help={ __( 'Enter the body of the autoresponder email.', 'otter-blocks' ) } + disabled + className="o-disabled" + /> -
- { __( 'Unlock this with Otter Pro.', 'otter-blocks' ) } } - variant="upsell" + { + ( ! Boolean( window?.otterPro?.isActive ) && Boolean( window?.themeisleGutenberg?.hasPro ) ) && ( + -

{ __( 'Automatically send follow-up emails to your users with the Autoresponder feature.', 'otter-blocks' ) }

-
-
- )} + ) + } + + { + ( ! Boolean( window?.themeisleGutenberg?.hasPro ) ) && ( +
+ { __( 'Unlock this with Otter Pro.', 'otter-blocks' ) } } + variant="upsell" + /> +

{ __( 'Automatically send follow-up emails to your users with the Autoresponder feature.', 'otter-blocks' ) }

+
+ ) + } +
+
); }; diff --git a/src/pro/plugins/stripe-checkout/index.js b/src/pro/plugins/stripe-checkout/index.js index 1ad40195b..5a381f8df 100644 --- a/src/pro/plugins/stripe-checkout/index.js +++ b/src/pro/plugins/stripe-checkout/index.js @@ -12,10 +12,6 @@ const Autoresponder = ( Template, attributes, setAttributes ) => { return ( { Template } - ); } From cffbc7ea6a5f6d5f2013d5af3631d60147a04bb8 Mon Sep 17 00:00:00 2001 From: "Soare Robert Daniel (Mac 2023)" Date: Tue, 30 May 2023 10:58:32 +0300 Subject: [PATCH 04/13] chore: review --- .../inc/plugins/class-stripe-pro-features.php | 8 ++++---- src/blocks/blocks/form/inspector.js | 2 +- src/blocks/blocks/stripe-checkout/inspector.js | 12 ++++-------- src/pro/plugins/form/index.js | 7 ++----- src/pro/plugins/stripe-checkout/index.js | 13 +++++++++---- 5 files changed, 20 insertions(+), 22 deletions(-) diff --git a/plugins/otter-pro/inc/plugins/class-stripe-pro-features.php b/plugins/otter-pro/inc/plugins/class-stripe-pro-features.php index b6288d2d8..e2d38a2c1 100644 --- a/plugins/otter-pro/inc/plugins/class-stripe-pro-features.php +++ b/plugins/otter-pro/inc/plugins/class-stripe-pro-features.php @@ -36,7 +36,7 @@ public function init() { */ public function autoresponder( $attributes, $stripe, $session_id ) { - if ( ! isset( $attributes['autoresponder'] ) ) { + if ( ! isset( $attributes['autoresponder'] ) || ! isset( $attributes['autoresponder']['subject'] ) || ! isset( $attributes['autoresponder']['body'] ) ) { return; } @@ -60,12 +60,12 @@ public function autoresponder( $attributes, $stripe, $session_id ) { $to = $email; $headers[] = 'Content-Type: text/html'; $headers[] = 'From: ' . get_bloginfo( 'name', 'display' ); - $subject = isset( $attributes['autoresponder']['subject'] ) ? $attributes['autoresponder']['subject'] : __( 'Thank you for your purchase', 'otter-blocks' ); - $body = isset( $attributes['autoresponder']['body'] ) ? $attributes['autoresponder']['body'] : __( 'Thank you for choosing our online store for your recent purchase. We greatly appreciate your business and trust in our products.', 'otter-blocks' ); + $subject = $attributes['autoresponder']['subject']; + $body = $attributes['autoresponder']['body']; // phpcs:ignore if ( wp_mail( $to, $subject, $body, $headers ) ) { - set_transient( $transient_key, true, 60 * 24 * 7 ); + set_transient( $transient_key, true, WEEK_IN_SECONDS ); } } diff --git a/src/blocks/blocks/form/inspector.js b/src/blocks/blocks/form/inspector.js index 198605425..4e64fccd1 100644 --- a/src/blocks/blocks/form/inspector.js +++ b/src/blocks/blocks/form/inspector.js @@ -261,7 +261,7 @@ const FormOptions = ({ formOptions, setFormOption, attributes, setAttributes }) false } - label={ __( 'Autoresponder (Pro)', 'otter-blocks' ) } + label={ __( 'Autoresponder', 'otter-blocks' ) } onDeselect={ () => {} } > { return ( - { GIFT2023 and you can use it on our website.


This is a template.', 'otter-blocks' )} rows={2} value={ undefined } onChange={ () => {} } @@ -80,7 +77,6 @@ const ProFeatures = () => { ) }
-
); }; diff --git a/src/pro/plugins/form/index.js b/src/pro/plugins/form/index.js index b0d4accdc..552784c35 100644 --- a/src/pro/plugins/form/index.js +++ b/src/pro/plugins/form/index.js @@ -4,24 +4,21 @@ import { __ } from '@wordpress/i18n'; import { __experimentalToolsPanelItem as ToolsPanelItem, - Button, - Modal, TextControl, FormTokenField, ToggleControl, Notice, SelectControl } from '@wordpress/components'; import { addFilter } from '@wordpress/hooks'; -import { useState, Fragment } from '@wordpress/element'; +import { Fragment } from '@wordpress/element'; /** * Internal dependencies */ import { Notice as OtterNotice } from '../../../blocks/components'; -import { RichTextEditor } from '../../../blocks/components'; import { FieldInputWidth, HideFieldLabelToggle } from '../../../blocks/blocks/form/common'; import { setSavedState } from '../../../blocks/helpers/helper-functions'; -import AutoreponderBodyModal from '../../components/autoresponder/index.js'; +import AutoresponderBodyModal from '../../components/autoresponder/index.js'; // +-------------- Autoresponder --------------+ diff --git a/src/pro/plugins/stripe-checkout/index.js b/src/pro/plugins/stripe-checkout/index.js index 5a381f8df..7187bd77a 100644 --- a/src/pro/plugins/stripe-checkout/index.js +++ b/src/pro/plugins/stripe-checkout/index.js @@ -1,9 +1,14 @@ +/** + * WordPress dependencies + */ import { Fragment } from '@wordpress/element'; -import { Notice, Notice as OtterNotice } from '../../../blocks/components'; import { __ } from '@wordpress/i18n'; -import { ExternalLink, PanelBody, TextareaControl, TextControl, ToggleControl } from '@wordpress/components'; -import { setUtm } from '../../../blocks/helpers/helper-functions'; import { addFilter } from '@wordpress/hooks'; +import { PanelBody, TextControl, ToggleControl } from '@wordpress/components'; + +/** + * Internal dependencies + */ import AutoresponderBodyModal from '../../components/autoresponder/index.js'; const Autoresponder = ( Template, attributes, setAttributes ) => { @@ -46,7 +51,7 @@ const Autoresponder = ( Template, attributes, setAttributes ) => { /> GIFT2023 and you can use it on our website.', 'otter-blocks' ) } onChange={ ( body ) => setAttributes({ autoresponder: { ...attributes.autoresponder, body }}) } /> ) From 4e8e5cbdfbe96dfb9901a3851c1b75df2b0974f4 Mon Sep 17 00:00:00 2001 From: "Soare Robert Daniel (Mac 2023)" Date: Tue, 30 May 2023 11:01:29 +0300 Subject: [PATCH 05/13] chore: minor --- .../blocks/stripe-checkout/inspector.js | 100 +++++++++--------- 1 file changed, 49 insertions(+), 51 deletions(-) diff --git a/src/blocks/blocks/stripe-checkout/inspector.js b/src/blocks/blocks/stripe-checkout/inspector.js index ab8aef8e1..b54cb7d5c 100644 --- a/src/blocks/blocks/stripe-checkout/inspector.js +++ b/src/blocks/blocks/stripe-checkout/inspector.js @@ -26,58 +26,56 @@ import { setUtm } from '../../helpers/helper-functions'; const ProFeatures = () => { return ( - - - {}} - help={__( - 'Enter the subject of the autoresponder email.', - 'otter-blocks' - )} - className="o-disabled" - /> - - GIFT2023 and you can use it on our website.


This is a template.', 'otter-blocks' )} - rows={2} - value={ undefined } - onChange={ () => {} } - help={ __( 'Enter the body of the autoresponder email.', 'otter-blocks' ) } - disabled - className="o-disabled" - /> - - { - ( ! Boolean( window?.otterPro?.isActive ) && Boolean( window?.themeisleGutenberg?.hasPro ) ) && ( - + {}} + help={__( + 'Enter the subject of the autoresponder email.', + 'otter-blocks' + )} + className="o-disabled" + /> + + GIFT2023 and you can use it on our website.


This is a template.', 'otter-blocks' )} + rows={2} + value={ undefined } + onChange={ () => {} } + help={ __( 'Enter the body of the autoresponder email.', 'otter-blocks' ) } + disabled + className="o-disabled" + /> + + { + ( ! Boolean( window?.otterPro?.isActive ) && Boolean( window?.themeisleGutenberg?.hasPro ) ) && ( + + ) + } + + { + ( ! Boolean( window?.themeisleGutenberg?.hasPro ) ) && ( +
+ { __( 'Unlock this with Otter Pro.', 'otter-blocks' ) } } + variant="upsell" /> - ) - } - - { - ( ! Boolean( window?.themeisleGutenberg?.hasPro ) ) && ( -
- { __( 'Unlock this with Otter Pro.', 'otter-blocks' ) } } - variant="upsell" - /> -

{ __( 'Automatically send follow-up emails to your users with the Autoresponder feature.', 'otter-blocks' ) }

-
- ) - } - - +

{ __( 'Automatically send follow-up emails to your users with the Autoresponder feature.', 'otter-blocks' ) }

+
+ ) + } +
); }; From cffc78cf609c2ffcfacb8498d7a00fbaea40830d Mon Sep 17 00:00:00 2001 From: "Soare Robert Daniel (Mac 2023)" Date: Thu, 8 Jun 2023 14:31:18 +0300 Subject: [PATCH 06/13] chore: improve text --- plugins/otter-pro/inc/plugins/class-stripe-pro-features.php | 3 +-- src/blocks/blocks/stripe-checkout/inspector.js | 1 + src/pro/plugins/stripe-checkout/index.js | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/plugins/otter-pro/inc/plugins/class-stripe-pro-features.php b/plugins/otter-pro/inc/plugins/class-stripe-pro-features.php index e2d38a2c1..ba93a67e8 100644 --- a/plugins/otter-pro/inc/plugins/class-stripe-pro-features.php +++ b/plugins/otter-pro/inc/plugins/class-stripe-pro-features.php @@ -47,12 +47,11 @@ public function autoresponder( $attributes, $stripe, $session_id ) { $transient_key = 'otter_stripe_checkout_' . $session_id; $transient = get_transient( $transient_key ); - if ( false !== $transient ) { return; } - $email = $stripe->get_session_email( $session_id ); + $email = $stripe->get_session_email( $session_id ); if ( ! $email ) { return; } diff --git a/src/blocks/blocks/stripe-checkout/inspector.js b/src/blocks/blocks/stripe-checkout/inspector.js index b54cb7d5c..e70aafce4 100644 --- a/src/blocks/blocks/stripe-checkout/inspector.js +++ b/src/blocks/blocks/stripe-checkout/inspector.js @@ -28,6 +28,7 @@ const ProFeatures = () => { return ( { { /> GIFT2023 and you can use it on our website.', 'otter-blocks' ) } + value={ attributes.autoresponder?.body ?? __( 'Message example: We appreciate your recent purchase made on our website. You have received a promotional code, namely EXAMPLE, which can be applied during checkout on our website.', 'otter-blocks' ) } onChange={ ( body ) => setAttributes({ autoresponder: { ...attributes.autoresponder, body }}) } /> ) From adb19188ff44e2f4de5998425f72ca4e937d2cb1 Mon Sep 17 00:00:00 2001 From: "Soare Robert Daniel (Mac 2023)" Date: Thu, 8 Jun 2023 16:09:05 +0300 Subject: [PATCH 07/13] chore: review --- inc/render/class-stripe-checkout-block.php | 4 +--- src/blocks/blocks/stripe-checkout/inspector.js | 7 ++----- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/inc/render/class-stripe-checkout-block.php b/inc/render/class-stripe-checkout-block.php index 81bedc1bb..f1e463b46 100644 --- a/inc/render/class-stripe-checkout-block.php +++ b/inc/render/class-stripe-checkout-block.php @@ -40,9 +40,7 @@ public function render( $attributes ) { if ( 'success' === $status ) { $message = isset( $attributes['successMessage'] ) ? wp_kses_post( $attributes['successMessage'] ) : __( 'Your payment was successful. If you have any questions, please email orders@example.com.', 'otter-blocks' ); - if ( has_action( 'otter_blocks_stripe_checkout_success' ) ) { - do_action( 'otter_blocks_stripe_checkout_success', $attributes, $stripe, $session_id ); - } + do_action( 'otter_blocks_stripe_checkout_success', $attributes, $stripe, $session_id ); } else { $message = isset( $attributes['cancelMessage'] ) ? wp_kses_post( $attributes['cancelMessage'] ) : __( 'Your payment was unsuccessful. If you have any questions, please email orders@example.com.', 'otter-blocks' ); } diff --git a/src/blocks/blocks/stripe-checkout/inspector.js b/src/blocks/blocks/stripe-checkout/inspector.js index e70aafce4..056815a60 100644 --- a/src/blocks/blocks/stripe-checkout/inspector.js +++ b/src/blocks/blocks/stripe-checkout/inspector.js @@ -36,8 +36,7 @@ const ProFeatures = () => { 'Thank you for your purchase', 'otter-blocks' )} - value={ undefined } - onChange={ () => {}} + disabled help={__( 'Enter the subject of the autoresponder email.', 'otter-blocks' @@ -47,10 +46,8 @@ const ProFeatures = () => { GIFT2023 and you can use it on our website.


This is a template.', 'otter-blocks' )} + placeholder={ __( 'W e appreciate your recent purchase made on our website. You have received a promotional code, namely EXAMPLE, which can be applied during checkout on our website', 'otter-blocks' )} rows={2} - value={ undefined } - onChange={ () => {} } help={ __( 'Enter the body of the autoresponder email.', 'otter-blocks' ) } disabled className="o-disabled" From 81f66e52067e76e1e34982170fff30e559c80a65 Mon Sep 17 00:00:00 2001 From: "Soare Robert Daniel (Mac 2023)" Date: Wed, 14 Jun 2023 11:48:16 +0300 Subject: [PATCH 08/13] chore: review --- src/pro/plugins/stripe-checkout/index.js | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/src/pro/plugins/stripe-checkout/index.js b/src/pro/plugins/stripe-checkout/index.js index 80366f1a8..60edc731c 100644 --- a/src/pro/plugins/stripe-checkout/index.js +++ b/src/pro/plugins/stripe-checkout/index.js @@ -12,15 +12,6 @@ import { PanelBody, TextControl, ToggleControl } from '@wordpress/components'; import AutoresponderBodyModal from '../../components/autoresponder/index.js'; const Autoresponder = ( Template, attributes, setAttributes ) => { - - if ( ! Boolean( window?.otterPro?.isActive ) ) { - return ( - - { Template } - - ); - } - return ( { ); }; -addFilter( 'otter.stripe-checkout.inspector', 'themeisle-gutenberg/stripe-checkout-inspector', Autoresponder ); +if ( Boolean( window?.otterPro?.isActive ) ) { + addFilter( 'otter.stripe-checkout.inspector', 'themeisle-gutenberg/stripe-checkout-inspector', Autoresponder ); +} + From fa5df786afa7e54a3122d950ec55a542fc6fd512 Mon Sep 17 00:00:00 2001 From: "Soare Robert Daniel (Mac 2023)" Date: Wed, 14 Jun 2023 12:03:40 +0300 Subject: [PATCH 09/13] chore: phpstan --- .../inc/plugins/class-stripe-pro-features.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/plugins/otter-pro/inc/plugins/class-stripe-pro-features.php b/plugins/otter-pro/inc/plugins/class-stripe-pro-features.php index ba93a67e8..ff5f80e98 100644 --- a/plugins/otter-pro/inc/plugins/class-stripe-pro-features.php +++ b/plugins/otter-pro/inc/plugins/class-stripe-pro-features.php @@ -8,13 +8,13 @@ namespace ThemeIsle\OtterPro\Plugins; /** - * Class Live_Search + * Class Stripe_Pro_Features */ class Stripe_Pro_Features { /** * The main instance var. * - * @var Live_Search + * @var Stripe_Pro_Features|null */ public static $instance = null; @@ -30,9 +30,9 @@ public function init() { /** * Autoresponder. * - * @param mixed $attributes Block attributes. - * @param \ThemeIsle\GutenbergBlocks\Plugins\Stripe_API $stripe Stripe API object. - * @param string $session_id Session ID. + * @param mixed $attributes Block attributes. + * @param \ThemeIsle\GutenbergBlocks\Plugins\Stripe_API|null $stripe Stripe API object. + * @param string|null $session_id Session ID. */ public function autoresponder( $attributes, $stripe, $session_id ) { @@ -75,7 +75,7 @@ public function autoresponder( $attributes, $stripe, $session_id ) { * @static * @since 1.7.1 * @access public - * @return Live_Search + * @return Stripe_Pro_Features */ public static function instance() { if ( is_null( self::$instance ) ) { From 640087434b51d74f4724c7571b7db39bfcbbedb9 Mon Sep 17 00:00:00 2001 From: "Soare Robert Daniel (Mac 2023)" Date: Tue, 20 Jun 2023 16:20:39 +0300 Subject: [PATCH 10/13] chore: wp_email phpcs --- inc/server/class-form-server.php | 8 ++++---- plugins/otter-pro/inc/plugins/class-form-pro-features.php | 2 +- .../otter-pro/inc/plugins/class-stripe-pro-features.php | 2 +- src/blocks/blocks/stripe-checkout/inspector.js | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/inc/server/class-form-server.php b/inc/server/class-form-server.php index a96a020a8..5ed878311 100644 --- a/inc/server/class-form-server.php +++ b/inc/server/class-form-server.php @@ -371,7 +371,7 @@ public function send_default_email( $form_data ) { } } - // phpcs:ignore + // phpcs:ignore WordPressVIPMinimum.Functions.RestrictedFunctions.wp_mail_wp_mail $email_was_send = wp_mail( $to, $email_subject, $email_body, $headers, $attachments ); if ( ! $email_was_send ) { $is_warning = Pro::is_pro_active() && strstr( $form_options->get_submissions_save_location(), 'database' ); @@ -541,8 +541,8 @@ public static function send_error_email( $form_data ) { // Sent the form date to the admin site as a default behaviour. $to = sanitize_email( get_site_option( 'admin_email' ) ); $headers = array( 'Content-Type: text/html; charset=UTF-8', 'From: ' . esc_url( get_site_url() ) ); - // phpcs:ignore - wp_mail( $to, $email_subject, $email_body, $headers ); + // phpcs:ignore WordPressVIPMinimum.Functions.RestrictedFunctions.wp_mail_wp_mail + wp_mail( $to, $email_subject, $email_body, $headers ); } /** @@ -563,7 +563,7 @@ public static function send_test_email( $form_data ) { $to = $form_data->get_payload_field( 'to' ); } $headers = array( 'Content-Type: text/html; charset=UTF-8', 'From: ' . get_bloginfo( 'name', 'display' ) . '<' . $to . '>' ); - // phpcs:ignore + // phpcs:ignore WordPressVIPMinimum.Functions.RestrictedFunctions.wp_mail_wp_mail $res->set_success( wp_mail( $to, $email_subject, $email_body, $headers ) ); } catch ( Exception $e ) { $res->set_code( Form_Data_Response::ERROR_RUNTIME_ERROR ); diff --git a/plugins/otter-pro/inc/plugins/class-form-pro-features.php b/plugins/otter-pro/inc/plugins/class-form-pro-features.php index 8b4394b4d..2ef9c3056 100644 --- a/plugins/otter-pro/inc/plugins/class-form-pro-features.php +++ b/plugins/otter-pro/inc/plugins/class-form-pro-features.php @@ -336,7 +336,7 @@ public function send_autoresponder( $form_data ) { $autoresponder = $form_data->get_form_options()->get_autoresponder(); $body = $this->replace_magic_tags( $autoresponder['body'], $form_data->get_form_inputs() ); - // phpcs:ignore + // phpcs:ignore WordPressVIPMinimum.Functions.RestrictedFunctions.wp_mail_wp_mail if ( ! wp_mail( $to, $autoresponder['subject'], $body, $headers ) ) { $form_data->add_warning( \ThemeIsle\GutenbergBlocks\Integration\Form_Data_Response::ERROR_AUTORESPONDER_COULD_NOT_SEND ); } diff --git a/plugins/otter-pro/inc/plugins/class-stripe-pro-features.php b/plugins/otter-pro/inc/plugins/class-stripe-pro-features.php index ff5f80e98..729c7f53b 100644 --- a/plugins/otter-pro/inc/plugins/class-stripe-pro-features.php +++ b/plugins/otter-pro/inc/plugins/class-stripe-pro-features.php @@ -62,7 +62,7 @@ public function autoresponder( $attributes, $stripe, $session_id ) { $subject = $attributes['autoresponder']['subject']; $body = $attributes['autoresponder']['body']; - // phpcs:ignore + // phpcs:ignore WordPressVIPMinimum.Functions.RestrictedFunctions.wp_mail_wp_mail if ( wp_mail( $to, $subject, $body, $headers ) ) { set_transient( $transient_key, true, WEEK_IN_SECONDS ); } diff --git a/src/blocks/blocks/stripe-checkout/inspector.js b/src/blocks/blocks/stripe-checkout/inspector.js index 056815a60..6e2497e1e 100644 --- a/src/blocks/blocks/stripe-checkout/inspector.js +++ b/src/blocks/blocks/stripe-checkout/inspector.js @@ -46,7 +46,7 @@ const ProFeatures = () => { EXAMPLE, which can be applied during checkout on our website', 'otter-blocks' )} + placeholder={ __( 'We appreciate your recent purchase made on our website. You have received a promotional code, namely EXAMPLE, which can be applied during checkout on our website', 'otter-blocks' )} rows={2} help={ __( 'Enter the body of the autoresponder email.', 'otter-blocks' ) } disabled From 13effce1452901b0d63418e951f1f1fcb7929c17 Mon Sep 17 00:00:00 2001 From: "Soare Robert Daniel (Mac 2023)" Date: Fri, 23 Jun 2023 11:00:39 +0300 Subject: [PATCH 11/13] chore: add area ID to RichTextEditor --- src/blocks/components/rich-text-editor/index.js | 17 ++++++++++++----- src/pro/components/autoresponder/index.js | 3 ++- src/pro/plugins/stripe-checkout/index.js | 5 ++++- 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/src/blocks/components/rich-text-editor/index.js b/src/blocks/components/rich-text-editor/index.js index 9a71a1158..dc7fb4177 100644 --- a/src/blocks/components/rich-text-editor/index.js +++ b/src/blocks/components/rich-text-editor/index.js @@ -20,10 +20,19 @@ const RichTextEditor = ({ value, onChange, help = '', - allowRawHTML = false + allowRawHTML = false, + area = '' }) => { const instanceId = useInstanceId( RichTextEditor ); + const editorRef = useRef( null ); + + const removeEditor = () => { + if ( editorRef?.current?.id !== undefined ) { + wp.oldEditor.remove( editorRef.current.id ); + } + }; + useEffect( () => { const settings = { classic_block_editor: true, // eslint-disable-line camelcase @@ -47,12 +56,10 @@ const RichTextEditor = ({ onChange( allowRawHTML ? decodeHTMLEntities( editor.getContent() ) : editor.getContent() ); }); - return () => editorRef?.current?.id !== undefined ? wp.oldEditor.remove( editorRef.current.id ) : undefined; + return removeEditor; }, []); - const id = `inspector-textarea-control-${ instanceId }`; - - const editorRef = useRef( null ); + const id = `inspector-textarea-control-${ instanceId }-${ area }`; const onChangeValue = ( e ) => onChange( e.target.value ); diff --git a/src/pro/components/autoresponder/index.js b/src/pro/components/autoresponder/index.js index e4b16a55b..fe89d7838 100644 --- a/src/pro/components/autoresponder/index.js +++ b/src/pro/components/autoresponder/index.js @@ -3,7 +3,7 @@ import { Button, Modal } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; import { RichTextEditor } from '../../../blocks/components'; -const AutoresponderBodyModal = ({ value, onChange }) => { +const AutoresponderBodyModal = ({ value, onChange, area }) => { const [ isOpen, setOpen ] = useState( false ); return ( @@ -19,6 +19,7 @@ const AutoresponderBodyModal = ({ value, onChange }) => { onChange={ onChange } help={ __( 'Enter the body of the autoresponder email.', 'otter-blocks' ) } allowRawHTML + area={ area } /> ) } diff --git a/src/pro/plugins/stripe-checkout/index.js b/src/pro/plugins/stripe-checkout/index.js index 60edc731c..98bfe5d86 100644 --- a/src/pro/plugins/stripe-checkout/index.js +++ b/src/pro/plugins/stripe-checkout/index.js @@ -44,7 +44,10 @@ const Autoresponder = ( Template, attributes, setAttributes ) => { EXAMPLE, which can be applied during checkout on our website.', 'otter-blocks' ) } - onChange={ ( body ) => setAttributes({ autoresponder: { ...attributes.autoresponder, body }}) } /> + onChange={ ( body ) => setAttributes({ autoresponder: { ...attributes.autoresponder, body }}) } + area="stripe-autoresponder" + /> + ) } From 2516cf19a8ad361085c45aeb8c1e99400fd36c31 Mon Sep 17 00:00:00 2001 From: "Soare Robert Daniel (Mac 2023)" Date: Fri, 7 Jul 2023 11:47:54 +0300 Subject: [PATCH 12/13] chore: stripe placeholders notification --- src/blocks/editor.scss | 4 ++++ src/pro/components/autoresponder/index.js | 5 +++-- src/pro/plugins/form/index.js | 2 +- src/pro/plugins/stripe-checkout/index.js | 10 ++++++++++ 4 files changed, 18 insertions(+), 3 deletions(-) diff --git a/src/blocks/editor.scss b/src/blocks/editor.scss index cf0af68f8..a4233aebc 100644 --- a/src/blocks/editor.scss +++ b/src/blocks/editor.scss @@ -145,3 +145,7 @@ svg.o-block-icon { } } } + +.o-autoresponder-margin { + margin-top: 10px; +} diff --git a/src/pro/components/autoresponder/index.js b/src/pro/components/autoresponder/index.js index fe89d7838..aa62ceb68 100644 --- a/src/pro/components/autoresponder/index.js +++ b/src/pro/components/autoresponder/index.js @@ -2,8 +2,9 @@ import { useState } from '@wordpress/element'; import { Button, Modal } from '@wordpress/components'; import { __ } from '@wordpress/i18n'; import { RichTextEditor } from '../../../blocks/components'; +import classNames from 'classnames'; -const AutoresponderBodyModal = ({ value, onChange, area }) => { +const AutoresponderBodyModal = ({ value, onChange, area, addExtraMargin }) => { const [ isOpen, setOpen ] = useState( false ); return ( @@ -23,10 +24,10 @@ const AutoresponderBodyModal = ({ value, onChange, area }) => { /> ) } -
diff --git a/src/pro/plugins/form/index.js b/src/pro/plugins/form/index.js index e8de165ac..7d4adee91 100644 --- a/src/pro/plugins/form/index.js +++ b/src/pro/plugins/form/index.js @@ -27,7 +27,7 @@ const AutoresponderBody = ({ formOptions, setFormOption }) => { setFormOption({ autoresponder: { ...formOptions.autoresponder, body }}); }; - return ; + return ; }; const helpMessages = { diff --git a/src/pro/plugins/stripe-checkout/index.js b/src/pro/plugins/stripe-checkout/index.js index 98bfe5d86..533e29e69 100644 --- a/src/pro/plugins/stripe-checkout/index.js +++ b/src/pro/plugins/stripe-checkout/index.js @@ -10,6 +10,7 @@ import { PanelBody, TextControl, ToggleControl } from '@wordpress/components'; * Internal dependencies */ import AutoresponderBodyModal from '../../components/autoresponder/index.js'; +import { Notice } from '../../../blocks/components'; const Autoresponder = ( Template, attributes, setAttributes ) => { return ( @@ -48,6 +49,15 @@ const Autoresponder = ( Template, attributes, setAttributes ) => { area="stripe-autoresponder" /> + { + ( ! Boolean( attributes.autoresponder?.title ) && ! Boolean( attributes.autoresponder.body ) ) && ( + + ) + } +
) } From 53e4c8324a904e62c90fb23014970f1456477d55 Mon Sep 17 00:00:00 2001 From: "Soare Robert Daniel (Mac 2023)" Date: Mon, 10 Jul 2023 13:23:51 +0300 Subject: [PATCH 13/13] chore: remove small notice for Stripe autoresponder --- src/pro/plugins/stripe-checkout/index.js | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/pro/plugins/stripe-checkout/index.js b/src/pro/plugins/stripe-checkout/index.js index 533e29e69..14bb4f927 100644 --- a/src/pro/plugins/stripe-checkout/index.js +++ b/src/pro/plugins/stripe-checkout/index.js @@ -48,16 +48,6 @@ const Autoresponder = ( Template, attributes, setAttributes ) => { onChange={ ( body ) => setAttributes({ autoresponder: { ...attributes.autoresponder, body }}) } area="stripe-autoresponder" /> - - { - ( ! Boolean( attributes.autoresponder?.title ) && ! Boolean( attributes.autoresponder.body ) ) && ( - - ) - } - ) }