Skip to content

Commit

Permalink
feat: add option for a button after checkout
Browse files Browse the repository at this point in the history
  • Loading branch information
leogermani committed Aug 30, 2023
1 parent f1fcf22 commit 53690bd
Show file tree
Hide file tree
Showing 6 changed files with 130 additions and 7 deletions.
49 changes: 42 additions & 7 deletions includes/class-modal-checkout.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,15 +43,21 @@ public static function init() {
add_filter( 'woocommerce_checkout_get_value', [ __CLASS__, 'woocommerce_checkout_get_value' ], 10, 2 );
add_filter( 'woocommerce_checkout_fields', [ __CLASS__, 'woocommerce_checkout_fields' ] );
add_filter( 'woocommerce_update_order_review_fragments', [ __CLASS__, 'order_review_fragments' ] );
add_action( 'woocommerce_thankyou', [ __CLASS__, 'woocommerce_thankyou' ] ); // Core Woo, not present in Newspack theme custom template.
add_action( 'newspack_woocommerce_thankyou', [ __CLASS__, 'woocommerce_thankyou' ] ); // Newspack Theme.
}

/**
* Process checkout request for modal.
*/
public static function process_checkout_request() {
$is_newspack_checkout = filter_input( INPUT_GET, 'newspack_checkout', FILTER_SANITIZE_NUMBER_INT );
$product_id = filter_input( INPUT_GET, 'product_id', FILTER_SANITIZE_NUMBER_INT );
$variation_id = filter_input( INPUT_GET, 'variation_id', FILTER_SANITIZE_NUMBER_INT );
$is_newspack_checkout = filter_input( INPUT_GET, 'newspack_checkout', FILTER_SANITIZE_NUMBER_INT );
$product_id = filter_input( INPUT_GET, 'product_id', FILTER_SANITIZE_NUMBER_INT );
$variation_id = filter_input( INPUT_GET, 'variation_id', FILTER_SANITIZE_NUMBER_INT );
$after_success_behavior = filter_input( INPUT_GET, 'after_success_behavior', FILTER_SANITIZE_STRING );
$after_success_url = filter_input( INPUT_GET, 'after_success_url', FILTER_SANITIZE_STRING );
$after_success_button_label = filter_input( INPUT_GET, 'after_success_button_label', FILTER_SANITIZE_STRING );

if ( ! $is_newspack_checkout || ! $product_id ) {
return;
}
Expand All @@ -70,6 +76,8 @@ public static function process_checkout_request() {
wp_parse_str( $parsed_url['query'], $params );
}

$params = array_merge( $params, compact( 'after_success_behavior', 'after_success_url', 'after_success_button_label' ) );

if ( function_exists( 'wpcom_vip_url_to_postid' ) ) {
$referer_post_id = wpcom_vip_url_to_postid( $referer );
} else {
Expand Down Expand Up @@ -134,9 +142,9 @@ function ( $item ) {
}
$query_args['modal_checkout'] = 1;

// Pass through UTM params so they can be forwarded to the WooCommerce checkout flow.
// Pass through UTM and after_success params so they can be forwarded to the WooCommerce checkout flow.
foreach ( $params as $param => $value ) {
if ( 'utm' === substr( $param, 0, 3 ) ) {
if ( 'utm' === substr( $param, 0, 3 ) || 'after_success' === substr( $param, 0, 13 ) ) {
$param = sanitize_text_field( $param );
$query_args[ $param ] = sanitize_text_field( $value );
}
Expand Down Expand Up @@ -319,10 +327,14 @@ public static function woocommerce_get_return_url( $url ) {
if ( ! isset( $_REQUEST['modal_checkout'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
return $url;
}

return add_query_arg(
[
'modal_checkout' => '1',
'email' => isset( $_REQUEST['billing_email'] ) ? rawurlencode( sanitize_email( wp_unslash( $_REQUEST['billing_email'] ) ) ) : '', // phpcs:ignore WordPress.Security.NonceVerification.Recommended
'modal_checkout' => '1',
'email' => isset( $_REQUEST['billing_email'] ) ? rawurlencode( sanitize_email( wp_unslash( $_REQUEST['billing_email'] ) ) ) : '', // phpcs:ignore WordPress.Security.NonceVerification.Recommended
'after_success_behavior' => isset( $_REQUEST['after_success_behavior'] ) ? rawurlencode( sanitize_text_field( wp_unslash( $_REQUEST['after_success_behavior'] ) ) ) : '', // phpcs:ignore WordPress.Security.NonceVerification.Recommended
'after_success_url' => isset( $_REQUEST['after_success_url'] ) ? rawurlencode( sanitize_text_field( wp_unslash( $_REQUEST['after_success_url'] ) ) ) : '', // phpcs:ignore WordPress.Security.NonceVerification.Recommended
'after_success_button_label' => isset( $_REQUEST['after_success_button_label'] ) ? rawurlencode( sanitize_text_field( wp_unslash( $_REQUEST['after_success_button_label'] ) ) ) : '', // phpcs:ignore WordPress.Security.NonceVerification.Recommended
],
$url
);
Expand Down Expand Up @@ -533,5 +545,28 @@ public static function order_review_fragments( $fragments ) {
}
return $fragments;
}

/**
* Adds an additional button to the Thank you page
*
* @return void
*/
public static function woocommerce_thankyou() {
// phpcs:disable WordPress.Security.NonceVerification.Recommended
if ( ! isset( $_REQUEST['modal_checkout'] ) ||
empty( $_REQUEST['after_success_behavior'] ) ||
empty( $_REQUEST['after_success_button_label'] ) ||
empty( $_REQUEST['after_success_url'] )
) {
return;
}

?>
<a class="button" href="<?php echo esc_url( sanitize_text_field( wp_unslash( $_REQUEST['after_success_url'] ) ) ); ?>">
<?php echo esc_html( sanitize_text_field( wp_unslash( $_REQUEST['after_success_button_label'] ) ) ); ?>
</a>
<?php
// phpcs:enable
}
}
Modal_Checkout::init();
9 changes: 9 additions & 0 deletions src/blocks/checkout-button/block.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,15 @@
},
"gradient": {
"type": "string"
},
"afterSuccessBehavior": {
"type": "string"
},
"afterSuccessButtonLabel": {
"type": "string"
},
"afterSuccessURL": {
"type": "string"
}
},
"supports": {
Expand Down
45 changes: 45 additions & 0 deletions src/blocks/checkout-button/edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,48 @@ function ProductControl( props ) {
);
}

function RedirectAfterSuccess( props ) {
const { attributes, setAttributes } = props;
return (
<>
<SelectControl
label={ __( 'Redirect after success', 'newspack-blocks' ) }
help={ __(
'Select whether the user should be presented with a button to navigate after a successfull purchase.',
'newspack-blocks'
) }
value={ attributes.afterSuccessBehavior }
options={ [
{ label: __( 'Do not show a button', 'newspack-blocks' ), value: '' },
{ label: __( 'Go to a custom URL', 'newspack-blocks' ), value: 'custom' },
{ label: __( 'Go to the referrer page', 'newspack-blocks' ), value: 'referrer' },
] }
onChange={ value => {
setAttributes( { afterSuccessBehavior: value.toString() } );
} }
/>
{ attributes.afterSuccessBehavior !== '' && (
<>
<TextControl
label={ __( 'Button Label', 'newspack-blocks' ) }
placeholder={ __( 'Continue browsing', 'newspack-blocks' ) }
value={ attributes.afterSuccessButtonLabel || '' }
onChange={ value => setAttributes( { afterSuccessButtonLabel: value } ) }
/>
{ attributes.afterSuccessBehavior === 'custom' && (
<TextControl
label={ __( 'Custom URL', 'newspack-blocks' ) }
placeholder={ __( 'https://example.com', 'newspack-blocks' ) }
value={ attributes.afterSuccessURL || '' }
onChange={ value => setAttributes( { afterSuccessURL: value } ) }
/>
) }
</>
) }
</>
);
}

function CheckoutButtonEdit( props ) {
const { attributes, setAttributes, className } = props;
const { placeholder, style, text, product, price, variation } = attributes;
Expand Down Expand Up @@ -291,6 +333,9 @@ function CheckoutButtonEdit( props ) {
) }
</ProductControl>
</PanelBody>
<PanelBody title={ __( 'After purchase', 'newspack-blocks' ) }>
<RedirectAfterSuccess setAttributes={ setAttributes } attributes={ attributes } />
</PanelBody>
{ nyp?.isNYP && (
<PanelBody title={ __( 'Name Your Price', 'newspack-blocks' ) }>
<p>
Expand Down
12 changes: 12 additions & 0 deletions src/blocks/checkout-button/save.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,18 @@ export default function save( { attributes, className } ) {
/>
<input type="hidden" name="product_id" value={ product } />
<input type="hidden" name="newspack_checkout" value="1" />
<input
type="hidden"
name="after_success_behavior"
value={ attributes.afterSuccessBehavior }
/>
<input
type="hidden"
name="after_success_button_label"
value={ attributes.afterSuccessButtonLabel }
/>
<input type="hidden" name="after_success_url" value={ attributes.afterSuccessURL } />

{ price && <input type="hidden" name="price" value={ price } /> }
{ variation && <input type="hidden" name="variation_id" value={ variation } /> }
{ is_variable && <input type="hidden" name="is_variable" value="1" /> }
Expand Down
14 changes: 14 additions & 0 deletions src/modal-checkout/modal.js
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,20 @@ domReady( () => {
forms.forEach( form => {
form.appendChild( modalCheckoutInput.cloneNode() );
form.target = iframeName;

// Fill in the referrer field.
const afterSuccessUrlInput = form.querySelector( 'input[name="after_success_url"]' );
const afterSuccessBehaviorInput = form.querySelector(
'input[name="after_success_behavior"]'
);
if (
afterSuccessBehaviorInput &&
afterSuccessUrlInput &&
'referrer' === afterSuccessBehaviorInput.getAttribute( 'value' )
) {
afterSuccessUrlInput.setAttribute( 'value', document.referrer );
}

form.addEventListener( 'submit', ev => {
const formData = new FormData( form );
// Clear any open variation modal.
Expand Down
8 changes: 8 additions & 0 deletions src/modal-checkout/templates/checkout-form.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@
$form_method = $edit_billing ? 'get' : 'post';
$form_billing_fields = \Newspack_Blocks\Modal_Checkout::get_prefilled_fields();

$after_success_behavior = filter_input( INPUT_GET, 'after_success_behavior', FILTER_SANITIZE_STRING );
$after_success_url = filter_input( INPUT_GET, 'after_success_url', FILTER_SANITIZE_STRING );
$after_success_button_label = filter_input( INPUT_GET, 'after_success_button_label', FILTER_SANITIZE_STRING );

if ( $edit_billing ) {
$form_class .= ' edit-billing';
}
Expand Down Expand Up @@ -70,6 +74,10 @@
<form name="checkout" method="<?php echo esc_attr( $form_method ); ?>" class="<?php echo esc_attr( $form_class ); ?>" action="<?php echo esc_url( $form_action ); ?>" enctype="multipart/form-data">

<input type="hidden" name="modal_checkout" value="1" />
<input type="hidden" name="after_success_behavior" value="<?php echo esc_attr( $after_success_behavior ); ?>" />
<input type="hidden" name="after_success_url" value="<?php echo esc_attr( $after_success_url ); ?>" />
<input type="hidden" name="after_success_button_label" value="<?php echo esc_attr( $after_success_button_label ); ?>" />

<?php
if ( $edit_billing ) {
wp_nonce_field( 'newspack_blocks_edit_billing', 'newspack_blocks_edit_billing_nonce' );
Expand Down

0 comments on commit 53690bd

Please sign in to comment.