-
Notifications
You must be signed in to change notification settings - Fork 6
feat(membership-plans): improvements #110
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
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -55,7 +55,7 @@ public static function render() { | |
| <?php | ||
| printf( | ||
| /* translators: last fetch date. */ | ||
| esc_html__( 'Plans from Nodes were last fetched on %s.', 'newspack-network' ), | ||
| esc_html__( 'Plans were last fetched on %s.', 'newspack-network' ), | ||
| esc_html( gmdate( 'Y-m-d H:i', (int) $plans_cache['last_updated'] ) ) | ||
| ); | ||
| ?> | ||
|
|
@@ -75,16 +75,15 @@ public static function render() { | |
| * @param \Newspack_Network\Node\Node $node The node. | ||
| * @param string $collection_endpoint The collection endpoint. | ||
| * @param string $collection_endpoint_id The collection endpoint ID. | ||
| * @param array $query_args The query args. | ||
| */ | ||
| public static function fetch_collection_from_api( $node, $collection_endpoint, $collection_endpoint_id ) { | ||
| $endpoint = sprintf( '%s/wp-json/%s', $node->get_url(), $collection_endpoint ); | ||
| if ( Network_Admin::use_experimental_auditing_features() ) { | ||
| $endpoint = add_query_arg( 'include_active_members_emails', 1, $endpoint ); | ||
| } | ||
| public static function fetch_collection_from_api( $node, $collection_endpoint, $collection_endpoint_id, $query_args = [] ) { | ||
| $endpoint = add_query_arg( $query_args, sprintf( '%s/wp-json/%s', $node->get_url(), $collection_endpoint ) ); | ||
| $response = wp_remote_get( // phpcs:ignore | ||
| $endpoint, | ||
| [ | ||
| 'headers' => $node->get_authorization_headers( 'get-woo-' . $collection_endpoint_id ), | ||
| 'timeout' => 60, // phpcs:ignore | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nonblocking nit: Does the default not work here?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What do you mean? Default timeout is
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah. Whoops. For some reason I thought this was |
||
| ] | ||
| ); | ||
| if ( is_wp_error( $response ) || 200 !== wp_remote_retrieve_response_code( $response ) ) { | ||
|
|
@@ -104,27 +103,29 @@ private static function get_membership_plans_from_cache() { | |
| /** | ||
| * Get membership plans from all nodes. | ||
| */ | ||
| public static function get_membershp_plans_from_network() { | ||
| public static function get_membership_plans_from_network() { | ||
| $plans_cache = self::get_membership_plans_from_cache(); | ||
| if ( $plans_cache && isset( $plans_cache['plans'] ) ) { | ||
| return $plans_cache['plans']; | ||
| return $plans_cache; | ||
| } | ||
| $by_network_pass_id = []; | ||
| $membership_plans = []; | ||
|
|
||
| if ( Network_Admin::use_experimental_auditing_features() ) { | ||
| $local_membership_plans = self::get_local_membership_plans(); | ||
| foreach ( $local_membership_plans as $local_plan ) { | ||
| if ( $local_plan['network_pass_id'] ) { | ||
| $by_network_pass_id[ $local_plan['network_pass_id'] ][ $local_plan['site_url'] ] = $local_plan['active_members_emails']; | ||
| } | ||
| $local_membership_plans = self::get_local_membership_plans(); | ||
| foreach ( $local_membership_plans as $local_plan ) { | ||
| if ( $local_plan['network_pass_id'] ) { | ||
| $by_network_pass_id[ $local_plan['network_pass_id'] ][ $local_plan['site_url'] ] = $local_plan['active_members_emails']; | ||
| } | ||
| $membership_plans = array_merge( $local_membership_plans, $membership_plans ); | ||
| } | ||
| $membership_plans = array_merge( $local_membership_plans, $membership_plans ); | ||
|
|
||
| $nodes = \Newspack_Network\Hub\Nodes::get_all_nodes(); | ||
| foreach ( $nodes as $node ) { | ||
| $node_plans = self::fetch_collection_from_api( $node, 'wc/v2/memberships/plans', 'membership-plans' ); | ||
| $query_args = []; | ||
| if ( \Newspack_Network\Admin::use_experimental_auditing_features() ) { | ||
| $query_args['include_active_members_emails'] = 1; | ||
| } | ||
| $node_plans = self::fetch_collection_from_api( $node, 'wc/v2/memberships/plans', 'membership-plans', $query_args ); | ||
| foreach ( $node_plans as $plan ) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Getting the following warning on this line:
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed in a4ab6df |
||
| $network_pass_id = null; | ||
| foreach ( $plan->meta_data as $meta ) { | ||
|
|
@@ -139,15 +140,17 @@ public static function get_membershp_plans_from_network() { | |
| $by_network_pass_id[ $network_pass_id ][ $node->get_url() ] = $plan->active_members_emails; | ||
| } | ||
| $membership_plans[] = [ | ||
| 'id' => $plan->id, | ||
| 'site_url' => $node->get_url(), | ||
| 'name' => $plan->name, | ||
| 'network_pass_id' => $network_pass_id, | ||
| 'active_members_count' => $plan->active_members_count, | ||
| 'id' => $plan->id, | ||
| 'site_url' => $node->get_url(), | ||
| 'name' => $plan->name, | ||
| 'network_pass_id' => $network_pass_id, | ||
| 'active_memberships_count' => $plan->active_memberships_count, | ||
| 'active_subscriptions_count' => $plan->active_subscriptions_count, | ||
| ]; | ||
| } | ||
| } | ||
|
|
||
| $discrepancies_emails = []; | ||
| if ( Network_Admin::use_experimental_auditing_features() ) { | ||
| $discrepancies = []; | ||
| foreach ( $by_network_pass_id as $plan_network_pass_id => $by_site ) { | ||
|
|
@@ -156,6 +159,15 @@ public static function get_membershp_plans_from_network() { | |
| $discrepancies[ $plan_network_pass_id ][ $site_url ] = array_diff( $emails, $shared_emails ); | ||
| } | ||
| } | ||
|
|
||
| // Get all emails which are discrepant across all sites. | ||
| foreach ( $discrepancies as $plan_network_id => $plan_discrepancies ) { | ||
| foreach ( $plan_discrepancies as $site_url => $plan_site_discrepancies ) { | ||
| $discrepancies_emails = array_merge( $discrepancies_emails, $plan_site_discrepancies ); | ||
| } | ||
| } | ||
| $discrepancies_emails = array_unique( $discrepancies_emails ); | ||
|
|
||
| $membership_plans = array_map( | ||
| function( $plan ) use ( $discrepancies ) { | ||
| if ( isset( | ||
|
|
@@ -170,12 +182,13 @@ function( $plan ) use ( $discrepancies ) { | |
| $membership_plans | ||
| ); | ||
| } | ||
| $plans_to_save = [ | ||
| 'plans' => $membership_plans, | ||
| 'last_updated' => time(), | ||
| $memberships_data = [ | ||
| 'plans' => $membership_plans, | ||
| 'discrepancies_emails' => $discrepancies_emails, | ||
| 'last_updated' => time(), | ||
| ]; | ||
| update_option( self::OPTIONS_CACHE_KEY_PLANS, $plans_to_save ); | ||
| return $membership_plans; | ||
| update_option( self::OPTIONS_CACHE_KEY_PLANS, $memberships_data ); | ||
| return $memberships_data; | ||
| } | ||
|
|
||
| /** | ||
|
|
@@ -187,15 +200,21 @@ public static function get_local_membership_plans() { | |
| return []; | ||
| } | ||
| foreach ( wc_memberships_get_membership_plans() as $plan ) { | ||
| $network_pass_id = get_post_meta( $plan->post->ID, \Newspack_Network\Woocommerce_Memberships\Admin::NETWORK_ID_META_KEY, true ); | ||
| $plan_data = [ | ||
| 'id' => $plan->post->ID, | ||
| 'site_url' => get_site_url(), | ||
| 'name' => $plan->post->post_title, | ||
| 'network_pass_id' => get_post_meta( $plan->post->ID, \Newspack_Network\Woocommerce_Memberships\Admin::NETWORK_ID_META_KEY, true ), | ||
| 'active_members_count' => $plan->get_memberships_count( 'active' ), | ||
| 'id' => $plan->post->ID, | ||
| 'site_url' => get_site_url(), | ||
| 'name' => $plan->post->post_title, | ||
| 'network_pass_id' => $network_pass_id, | ||
| 'active_memberships_count' => $plan->get_memberships_count( 'active' ), | ||
| ]; | ||
| if ( Network_Admin::use_experimental_auditing_features() ) { | ||
| $plan_data['active_members_emails'] = \Newspack_Network\Woocommerce_Memberships\Admin::get_active_members_emails( $plan ); | ||
| if ( $network_pass_id ) { | ||
| $plan_data['active_subscriptions_count'] = \Newspack_Network\Woocommerce_Memberships\Admin::get_plan_related_active_subscriptions( $plan ); | ||
| } else { | ||
| $plan_data['active_subscriptions_count'] = __( 'Only displayed for plans with a Network ID.', 'newspack-network' ); | ||
| } | ||
| } | ||
| $membership_plans[] = $plan_data; | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -66,6 +66,7 @@ public static function init() { | |
| add_filter( 'post_row_actions', array( __CLASS__, 'post_row_actions' ), 99, 2 ); // After the Memberships plugin. | ||
| add_filter( 'map_meta_cap', array( __CLASS__, 'map_meta_cap' ), 20, 4 ); | ||
| add_filter( 'wc_memberships_rest_api_membership_plan_data', [ __CLASS__, 'add_data_to_membership_plan_response' ], 2, 3 ); | ||
| add_filter( 'woocommerce_rest_prepare_wc_user_membership', [ __CLASS__, 'add_data_to_wc_user_membership_response' ], 2, 3 ); | ||
| add_filter( 'request', [ __CLASS__, 'request_query' ] ); | ||
| add_action( 'pre_user_query', [ __CLASS__, 'pre_user_query' ] ); | ||
| add_action( 'admin_notices', [ __CLASS__, 'admin_notices' ] ); | ||
|
|
@@ -100,14 +101,45 @@ function ( $membership ) { | |
| */ | ||
| public static function add_data_to_membership_plan_response( $data, $plan, $request ) { | ||
| if ( $request && isset( $request->get_headers()['x_np_network_signature'] ) ) { | ||
| $data['active_members_count'] = $plan->get_memberships_count( 'active' ); | ||
| if ( $request->get_param( 'include_active_members_emails' ) ) { | ||
| $data['active_members_emails'] = self::get_active_members_emails( $plan ); | ||
| $data['active_memberships_count'] = $plan->get_memberships_count( 'active' ); | ||
| $network_pass_id = get_post_meta( $plan->id, self::NETWORK_ID_META_KEY, true ); | ||
| if ( $network_pass_id && $request->get_param( 'include_active_members_emails' ) ) { | ||
| $data['active_subscriptions_count'] = self::get_plan_related_active_subscriptions( $plan ); | ||
| $data['active_members_emails'] = array_values( array_unique( self::get_active_members_emails( $plan ) ) ); | ||
| } else { | ||
| $data['active_subscriptions_count'] = __( 'Only displayed for plans with a Network ID.', 'newspack-network' ); | ||
| } | ||
| } | ||
| return $data; | ||
| } | ||
|
|
||
| /** | ||
| * Get the active subscriptions related to a membership plan. | ||
| * | ||
| * @param \WC_Memberships_Membership_Plan $plan The membership plan. | ||
| */ | ||
| public static function get_plan_related_active_subscriptions( $plan ) { | ||
| $product_ids = $plan->get_product_ids(); | ||
| $subscriptions = wcs_get_subscriptions_for_product( $product_ids, 'ids', [ 'subscription_status' => 'active' ] ); | ||
| return count( $subscriptions ); | ||
| } | ||
|
|
||
| /** | ||
| * Filter user membership data from REST API. | ||
| * | ||
| * @param \WP_REST_Response $response the response object. | ||
| * @param null|\WP_Post $user the user membership post object. | ||
| * @param \WP_REST_Request $request the request object. | ||
| */ | ||
| public static function add_data_to_wc_user_membership_response( $response, $user, $request ) { | ||
| if ( $request && isset( $request->get_headers()['x_np_network_signature'] ) ) { | ||
| // Add network plan ID to the response. | ||
| $plan = wc_memberships_get_membership_plan( $response->data['plan_id'] ); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looks like
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed in a4ab6df |
||
| $response->data['plan_network_id'] = get_post_meta( $plan->id, self::NETWORK_ID_META_KEY, true ); | ||
| } | ||
| return $response; | ||
| } | ||
|
|
||
| /** | ||
| * Adds a meta box to the membership plan edit screen. | ||
| */ | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we sanitize these to address the
WordPress.Security.ValidatedSanitizedInput.InputNotSanitizedwarning?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done in a4ab6df