Skip to content

Commit

Permalink
feat(donate-block): support modal checkout (#2256)
Browse files Browse the repository at this point in the history
  • Loading branch information
miguelpeixe authored Feb 28, 2023
1 parent b753543 commit 34226dd
Show file tree
Hide file tree
Showing 4 changed files with 184 additions and 12 deletions.
71 changes: 70 additions & 1 deletion assets/wizards/readerRevenue/views/donation/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
*/
import { useDispatch } from '@wordpress/data';
import { __ } from '@wordpress/i18n';
import { ToggleControl } from '@wordpress/components';
import { ToggleControl, CheckboxControl } from '@wordpress/components';

/**
* Internal dependencies.
Expand Down Expand Up @@ -54,11 +54,23 @@ type WizardData = {
currencySymbol: string;
tiered: boolean;
minimumDonation: string;
billingFields: string[];
};
donation_page: {
editUrl: string;
status: string;
};
available_billing_fields: {
[ key: string ]: {
autocomplete: string;
class: string[];
label: string;
priority: number;
required: boolean;
type: string;
validate: string[];
};
};
};

export const DonationAmounts = () => {
Expand Down Expand Up @@ -229,6 +241,62 @@ export const DonationAmounts = () => {
);
};

const BillingFields = () => {
const wizardData = Wizard.useWizardData( 'reader-revenue' ) as WizardData;

const { updateWizardSettings } = useDispatch( Wizard.STORE_NAMESPACE );

const changeHandler = path => value =>
updateWizardSettings( {
slug: 'newspack-reader-revenue-wizard',
path: [ 'donation_data', ...path ],
value,
} );

const availableFields = wizardData.available_billing_fields;
if ( ! availableFields || ! Object.keys( availableFields ).length ) {
return null;
}

const billingFields = wizardData.donation_data.billingFields.length
? wizardData.donation_data.billingFields
: Object.keys( availableFields );

return (
<>
<Card noBorder headerActions>
<SectionHeader
title={ __( 'Billing Fields', 'newspack' ) }
description={ __(
'Configure which billing fields should be rendered on the donation form.',
'newspack'
) }
noMargin
/>
</Card>
<Grid columns={ 3 } rowGap={ 16 }>
{ Object.keys( availableFields ).map( fieldKey => (
<CheckboxControl
key={ fieldKey }
label={ availableFields[ fieldKey ].label }
checked={ billingFields.includes( fieldKey ) }
disabled={ fieldKey === 'billing_email' } // Email is always required.
onChange={ () => {
let newFields = [ ...billingFields ];
if ( billingFields.includes( fieldKey ) ) {
newFields = newFields.filter( field => field !== fieldKey );
} else {
newFields = [ ...newFields, fieldKey ];
}
changeHandler( [ 'billingFields' ] )( newFields );
} }
/>
) ) }
</Grid>
</>
);
};

const Donation = () => {
const wizardData = Wizard.useWizardData( 'reader-revenue' ) as WizardData;

Expand Down Expand Up @@ -275,6 +343,7 @@ const Donation = () => {
</>
) }
<DonationAmounts />
<BillingFields />
<div className="newspack-buttons-card">
<Button variant="primary" onClick={ onSave } href={ undefined }>
{ __( 'Save Settings' ) }
Expand Down
94 changes: 93 additions & 1 deletion includes/class-donations.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ class Donations {
const DONATION_PRODUCT_ID_OPTION = 'newspack_donation_product_id';
const DONATION_PAGE_ID_OPTION = 'newspack_donation_page_id';
const DONATION_SETTINGS_OPTION = 'newspack_donations_settings';
const DONATION_BILLING_FIELDS_OPTION = 'newspack_donations_billing_fields';
const DONATION_ORDER_META_KEYS = [
'referer_tags' => [
'label' => 'Post Tags',
Expand Down Expand Up @@ -71,6 +72,8 @@ public static function init() {
add_filter( 'pre_option_woocommerce_enable_guest_checkout', [ __CLASS__, 'disable_guest_checkout' ] );
add_action( 'woocommerce_check_cart_items', [ __CLASS__, 'handle_cart' ] );
add_filter( 'amp_skip_post', [ __CLASS__, 'should_skip_amp' ], 10, 2 );
add_filter( 'newspack_blocks_donate_billing_fields_keys', [ __CLASS__, 'get_billing_fields' ] );
add_filter( 'woocommerce_thankyou_order_received_text', [ __CLASS__, 'woocommerce_thankyou_order_received_text' ], 100, 2 );
add_action( 'woocommerce_checkout_create_order_line_item', [ __CLASS__, 'checkout_create_order_line_item' ], 10, 4 );
}
}
Expand Down Expand Up @@ -375,7 +378,8 @@ public static function get_donation_settings() {
self::update_donation_product( [ 'minimumDonation' => $settings['minimumDonation'] ] );
}

$parsed_settings['platform'] = self::get_platform_slug();
$parsed_settings['platform'] = self::get_platform_slug();
$parsed_settings['billingFields'] = self::get_billing_fields();

return $parsed_settings;
}
Expand All @@ -397,6 +401,13 @@ public static function set_donation_settings( $args ) {
return $ready;
}
self::update_donation_product( $configuration );

// Update the billing fields.
$billing_fields = $args['billingFields'];
if ( ! empty( $billing_fields ) ) {
$billing_fields = array_map( 'sanitize_text_field', $billing_fields );
self::update_billing_fields( $billing_fields );
}
}

Logger::log( 'Save donation settings' );
Expand Down Expand Up @@ -583,6 +594,8 @@ public static function process_donation_form() {
return;
}

$is_modal_checkout = filter_input( INPUT_GET, 'modal_checkout', FILTER_SANITIZE_NUMBER_INT );

// Parse values from the form.
$donation_frequency = filter_input( INPUT_GET, 'donation_frequency', FILTER_SANITIZE_FULL_SPECIAL_CHARS );
if ( ! $donation_frequency ) {
Expand Down Expand Up @@ -669,6 +682,9 @@ function ( $item ) {
if ( ! empty( $referer_categories ) ) {
$query_args['referer_categories'] = implode( ',', $referer_categories );
}
if ( $is_modal_checkout ) {
$query_args['modal_checkout'] = 1;
}

// Pass through UTM params so they can be forwarded to the WooCommerce checkout flow.
foreach ( $params as $param => $value ) {
Expand Down Expand Up @@ -912,6 +928,30 @@ public static function can_use_streamlined_donate_block() {
return false;
}

/**
* Whether the WC cart contains a donation product.
*
* @return bool
*/
public static function is_donation_cart() {
if ( ! self::is_platform_wc() ) {
return false;
}
$donation_products_ids = array_values( self::get_donation_product_child_products_ids() );
if ( empty( $donation_products_ids ) ) {
return false;
}
if ( ! WC()->cart || ! WC()->cart->cart_contents || ! is_array( WC()->cart->cart_contents ) ) {
return false;
}
foreach ( WC()->cart->cart_contents as $prod_in_cart ) {
if ( isset( $prod_in_cart['product_id'] ) && in_array( $prod_in_cart['product_id'], $donation_products_ids ) ) {
return true;
}
}
return false;
}

/**
* Manipulate WC's cart, if needed.
* If WC is not the donations platform, the donation products should not be buyable.
Expand All @@ -927,5 +967,57 @@ public static function handle_cart() {
}
}
}

/**
* Get the checkout billing fields keys for the donation form.
*
* @return string[]
*/
public static function get_billing_fields() {
$billing_fields = get_option( self::DONATION_BILLING_FIELDS_OPTION, [] );

// If empty, return empty array so it uses the default.
if ( empty( $billing_fields ) ) {
return $billing_fields;
}

// Email is required, so it should always be in the list.
if ( ! in_array( 'billing_email', $billing_fields, true ) ) {
$billing_fields[] = 'billing_email';
}

return $billing_fields;
}

/**
* Update the checkout billing fields keys for the donation form.
*
* @param string[] $billing_fields Checkout fields keys.
*
* @return string[] Updated checkout fields keys.
*/
public static function update_billing_fields( $billing_fields ) {
update_option( self::DONATION_BILLING_FIELDS_OPTION, $billing_fields );
return $billing_fields;
}

/**
* Get the donation "thank you, order received" text.
*
* @param string $text The text to display.
* @param object $order The order object.
*
* @return string
*/
public static function woocommerce_thankyou_order_received_text( $text, $order ) {
if ( ! $order ) {
return $text;
}
$product_id = self::get_order_donation_product_id( $order->get_id() );
if ( ! $product_id ) {
return $text;
}
return __( 'Thank you for your donation!', 'newspack-blocks' );
}
}
Donations::init();
30 changes: 20 additions & 10 deletions includes/wizards/class-reader-revenue-wizard.php
Original file line number Diff line number Diff line change
Expand Up @@ -432,19 +432,29 @@ public function fetch_all_data() {
$stripe_data = Stripe_Connection::get_stripe_data();
$stripe_data['can_use_stripe_platform'] = Donations::can_use_stripe_platform();

$billing_fields = [];
if ( $wc_installed && Donations::is_platform_wc() ) {
$checkout = new \WC_Checkout();
$fields = $checkout->get_checkout_fields();
if ( ! empty( $fields['billing'] ) ) {
$billing_fields = $fields['billing'];
}
}

$args = [
'country_state_fields' => newspack_get_countries(),
'currency_fields' => newspack_get_currencies_options(),
'location_data' => [],
'stripe_data' => $stripe_data,
'donation_data' => Donations::get_donation_settings(),
'donation_page' => Donations::get_donation_page_info(),
'salesforce_settings' => [],
'platform_data' => [
'country_state_fields' => newspack_get_countries(),
'currency_fields' => newspack_get_currencies_options(),
'location_data' => [],
'stripe_data' => $stripe_data,
'donation_data' => Donations::get_donation_settings(),
'donation_page' => Donations::get_donation_page_info(),
'available_billing_fields' => $billing_fields,
'salesforce_settings' => [],
'platform_data' => [
'platform' => $platform,
],
'is_ssl' => is_ssl(),
'errors' => [],
'is_ssl' => is_ssl(),
'errors' => [],
];
if ( 'wc' === $platform && $wc_installed ) {
$plugin_status = true;
Expand Down
1 change: 1 addition & 0 deletions tests/unit-tests/donations.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ public function test_donations_settings() {
'platform',
'minimumDonation',
'currencySymbol',
'billingFields',
],
array_keys( $donation_settings ),
'Donation settings have the expected keys.'
Expand Down

0 comments on commit 34226dd

Please sign in to comment.