Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Autoresponder to Stripe #1675

Merged
merged 15 commits into from
Jul 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions inc/plugins/class-stripe-api.php
Original file line number Diff line number Diff line change
Expand Up @@ -321,4 +321,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'];
}
}
2 changes: 2 additions & 0 deletions inc/render/class-stripe-checkout-block.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ 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 [email protected].', 'otter-blocks' );

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 [email protected].', 'otter-blocks' );
}
Expand Down
8 changes: 4 additions & 4 deletions inc/server/class-form-server.php
Original file line number Diff line number Diff line change
Expand Up @@ -376,7 +376,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' );
Expand Down Expand Up @@ -546,8 +546,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 );
}

/**
Expand All @@ -568,7 +568,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 );
Expand Down
1 change: 1 addition & 0 deletions plugins/otter-pro/inc/class-main.php
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
2 changes: 1 addition & 1 deletion plugins/otter-pro/inc/plugins/class-form-pro-features.php
Original file line number Diff line number Diff line change
Expand Up @@ -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 );
}
Expand Down
115 changes: 115 additions & 0 deletions plugins/otter-pro/inc/plugins/class-stripe-pro-features.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
<?php
/**
* Stripe Pro Features.
*
* @package ThemeIsle\OtterPro\Plugins
*/

namespace ThemeIsle\OtterPro\Plugins;

/**
* Class Stripe_Pro_Features
*/
class Stripe_Pro_Features {
/**
* The main instance var.
*
* @var Stripe_Pro_Features|null
*/
public static $instance = null;

/**
* Initialize the class
*/
public function init() {
if ( License::has_active_license() ) {
add_action( 'otter_blocks_stripe_checkout_success', array( $this, 'autoresponder' ), 10, 3 );
}
}

/**
* Autoresponder.
*
* @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 ) {

if ( ! isset( $attributes['autoresponder'] ) || ! isset( $attributes['autoresponder']['subject'] ) || ! isset( $attributes['autoresponder']['body'] ) ) {
return;
}

if ( empty( $session_id ) || empty( $stripe ) ) {
return;
}

$transient_key = 'otter_stripe_checkout_' . $session_id;

$transient = get_transient( $transient_key );
if ( false !== $transient ) {
return;
}

$email = $stripe->get_session_email( $session_id );
if ( ! $email ) {
return;
}

$to = $email;
$headers[] = 'Content-Type: text/html';
$headers[] = 'From: ' . get_bloginfo( 'name', 'display' );
$subject = $attributes['autoresponder']['subject'];
$body = $attributes['autoresponder']['body'];

// phpcs:ignore WordPressVIPMinimum.Functions.RestrictedFunctions.wp_mail_wp_mail
if ( wp_mail( $to, $subject, $body, $headers ) ) {
set_transient( $transient_key, true, WEEK_IN_SECONDS );
}
}

/**
* The instance method for the static class.
* Defines and returns the instance of the static class.
*
* @static
* @since 1.7.1
* @access public
* @return Stripe_Pro_Features
*/
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&#8217; 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&#8217; huh?', 'otter-blocks' ), '1.0.0' );
}
}
2 changes: 1 addition & 1 deletion src/blocks/blocks/form/inspector.js
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ const FormOptions = ({ formOptions, setFormOption, attributes, setAttributes })
</ToolsPanelItem>
<ToolsPanelItem
hasValue={ () => false }
label={ __( 'Autoresponder (Pro)', 'otter-blocks' ) }
label={ __( 'Autoresponder', 'otter-blocks' ) }
onDeselect={ () => {} }
>
<TextControl
Expand Down
5 changes: 4 additions & 1 deletion src/blocks/blocks/stripe-checkout/block.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,14 @@
},
"cancelMessage": {
"type": "string"
},
"autoresponder": {
"type": "object"
}
},
"supports": {
"html": false
},
"editorStyle": "otter-stripe-checkout-editor",
"style": "otter-stripe-checkout-style"
}
}
70 changes: 66 additions & 4 deletions src/blocks/blocks/stripe-checkout/inspector.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
* WordPress dependencies
*/
import { __ } from '@wordpress/i18n';

import { Fragment, useState } from '@wordpress/element';
import { applyFilters } from '@wordpress/hooks';
import { InspectorControls } from '@wordpress/block-editor';

import {
Expand All @@ -13,14 +14,68 @@ 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 as OtterNotice, Notice, RichTextEditor } from '../../components/index.js';
import { setUtm } from '../../helpers/helper-functions';

const ProFeatures = () => {
return (
<PanelBody
title={ __( 'Autoresponder', 'otter-blocks' ) }
initialOpen={ false }
>
<TextControl
label={__( 'Autoresponder Subject', 'otter-blocks' )}
placeholder={__(
'Thank you for your purchase',
'otter-blocks'
)}
disabled
help={__(
'Enter the subject of the autoresponder email.',
'otter-blocks'
)}
className="o-disabled"
/>

<TextareaControl
label={ __( 'Autoresponder Body', 'otter-blocks' ) }
placeholder={ __( 'We appreciate your recent purchase made on our website. You have received a promotional code, namely <strong>EXAMPLE</strong>, which can be applied during checkout on our <a href="https://themeisle.com/plugins/otter-blocks/">website</a>', 'otter-blocks' )}
rows={2}
help={ __( 'Enter the body of the autoresponder email.', 'otter-blocks' ) }
disabled
className="o-disabled"
/>

{
( ! Boolean( window?.otterPro?.isActive ) && Boolean( window?.themeisleGutenberg?.hasPro ) ) && (
<OtterNotice
notice={ __( 'You need to activate Otter Pro.', 'otter-blocks' ) }
instructions={ __( 'You need to activate your Otter Pro license to use Pro features of Stripe Checkout.', 'otter-blocks' ) }
/>
)
}

{
( ! Boolean( window?.themeisleGutenberg?.hasPro ) ) && (
<div>
<Notice
notice={ <ExternalLink href={ setUtm( window.themeisleGutenberg.upgradeLink, 'form-block' ) }>{ __( 'Unlock this with Otter Pro.', 'otter-blocks' ) }</ExternalLink> }
variant="upsell"
/>
<p className="description">{ __( 'Automatically send follow-up emails to your users with the Autoresponder feature.', 'otter-blocks' ) }</p>
</div>
)
}
</PanelBody>
);
};

const Inspector = ({
attributes,
Expand Down Expand Up @@ -160,6 +215,13 @@ const Inspector = ({
{ __( 'Save API Key', 'otter-blocks' ) }
</Button>
</PanelBody>

{ applyFilters(
'otter.stripe-checkout.inspector',
<ProFeatures />,
attributes,
setAttributes
) }
</InspectorControls>
);
};
Expand Down
4 changes: 4 additions & 0 deletions src/blocks/blocks/stripe-checkout/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ type Attributes = {
price: string
successMessage: string
cancelMessage: string
autoresponder: {
subject: string
body: string
}
}

export type StripeCheckoutProps = BlockProps<Attributes>
Expand Down
17 changes: 12 additions & 5 deletions src/blocks/components/rich-text-editor/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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 );

Expand Down
4 changes: 4 additions & 0 deletions src/blocks/editor.scss
Original file line number Diff line number Diff line change
Expand Up @@ -145,3 +145,7 @@ svg.o-block-icon {
}
}
}

.o-autoresponder-margin {
margin-top: 10px;
}
Loading