diff --git a/_inc/lib/class-jetpack-currencies.php b/_inc/lib/class-jetpack-currencies.php
new file mode 100644
index 000000000000..adebcf2b94d7
--- /dev/null
+++ b/_inc/lib/class-jetpack-currencies.php
@@ -0,0 +1,176 @@
+ array(
+ 'format' => '%1$s%2$s', // 1: Symbol 2: currency value
+ 'symbol' => '$',
+ 'decimal' => 2,
+ ),
+ 'GBP' => array(
+ 'format' => '%1$s%2$s', // 1: Symbol 2: currency value
+ 'symbol' => '£',
+ 'decimal' => 2,
+ ),
+ 'JPY' => array(
+ 'format' => '%1$s%2$s', // 1: Symbol 2: currency value
+ 'symbol' => '¥',
+ 'decimal' => 0,
+ ),
+ 'BRL' => array(
+ 'format' => '%1$s%2$s', // 1: Symbol 2: currency value
+ 'symbol' => 'R$',
+ 'decimal' => 2,
+ ),
+ 'EUR' => array(
+ 'format' => '%1$s%2$s', // 1: Symbol 2: currency value
+ 'symbol' => '€',
+ 'decimal' => 2,
+ ),
+ 'NZD' => array(
+ 'format' => '%1$s%2$s', // 1: Symbol 2: currency value
+ 'symbol' => 'NZ$',
+ 'decimal' => 2,
+ ),
+ 'AUD' => array(
+ 'format' => '%1$s%2$s', // 1: Symbol 2: currency value
+ 'symbol' => 'A$',
+ 'decimal' => 2,
+ ),
+ 'CAD' => array(
+ 'format' => '%1$s%2$s', // 1: Symbol 2: currency value
+ 'symbol' => 'C$',
+ 'decimal' => 2,
+ ),
+ 'ILS' => array(
+ 'format' => '%2$s %1$s', // 1: Symbol 2: currency value
+ 'symbol' => '₪',
+ 'decimal' => 2,
+ ),
+ 'RUB' => array(
+ 'format' => '%2$s %1$s', // 1: Symbol 2: currency value
+ 'symbol' => '₽',
+ 'decimal' => 2,
+ ),
+ 'MXN' => array(
+ 'format' => '%1$s%2$s', // 1: Symbol 2: currency value
+ 'symbol' => 'MX$',
+ 'decimal' => 2,
+ ),
+ 'MYR' => array(
+ 'format' => '%2$s%1$s', // 1: Symbol 2: currency value
+ 'symbol' => 'RM',
+ 'decimal' => 2,
+ ),
+ 'SEK' => array(
+ 'format' => '%2$s %1$s', // 1: Symbol 2: currency value
+ 'symbol' => 'Skr',
+ 'decimal' => 2,
+ ),
+ 'HUF' => array(
+ 'format' => '%2$s %1$s', // 1: Symbol 2: currency value
+ 'symbol' => 'Ft',
+ 'decimal' => 0, // Decimals are supported by Stripe but not by PayPal.
+ ),
+ 'CHF' => array(
+ 'format' => '%2$s %1$s', // 1: Symbol 2: currency value
+ 'symbol' => 'CHF',
+ 'decimal' => 2,
+ ),
+ 'CZK' => array(
+ 'format' => '%2$s %1$s', // 1: Symbol 2: currency value
+ 'symbol' => 'Kč',
+ 'decimal' => 2,
+ ),
+ 'DKK' => array(
+ 'format' => '%2$s %1$s', // 1: Symbol 2: currency value
+ 'symbol' => 'Dkr',
+ 'decimal' => 2,
+ ),
+ 'HKD' => array(
+ 'format' => '%2$s %1$s', // 1: Symbol 2: currency value
+ 'symbol' => 'HK$',
+ 'decimal' => 2,
+ ),
+ 'NOK' => array(
+ 'format' => '%2$s %1$s', // 1: Symbol 2: currency value
+ 'symbol' => 'Kr',
+ 'decimal' => 2,
+ ),
+ 'PHP' => array(
+ 'format' => '%2$s %1$s', // 1: Symbol 2: currency value
+ 'symbol' => '₱',
+ 'decimal' => 2,
+ ),
+ 'PLN' => array(
+ 'format' => '%2$s %1$s', // 1: Symbol 2: currency value
+ 'symbol' => 'PLN',
+ 'decimal' => 2,
+ ),
+ 'SGD' => array(
+ 'format' => '%1$s%2$s', // 1: Symbol 2: currency value
+ 'symbol' => 'S$',
+ 'decimal' => 2,
+ ),
+ 'TWD' => array(
+ 'format' => '%1$s%2$s', // 1: Symbol 2: currency value
+ 'symbol' => 'NT$',
+ 'decimal' => 0, // Decimals are supported by Stripe but not by PayPal.
+ ),
+ 'THB' => array(
+ 'format' => '%2$s%1$s', // 1: Symbol 2: currency value
+ 'symbol' => '฿',
+ 'decimal' => 2,
+ ),
+ 'INR' => array(
+ 'format' => '%2$s %1$s', // 1: Symbol 2: currency value
+ 'symbol' => '₹',
+ 'decimal' => 0,
+ ),
+ );
+
+ /**
+ * Format a price with currency.
+ *
+ * Uses currency-aware formatting to output a formatted price with a simple fallback.
+ *
+ * Largely inspired by WordPress.com's Store_Price::display_currency
+ *
+ * @param string $price Price.
+ * @param string $currency Currency.
+ * @param bool $symbol Whether to display the currency symbol.
+ * @return string Formatted price.
+ */
+ public static function format_price( $price, $currency, $symbol = true ) {
+ // Fall back to unspecified currency symbol like `¤1,234.05`.
+ // @link https://en.wikipedia.org/wiki/Currency_sign_(typography).
+ if ( ! array_key_exists( $currency, self::CURRENCIES ) ) {
+ return '¤' . number_format_i18n( $price, 2 );
+ }
+
+ $currency_details = self::CURRENCIES[ $currency ];
+
+ // Ensure USD displays as 1234.56 even in non-US locales.
+ $amount = 'USD' === $currency
+ ? number_format( $price, $currency_details['decimal'], '.', ',' )
+ : number_format_i18n( $price, $currency_details['decimal'] );
+
+ return sprintf(
+ $currency_details['format'],
+ $symbol ? $currency_details['symbol'] : '',
+ $amount
+ );
+ }
+}
diff --git a/bin/phpcs-requirelist.js b/bin/phpcs-requirelist.js
index 244d96f147cb..30926fdf56f3 100644
--- a/bin/phpcs-requirelist.js
+++ b/bin/phpcs-requirelist.js
@@ -23,6 +23,7 @@ module.exports = [
'_inc/lib/admin-pages/class-jetpack-about-page.php',
'_inc/lib/class.media-extractor.php',
'_inc/lib/class.media-summary.php',
+ '_inc/lib/class-jetpack-currencies.php',
'_inc/lib/class-jetpack-instagram-gallery-helper.php',
'_inc/lib/class-jetpack-tweetstorm-helper.php',
'_inc/lib/class-jetpack-mapbox-helper.php',
diff --git a/extensions/blocks/donations/attributes.js b/extensions/blocks/donations/attributes.js
deleted file mode 100644
index 6c53e5672532..000000000000
--- a/extensions/blocks/donations/attributes.js
+++ /dev/null
@@ -1,56 +0,0 @@
-/**
- * WordPress dependencies
- */
-import { __ } from '@wordpress/i18n';
-
-export default {
- currency: {
- type: 'string',
- default: 'USD',
- },
- oneTimeDonation: {
- type: 'object',
- default: {
- show: true,
- planId: null,
- amounts: [ 5, 15, 100 ],
- heading: __( 'Make a one-time donation', 'jetpack' ),
- extraText: __( 'Your contribution is appreciated.', 'jetpack' ),
- buttonText: __( 'Donate', 'jetpack' ),
- },
- },
- monthlyDonation: {
- type: 'object',
- default: {
- show: true,
- planId: null,
- amounts: [ 5, 15, 100 ],
- heading: __( 'Make a monthly donation', 'jetpack' ),
- extraText: __( 'Your contribution is appreciated.', 'jetpack' ),
- buttonText: __( 'Donate monthly', 'jetpack' ),
- },
- },
- annualDonation: {
- type: 'object',
- default: {
- show: true,
- planId: null,
- amounts: [ 5, 15, 100 ],
- heading: __( 'Make a yearly donation', 'jetpack' ),
- extraText: __( 'Your contribution is appreciated.', 'jetpack' ),
- buttonText: __( 'Donate yearly', 'jetpack' ),
- },
- },
- showCustomAmount: {
- type: 'boolean',
- default: true,
- },
- chooseAmountText: {
- type: 'string',
- default: __( 'Choose an amount', 'jetpack' ),
- },
- customAmountText: {
- type: 'string',
- default: __( 'Or enter a custom amount', 'jetpack' ),
- },
-};
diff --git a/extensions/blocks/donations/common.scss b/extensions/blocks/donations/common.scss
index 75878343077f..7b41d68af360 100644
--- a/extensions/blocks/donations/common.scss
+++ b/extensions/blocks/donations/common.scss
@@ -91,8 +91,6 @@
}
.donations__separator {
- line-height: 8px;
- height: 8px;
margin-bottom: 16px;
margin-top: 16px;
diff --git a/extensions/blocks/donations/deprecated/v1/index.js b/extensions/blocks/donations/deprecated/v1/index.js
new file mode 100644
index 000000000000..f76d36a9c04f
--- /dev/null
+++ b/extensions/blocks/donations/deprecated/v1/index.js
@@ -0,0 +1,226 @@
+/**
+ * External dependencies
+ */
+import formatCurrency, { CURRENCIES } from '@automattic/format-currency';
+
+/**
+ * WordPress dependencies
+ */
+import { RichText } from '@wordpress/block-editor';
+import { __ } from '@wordpress/i18n';
+
+/**
+ * Internal dependencies
+ */
+import { minimumTransactionAmountForCurrency } from '../../../../shared/currencies';
+
+export default {
+ attributes: {
+ currency: {
+ type: 'string',
+ default: 'USD',
+ },
+ oneTimeDonation: {
+ type: 'object',
+ default: {
+ show: true,
+ planId: null,
+ amounts: [ 5, 15, 100 ],
+ heading: __( 'Make a one-time donation', 'jetpack' ),
+ extraText: __( 'Your contribution is appreciated.', 'jetpack' ),
+ buttonText: __( 'Donate', 'jetpack' ),
+ },
+ },
+ monthlyDonation: {
+ type: 'object',
+ default: {
+ show: true,
+ planId: null,
+ amounts: [ 5, 15, 100 ],
+ heading: __( 'Make a monthly donation', 'jetpack' ),
+ extraText: __( 'Your contribution is appreciated.', 'jetpack' ),
+ buttonText: __( 'Donate monthly', 'jetpack' ),
+ },
+ },
+ annualDonation: {
+ type: 'object',
+ default: {
+ show: true,
+ planId: null,
+ amounts: [ 5, 15, 100 ],
+ heading: __( 'Make a yearly donation', 'jetpack' ),
+ extraText: __( 'Your contribution is appreciated.', 'jetpack' ),
+ buttonText: __( 'Donate yearly', 'jetpack' ),
+ },
+ },
+ showCustomAmount: {
+ type: 'boolean',
+ default: true,
+ },
+ chooseAmountText: {
+ type: 'string',
+ default: __( 'Choose an amount', 'jetpack' ),
+ },
+ customAmountText: {
+ type: 'string',
+ default: __( 'Or enter a custom amount', 'jetpack' ),
+ },
+ },
+ supports: {
+ html: false,
+ },
+ save: ( { attributes } ) => {
+ const {
+ currency,
+ oneTimeDonation,
+ monthlyDonation,
+ annualDonation,
+ showCustomAmount,
+ chooseAmountText,
+ customAmountText,
+ } = attributes;
+
+ if ( ! oneTimeDonation || ! oneTimeDonation.show || oneTimeDonation.planId === -1 ) {
+ return null;
+ }
+
+ const tabs = {
+ 'one-time': { title: __( 'One-Time', 'jetpack' ) },
+ ...( monthlyDonation.show && { '1 month': { title: __( 'Monthly', 'jetpack' ) } } ),
+ ...( annualDonation.show && { '1 year': { title: __( 'Yearly', 'jetpack' ) } } ),
+ };
+
+ return (
+
+
+ { Object.keys( tabs ).length > 1 && (
+
+ { Object.entries( tabs ).map( ( [ interval, { title } ] ) => (
+
+ { title }
+
+ ) ) }
+
+ ) }
+
+
+
+ { monthlyDonation.show && (
+
+ ) }
+ { annualDonation.show && (
+
+ ) }
+
+
+ { oneTimeDonation.amounts.map( amount => (
+
+ { formatCurrency( amount, currency ) }
+
+ ) ) }
+
+ { monthlyDonation.show && (
+
+ { monthlyDonation.amounts.map( amount => (
+
+ { formatCurrency( amount, currency ) }
+
+ ) ) }
+
+ ) }
+ { annualDonation.show && (
+
+ { annualDonation.amounts.map( amount => (
+
+ { formatCurrency( amount, currency ) }
+
+ ) ) }
+
+ ) }
+ { showCustomAmount && (
+ <>
+
+
+ { CURRENCIES[ currency ].symbol }
+
+
+ >
+ ) }
+
——
+
+ { monthlyDonation.show && (
+
+ ) }
+ { annualDonation.show && (
+
+ ) }
+
+
+
+ { monthlyDonation.show && (
+
+
+
+ ) }
+ { annualDonation.show && (
+
+
+
+ ) }
+
+
+
+
+ );
+ },
+};
diff --git a/extensions/blocks/donations/donations.php b/extensions/blocks/donations/donations.php
index 134e6ac077a0..a392791bf731 100644
--- a/extensions/blocks/donations/donations.php
+++ b/extensions/blocks/donations/donations.php
@@ -26,6 +26,60 @@ function register_block() {
array(
'render_callback' => __NAMESPACE__ . '\render_block',
'plan_check' => true,
+ 'attributes' => array(
+ 'currency' => array(
+ 'type' => 'string',
+ 'default' => 'USD',
+ ),
+ 'oneTimeDonation' => array(
+ 'type' => 'object',
+ 'default' => array(
+ 'show' => true,
+ 'planId' => null,
+ 'amounts' => array( 5, 15, 100 ),
+ 'heading' => __( 'Make a one-time donation', 'jetpack' ),
+ 'extraText' => __( 'Your contribution is appreciated.', 'jetpack' ),
+ 'buttonText' => __( 'Donate', 'jetpack' ),
+ ),
+ ),
+ 'monthlyDonation' => array(
+ 'type' => 'object',
+ 'default' => array(
+ 'show' => true,
+ 'planId' => null,
+ 'amounts' => array( 5, 15, 100 ),
+ 'heading' => __( 'Make a monthly donation', 'jetpack' ),
+ 'extraText' => __( 'Your contribution is appreciated.', 'jetpack' ),
+ 'buttonText' => __( 'Donate monthly', 'jetpack' ),
+ ),
+ ),
+ 'annualDonation' => array(
+ 'type' => 'object',
+ 'default' => array(
+ 'show' => true,
+ 'planId' => null,
+ 'amounts' => array( 5, 15, 100 ),
+ 'heading' => __( 'Make a yearly donation', 'jetpack' ),
+ 'extraText' => __( 'Your contribution is appreciated.', 'jetpack' ),
+ 'buttonText' => __( 'Donate yearly', 'jetpack' ),
+ ),
+ ),
+ 'showCustomAmount' => array(
+ 'type' => 'boolean',
+ 'default' => true,
+ ),
+ 'chooseAmountText' => array(
+ 'type' => 'string',
+ 'default' => __( 'Choose an amount', 'jetpack' ),
+ ),
+ 'customAmountText' => array(
+ 'type' => 'string',
+ 'default' => __( 'Or enter a custom amount', 'jetpack' ),
+ ),
+ 'fallbackLinkUrl' => array(
+ 'type' => 'string',
+ ),
+ ),
)
);
}
@@ -40,29 +94,163 @@ function register_block() {
* @return string
*/
function render_block( $attr, $content ) {
- Jetpack_Gutenberg::load_assets_as_required( FEATURE_NAME, array( 'thickbox' ) );
+ // Keep content as-is if rendered in other contexts than frontend (i.e. feed, emails, API, etc.).
+ if ( ! jetpack_is_frontend() ) {
+ return $content;
+ }
- require_once JETPACK__PLUGIN_DIR . '/modules/memberships/class-jetpack-memberships.php';
+ Jetpack_Gutenberg::load_assets_as_required( FEATURE_NAME, array( 'thickbox' ) );
add_thickbox();
+ require_once JETPACK__PLUGIN_DIR . 'modules/memberships/class-jetpack-memberships.php';
+ jetpack_require_lib( 'class-jetpack-currencies' );
+
$donations = array(
- 'one-time' => $attr['oneTimeDonation'],
- 'monthly' => $attr['monthlyDonation'],
- 'annual' => $attr['annualDonation'],
+ 'one-time' => array_merge(
+ array(
+ 'title' => __( 'One-Time', 'jetpack' ),
+ 'class' => 'donations__one-time-item',
+ ),
+ $attr['oneTimeDonation']
+ ),
);
+ if ( $attr['monthlyDonation']['show'] ) {
+ $donations['1 month'] = array_merge(
+ array(
+ 'title' => __( 'Monthly', 'jetpack' ),
+ 'class' => 'donations__monthly-item',
+ ),
+ $attr['monthlyDonation']
+ );
+ }
+ if ( $attr['annualDonation']['show'] ) {
+ $donations['1 year'] = array_merge(
+ array(
+ 'title' => __( 'Yearly', 'jetpack' ),
+ 'class' => 'donations__annual-item',
+ ),
+ $attr['annualDonation']
+ );
+ }
+
+ $currency = $attr['currency'];
+ $nav = '';
+ $headings = '';
+ $amounts = '';
+ $extra_text = '';
+ $buttons = '';
foreach ( $donations as $interval => $donation ) {
- if ( ! $donation['show'] ) {
- continue;
- }
$plan_id = (int) $donation['planId'];
$plan = get_post( $plan_id );
if ( ! $plan || is_wp_error( $plan ) ) {
continue;
}
- $url = \Jetpack_Memberships::get_instance()->get_subscription_url( $plan_id );
- $content = preg_replace( '/(donations__donate-button donations__' . $interval . '-item")/i', '$1 href="' . esc_url( $url ) . '"', $content );
+ if ( count( $donations ) > 1 ) {
+ if ( ! $nav ) {
+ $nav .= '';
+ }
+ $nav .= sprintf(
+ '
%2$s
',
+ esc_attr( $interval ),
+ esc_html( $donation['title'] )
+ );
+ }
+ $headings .= sprintf(
+ '
%2$s
',
+ esc_attr( $donation['class'] ),
+ wp_kses_post( $donation['heading'] )
+ );
+ $amounts .= sprintf(
+ '
',
+ esc_attr( $donation['class'] )
+ );
+ foreach ( $donation['amounts'] as $amount ) {
+ $amounts .= sprintf(
+ '
%2$s
',
+ esc_attr( $amount ),
+ esc_html( \Jetpack_Currencies::format_price( $amount, $currency ) )
+ );
+ }
+ $amounts .= '
';
+ $extra_text .= sprintf(
+ '
%2$s
',
+ esc_attr( $donation['class'] ),
+ wp_kses_post( $donation['extraText'] )
+ );
+ $buttons .= sprintf(
+ '
%3$s',
+ esc_attr( $donation['class'] ),
+ esc_url( \Jetpack_Memberships::get_instance()->get_subscription_url( $plan_id ) ),
+ wp_kses_post( $donation['buttonText'] )
+ );
+ }
+ if ( $nav ) {
+ $nav .= '
';
+ }
+
+ $custom_amount = '';
+ if ( $attr['showCustomAmount'] ) {
+ $custom_amount .= sprintf(
+ '%s
',
+ wp_kses_post( $attr['customAmountText'] )
+ );
+ $default_custom_amount = \Jetpack_Memberships::SUPPORTED_CURRENCIES[ $currency ] * 100;
+ $custom_amount .= sprintf(
+ '',
+ esc_html( \Jetpack_Currencies::CURRENCIES[ $attr['currency'] ]['symbol'] ),
+ esc_attr( $attr['currency'] ),
+ esc_attr( \Jetpack_Currencies::format_price( $default_custom_amount, $currency, false ) )
+ );
}
- return $content;
+ return sprintf(
+ '
+
+
+ %2$s
+
+
+ %3$s
+
%4$s
+ %5$s
+ %6$s
+
+ %7$s
+ %8$s
+
+
+
+',
+ esc_attr( Blocks::classes( FEATURE_NAME, $attr ) ),
+ $nav,
+ $headings,
+ $attr['chooseAmountText'],
+ $amounts,
+ $custom_amount,
+ $extra_text,
+ $buttons
+ );
+}
+
+/**
+ * Determine if AMP should be disabled on posts having Donations blocks.
+ *
+ * @param bool $skip Skipped.
+ * @param int $post_id Post ID.
+ * @param WP_Post $post Post.
+ *
+ * @return bool Whether to skip the post from AMP.
+ */
+function amp_skip_post( $skip, $post_id, $post ) {
+ // When AMP is on standard mode, there are no non-AMP posts to link to where the donation can be completed, so let's
+ // prevent the post from being available in AMP.
+ if ( function_exists( 'amp_is_canonical' ) && \amp_is_canonical() && has_block( BLOCK_NAME, $post->post_content ) ) {
+ return true;
+ }
+ return $skip;
}
+add_filter( 'amp_skip_post', __NAMESPACE__ . '\amp_skip_post', 10, 3 );
diff --git a/extensions/blocks/donations/edit.js b/extensions/blocks/donations/edit.js
index acf7a91b5cd6..c0667a599be9 100644
--- a/extensions/blocks/donations/edit.js
+++ b/extensions/blocks/donations/edit.js
@@ -1,6 +1,7 @@
/**
* WordPress dependencies
*/
+import { useSelect } from '@wordpress/data';
import { useState, useEffect } from '@wordpress/element';
import { __ } from '@wordpress/i18n';
@@ -13,7 +14,7 @@ import fetchDefaultProducts from './fetch-default-products';
import fetchStatus from './fetch-status';
const Edit = props => {
- const { attributes, className } = props;
+ const { attributes, className, setAttributes } = props;
const { currency } = attributes;
const [ loadingError, setLoadingError ] = useState( '' );
@@ -21,6 +22,11 @@ const Edit = props => {
const [ stripeConnectUrl, setStripeConnectUrl ] = useState( false );
const [ products, setProducts ] = useState( [] );
+ const post = useSelect( select => select( 'core/editor' ).getCurrentPost(), [] );
+ useEffect( () => {
+ setAttributes( { fallbackLinkUrl: post.link } );
+ }, [ post.link, setAttributes ] );
+
const apiError = message => {
setLoadingError( message );
};
diff --git a/extensions/blocks/donations/index.js b/extensions/blocks/donations/index.js
index f5e5b0ba3237..cd4b41be5358 100644
--- a/extensions/blocks/donations/index.js
+++ b/extensions/blocks/donations/index.js
@@ -1,16 +1,20 @@
/**
* External dependencies
*/
+import GridiconHeart from 'gridicons/dist/heart-outline';
+
+/**
+ * WordPress dependencies
+ */
import { __ } from '@wordpress/i18n';
/**
* Internal dependencies
*/
-import attributes from './attributes';
import edit from './edit';
import save from './save';
-import GridiconHeart from 'gridicons/dist/heart-outline';
import { getIconColor } from '../../shared/block-icons';
+import deprecatedV1 from './deprecated/v1';
/**
* Style dependencies
@@ -34,6 +38,6 @@ export const settings = {
},
edit,
save,
- attributes,
example: {},
+ deprecated: [ deprecatedV1 ],
};
diff --git a/extensions/blocks/donations/save.js b/extensions/blocks/donations/save.js
index 482ca6607ede..b07302e278dd 100644
--- a/extensions/blocks/donations/save.js
+++ b/extensions/blocks/donations/save.js
@@ -1,170 +1,62 @@
-/**
- * External dependencies
- */
-import formatCurrency, { CURRENCIES } from '@automattic/format-currency';
-
/**
* WordPress dependencies
*/
import { RichText } from '@wordpress/block-editor';
-import { __ } from '@wordpress/i18n';
-
-/**
- * Internal dependencies
- */
-import { minimumTransactionAmountForCurrency } from '../../shared/currencies';
const Save = ( { attributes } ) => {
- const {
- currency,
- oneTimeDonation,
- monthlyDonation,
- annualDonation,
- showCustomAmount,
- chooseAmountText,
- customAmountText,
- } = attributes;
+ const { fallbackLinkUrl, oneTimeDonation, monthlyDonation, annualDonation } = attributes;
- if ( ! oneTimeDonation || ! oneTimeDonation.show || oneTimeDonation.planId === -1 ) {
+ if (
+ ! oneTimeDonation ||
+ ! oneTimeDonation.show ||
+ ! oneTimeDonation.planId ||
+ oneTimeDonation.planId === -1
+ ) {
return null;
}
- const tabs = {
- 'one-time': { title: __( 'One-Time', 'jetpack' ) },
- ...( monthlyDonation.show && { '1 month': { title: __( 'Monthly', 'jetpack' ) } } ),
- ...( annualDonation.show && { '1 year': { title: __( 'Yearly', 'jetpack' ) } } ),
- };
-
return (
-
- { Object.keys( tabs ).length > 1 && (
-
- { Object.entries( tabs ).map( ( [ interval, { title } ] ) => (
-
- { title }
-
- ) ) }
-
- ) }
-
-
-
- { monthlyDonation.show && (
-
- ) }
- { annualDonation.show && (
-
- ) }
-
-
- { oneTimeDonation.amounts.map( amount => (
-
- { formatCurrency( amount, currency ) }
-
- ) ) }
-
- { monthlyDonation.show && (
-
- { monthlyDonation.amounts.map( amount => (
-
- { formatCurrency( amount, currency ) }
-
- ) ) }
-
- ) }
- { annualDonation.show && (
-
- { annualDonation.amounts.map( amount => (
-
- { formatCurrency( amount, currency ) }
-
- ) ) }
-
- ) }
- { showCustomAmount && (
- <>
-
-
- { CURRENCIES[ currency ].symbol }
-
-
- >
- ) }
-
——
-
- { monthlyDonation.show && (
-
- ) }
- { annualDonation.show && (
-
- ) }
-
-
-
- { monthlyDonation.show && (
-
-
-
- ) }
- { annualDonation.show && (
-
-
-
- ) }
-
-
-
+
+
+
+ { monthlyDonation.show && (
+ <>
+
+
+
+
+ >
+ ) }
+ { annualDonation.show && (
+ <>
+
+
+
+
+ >
+ ) }
);
};
diff --git a/extensions/blocks/donations/tab.js b/extensions/blocks/donations/tab.js
index b231d9e0a2e8..23f4aa500df5 100644
--- a/extensions/blocks/donations/tab.js
+++ b/extensions/blocks/donations/tab.js
@@ -140,7 +140,7 @@ const Tab = ( { activeTab, attributes, setAttributes } ) => {
/>
>
) }
-
——
+
post_content ) ) {
+ if ( function_exists( 'amp_is_canonical' ) && \amp_is_canonical() && has_block( BLOCK_NAME, $post->post_content ) ) {
return true;
}
return $skip;
diff --git a/extensions/shared/currencies.js b/extensions/shared/currencies.js
index 7d13b43f1db5..e638f61cd441 100644
--- a/extensions/shared/currencies.js
+++ b/extensions/shared/currencies.js
@@ -8,10 +8,8 @@ import { CURRENCIES } from '@automattic/format-currency';
*
* @link https://stripe.com/docs/currencies#minimum-and-maximum-charge-amounts
*
- * List has to be in sync with the Memberships library in WP.com.
- * @see Memberships_Product::SUPPORTED_CURRENCIES
- *
- * @type { [currency: string]: number }
+ * List has to be in with `Jetpack_Memberships::SUPPORTED_CURRENCIES` in modules/memberships/class-jetpack-memberships.php and
+ * `Memberships_Product::SUPPORTED_CURRENCIES` in the WP.com memberships library.
*/
export const SUPPORTED_CURRENCIES = {
USD: 0.5,
diff --git a/modules/memberships/class-jetpack-memberships.php b/modules/memberships/class-jetpack-memberships.php
index 1cabbcde0901..cb87fda2ddf1 100644
--- a/modules/memberships/class-jetpack-memberships.php
+++ b/modules/memberships/class-jetpack-memberships.php
@@ -66,6 +66,34 @@ class Jetpack_Memberships {
*/
private static $instance;
+ /**
+ * Currencies we support and Stripe's minimum amount for a transaction in that currency.
+ *
+ * @link https://stripe.com/docs/currencies#minimum-and-maximum-charge-amounts
+ *
+ * List has to be in with `SUPPORTED_CURRENCIES` in extensions/shared/currencies.js and
+ * `Memberships_Product::SUPPORTED_CURRENCIES` in the WP.com memberships library.
+ */
+ const SUPPORTED_CURRENCIES = array(
+ 'USD' => 0.5,
+ 'AUD' => 0.5,
+ 'BRL' => 0.5,
+ 'CAD' => 0.5,
+ 'CHF' => 0.5,
+ 'DKK' => 2.5,
+ 'EUR' => 0.5,
+ 'GBP' => 0.3,
+ 'HKD' => 4.0,
+ 'INR' => 0.5,
+ 'JPY' => 50,
+ 'MXN' => 10,
+ 'NOK' => 3.0,
+ 'NZD' => 0.5,
+ 'PLN' => 2.0,
+ 'SEK' => 3.0,
+ 'SGD' => 0.5,
+ );
+
/**
* Jetpack_Memberships constructor.
*/
diff --git a/modules/simple-payments/simple-payments.php b/modules/simple-payments/simple-payments.php
index 66fd2a142f13..8d36a00774dc 100644
--- a/modules/simple-payments/simple-payments.php
+++ b/modules/simple-payments/simple-payments.php
@@ -290,28 +290,8 @@ public function output_shortcode( $data ) {
* @return string Formatted price.
*/
private function format_price( $price, $currency ) {
- $currency_details = self::get_currency( $currency );
-
- if ( $currency_details ) {
- // Ensure USD displays as 1234.56 even in non-US locales.
- $amount = 'USD' === $currency
- ? number_format( $price, $currency_details['decimal'], '.', ',' )
- : number_format_i18n( $price, $currency_details['decimal'] );
-
- return sprintf(
- $currency_details['format'],
- $currency_details['symbol'],
- $amount
- );
- }
-
- // Fall back to unspecified currency symbol like `¤1,234.05`.
- // @link https://en.wikipedia.org/wiki/Currency_sign_(typography).
- if ( ! $currency ) {
- return '¤' . number_format_i18n( $price, 2 );
- }
-
- return number_format_i18n( $price, 2 ) . ' ' . $currency;
+ require_once JETPACK__PLUGIN_DIR . 'class.jetpack-currencies.php';
+ return Jetpack_Currencies::format_price( $price, $currency );
}
/**
@@ -573,128 +553,8 @@ function setup_cpts() {
* @return ?array Currency object or null if not found.
*/
private static function get_currency( $the_currency ) {
- $currencies = array(
- 'USD' => array(
- 'format' => '%1$s%2$s', // 1: Symbol 2: currency value
- 'symbol' => '$',
- 'decimal' => 2,
- ),
- 'GBP' => array(
- 'format' => '%1$s%2$s', // 1: Symbol 2: currency value
- 'symbol' => '£',
- 'decimal' => 2,
- ),
- 'JPY' => array(
- 'format' => '%1$s%2$s', // 1: Symbol 2: currency value
- 'symbol' => '¥',
- 'decimal' => 0,
- ),
- 'BRL' => array(
- 'format' => '%1$s%2$s', // 1: Symbol 2: currency value
- 'symbol' => 'R$',
- 'decimal' => 2,
- ),
- 'EUR' => array(
- 'format' => '%1$s%2$s', // 1: Symbol 2: currency value
- 'symbol' => '€',
- 'decimal' => 2,
- ),
- 'NZD' => array(
- 'format' => '%1$s%2$s', // 1: Symbol 2: currency value
- 'symbol' => 'NZ$',
- 'decimal' => 2,
- ),
- 'AUD' => array(
- 'format' => '%1$s%2$s', // 1: Symbol 2: currency value
- 'symbol' => 'A$',
- 'decimal' => 2,
- ),
- 'CAD' => array(
- 'format' => '%1$s%2$s', // 1: Symbol 2: currency value
- 'symbol' => 'C$',
- 'decimal' => 2,
- ),
- 'ILS' => array(
- 'format' => '%2$s %1$s', // 1: Symbol 2: currency value
- 'symbol' => '₪',
- 'decimal' => 2,
- ),
- 'RUB' => array(
- 'format' => '%2$s %1$s', // 1: Symbol 2: currency value
- 'symbol' => '₽',
- 'decimal' => 2,
- ),
- 'MXN' => array(
- 'format' => '%1$s%2$s', // 1: Symbol 2: currency value
- 'symbol' => 'MX$',
- 'decimal' => 2,
- ),
- 'MYR' => array(
- 'format' => '%2$s%1$s', // 1: Symbol 2: currency value
- 'symbol' => 'RM',
- 'decimal' => 2,
- ),
- 'SEK' => array(
- 'format' => '%2$s %1$s', // 1: Symbol 2: currency value
- 'symbol' => 'Skr',
- 'decimal' => 2,
- ),
- 'HUF' => array(
- 'format' => '%2$s %1$s', // 1: Symbol 2: currency value
- 'symbol' => 'Ft',
- 'decimal' => 0, // Decimals are supported by Stripe but not by PayPal.
- ),
- 'CHF' => array(
- 'format' => '%2$s %1$s', // 1: Symbol 2: currency value
- 'symbol' => 'CHF',
- 'decimal' => 2,
- ),
- 'CZK' => array(
- 'format' => '%2$s %1$s', // 1: Symbol 2: currency value
- 'symbol' => 'Kč',
- 'decimal' => 2,
- ),
- 'DKK' => array(
- 'format' => '%2$s %1$s', // 1: Symbol 2: currency value
- 'symbol' => 'Dkr',
- 'decimal' => 2,
- ),
- 'HKD' => array(
- 'format' => '%2$s %1$s', // 1: Symbol 2: currency value
- 'symbol' => 'HK$',
- 'decimal' => 2,
- ),
- 'NOK' => array(
- 'format' => '%2$s %1$s', // 1: Symbol 2: currency value
- 'symbol' => 'Kr',
- 'decimal' => 2,
- ),
- 'PHP' => array(
- 'format' => '%2$s %1$s', // 1: Symbol 2: currency value
- 'symbol' => '₱',
- 'decimal' => 2,
- ),
- 'PLN' => array(
- 'format' => '%2$s %1$s', // 1: Symbol 2: currency value
- 'symbol' => 'PLN',
- 'decimal' => 2,
- ),
- 'SGD' => array(
- 'format' => '%1$s%2$s', // 1: Symbol 2: currency value
- 'symbol' => 'S$',
- 'decimal' => 2,
- ),
- 'TWD' => array(
- 'format' => '%1$s%2$s', // 1: Symbol 2: currency value
- 'symbol' => 'NT$',
- 'decimal' => 0, // Decimals are supported by Stripe but not by PayPal.
- ),
- 'THB' => array(
- 'format' => '%2$s%1$s', // 1: Symbol 2: currency value
- 'symbol' => '฿',
- 'decimal' => 2,
- ),
- );
+ require_once JETPACK__PLUGIN_DIR . 'class.jetpack-currencies.php';
+ $currencies = Jetpack_Currencies::CURRENCIES;
if ( isset( $currencies[ $the_currency ] ) ) {
return $currencies[ $the_currency ];
diff --git a/tests/php/_inc/lib/test-class-jetpack-currencies.php b/tests/php/_inc/lib/test-class-jetpack-currencies.php
new file mode 100644
index 000000000000..3f7982530b1c
--- /dev/null
+++ b/tests/php/_inc/lib/test-class-jetpack-currencies.php
@@ -0,0 +1,59 @@
+number_format;
+ $wp_locale->number_format = array(
+ 'thousands_sep' => '-',
+ 'decimal_point' => '|',
+ );
+ $formatted_price = Jetpack_Currencies::format_price( '12345.67890', 'USD' );
+ $this->assertEquals( '$12,345.68', $formatted_price );
+ $wp_locale->number_format = $previous_number_format;
+ }
+
+ /**
+ * Test that non-USD currencies are formatted according to the user locale.
+ */
+ public function test_format_price_non_usd() {
+ global $wp_locale;
+ $previous_number_format = $wp_locale->number_format;
+ $wp_locale->number_format = array(
+ 'thousands_sep' => '-',
+ 'decimal_point' => '|',
+ );
+ $formatted_price = Jetpack_Currencies::format_price( '12345.67890', 'EUR' );
+ $this->assertEquals( '€12-345|68', $formatted_price );
+ $wp_locale->number_format = $previous_number_format;
+ }
+
+ /**
+ * Test that no currency symbol is displayed when specified.
+ */
+ public function test_format_price_no_currency_symbol() {
+ $formatted_price = Jetpack_Currencies::format_price( '12345.67890', 'USD', false );
+ $this->assertEquals( '12,345.68', $formatted_price );
+ }
+
+ /**
+ * Test that the unspecified currency symbol is displayed when the currency is not found.
+ */
+ public function test_format_price_unspecified_currency_symbol() {
+ $formatted_price = Jetpack_Currencies::format_price( '12345.67890', 'TEST', false );
+ $this->assertEquals( '¤12,345.68', $formatted_price );
+ }
+}