diff --git a/CHANGELOG.md b/CHANGELOG.md index 7b217d603..8729ab80b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,24 @@ +# [2.5.0-alpha.2](https://github.com/Automattic/newspack-blocks/compare/v2.5.0-alpha.1...v2.5.0-alpha.2) (2023-12-22) + + +### Bug Fixes + +* avoid duplicity with linked guest authors ([#1632](https://github.com/Automattic/newspack-blocks/issues/1632)) ([608979c](https://github.com/Automattic/newspack-blocks/commit/608979c1e9cb63a7098da27c69c337ec233b7429)) +* **modal-checkout:** show order details table with fees ([#1633](https://github.com/Automattic/newspack-blocks/issues/1633)) ([07c0642](https://github.com/Automattic/newspack-blocks/commit/07c0642e77a075750c6f436f12af99cd3e2ef360)) + + +### Features + +* **modal-checkout:** allow anonymous purchase for registered email ([#1615](https://github.com/Automattic/newspack-blocks/issues/1615)) ([a0040b4](https://github.com/Automattic/newspack-blocks/commit/a0040b43a3f97c889e5bb5b5b96f07777b52a670)) + +# [2.5.0-alpha.1](https://github.com/Automattic/newspack-blocks/compare/v2.4.0...v2.5.0-alpha.1) (2023-12-15) + + +### Features + +* accessibility improvements to the donate block tabs ([#1622](https://github.com/Automattic/newspack-blocks/issues/1622)) ([115e9fb](https://github.com/Automattic/newspack-blocks/commit/115e9fb95c78a13f1d87f4d086e767311dc7007d)) +* **donate:** support empty value for "other" tier ([#1604](https://github.com/Automattic/newspack-blocks/issues/1604)) ([61ffdbc](https://github.com/Automattic/newspack-blocks/commit/61ffdbc57e6fda320766d4de99f097edac9e58f7)) + # [2.4.0](https://github.com/Automattic/newspack-blocks/compare/v2.3.0...v2.4.0) (2023-12-11) diff --git a/includes/class-modal-checkout.php b/includes/class-modal-checkout.php index 64e915744..bec59c382 100644 --- a/includes/class-modal-checkout.php +++ b/includes/class-modal-checkout.php @@ -52,6 +52,10 @@ public static function init() { add_filter( 'woocommerce_order_button_text', [ __CLASS__, 'order_button_text' ] ); add_filter( 'option_woocommerce_subscriptions_order_button_text', [ __CLASS__, 'order_button_text' ] ); + /** Custom handling for registered users. */ + add_filter( 'woocommerce_checkout_customer_id', [ __CLASS__, 'associate_existing_user' ] ); + add_filter( 'woocommerce_checkout_posted_data', [ __CLASS__, 'skip_account_creation' ], 11 ); + // Remove some stuff from the modal checkout page. It's displayed in an iframe, so it should not be treated as a separate page. add_action( 'wp_enqueue_scripts', [ __CLASS__, 'dequeue_scripts' ], 11 ); add_filter( 'newspack_reader_activation_should_render_auth', [ __CLASS__, 'is_not_modal_checkout_filter' ] ); @@ -697,6 +701,9 @@ public static function should_show_order_details() { if ( 1 < $cart->get_cart_contents_count() ) { return true; } + if ( ! empty( $cart->get_fees() ) ) { + return true; + } return false; } @@ -973,6 +980,50 @@ public static function order_button_text( $text ) { return $text; } + /** + * If a reader tries to make a purchase with an email address that + * has been previously registered, automatically associate the transaction + * with the user. + * + * @param int $customer_id Current customer ID. + * + * @return int Modified $customer_id + */ + public static function associate_existing_user( $customer_id ) { + if ( ! self::is_modal_checkout() ) { + return $customer_id; + } + $billing_email = filter_input( INPUT_POST, 'billing_email', FILTER_SANITIZE_EMAIL ); + if ( $billing_email ) { + $customer = \get_user_by( 'email', $billing_email ); + if ( $customer ) { + $customer_id = $customer->ID; + } + } + return $customer_id; + } + + /** + * Don't force account registration/login on Woo purchases for existing users. + * + * @param array $data Array of Woo checkout data. + * + * @return array Modified $data. + */ + public static function skip_account_creation( $data ) { + if ( ! self::is_modal_checkout() ) { + return $data; + } + $email = $data['billing_email']; + $customer = \get_user_by( 'email', $email ); + if ( $customer ) { + $data['createaccount'] = 0; + \add_filter( 'woocommerce_checkout_registration_required', '__return_false', 9999 ); + } + + return $data; + } + /** * Filter the a value dependent on the page not being modal checkout. * diff --git a/newspack-blocks.php b/newspack-blocks.php index 25e843806..871852dbf 100755 --- a/newspack-blocks.php +++ b/newspack-blocks.php @@ -7,7 +7,7 @@ * Author URI: https://newspack.com/ * Text Domain: newspack-blocks * Domain Path: /languages - * Version: 2.4.0 + * Version: 2.5.0-alpha.2 * * @package Newspack_Blocks */ @@ -15,7 +15,7 @@ define( 'NEWSPACK_BLOCKS__PLUGIN_FILE', __FILE__ ); define( 'NEWSPACK_BLOCKS__BLOCKS_DIRECTORY', 'dist/' ); define( 'NEWSPACK_BLOCKS__PLUGIN_DIR', plugin_dir_path( NEWSPACK_BLOCKS__PLUGIN_FILE ) ); -define( 'NEWSPACK_BLOCKS__VERSION', '2.4.0' ); +define( 'NEWSPACK_BLOCKS__VERSION', '2.5.0-alpha.2' ); require_once NEWSPACK_BLOCKS__PLUGIN_DIR . 'includes/class-newspack-blocks.php'; require_once NEWSPACK_BLOCKS__PLUGIN_DIR . 'includes/class-newspack-blocks-api.php'; diff --git a/package-lock.json b/package-lock.json index 0272bbe04..1f741972a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@automattic/newspack-blocks", - "version": "2.4.0", + "version": "2.5.0-alpha.2", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@automattic/newspack-blocks", - "version": "2.4.0", + "version": "2.5.0-alpha.2", "hasInstallScript": true, "license": "GPL-3.0-or-later", "dependencies": { diff --git a/package.json b/package.json index 09c981200..9ceeaa927 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@automattic/newspack-blocks", - "version": "2.4.0", + "version": "2.5.0-alpha.2", "author": "Automattic", "devDependencies": { "@rushstack/eslint-patch": "^1.5.1", diff --git a/src/blocks/author-profile/class-wp-rest-newspack-authors-controller.php b/src/blocks/author-profile/class-wp-rest-newspack-authors-controller.php index 003bd9bf6..4c88efd10 100644 --- a/src/blocks/author-profile/class-wp-rest-newspack-authors-controller.php +++ b/src/blocks/author-profile/class-wp-rest-newspack-authors-controller.php @@ -84,6 +84,8 @@ public function get_authors( $request ) { // Total number of users and guest authors. $guest_author_total = 0; $user_total = 0; + $guest_authors = []; + $linked_guest_authors = []; // Get Co-authors guest authors. if ( $is_guest_author ) { @@ -108,6 +110,14 @@ public function get_authors( $request ) { $guest_author_total = count( $guest_authors ); } + foreach ( $guest_authors as $ga ) { + $linked_guest_author = get_post_meta( $ga->ID, 'cap-linked_account', true ); + + if ( $linked_guest_author ) { + $linked_guest_authors[] = $linked_guest_author; + } + } + $users = []; // If passed an author ID. @@ -187,8 +197,14 @@ function( $acc, $guest_author ) use ( $fields, $avatar_hide_default ) { ), array_reduce( $users, - function( $acc, $user ) use ( $fields, $avatar_hide_default ) { + function( $acc, $user ) use ( $fields, $avatar_hide_default, $linked_guest_authors ) { if ( $user ) { + + // This user is linked to a guest author already returned in the query, so skip it. + if ( in_array( $user->data->user_login, $linked_guest_authors, true ) ) { + return $acc; + } + $user_data = [ 'id' => intval( $user->data->ID ), 'registered' => $user->data->user_registered, diff --git a/src/blocks/donate/edit/FrequencyBasedLayout.tsx b/src/blocks/donate/edit/FrequencyBasedLayout.tsx index 8d8d857d4..cd70edc42 100644 --- a/src/blocks/donate/edit/FrequencyBasedLayout.tsx +++ b/src/blocks/donate/edit/FrequencyBasedLayout.tsx @@ -7,7 +7,7 @@ import classNames from 'classnames'; * WordPress dependencies */ import { __ } from '@wordpress/i18n'; -import { useMemo, useEffect, useRef } from '@wordpress/element'; +import { useMemo, useEffect, useRef, useState } from '@wordpress/element'; import { SelectControl } from '@wordpress/components'; import { RichText } from '@wordpress/block-editor'; @@ -68,6 +68,8 @@ const FrequencyBasedLayout = ( props: { isTiered: boolean } & ComponentProps ) = const isRenderingStripePaymentForm = window.newspack_blocks_data?.is_rendering_stripe_payment_form; + const [ selectedFrequency, setSelectedFrequency ] = useState( attributes.defaultFrequency ); + const renderFrequencySelect = ( frequencySlug: DonationFrequencySlug ) => ( <> setSelectedFrequency( evt.target.value as 'once' | 'month' | 'year' ) } /> -