get_gateway_id(); $payment_meta_table = self::get_subscription_payment_meta( $subscription, $token_payment_gateway ); $token_meta_key = ''; // Attempt to find the token meta key from the subscription payment meta and the old token. if ( is_array( $payment_meta_table ) ) { foreach ( $payment_meta_table as $meta_table => $meta ) { foreach ( $meta as $meta_key => $meta_data ) { if ( $old_token->get_token() === $meta_data['value'] ) { $token_meta_key = $meta_key; break 2; } } } } $updated = update_post_meta( $subscription->get_id(), $token_meta_key, $new_token->get_token(), $old_token->get_token() ); if ( $updated ) { do_action( 'woocommerce_subscription_token_changed', $subscription, $new_token, $old_token ); } return $updated; } /** * Get all payment meta on a subscription for a gateway. * * @param WC_Subscription $subscription The subscription to update. * @param string $gateway_id The target gateway ID. * @return bool|array Payment meta data. False if no meta is found. * @since 2.5.0 */ public static function get_subscription_payment_meta( $subscription, $gateway_id ) { $payment_method_meta = apply_filters( 'woocommerce_subscription_payment_meta', array(), $subscription ); if ( is_array( $payment_method_meta ) && isset( $payment_method_meta[ $gateway_id ] ) && is_array( $payment_method_meta[ $gateway_id ] ) ) { return $payment_method_meta[ $gateway_id ]; } return false; } /** * Get subscriptions by a WC_Payment_Token. All automatic subscriptions with the token's payment method, * customer id and token value stored in post meta will be returned. * * @param WC_Payment_Token $payment_token Payment token object. * @return array subscription posts * @since 2.5.0 */ public static function get_subscriptions_from_token( $payment_token ) { $meta_query = array( array( 'key' => '_payment_method', 'value' => $payment_token->get_gateway_id(), ), array( 'key' => '_requires_manual_renewal', 'value' => 'false', ), array( 'value' => $payment_token->get_token(), ), ); $subscription_ids = get_posts( array( 'post_type' => 'shop_subscription', 'post_status' => array( 'wc-pending', 'wc-active', 'wc-on-hold' ), 'meta_query' => $meta_query, 'posts_per_page' => -1, 'fields' => 'ids', 'post__in' => WCS_Customer_Store::instance()->get_users_subscription_ids( $payment_token->get_user_id() ), ) ); if ( has_filter( 'woocommerce_subscriptions_by_payment_token' ) ) { wcs_deprecated_function( 'The "woocommerce_subscriptions_by_payment_token" hook should no longer be used. It previously filtered post objects and in moving to CRUD and Subscription APIs the "woocommerce_subscriptions_by_payment_token"', '2.5.0', 'woocommerce_subscriptions_from_payment_token' ); $subscription_posts = apply_filters( 'woocommerce_subscriptions_by_payment_token', array_map( 'get_post', $subscription_ids ), $payment_token ); $subscription_ids = array_unique( array_merge( $subscription_ids, wp_list_pluck( $subscription_posts, 'ID' ) ) ); } $user_subscriptions = array(); foreach ( $subscription_ids as $subscription_id ) { $user_subscriptions[ $subscription_id ] = wcs_get_subscription( $subscription_id ); } return apply_filters( 'woocommerce_subscriptions_from_payment_token', $user_subscriptions, $payment_token ); } /** * Get a list of customer payment tokens. Caches results to avoid multiple database queries per request * * @param int (optional) The customer id - defaults to the current user. * @param string (optional) Gateway ID for getting tokens for a specific gateway. * @return array of WC_Payment_Token objects. * @since 2.2.7 */ public static function get_customer_tokens( $customer_id = '', $gateway_id = '' ) { if ( '' === $customer_id ) { $customer_id = get_current_user_id(); } if ( ! isset( self::$customer_tokens[ $customer_id ][ $gateway_id ] ) ) { self::$customer_tokens[ $customer_id ][ $gateway_id ] = parent::get_customer_tokens( $customer_id, $gateway_id ); } return self::$customer_tokens[ $customer_id ][ $gateway_id ]; } /** * Get the customer's alternative token. * * @param WC_Payment_Token $token The token to find an alternative for. * @return WC_Payment_Token The customer's alternative token. * @since 2.2.7 */ public static function get_customers_alternative_token( $token ) { $payment_tokens = self::get_customer_tokens( $token->get_gateway_id(), $token->get_user_id() ); $alternative_token = null; // Remove the token we're trying to find an alternative for. unset( $payment_tokens[ $token->get_id() ] ); if ( count( $payment_tokens ) === 1 ) { $alternative_token = reset( $payment_tokens ); } else { foreach ( $payment_tokens as $payment_token ) { // If there is a default token we can use it as an alternative. if ( $payment_token->is_default() ) { $alternative_token = $payment_token; break; } } } return $alternative_token; } /** * Determine if the customer has an alternative token. * * @param WC_Payment_Token $token Payment token object. * @return bool * @since 2.2.7 */ public static function customer_has_alternative_token( $token ) { return self::get_customers_alternative_token( $token ) !== null; } }