From a99c80563aa147048bbde263927e53488ff34bf3 Mon Sep 17 00:00:00 2001 From: Dharmesh Patel Date: Wed, 23 Jul 2025 17:53:26 +0530 Subject: [PATCH 1/8] Add Dynamic_Props class to store dynamic properties for order object. --- woocommerce/payment-gateway/Dynamic_Props.php | 137 ++++++++++++++++++ 1 file changed, 137 insertions(+) create mode 100644 woocommerce/payment-gateway/Dynamic_Props.php diff --git a/woocommerce/payment-gateway/Dynamic_Props.php b/woocommerce/payment-gateway/Dynamic_Props.php new file mode 100644 index 000000000..27fd6da93 --- /dev/null +++ b/woocommerce/payment-gateway/Dynamic_Props.php @@ -0,0 +1,137 @@ +|null + */ + private static ?\WeakMap $map = null; + + /** + * Sets a property on the order object. + * + * ```php + * Dynamic_Props::set($order, 'customer_id', 123); + * Dynamic_Props::set($order, 'payment_total', '99.99'); + * ``` + * + * @param \WC_Order $order The order object to store data on. + * @param string $key The property key. + * @param mixed $value The value to store. + * + * @return void + */ + public static function set( \WC_Order &$order, string $key, mixed $value ): void { + if ( self::use_weak_map() ) { + self::init_weak_map(); + if ( ! isset( self::$map[ $order ] ) ) { + self::$map[ $order ] = new \stdClass(); + } + self::$map[ $order ]->{ $key } = $value; + } else { + $order->{ $key } = $value; + } + } + + /** + * Gets a property from the order object. + * + * ```php + * $customer_id = Dynamic_Props::get($order, 'customer_id'); + * $total = Dynamic_Props::get($order, 'payment_total'); + * $token = Dynamic_Props::get($order, 'payment', 'token', 'DEFAULT_TOKEN'); + * ``` + * + * @param \WC_Order $order The order object to retrieve data from. + * @param string $key The property key. + * @param string $nested_key The nested property key. + * @param mixed $default Default value if not found. + * + * @return mixed The stored value or default if not found. + */ + public static function get( \WC_Order $order, string $key, $nested_key = null, $default = null ): mixed { + if ( self::use_weak_map() ) { + self::init_weak_map(); + if ( is_null( $nested_key ) ) { + return self::$map[ $order ]->{ $key } ?? $default; + } else { + return self::$map[ $order ]->{ $key }->{ $nested_key } ?? $default; + } + } + if ( is_null( $nested_key ) ) { + return $order->{ $key } ?? $default; + } else { + return $order->{ $key }->{ $nested_key } ?? $default; + } + } + + /** + * Unsets a property on the order object. + * + * @param \WC_Order $order The order object to unset data from. + * @param string $key The property key. + * + * @return void + */ + public static function unset( \WC_Order &$order, string $key ): void { + if ( self::use_weak_map() ) { + self::init_weak_map(); + unset( self::$map[ $order ]->{ $key } ); + } else { + unset( $order->{ $key } ); + } + } + + /** + * Checks if WeakMap should be used based on PHP version. + * + * @return bool True if WeakMap should be used, false otherwise. + */ + private static function use_weak_map(): bool { + static $use_weak_map = null; + + if ( null === $use_weak_map ) { + $use_weak_map = version_compare( PHP_VERSION, '8.0', '>=' ) && class_exists( '\WeakMap' ); + } + + return $use_weak_map; + } + + /** + * Initializes WeakMap storage if not already initialized. + * + * @return void + */ + private static function init_weak_map(): void { + if ( null === self::$map ) { + self::$map = new \WeakMap(); + } + } +} From a773144650a412cb9ead623c47c783541d8b751a Mon Sep 17 00:00:00 2001 From: Dharmesh Patel Date: Wed, 23 Jul 2025 18:19:34 +0530 Subject: [PATCH 2/8] Replace dynamic props usage with Dynamic_Props class. --- .../Abstract_Hosted_Payment_Handler.php | 18 ++- .../payment-gateway/Handlers/Capture.php | 5 +- .../class-sv-wc-payment-gateway-direct.php | 96 +++++++------ .../class-sv-wc-payment-gateway-hosted.php | 42 ++++-- .../class-sv-wc-payment-gateway.php | 136 +++++++++++------- ...payment-gateway-integration-pre-orders.php | 59 ++++---- ...ment-gateway-integration-subscriptions.php | 61 +++++--- ...payment-gateway-payment-tokens-handler.php | 13 +- 8 files changed, 261 insertions(+), 169 deletions(-) diff --git a/woocommerce/payment-gateway/Handlers/Abstract_Hosted_Payment_Handler.php b/woocommerce/payment-gateway/Handlers/Abstract_Hosted_Payment_Handler.php index 988e87c23..914958873 100644 --- a/woocommerce/payment-gateway/Handlers/Abstract_Hosted_Payment_Handler.php +++ b/woocommerce/payment-gateway/Handlers/Abstract_Hosted_Payment_Handler.php @@ -25,6 +25,7 @@ namespace SkyVerge\WooCommerce\PluginFramework\v5_15_12\Payment_Gateway\Handlers; use SkyVerge\WooCommerce\PluginFramework\v5_15_12 as FrameworkBase; +use SkyVerge\WooCommerce\PluginFramework\v5_15_12\Payment_Gateway\Dynamic_Props; if ( ! class_exists( '\\SkyVerge\\WooCommerce\\PluginFramework\\v5_15_12\\Payment_Gateway\\Handlers\\Abstract_Hosted_Payment_Handler' ) ) : @@ -325,20 +326,25 @@ protected function get_order_from_response( FrameworkBase\SV_WC_Payment_Gateway_ $order = $this->get_gateway()->get_order( $order ); - $order->payment->account_number = $response->get_account_number(); + $payment = Dynamic_Props::get( $order, 'payment', null, new \stdClass() ); + + $payment->account_number = $response->get_account_number(); if ( $response instanceof FrameworkBase\SV_WC_Payment_Gateway_API_Payment_Notification_Credit_Card_Response ) { - $order->payment->exp_month = $response->get_exp_month(); - $order->payment->exp_year = $response->get_exp_year(); - $order->payment->card_type = $response->get_card_type(); + $payment->exp_month = $response->get_exp_month(); + $payment->exp_year = $response->get_exp_year(); + $payment->card_type = $response->get_card_type(); } elseif ( $response instanceof FrameworkBase\SV_WC_Payment_Gateway_API_Payment_Notification_eCheck_Response ) { - $order->payment->account_type = $response->get_account_type(); - $order->payment->check_number = $response->get_check_number(); + $payment->account_type = $response->get_account_type(); + $payment->check_number = $response->get_check_number(); } + // Set payment info on the order object. + Dynamic_Props::set( $order, 'payment', $payment ); + return $order; } diff --git a/woocommerce/payment-gateway/Handlers/Capture.php b/woocommerce/payment-gateway/Handlers/Capture.php index 33b298ab2..866ce1613 100644 --- a/woocommerce/payment-gateway/Handlers/Capture.php +++ b/woocommerce/payment-gateway/Handlers/Capture.php @@ -25,6 +25,7 @@ namespace SkyVerge\WooCommerce\PluginFramework\v5_15_12\Payment_Gateway\Handlers; use SkyVerge\WooCommerce\PluginFramework\v5_15_12 as Framework; +use SkyVerge\WooCommerce\PluginFramework\v5_15_12\Payment_Gateway\Dynamic_Props; defined( 'ABSPATH' ) or exit; @@ -189,7 +190,7 @@ public function perform_capture( \WC_Order $order, $amount = null ) { /* translators: Placeholders: %1$s - payment gateway title (such as Authorize.net, Braintree, etc), %2$s - transaction amount. Definitions: Capture, as in capture funds from a credit card. */ __( '%1$s Capture of %2$s Approved', 'woocommerce-plugin-framework' ), $this->get_gateway()->get_method_title(), - wc_price( $order->capture->amount, [ + wc_price( Dynamic_Props::get( $order, 'capture', 'amount' ), [ 'currency' => $order->get_currency() ] ) ); @@ -255,7 +256,7 @@ public function perform_capture( \WC_Order $order, $amount = null ) { */ public function do_capture_success( \WC_Order $order, Framework\SV_WC_Payment_Gateway_API_Response $response ) { - $total_captured = (float) $this->get_gateway()->get_order_meta( $order, 'capture_total' ) + (float) $order->capture->amount; + $total_captured = (float) $this->get_gateway()->get_order_meta( $order, 'capture_total' ) + (float) Dynamic_Props::get( $order, 'capture', 'amount' ); $this->get_gateway()->update_order_meta( $order, 'capture_total', Framework\SV_WC_Helper::number_format( $total_captured ) ); $this->get_gateway()->update_order_meta( $order, 'charge_captured', $this->get_gateway()->supports_credit_card_partial_capture() && $this->get_gateway()->is_partial_capture_enabled() && $total_captured < (float) $this->get_order_capture_maximum( $order ) ? 'partial' : 'yes' ); diff --git a/woocommerce/payment-gateway/class-sv-wc-payment-gateway-direct.php b/woocommerce/payment-gateway/class-sv-wc-payment-gateway-direct.php index 8c63d045e..87fb92923 100644 --- a/woocommerce/payment-gateway/class-sv-wc-payment-gateway-direct.php +++ b/woocommerce/payment-gateway/class-sv-wc-payment-gateway-direct.php @@ -25,6 +25,7 @@ namespace SkyVerge\WooCommerce\PluginFramework\v5_15_12; use SkyVerge\WooCommerce\PluginFramework\v5_15_12\Blocks\Blocks_Handler; +use SkyVerge\WooCommerce\PluginFramework\v5_15_12\Payment_Gateway\Dynamic_Props; defined( 'ABSPATH' ) or exit; @@ -372,7 +373,7 @@ public function process_payment( $order_id ) { if ( $this->supports_tokenization() && 0 !== (int) $order->get_user_id() ) { // if already paying with an existing method, try and updated it locally and remotely - if ( ! empty( $order->payment->token ) ) { + if ( ! empty( Dynamic_Props::get( $order, 'payment', 'token' ) ) ) { $this->update_transaction_payment_method( $order ); @@ -388,7 +389,7 @@ public function process_payment( $order_id ) { if ( $this->should_skip_transaction( $order ) || $this->do_transaction( $order ) ) { // add transaction data for zero-dollar "orders" - if ( '0.00' === $order->payment_total ) { + if ( '0.00' === Dynamic_Props::get( $order, 'payment_total' ) ) { $this->add_transaction_data( $order ); } @@ -502,7 +503,7 @@ protected function get_notices_as_user_messages( ?string $type = null ) : array */ protected function update_transaction_payment_method( \WC_Order $order ) { - $token = $this->get_payment_tokens_handler()->get_token( $order->get_user_id(), $order->payment->token ); + $token = $this->get_payment_tokens_handler()->get_token( $order->get_user_id(), Dynamic_Props::get( $order, 'payment', 'token' ) ); $address = new Addresses\Customer_Address(); $address->set_from_order( $order ); @@ -599,43 +600,46 @@ public function get_order( $order_id ) { $order = parent::get_order( $order_id ); + // Get payment info from the order object. + $payment = Dynamic_Props::get( $order, 'payment', null, new \stdClass() ); + // payment info if ( SV_WC_Helper::get_posted_value( 'wc-' . $this->get_id_dasherized() . '-account-number' ) && ! SV_WC_Helper::get_posted_value( 'wc-' . $this->get_id_dasherized() . '-payment-token' ) ) { // common attributes - $order->payment->account_number = str_replace( array( ' ', '-' ), '', SV_WC_Helper::get_posted_value( 'wc-' . $this->get_id_dasherized() . '-account-number' ) ); - $order->payment->last_four = substr( $order->payment->account_number, -4 ); + $payment->account_number = str_replace( array( ' ', '-' ), '', SV_WC_Helper::get_posted_value( 'wc-' . $this->get_id_dasherized() . '-account-number' ) ); + $payment->last_four = substr( $payment->account_number, -4 ); if ( $this->is_credit_card_gateway() ) { // credit card specific attributes - $order->payment->card_type = SV_WC_Helper::get_posted_value( 'wc-' . $this->get_id_dasherized() . '-card-type' ); - $order->payment->exp_month = SV_WC_Helper::get_posted_value( 'wc-' . $this->get_id_dasherized() . '-exp-month' ); - $order->payment->exp_year = SV_WC_Helper::get_posted_value( 'wc-' . $this->get_id_dasherized() . '-exp-year' ); + $payment->card_type = SV_WC_Helper::get_posted_value( 'wc-' . $this->get_id_dasherized() . '-card-type' ); + $payment->exp_month = SV_WC_Helper::get_posted_value( 'wc-' . $this->get_id_dasherized() . '-exp-month' ); + $payment->exp_year = SV_WC_Helper::get_posted_value( 'wc-' . $this->get_id_dasherized() . '-exp-year' ); // add card type for gateways that don't require it displayed at checkout - if ( empty( $order->payment->card_type ) ) { - $order->payment->card_type = SV_WC_Payment_Gateway_Helper::card_type_from_account_number( $order->payment->account_number ); + if ( empty( $payment->card_type ) ) { + $payment->card_type = SV_WC_Payment_Gateway_Helper::card_type_from_account_number( $payment->account_number ); } // handle single expiry field formatted like "MM / YY" or "MM / YYYY" if ( SV_WC_Helper::get_posted_value( 'wc-' . $this->get_id_dasherized() . '-expiry' ) ) { - [ $order->payment->exp_month, $order->payment->exp_year ] = array_map( 'trim', explode( '/', SV_WC_Helper::get_posted_value( 'wc-' . $this->get_id_dasherized() . '-expiry' ) ) ); + [ $payment->exp_month, $payment->exp_year ] = array_map( 'trim', explode( '/', SV_WC_Helper::get_posted_value( 'wc-' . $this->get_id_dasherized() . '-expiry' ) ) ); } // add CSC if enabled if ( $this->csc_enabled() ) { - $order->payment->csc = SV_WC_Helper::get_posted_value( 'wc-' . $this->get_id_dasherized() . '-csc' ); + $payment->csc = SV_WC_Helper::get_posted_value( 'wc-' . $this->get_id_dasherized() . '-csc' ); } } elseif ( $this->is_echeck_gateway() ) { // echeck specific attributes - $order->payment->routing_number = SV_WC_Helper::get_posted_value( 'wc-' . $this->get_id_dasherized() . '-routing-number' ); - $order->payment->account_type = SV_WC_Helper::get_posted_value( 'wc-' . $this->get_id_dasherized() . '-account-type' ); - $order->payment->check_number = SV_WC_Helper::get_posted_value( 'wc-' . $this->get_id_dasherized() . '-check-number' ); - $order->payment->drivers_license_number = SV_WC_Helper::get_posted_value( 'wc-' . $this->get_id_dasherized() . '-drivers-license-number' ); - $order->payment->drivers_license_state = SV_WC_Helper::get_posted_value( 'wc-' . $this->get_id_dasherized() . '-drivers-license-state' ); + $payment->routing_number = SV_WC_Helper::get_posted_value( 'wc-' . $this->get_id_dasherized() . '-routing-number' ); + $payment->account_type = SV_WC_Helper::get_posted_value( 'wc-' . $this->get_id_dasherized() . '-account-type' ); + $payment->check_number = SV_WC_Helper::get_posted_value( 'wc-' . $this->get_id_dasherized() . '-check-number' ); + $payment->drivers_license_number = SV_WC_Helper::get_posted_value( 'wc-' . $this->get_id_dasherized() . '-drivers-license-number' ); + $payment->drivers_license_state = SV_WC_Helper::get_posted_value( 'wc-' . $this->get_id_dasherized() . '-drivers-license-state' ); } @@ -644,25 +648,25 @@ public function get_order( $order_id ) { // paying with tokenized payment method (we've already verified that this token exists in the validate_fields method) $token = $this->get_payment_tokens_handler()->get_token( $order->get_user_id(), $token_value ); - $order->payment->token = $token->get_id(); - $order->payment->account_number = $token->get_last_four(); - $order->payment->last_four = $token->get_last_four(); + $payment->token = $token->get_id(); + $payment->account_number = $token->get_last_four(); + $payment->last_four = $token->get_last_four(); if ( $this->is_credit_card_gateway() ) { // credit card specific attributes - $order->payment->card_type = $token->get_card_type(); - $order->payment->exp_month = $token->get_exp_month(); - $order->payment->exp_year = $token->get_exp_year(); + $payment->card_type = $token->get_card_type(); + $payment->exp_month = $token->get_exp_month(); + $payment->exp_year = $token->get_exp_year(); if ( $this->csc_enabled_for_tokens() ) { - $order->payment->csc = SV_WC_Helper::get_posted_value( 'wc-' . $this->get_id_dasherized() . '-csc' ); + $payment->csc = SV_WC_Helper::get_posted_value( 'wc-' . $this->get_id_dasherized() . '-csc' ); } } elseif ( $this->is_echeck_gateway() ) { // echeck specific attributes - $order->payment->account_type = $token->get_account_type(); + $payment->account_type = $token->get_account_type(); } // make this the new default payment token @@ -670,10 +674,13 @@ public function get_order( $order_id ) { } // standardize expiration date year to 2 digits - if ( ! empty( $order->payment->exp_year ) && 4 === strlen( $order->payment->exp_year ) ) { - $order->payment->exp_year = substr( $order->payment->exp_year, 2 ); + if ( ! empty( $payment->exp_year ) && 4 === strlen( $payment->exp_year ) ) { + $payment->exp_year = substr( $payment->exp_year, 2 ); } + // Set payment info on the order object. + Dynamic_Props::set( $order, 'payment', $payment ); + /** * Direct Gateway Get Order Filter. * @@ -706,16 +713,16 @@ protected function do_check_transaction( $order, $response = null ) { // success! update order record if ( $response->transaction_approved() ) { - $last_four = substr( $order->payment->account_number, -4 ); + $last_four = substr( Dynamic_Props::get( $order, 'payment', 'account_number', '' ), -4 ); // check order note. there may not be an account_type available, but that's fine /* translators: Placeholders: %1$s - Payment method title, %2$s - Payment account type (savings/checking) (may or may not be available), %3$s - Last four digits of the account */ - $message = sprintf( esc_html__( '%1$s Check Transaction Approved: %2$s account ending in %3$s', 'woocommerce-plugin-framework' ), $this->get_method_title(), $order->payment->account_type, $last_four ); + $message = sprintf( esc_html__( '%1$s Check Transaction Approved: %2$s account ending in %3$s', 'woocommerce-plugin-framework' ), $this->get_method_title(), Dynamic_Props::get( $order, 'payment', 'account_type' ), $last_four ); // optional check number - if ( ! empty( $order->payment->check_number ) ) { + if ( ! empty( Dynamic_Props::get( $order, 'payment', 'check_number' ) ) ) { /* translators: Placeholder: %s - Bank check number */ - $message .= '. ' . sprintf( esc_html__( 'Check number %s', 'woocommerce-plugin-framework' ), $order->payment->check_number ); + $message .= '. ' . sprintf( esc_html__( 'Check number %s', 'woocommerce-plugin-framework' ), Dynamic_Props::get( $order, 'payment', 'check_number' ) ); } // adds the transaction id (if any) to the order note @@ -771,12 +778,12 @@ protected function do_credit_card_transaction( $order, $response = null ) { // success! update order record if ( $response->transaction_approved() ) { - $account_number = ! empty( $order->payment->account_number ) ? $order->payment->account_number : null; + $account_number = ! empty( Dynamic_Props::get( $order, 'payment', 'account_number' ) ) ? Dynamic_Props::get( $order, 'payment', 'account_number' ) : null; $last_four = $account_number ? substr( $account_number, -4 ) : ''; // use direct card type if set, or try to guess it from card number - if ( ! empty( $order->payment->card_type ) ) { - $card_type = $order->payment->card_type; + if ( ! empty( Dynamic_Props::get( $order, 'payment', 'card_type' ) ) ) { + $card_type = Dynamic_Props::get( $order, 'payment', 'card_type' ); } elseif ( $first_four = $account_number ? substr( $account_number, 0, 4 ) : '' ) { $card_type = SV_WC_Payment_Gateway_Helper::card_type_from_account_number( $first_four ); } else { @@ -806,12 +813,12 @@ protected function do_credit_card_transaction( $order, $response = null ) { } // add the expiry date if it is available - if ( ! empty( $order->payment->exp_month ) && ! empty( $order->payment->exp_year ) ) { + if ( ! empty( Dynamic_Props::get( $order, 'payment', 'exp_month' ) ) && ! empty( Dynamic_Props::get( $order, 'payment', 'exp_year' ) ) ) { $message .= ' ' . sprintf( /* translators: Placeholder: %s - Credit card expiry date */ __( '(expires %s)', 'woocommerce-plugin-framework' ), - $order->payment->exp_month . '/' . substr( $order->payment->exp_year, -2 ) + Dynamic_Props::get( $order, 'payment', 'exp_month', '' ) . '/' . substr( Dynamic_Props::get( $order, 'payment', 'exp_year', '' ), -2 ) ); } @@ -1131,13 +1138,14 @@ protected function get_order_for_add_payment_method() { $order->set_props( $properties ); // other default info - $order->customer_id = $this->get_customer_id( $order->get_user_id() ); + Dynamic_Props::set( $order, 'customer_id', $this->get_customer_id( $order->get_user_id() ) ); /* translators: Placeholders: %1$s - site title, %2$s - customer email. Payment method as in a specific credit card, e-check or bank account */ - $order->description = sprintf( esc_html__( '%1$s - Add Payment Method for %2$s', 'woocommerce-plugin-framework' ), sanitize_text_field( SV_WC_Helper::get_site_name() ), $properties['billing_email'] ); + $description = sprintf( esc_html__( '%1$s - Add Payment Method for %2$s', 'woocommerce-plugin-framework' ), sanitize_text_field( SV_WC_Helper::get_site_name() ), $properties['billing_email'] ); + Dynamic_Props::set( $order, 'description', $description ); // force zero amount - $order->payment_total = '0.00'; + Dynamic_Props::set( $order, 'payment_total', '0.00' ); /** * Direct Gateway Get Order for Add Payment Method Filter. @@ -1168,12 +1176,12 @@ protected function add_add_payment_method_customer_data( $order, $response ) { // set customer ID from response if available if ( $this->supports_customer_id() && method_exists( $response, 'get_customer_id' ) && $response->get_customer_id() ) { - $order->customer_id = $customer_id = $response->get_customer_id(); + Dynamic_Props::set( $order, 'customer_id', $customer_id = $response->get_customer_id() ); } else { // default to the customer ID on "order" - $customer_id = $order->customer_id; + $customer_id = Dynamic_Props::get( $order, 'customer_id' ); } // update the user @@ -1283,7 +1291,7 @@ public function transaction_forced() { */ protected function should_tokenize_before_sale( \WC_Order $order ): bool { - $result = $this->get_payment_tokens_handler()->should_tokenize() && ( '0.00' === $order->payment_total || $this->tokenize_before_sale() ); + $result = $this->get_payment_tokens_handler()->should_tokenize() && ( '0.00' === Dynamic_Props::get( $order, 'payment_total' ) || $this->tokenize_before_sale() ); /** * Filters whether tokenization should be performed before the sale, for a given order. @@ -1374,7 +1382,7 @@ protected function can_tokenize_with_or_after_sale( \WC_Order $order ): bool { */ return apply_filters( "wc_payment_gateway_{$this->get_id()}_can_tokenize_with_or_after_sale", - $order->payment_total > 0, + Dynamic_Props::get( $order, 'payment_total' ) > 0, $order, $this ); @@ -1411,7 +1419,7 @@ protected function should_skip_transaction( \WC_Order $order ): bool { return apply_filters( "wc_payment_gateway_{$this->get_id()}_should_skip_transaction", // the order amount will be $0 if a WooCommerce Subscriptions free trial product is being processed - ( '0.00' === $order->payment_total && ! $this->transaction_forced() ), + ( '0.00' === Dynamic_Props::get( $order, 'payment_total' ) && ! $this->transaction_forced() ), $order, $this ); diff --git a/woocommerce/payment-gateway/class-sv-wc-payment-gateway-hosted.php b/woocommerce/payment-gateway/class-sv-wc-payment-gateway-hosted.php index 2d499d0ea..8e467eadf 100644 --- a/woocommerce/payment-gateway/class-sv-wc-payment-gateway-hosted.php +++ b/woocommerce/payment-gateway/class-sv-wc-payment-gateway-hosted.php @@ -24,6 +24,8 @@ namespace SkyVerge\WooCommerce\PluginFramework\v5_15_12; +use SkyVerge\WooCommerce\PluginFramework\v5_15_12\Payment_Gateway\Dynamic_Props; + defined( 'ABSPATH' ) or exit; if ( ! class_exists( '\\SkyVerge\\WooCommerce\\PluginFramework\\v5_15_12\\SV_WC_Payment_Gateway_Hosted' ) ) : @@ -465,20 +467,25 @@ protected function get_order_from_response( $response ) { $order = $this->get_order( $order ); - $order->payment->account_number = $response->get_account_number(); + $payment = Dynamic_Props::get( $order, 'payment', null, new \stdClass() ); + + $payment->account_number = $response->get_account_number(); if ( self::PAYMENT_TYPE_CREDIT_CARD == $response->get_payment_type() ) { - $order->payment->exp_month = $response->get_exp_month(); - $order->payment->exp_year = $response->get_exp_year(); - $order->payment->card_type = $response->get_card_type(); + $payment->exp_month = $response->get_exp_month(); + $payment->exp_year = $response->get_exp_year(); + $payment->card_type = $response->get_card_type(); } elseif ( self::PAYMENT_TYPE_ECHECK == $response->get_payment_type() ) { - $order->payment->account_type = $response->get_account_type(); - $order->payment->check_number = $response->get_check_number(); + $payment->account_type = $response->get_account_type(); + $payment->check_number = $response->get_check_number(); } + // Set payment info on the order object. + Dynamic_Props::set( $order, 'payment', $payment ); + return $order; } @@ -596,7 +603,7 @@ protected function process_transaction_response( $order, $response ) { protected function process_tokenization_response( \WC_Order $order, $response ) { if ( is_callable( array( $response, 'get_customer_id' ) ) && $response->get_customer_id() ) { - $order->customer_id = $response->get_customer_id(); + Dynamic_Props::set( $order, 'customer_id', $response->get_customer_id() ); } $token = $response->get_payment_token(); @@ -655,21 +662,26 @@ protected function process_tokenization_response( \WC_Order $order, $response ) // add the payment method order data if ( $token ) { - $order->payment->token = $token->get_id(); - $order->payment->account_number = $token->get_last_four(); - $order->payment->last_four = $token->get_last_four(); + $payment = Dynamic_Props::get( $order, 'payment', null, new \stdClass() ); + + $payment->token = $token->get_id(); + $payment->account_number = $token->get_last_four(); + $payment->last_four = $token->get_last_four(); if ( $token->is_credit_card() ) { - $order->payment->exp_month = $token->get_exp_month(); - $order->payment->exp_year = $token->get_exp_year(); - $order->payment->card_type = $token->get_card_type(); + $payment->exp_month = $token->get_exp_month(); + $payment->exp_year = $token->get_exp_year(); + $payment->card_type = $token->get_card_type(); } elseif ( $token->is_echeck() ) { - $order->payment->account_type = $token->get_account_type(); - $order->payment->check_number = $token->get_check_number(); + $payment->account_type = $token->get_account_type(); + $payment->check_number = $token->get_check_number(); } + + // Set payment info on the order object + Dynamic_Props::set( $order, 'payment', $payment ); } // remove any tokens that were deleted on the hosted pay page diff --git a/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php b/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php index 9b943158c..d4954aa05 100755 --- a/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php +++ b/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php @@ -27,6 +27,7 @@ use Automattic\WooCommerce\Blocks\Integrations\IntegrationInterface; use SkyVerge\WooCommerce\PluginFramework\v5_15_12\Blocks\Blocks_Handler; use SkyVerge\WooCommerce\PluginFramework\v5_15_12\Payment_Gateway\Blocks\Gateway_Checkout_Block_Integration; +use SkyVerge\WooCommerce\PluginFramework\v5_15_12\Payment_Gateway\Dynamic_Props; use stdClass; defined( 'ABSPATH' ) or exit; @@ -1281,9 +1282,13 @@ public function get_apple_pay_currencies() { */ public function get_order_for_apple_pay( \WC_Order $order, SV_WC_Payment_Gateway_Apple_Pay_Payment_Response $response ) { - $order->payment->account_number = $response->get_last_four(); - $order->payment->last_four = $response->get_last_four(); - $order->payment->card_type = $response->get_card_type(); + $payment = Dynamic_Props::get( $order, 'payment', null, new \stdClass() ); + + $payment->account_number = $response->get_last_four(); + $payment->last_four = $response->get_last_four(); + $payment->card_type = $response->get_card_type(); + + Dynamic_Props::set( $order, 'payment', $payment ); return $order; } @@ -1336,11 +1341,16 @@ public function get_order_for_google_pay( \WC_Order $order, $response_data ) { $payment_method_data = $response_data['paymentMethodData']; - $order->payment->google_pay = base64_encode( $payment_method_data['tokenizationData']['token'] ); + $payment = Dynamic_Props::get( $order, 'payment', null, new \stdClass() ); + + $payment->google_pay = base64_encode( $payment_method_data['tokenizationData']['token'] ); // account last four - $order->payment->account_number = $payment_method_data['info']['cardDetails']; - $order->payment->card_type = SV_WC_Payment_Gateway_Helper::normalize_card_type( $payment_method_data['info']['cardNetwork'] ); + $payment->account_number = $payment_method_data['info']['cardDetails']; + $payment->card_type = SV_WC_Payment_Gateway_Helper::normalize_card_type( $payment_method_data['info']['cardNetwork'] ); + + // Set payment info on the order object. + Dynamic_Props::set( $order, 'payment', $payment ); return $order; } @@ -1933,23 +1943,30 @@ public function get_order( $order ) { } // set payment total here, so it can be modified for later by add-ons like subscriptions which may need to charge an amount different than the get_total() - $order->payment_total = number_format( $order->get_total(), 2, '.', '' ); + $payment_total = number_format( $order->get_total(), 2, '.', '' ); - $order->customer_id = ''; + Dynamic_Props::set( $order, 'payment_total', $payment_total ); + + Dynamic_Props::set( $order, 'customer_id', '' ); // logged in customer? if ( 0 != $order->get_user_id() && false !== ( $customer_id = $this->get_customer_id( $order->get_user_id(), array( 'order' => $order ) ) ) ) { - $order->customer_id = $customer_id; + Dynamic_Props::set( $order, 'customer_id', $customer_id ); } // add payment info - $order->payment = new \stdClass(); + $payment = new \stdClass(); // payment type (credit_card/check/etc) - $order->payment->type = str_replace( '-', '_', $this->get_payment_type() ); + $payment->type = str_replace( '-', '_', $this->get_payment_type() ); + + // Set payment info on the order object + Dynamic_Props::set( $order, 'payment', $payment ); /* translators: Placeholders: %1$s - site title, %2$s - order number */ - $order->description = sprintf( esc_html__( '%1$s - Order %2$s', 'woocommerce-plugin-framework' ), wp_specialchars_decode( SV_WC_Helper::get_site_name(), ENT_QUOTES ), $order->get_order_number() ); + $description = sprintf( esc_html__( '%1$s - Order %2$s', 'woocommerce-plugin-framework' ), wp_specialchars_decode( SV_WC_Helper::get_site_name(), ENT_QUOTES ), $order->get_order_number() ); + + Dynamic_Props::set( $order, 'description', $description ); // the get_order_with_unique_transaction_ref() call results in saving the order object, which we don't want to do if the order hasn't already been saved (such as when adding a payment method) if ( $order->get_id() ) { @@ -2069,7 +2086,7 @@ public function get_order_for_capture( $order, $amount = null ) { } // add capture info - $order->capture = new \stdClass(); + $capture = new \stdClass(); $total_captured = $this->get_order_meta( $order, 'capture_total' ); @@ -2078,11 +2095,14 @@ public function get_order_for_capture( $order, $amount = null ) { $amount = (float) $order->get_total() - (float) $total_captured; } - $order->capture->amount = SV_WC_Helper::number_format( $amount ); + $capture->amount = SV_WC_Helper::number_format( $amount ); /* translators: Placeholders: %1$s - site title, %2$s - order number. Definitions: Capture as in capture funds from a credit card. */ - $order->capture->description = sprintf( esc_html__( '%1$s - Capture for Order %2$s', 'woocommerce-plugin-framework' ), wp_specialchars_decode( SV_WC_Helper::get_site_name() ), $order->get_order_number() ); - $order->capture->trans_id = $this->get_order_meta( $order, 'trans_id' ); + $capture->description = sprintf( esc_html__( '%1$s - Capture for Order %2$s', 'woocommerce-plugin-framework' ), wp_specialchars_decode( SV_WC_Helper::get_site_name() ), $order->get_order_number() ); + $capture->trans_id = $this->get_order_meta( $order, 'trans_id' ); + + // Set capture info on the order object. + Dynamic_Props::set( $order, 'capture', $capture ); /** * Direct Gateway Capture Get Order Filter. @@ -2220,14 +2240,17 @@ protected function get_order_for_refund( $order, $amount, $reason ) { } // add refund info - $order->refund = new \stdClass(); - $order->refund->amount = number_format( $amount, 2, '.', '' ); + $refund = new \stdClass(); + $refund->amount = number_format( $amount, 2, '.', '' ); /* translators: Placeholders: %1$s - site title, %2$s - order number */ - $order->refund->reason = $reason ? $reason : sprintf( esc_html__( '%1$s - Refund for Order %2$s', 'woocommerce-plugin-framework' ), esc_html( SV_WC_Helper::get_site_name() ), $order->get_order_number() ); + $refund->reason = $reason ? $reason : sprintf( esc_html__( '%1$s - Refund for Order %2$s', 'woocommerce-plugin-framework' ), esc_html( SV_WC_Helper::get_site_name() ), $order->get_order_number() ); // almost all gateways require the original transaction ID, so include it by default - $order->refund->trans_id = $this->get_order_meta( $order, 'trans_id' ); + $refund->trans_id = $this->get_order_meta( $order, 'trans_id' ); + + // Set refund info on the order object. + Dynamic_Props::set( $order, 'refund', $refund ); /** * Payment Gateway Get Order For Refund Filter. @@ -2257,7 +2280,7 @@ protected function get_order_for_refund( $order, $amount, $reason ) { protected function add_refund_data( \WC_Order $order, $response ) { // indicate the order was refunded along with the refund amount - $this->add_order_meta( $order, 'refund_amount', $order->refund->amount ); + $this->add_order_meta( $order, 'refund_amount', Dynamic_Props::get( $order, 'refund', 'amount' ) ); // add refund transaction ID if ( $response && $response->get_transaction_id() ) { @@ -2293,7 +2316,7 @@ protected function add_refund_order_note( \WC_Order $order, $response ) { /* translators: Placeholders: %1$s - payment gateway title (such as Authorize.net, Braintree, etc), %2$s - a monetary amount */ esc_html__( '%1$s Refund in the amount of %2$s approved.', 'woocommerce-plugin-framework' ), $this->get_method_title(), - wc_price( $order->refund->amount, [ + wc_price( Dynamic_Props::get( $order, 'refund', 'amount' ), [ 'currency' => $order->get_currency() ] ) ); @@ -2404,7 +2427,7 @@ protected function maybe_void_instead_of_refund( $order, $response ) { protected function process_void( \WC_Order $order ) { // partial voids are not supported - if ( $order->refund->amount != $order->get_total() ) { + if ( Dynamic_Props::get( $order, 'refund', 'amount' ) != $order->get_total() ) { return new \WP_Error( 'wc_' . $this->get_id() . '_void_error', esc_html__( 'Oops, you cannot partially void this order. Please use the full order amount.', 'woocommerce-plugin-framework' ), 500 ); } @@ -2456,7 +2479,7 @@ protected function process_void( \WC_Order $order ) { protected function add_void_data( \WC_Order $order, $response ) { // indicate the order was voided along with the amount - $this->update_order_meta( $order, 'void_amount', $order->refund->amount ); + $this->update_order_meta( $order, 'void_amount', Dynamic_Props::get( $order, 'refund', 'amount' ) ); // add refund transaction ID if ( $response && $response->get_transaction_id() ) { @@ -2526,7 +2549,7 @@ public function mark_order_as_voided( $order, $response ) { /* translators: Placeholders: %1$s - payment gateway title, %2$s - a monetary amount. Void as in to void an order. */ esc_html__( '%1$s Void in the amount of %2$s approved.', 'woocommerce-plugin-framework' ), $this->get_method_title(), - wc_price( $order->refund->amount, [ + wc_price( Dynamic_Props::get( $order, 'refund', 'amount' ), [ 'currency' => $order->get_currency() ] ) ); @@ -2599,7 +2622,9 @@ protected function get_order_with_unique_transaction_ref( $order ) { $this->update_order_meta( $order, 'retry_count', $retry_count ); // generate a unique transaction ref based on the order number and retry count, for gateways that require a unique identifier for every transaction request - $order->unique_transaction_ref = ltrim( $order->get_order_number(), esc_html_x( '#', 'hash before order number', 'woocommerce-plugin-framework' ) ) . ( $retry_count > 0 ? '-' . $retry_count : '' ); + $unique_transaction_ref = ltrim( $order->get_order_number(), esc_html_x( '#', 'hash before order number', 'woocommerce-plugin-framework' ) ) . ( $retry_count > 0 ? '-' . $retry_count : '' ); + + Dynamic_Props::set( $order, 'unique_transaction_ref', $unique_transaction_ref ); return $order; } @@ -2676,13 +2701,15 @@ public function add_transaction_data( $order, $response = null ) { $this->add_customer_data( $order, $response ); } - if ( isset( $order->payment->token ) && $order->payment->token ) { - $this->update_order_meta( $order, 'payment_token', $order->payment->token ); + $payment = Dynamic_Props::get( $order, 'payment', null, new \stdClass() ); + + if ( isset( $payment->token ) && $payment->token ) { + $this->update_order_meta( $order, 'payment_token', $payment->token ); } // account number - if ( isset( $order->payment->account_number ) && $order->payment->account_number ) { - $this->update_order_meta( $order, 'account_four', substr( $order->payment->account_number, -4 ) ); + if ( isset( $payment->account_number ) && $payment->account_number ) { + $this->update_order_meta( $order, 'account_four', substr( $payment->account_number, -4 ) ); } if ( $this->is_credit_card_gateway() ) { @@ -2690,13 +2717,13 @@ public function add_transaction_data( $order, $response = null ) { // credit card gateway data if ( $response instanceof SV_WC_Payment_Gateway_API_Authorization_Response ) { - $this->update_order_meta( $order, 'authorization_amount', $order->payment_total ); + $this->update_order_meta( $order, 'authorization_amount', Dynamic_Props::get( $order, 'payment_total' ) ); if ( $response->get_authorization_code() ) { $this->update_order_meta( $order, 'authorization_code', $response->get_authorization_code() ); } - if ( $order->payment_total > 0 ) { + if ( Dynamic_Props::get( $order, 'payment_total' ) > 0 ) { // mark as captured if ( $this->perform_credit_card_charge( $order ) ) { @@ -2709,12 +2736,12 @@ public function add_transaction_data( $order, $response = null ) { } } - if ( isset( $order->payment->exp_year ) && $order->payment->exp_year && isset( $order->payment->exp_month ) && $order->payment->exp_month ) { - $this->update_order_meta( $order, 'card_expiry_date', $order->payment->exp_year . '-' . $order->payment->exp_month ); + if ( isset( $payment->exp_year ) && $payment->exp_year && isset( $payment->exp_month ) && $payment->exp_month ) { + $this->update_order_meta( $order, 'card_expiry_date', $payment->exp_year . '-' . $payment->exp_month ); } - if ( isset( $order->payment->card_type ) && $order->payment->card_type ) { - $this->update_order_meta( $order, 'card_type', $order->payment->card_type ); + if ( isset( $payment->card_type ) && $payment->card_type ) { + $this->update_order_meta( $order, 'card_type', $payment->card_type ); } } elseif ( $this->is_echeck_gateway() ) { @@ -2722,13 +2749,13 @@ public function add_transaction_data( $order, $response = null ) { // checking gateway data // optional account type (checking/savings) - if ( isset( $order->payment->account_type ) && $order->payment->account_type ) { - $this->update_order_meta( $order, 'account_type', $order->payment->account_type ); + if ( isset( $payment->account_type ) && $payment->account_type ) { + $this->update_order_meta( $order, 'account_type', $payment->account_type ); } // optional check number - if ( isset( $order->payment->check_number ) && $order->payment->check_number ) { - $this->update_order_meta( $order, 'check_number', $order->payment->check_number ); + if ( isset( $payment->check_number ) && $payment->check_number ) { + $this->update_order_meta( $order, 'check_number', $payment->check_number ); } } @@ -2779,12 +2806,13 @@ protected function add_customer_data( $order, $response = null ) { if ( $response && method_exists( $response, 'get_customer_id' ) && $response->get_customer_id() ) { - $order->customer_id = $customer_id = $response->get_customer_id(); + $customer_id = $response->get_customer_id(); + Dynamic_Props::set( $order, 'customer_id', $customer_id ); } else { // default to the customer ID set on the order - $customer_id = $order->customer_id; + $customer_id = Dynamic_Props::get( $order, 'customer_id' ); } // update the order with the customer ID, note environment is not appended here because it's already available @@ -2810,12 +2838,14 @@ protected function add_customer_data( $order, $response = null ) { */ public function get_credit_card_transaction_approved_message( \WC_Order $order, $response ) { - $last_four = ! empty( $order->payment->last_four ) ? $order->payment->last_four : substr( $order->payment->account_number, -4 ); + $payment = Dynamic_Props::get( $order, 'payment', null, new \stdClass() ); + + $last_four = ! empty( $payment->last_four ) ? $payment->last_four : substr( $payment->account_number, -4 ); // use direct card type if set, or try to guess it from card number - if ( ! empty( $order->payment->card_type ) ) { - $card_type = $order->payment->card_type; - } elseif ( $first_four = substr( $order->payment->account_number, 0, 4 ) ) { + if ( ! empty( $payment->card_type ) ) { + $card_type = $payment->card_type; + } elseif ( $first_four = substr( $payment->account_number, 0, 4 ) ) { $card_type = SV_WC_Payment_Gateway_Helper::card_type_from_account_number( $first_four ); } else { $card_type = 'card'; @@ -2840,12 +2870,12 @@ public function get_credit_card_transaction_approved_message( \WC_Order $order, } // add the expiry date if it is available - if ( ! empty( $order->payment->exp_month ) && ! empty( $order->payment->exp_year ) ) { + if ( ! empty( $payment->exp_month ) && ! empty( $payment->exp_year ) ) { $message .= ' ' . sprintf( /* translators: Placeholder: %s - Credit card expiry date */ __( '(expires %s)', 'woocommerce-plugin-framework' ), - $order->payment->exp_month . '/' . substr( $order->payment->exp_year, -2 ) + $payment->exp_month . '/' . substr( $payment->exp_year, -2 ) ); } @@ -2883,16 +2913,18 @@ public function get_credit_card_transaction_approved_message( \WC_Order $order, */ public function get_echeck_transaction_approved_message( \WC_Order $order, SV_WC_Payment_Gateway_API_Response $response ) { - $last_four = ! empty( $order->payment->last_four ) ? $order->payment->last_four : substr( $order->payment->account_number, -4 ); + $payment = Dynamic_Props::get( $order, 'payment', null, new \stdClass() ); + + $last_four = ! empty( $payment->last_four ) ? $payment->last_four : substr( $payment->account_number, -4 ); // check order note. there may not be an account_type available, but that's fine /* translators: Context: "Check" as in "bank check" (noun, not verb). Placeholders: %1$s - payment method title, %2$s - payment account type (savings/checking) (may or may not be available), %3$s - last four digits of the account */ - $message = sprintf( __( '%1$s Check Transaction Approved: %2$s account ending in %3$s', 'woocommerce-plugin-framework' ), $this->get_method_title(), $order->payment->account_type, $last_four ); + $message = sprintf( __( '%1$s Check Transaction Approved: %2$s account ending in %3$s', 'woocommerce-plugin-framework' ), $this->get_method_title(), $payment->account_type, $last_four ); // optional check number - if ( ! empty( $order->payment->check_number ) ) { + if ( ! empty( $payment->check_number ) ) { /* translators: Context: "Check" as in "bank check" (noun, not verb). Placeholder: %s - check number */ - $message .= '. ' . sprintf( esc_html__( 'Check number %s', 'woocommerce-plugin-framework' ), $order->payment->check_number ); + $message .= '. ' . sprintf( esc_html__( 'Check number %s', 'woocommerce-plugin-framework' ), $payment->check_number ); } // adds the transaction id (if any) to the order note diff --git a/woocommerce/payment-gateway/integrations/class-sv-wc-payment-gateway-integration-pre-orders.php b/woocommerce/payment-gateway/integrations/class-sv-wc-payment-gateway-integration-pre-orders.php index 1d76560bd..f225aba21 100644 --- a/woocommerce/payment-gateway/integrations/class-sv-wc-payment-gateway-integration-pre-orders.php +++ b/woocommerce/payment-gateway/integrations/class-sv-wc-payment-gateway-integration-pre-orders.php @@ -24,6 +24,8 @@ namespace SkyVerge\WooCommerce\PluginFramework\v5_15_12; +use SkyVerge\WooCommerce\PluginFramework\v5_15_12\Payment_Gateway\Dynamic_Props; + defined( 'ABSPATH' ) or exit; if ( ! class_exists( '\\SkyVerge\\WooCommerce\\PluginFramework\\v5_15_12\\SV_WC_Payment_Gateway_Integration_Pre_Orders' ) ) : @@ -139,44 +141,45 @@ public function get_order( $order ) { // normally a guest user wouldn't be assigned a customer id, but for a pre-order requiring tokenization, it might be if ( 0 == $order->get_user_id() && false !== ( $customer_id = $this->get_gateway()->get_guest_customer_id( $order ) ) ) { - $order->customer_id = $customer_id; + Dynamic_Props::set( $order, 'customer_id', $customer_id ); } // zero out the payment total since we're just tokenizing the payment method - $order->payment_total = '0.00'; + Dynamic_Props::set( $order, 'payment_total', '0.00' ); } elseif ( \WC_Pre_Orders_Order::order_has_payment_token( $order ) && ! is_checkout_pay_page() ) { // if this is a pre-order release payment with a tokenized payment method, get the payment token to complete the order + $payment = Dynamic_Props::get( $order, 'payment', null, new \stdClass() ); // retrieve the payment token - $order->payment->token = $this->get_gateway()->get_order_meta( $order, 'payment_token' ); + $payment->token = $this->get_gateway()->get_order_meta( $order, 'payment_token' ); // retrieve the optional customer id - $order->customer_id = $this->get_gateway()->get_order_meta( $order, 'customer_id' ); + Dynamic_Props::set( $order, 'customer_id', $this->get_gateway()->get_order_meta( $order, 'customer_id' ) ); // set token data on order - if ( $this->get_gateway()->get_payment_tokens_handler()->user_has_token( $order->get_user_id(), $order->payment->token ) ) { + if ( $this->get_gateway()->get_payment_tokens_handler()->user_has_token( $order->get_user_id(), $payment->token ) ) { // an existing registered user with a saved payment token - $token = $this->get_gateway()->get_payment_tokens_handler()->get_token( $order->get_user_id(), $order->payment->token ); + $token = $this->get_gateway()->get_payment_tokens_handler()->get_token( $order->get_user_id(), $payment->token ); // account last four - $order->payment->account_number = $token->get_last_four(); + $payment->account_number = $token->get_last_four(); if ( $this->get_gateway()->is_credit_card_gateway() ) { // card type - $order->payment->card_type = $token->get_card_type(); + $payment->card_type = $token->get_card_type(); // exp month/year - $order->payment->exp_month = $token->get_exp_month(); - $order->payment->exp_year = SV_WC_Payment_Gateway_Helper::format_exp_year( $token->get_exp_year() ); + $payment->exp_month = $token->get_exp_month(); + $payment->exp_year = SV_WC_Payment_Gateway_Helper::format_exp_year( $token->get_exp_year() ); } elseif ( $this->get_gateway()->is_echeck_gateway() ) { // account type (checking/savings) - $order->payment->account_type = $token->get_account_type(); + $payment->account_type = $token->get_account_type(); } } else { @@ -184,28 +187,31 @@ public function get_order( $order ) { // a guest user means that token data must be set from the original order // account number - $order->payment->account_number = $this->get_gateway()->get_order_meta( $order, 'account_four' ); + $payment->account_number = $this->get_gateway()->get_order_meta( $order, 'account_four' ); if ( $this->get_gateway()->is_credit_card_gateway() ) { // card type - $order->payment->card_type = $this->get_gateway()->get_order_meta( $order, 'card_type' ); + $payment->card_type = $this->get_gateway()->get_order_meta( $order, 'card_type' ); // expiry date if ( $expiry_date = $this->get_gateway()->get_order_meta( $order, 'card_expiry_date' ) ) { list( $exp_year, $exp_month ) = explode( '-', $expiry_date ); - $order->payment->exp_month = $exp_month; - $order->payment->exp_year = SV_WC_Payment_Gateway_Helper::format_exp_year( $exp_year ); + $payment->exp_month = $exp_month; + $payment->exp_year = SV_WC_Payment_Gateway_Helper::format_exp_year( $exp_year ); } } elseif ( $this->get_gateway()->is_echeck_gateway() ) { // account type - $order->payment->account_type = $this->get_gateway()->get_order_meta( $order, 'account_type' ); + $payment->account_type = $this->get_gateway()->get_order_meta( $order, 'account_type' ); } } + + // Set payment info on the order object + Dynamic_Props::set( $order, 'payment', $payment ); } return $order; @@ -233,8 +239,10 @@ public function process_payment( $result, $order_id ) { try { + $payment = Dynamic_Props::get( $order, 'payment', null, new \stdClass() ); + // using an existing tokenized payment method - if ( isset( $order->payment->token ) && $order->payment->token ) { + if ( isset( $payment->token ) && $payment->token ) { // save the tokenized card info for completing the pre-order in the future $this->get_gateway()->add_transaction_data( $order ); @@ -302,18 +310,21 @@ public function process_release_payment( $order ) { try { // set order defaults - $order = $this->get_gateway()->get_order( $order ); + $order = $this->get_gateway()->get_order( $order ); + $payment = Dynamic_Props::get( $order, 'payment', null, new \stdClass() ); // order description - $order->description = sprintf( + $description = sprintf( /* translators: Context: A payment is released for a pre-order. Placeholders: %1$s - Site name, %2$s - Order number */ __( '%1$s - Pre-Order Release Payment for Order %2$s', 'woocommerce-plugin-framework' ), esc_html( SV_WC_Helper::get_site_name() ), $order->get_order_number() ); + Dynamic_Props::set( $order, 'description', $description ); + // token is required - if ( ! $order->payment->token ) { + if ( ! $payment->token ) { throw new SV_WC_Payment_Gateway_Exception( __( 'Payment token missing/invalid.', 'woocommerce-plugin-framework' ) ); } @@ -333,7 +344,7 @@ public function process_release_payment( $order ) { // success! update order record if ( $response->transaction_approved() ) { - $last_four = substr( $order->payment->account_number, -4 ); + $last_four = substr( $payment->account_number, -4 ); // order note based on gateway type if ( $this->get_gateway()->is_credit_card_gateway() ) { @@ -343,9 +354,9 @@ public function process_release_payment( $order ) { __( '%1$s %2$s Pre-Order Release Payment Approved: %3$s ending in %4$s (expires %5$s)', 'woocommerce-plugin-framework' ), $this->get_gateway()->get_method_title(), $this->get_gateway()->perform_credit_card_authorization( $order ) ? 'Authorization' : 'Charge', - SV_WC_Payment_Gateway_Helper::payment_type_to_name( ! empty( $order->payment->card_type ) ? $order->payment->card_type : 'card' ), + SV_WC_Payment_Gateway_Helper::payment_type_to_name( ! empty( $payment->card_type ) ? $payment->card_type : 'card' ), $last_four, - ( ! empty( $order->payment->exp_month) && ! empty( $order->payment->exp_year ) ? $order->payment->exp_month . '/' . substr( $order->payment->exp_year, -2 ) : 'n/a' ) + ( ! empty( $payment->exp_month) && ! empty( $payment->exp_year ) ? $payment->exp_month . '/' . substr( $payment->exp_year, -2 ) : 'n/a' ) ); } elseif ( $this->get_gateway()->is_echeck_gateway() ) { @@ -355,7 +366,7 @@ public function process_release_payment( $order ) { /* translators: Context: A payment is released for a pre-order. Placeholders: %1$s - Payment gateway name, %2$s - Payment method type (e.g. 'Bank Account'), %3$s - Last four digits of the account */ __( '%1$s eCheck Pre-Order Release Payment Approved: %2$s ending in %3$s', 'woocommerce-plugin-framework' ), $this->get_gateway()->get_method_title(), - SV_WC_Payment_Gateway_Helper::payment_type_to_name( ! empty( $order->payment->account_type ) ? $order->payment->account_type : 'bank'), + SV_WC_Payment_Gateway_Helper::payment_type_to_name( ! empty( $payment->account_type ) ? $payment->account_type : 'bank'), $last_four ); diff --git a/woocommerce/payment-gateway/integrations/class-sv-wc-payment-gateway-integration-subscriptions.php b/woocommerce/payment-gateway/integrations/class-sv-wc-payment-gateway-integration-subscriptions.php index ba62a0e8b..a6f447d20 100644 --- a/woocommerce/payment-gateway/integrations/class-sv-wc-payment-gateway-integration-subscriptions.php +++ b/woocommerce/payment-gateway/integrations/class-sv-wc-payment-gateway-integration-subscriptions.php @@ -24,6 +24,8 @@ namespace SkyVerge\WooCommerce\PluginFramework\v5_15_12; +use SkyVerge\WooCommerce\PluginFramework\v5_15_12\Payment_Gateway\Dynamic_Props; + defined( 'ABSPATH' ) or exit; if ( ! class_exists( '\\SkyVerge\\WooCommerce\\PluginFramework\\v5_15_12\\SV_WC_Payment_Gateway_Integration_Subscriptions' ) ) : @@ -216,14 +218,14 @@ public function save_payment_meta( $order ) { $updated = false; // payment token - if ( ! empty( $order->payment->token ) ) { - $subscription->update_meta_data( $this->get_gateway()->get_order_meta_prefix() . 'payment_token', $order->payment->token ); + if ( ! empty( Dynamic_Props::get( $order, 'payment', 'token' ) ) ) { + $subscription->update_meta_data( $this->get_gateway()->get_order_meta_prefix() . 'payment_token', Dynamic_Props::get( $order, 'payment', 'token' ) ); $updated = true; } // customer ID - if ( ! empty( $order->customer_id ) ) { - $subscription->update_meta_data( $this->get_gateway()->get_order_meta_prefix() . 'customer_id', $order->customer_id ); + if ( ! empty( Dynamic_Props::get( $order, 'customer_id' ) ) ) { + $subscription->update_meta_data( $this->get_gateway()->get_order_meta_prefix() . 'customer_id', Dynamic_Props::get( $order, 'customer_id' ) ); $updated = true; } @@ -249,16 +251,18 @@ public function save_payment_meta( $order ) { */ public function add_subscriptions_details_to_order( $order, $gateway ) { - if ( isset( $order->payment ) ) { + $payment = Dynamic_Props::get( $order, 'payment' ); + + if ( $payment ) { // defaults - $order->payment->subscriptions = []; - $order->payment->recurring = ! empty( $order->payment->recurring ) ?: false; + $payment->subscriptions = []; + $payment->recurring = ! empty( $payment->recurring ) ?: false; // if the order contains a subscription (but is not a renewal) if ( wcs_order_contains_subscription( $order ) ) { - $order->payment->recurring = true; + $payment->recurring = true; // an order ID might be 0 if it's a mock order we use when adding a payment method // passing in an order with an ID of 0 to `wcs_get_subscriptions_for_order()` can cause very unexpected results @@ -270,7 +274,7 @@ public function add_subscriptions_details_to_order( $order, $gateway ) { if ( $subscription instanceof \WC_Subscription ) { - $order->payment->subscriptions[] = $this->add_subscription_details_to_order( $subscription, false ); + $payment->subscriptions[] = $this->add_subscription_details_to_order( $subscription, false ); } } } @@ -278,7 +282,7 @@ public function add_subscriptions_details_to_order( $order, $gateway ) { // order is for a subscription renewal } elseif ( wcs_order_contains_renewal( $order ) ) { - $order->payment->recurring = true; + $payment->recurring = true; // an order ID might be 0 if it's a mock order we use when adding a payment method // passing in an order with an ID of 0 to `wcs_get_subscriptions_for_order()` can cause very unexpected results @@ -290,11 +294,13 @@ public function add_subscriptions_details_to_order( $order, $gateway ) { if ( $subscription instanceof \WC_Subscription ) { - $order->payment->subscriptions[] = $this->add_subscription_details_to_order( $subscription, true ); + $payment->subscriptions[] = $this->add_subscription_details_to_order( $subscription, true ); } } } } + + Dynamic_Props::set( $order, 'payment', $payment ); } return $order; @@ -390,45 +396,52 @@ public function process_renewal_payment( $amount_to_charge, $order ) { */ public function get_order( $order ) { - $order->description = sprintf( + $description = sprintf( /* translators: Placeholders: %1$s - Site name, %2$s - Order number */ esc_html__( '%1$s - Subscription Renewal Order %2$s', 'woocommerce-plugin-framework' ), wp_specialchars_decode( SV_WC_Helper::get_site_name(), ENT_QUOTES ), $order->get_order_number() ); + Dynamic_Props::set( $order, 'description', $description ); + // override the payment total with the amount to charge given by Subscriptions - $order->payment_total = $this->renewal_payment_total; + Dynamic_Props::set( $order, 'payment_total', $this->renewal_payment_total ); + + $payment = Dynamic_Props::get( $order, 'payment', null, new \stdClass() ); // set payment token - $order->payment->token = $this->get_gateway()->get_order_meta( $order, 'payment_token' ); + $payment->token = $this->get_gateway()->get_order_meta( $order, 'payment_token' ); // use customer ID from renewal order, not user meta so the admin can update the customer ID for a subscription if needed $customer_id = $this->get_gateway()->get_order_meta( $order, 'customer_id' ); // only if a customer ID exists in order meta, otherwise this will default to the previously set value from user meta if ( ! empty( $customer_id ) ) { - $order->customer_id = $customer_id; + Dynamic_Props::set( $order, 'customer_id', $customer_id ); } // get the token object - $token = $this->get_gateway()->get_payment_tokens_handler()->get_token( $order->get_user_id(), $order->payment->token ); + $token = $this->get_gateway()->get_payment_tokens_handler()->get_token( $order->get_user_id(), $payment->token ); // set token data on the order - $order->payment->account_number = $token->get_last_four(); - $order->payment->last_four = $token->get_last_four(); + $payment->account_number = $token->get_last_four(); + $payment->last_four = $token->get_last_four(); if ( $token->is_credit_card() ) { - $order->payment->card_type = $token->get_card_type(); - $order->payment->exp_month = $token->get_exp_month(); - $order->payment->exp_year = SV_WC_Payment_Gateway_Helper::format_exp_year( $token->get_exp_year() ); + $payment->card_type = $token->get_card_type(); + $payment->exp_month = $token->get_exp_month(); + $payment->exp_year = SV_WC_Payment_Gateway_Helper::format_exp_year( $token->get_exp_year() ); } elseif ( $token->is_echeck() ) { - $order->payment->account_type = $token->get_account_type(); + $payment->account_type = $token->get_account_type(); } + // Set payment info on the order object + Dynamic_Props::set( $order, 'payment', $payment ); + return $order; } @@ -508,10 +521,12 @@ public function process_change_payment( $result, $order_id, $gateway ) { $subscription = $gateway->get_order( $order_id ); + $payment = Dynamic_Props::get( $subscription, 'payment', null, new \stdClass() ); + try { // if using a saved method, just add the data - if ( isset( $subscription->payment->token ) && $subscription->payment->token ) { + if ( isset( $payment->token ) && $payment->token ) { $gateway->add_transaction_data( $subscription ); diff --git a/woocommerce/payment-gateway/payment-tokens/class-sv-wc-payment-gateway-payment-tokens-handler.php b/woocommerce/payment-gateway/payment-tokens/class-sv-wc-payment-gateway-payment-tokens-handler.php index 5a7048f7a..44d5a6ca0 100644 --- a/woocommerce/payment-gateway/payment-tokens/class-sv-wc-payment-gateway-payment-tokens-handler.php +++ b/woocommerce/payment-gateway/payment-tokens/class-sv-wc-payment-gateway-payment-tokens-handler.php @@ -24,6 +24,8 @@ namespace SkyVerge\WooCommerce\PluginFramework\v5_15_12; +use SkyVerge\WooCommerce\PluginFramework\v5_15_12\Payment_Gateway\Dynamic_Props; + defined( 'ABSPATH' ) or exit; if ( ! class_exists( '\\SkyVerge\\WooCommerce\\PluginFramework\\v5_15_12\\SV_WC_Payment_Gateway_Payment_Tokens_Handler' ) ) : @@ -144,17 +146,19 @@ public function create_token( \WC_Order $order, $response = null, $environment_i // store the billing hash on the token for later use in case it needs to be updated $token->set_billing_hash( $address->get_hash() ); + $payment = Dynamic_Props::get( $order, 'payment', null, new \stdClass() ); + // set the resulting token on the order - $order->payment->token = $token->get_id(); + $payment->token = $token->get_id(); // for credit card transactions add the card type, if known (some gateways return the credit card type as part of the response, others may require it as part of the request, and still others it may never be known) if ( $gateway->is_credit_card_gateway() && $token->get_card_type() ) { - $order->payment->card_type = $token->get_card_type(); + $payment->card_type = $token->get_card_type(); } // checking/savings, if known if ( $gateway->is_echeck_gateway() && $token->get_account_type() ) { - $order->payment->account_type = $token->get_account_type(); + $payment->account_type = $token->get_account_type(); } // set the token to the user account @@ -162,6 +166,9 @@ public function create_token( \WC_Order $order, $response = null, $environment_i $this->add_token( $order->get_user_id(), $token, $environment_id ); } + // Set payment info on the order object. + Dynamic_Props::set( $order, 'payment', $payment ); + $order->add_order_note( $this->get_order_note( $token ) ); // add the standard transaction data From 43fd48e27f3afb841deb30c1b7e30b65ae6b097d Mon Sep 17 00:00:00 2001 From: Dharmesh Patel Date: Fri, 25 Jul 2025 20:08:49 +0530 Subject: [PATCH 3/8] Minor doc updates. --- .../class-sv-wc-payment-gateway-direct.php | 7 +++++-- .../payment-gateway/class-sv-wc-payment-gateway.php | 11 ++++++++--- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/woocommerce/payment-gateway/class-sv-wc-payment-gateway-direct.php b/woocommerce/payment-gateway/class-sv-wc-payment-gateway-direct.php index 87fb92923..a16c49eb7 100644 --- a/woocommerce/payment-gateway/class-sv-wc-payment-gateway-direct.php +++ b/woocommerce/payment-gateway/class-sv-wc-payment-gateway-direct.php @@ -567,8 +567,11 @@ protected function update_transaction_payment_method( \WC_Order $order ) { /** - * Add payment and transaction information as class members of WC_Order - * instance. The standard information that can be added includes: + * Add payment and transaction information to $order object. + * + * The standard information that can be added includes: + * + * It is set and get using Dynamic_Props class and not directly on $order object, but documented here for reference. * * $order->payment_total - the payment total * $order->customer_id - optional payment gateway customer id (useful for tokenized payments for certain gateways, etc) diff --git a/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php b/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php index d4954aa05..9f7f50cc5 100755 --- a/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php +++ b/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php @@ -1916,10 +1916,12 @@ public function get_payment_method_image_url( $type ) { /** - * Adds payment and transaction information as class members of {@see WC_Order} instance. + * Adds payment and transaction information on $order object. * * The standard information that can be added includes: * + * It is set and get using Dynamic_Props class and not directly on $order object, but documented here for reference. + * * $order->payment_total - the payment total * $order->customer_id - optional payment gateway customer id (useful for tokenized payments, etc) * $order->payment->type - one of 'credit_card' or 'check' @@ -2216,8 +2218,11 @@ public function process_refund( $order_id, $amount = null, $reason = '' ) { /** - * Add refund information as class members of WC_Order - * instance for use in refund transactions. Standard information includes: + * Add refund information to $order object. + * + * It is set and get using Dynamic_Props class and not directly on $order object, but documented here for reference. + * + * Standard information includes: * * $order->refund->amount = refund amount * $order->refund->reason = user-entered reason text for the refund From aa2fed642cc79cfd2593bfa086cad3e0f1e8474a Mon Sep 17 00:00:00 2001 From: Dharmesh Patel Date: Mon, 28 Jul 2025 14:58:39 +0530 Subject: [PATCH 4/8] Docs improvements. --- woocommerce/payment-gateway/Dynamic_Props.php | 75 +++++++++++++------ 1 file changed, 54 insertions(+), 21 deletions(-) diff --git a/woocommerce/payment-gateway/Dynamic_Props.php b/woocommerce/payment-gateway/Dynamic_Props.php index 27fd6da93..7988f3830 100644 --- a/woocommerce/payment-gateway/Dynamic_Props.php +++ b/woocommerce/payment-gateway/Dynamic_Props.php @@ -1,22 +1,27 @@ |null + * @since x.x.x + * @var \WeakMap|null */ private static ?\WeakMap $map = null; /** * Sets a property on the order object. * + * Stores a dynamic property either using WeakMap (PHP 8.0+) or direct property + * access (PHP 7.4+). The storage method is automatically determined based on + * PHP version and WeakMap availability. + * + * @since x.x.x + * + * @param \WC_Order $order The order object to store data on. + * @param string $key The property key. + * @param mixed $value The value to store. + * @return void + * + * @example * ```php * Dynamic_Props::set($order, 'customer_id', 123); * Dynamic_Props::set($order, 'payment_total', '99.99'); * ``` - * - * @param \WC_Order $order The order object to store data on. - * @param string $key The property key. - * @param mixed $value The value to store. - * - * @return void */ public static function set( \WC_Order &$order, string $key, mixed $value ): void { if ( self::use_weak_map() ) { @@ -63,18 +79,23 @@ public static function set( \WC_Order &$order, string $key, mixed $value ): void /** * Gets a property from the order object. * + * Retrieves a stored dynamic property using the appropriate storage method + * based on PHP version. Supports nested property access. + * + * @since x.x.x + * + * @param \WC_Order $order The order object to retrieve data from. + * @param string $key The property key. + * @param string $nested_key Optional. The nested property key. Default null. + * @param mixed $default Optional. Default value if not found. Default null. + * @return mixed The stored value or default if not found. + * + * @example * ```php * $customer_id = Dynamic_Props::get($order, 'customer_id'); * $total = Dynamic_Props::get($order, 'payment_total'); * $token = Dynamic_Props::get($order, 'payment', 'token', 'DEFAULT_TOKEN'); * ``` - * - * @param \WC_Order $order The order object to retrieve data from. - * @param string $key The property key. - * @param string $nested_key The nested property key. - * @param mixed $default Default value if not found. - * - * @return mixed The stored value or default if not found. */ public static function get( \WC_Order $order, string $key, $nested_key = null, $default = null ): mixed { if ( self::use_weak_map() ) { @@ -95,9 +116,13 @@ public static function get( \WC_Order $order, string $key, $nested_key = null, $ /** * Unsets a property on the order object. * - * @param \WC_Order $order The order object to unset data from. - * @param string $key The property key. + * Removes a stored dynamic property using the appropriate storage method + * based on PHP version. + * + * @since x.x.x * + * @param \WC_Order $order The order object to unset data from. + * @param string $key The property key to remove. * @return void */ public static function unset( \WC_Order &$order, string $key ): void { @@ -112,6 +137,10 @@ public static function unset( \WC_Order &$order, string $key ): void { /** * Checks if WeakMap should be used based on PHP version. * + * Determines whether to use WeakMap storage based on PHP version (8.0+) + * and WeakMap class availability. Result is cached for performance. + * + * @since x.x.x * @return bool True if WeakMap should be used, false otherwise. */ private static function use_weak_map(): bool { @@ -127,6 +156,10 @@ private static function use_weak_map(): bool { /** * Initializes WeakMap storage if not already initialized. * + * Ensures the WeakMap storage is initialized only once when needed. + * This lazy initialization helps with performance and memory usage. + * + * @since x.x.x * @return void */ private static function init_weak_map(): void { From 14eb0db3ecaa1f01ed288e6735ee76b38f10107d Mon Sep 17 00:00:00 2001 From: Dharmesh Patel Date: Wed, 27 Aug 2025 16:15:24 +0530 Subject: [PATCH 5/8] Update namespace to use v6_0_0 --- woocommerce/payment-gateway/Dynamic_Props.php | 2 +- .../payment-gateway/class-sv-wc-payment-gateway-hosted.php | 2 +- .../class-sv-wc-payment-gateway-integration-pre-orders.php | 2 +- .../class-sv-wc-payment-gateway-integration-subscriptions.php | 2 +- .../class-sv-wc-payment-gateway-payment-tokens-handler.php | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/woocommerce/payment-gateway/Dynamic_Props.php b/woocommerce/payment-gateway/Dynamic_Props.php index 7988f3830..f7b53e4da 100644 --- a/woocommerce/payment-gateway/Dynamic_Props.php +++ b/woocommerce/payment-gateway/Dynamic_Props.php @@ -9,7 +9,7 @@ * @since x.x.x */ -namespace SkyVerge\WooCommerce\PluginFramework\v5_15_12\Payment_Gateway; +namespace SkyVerge\WooCommerce\PluginFramework\v6_0_0\Payment_Gateway; /** * Dynamic property storage handler for WooCommerce order objects. diff --git a/woocommerce/payment-gateway/class-sv-wc-payment-gateway-hosted.php b/woocommerce/payment-gateway/class-sv-wc-payment-gateway-hosted.php index be9bedff7..e091618b3 100644 --- a/woocommerce/payment-gateway/class-sv-wc-payment-gateway-hosted.php +++ b/woocommerce/payment-gateway/class-sv-wc-payment-gateway-hosted.php @@ -24,7 +24,7 @@ namespace SkyVerge\WooCommerce\PluginFramework\v6_0_0; -use SkyVerge\WooCommerce\PluginFramework\v5_15_12\Payment_Gateway\Dynamic_Props; +use SkyVerge\WooCommerce\PluginFramework\v6_0_0\Payment_Gateway\Dynamic_Props; defined( 'ABSPATH' ) or exit; diff --git a/woocommerce/payment-gateway/integrations/class-sv-wc-payment-gateway-integration-pre-orders.php b/woocommerce/payment-gateway/integrations/class-sv-wc-payment-gateway-integration-pre-orders.php index 876d415b6..51a568e49 100644 --- a/woocommerce/payment-gateway/integrations/class-sv-wc-payment-gateway-integration-pre-orders.php +++ b/woocommerce/payment-gateway/integrations/class-sv-wc-payment-gateway-integration-pre-orders.php @@ -24,7 +24,7 @@ namespace SkyVerge\WooCommerce\PluginFramework\v6_0_0; -use SkyVerge\WooCommerce\PluginFramework\v5_15_12\Payment_Gateway\Dynamic_Props; +use SkyVerge\WooCommerce\PluginFramework\v6_0_0\Payment_Gateway\Dynamic_Props; defined( 'ABSPATH' ) or exit; diff --git a/woocommerce/payment-gateway/integrations/class-sv-wc-payment-gateway-integration-subscriptions.php b/woocommerce/payment-gateway/integrations/class-sv-wc-payment-gateway-integration-subscriptions.php index 3f85f3a71..f9b10e53e 100644 --- a/woocommerce/payment-gateway/integrations/class-sv-wc-payment-gateway-integration-subscriptions.php +++ b/woocommerce/payment-gateway/integrations/class-sv-wc-payment-gateway-integration-subscriptions.php @@ -24,7 +24,7 @@ namespace SkyVerge\WooCommerce\PluginFramework\v6_0_0; -use SkyVerge\WooCommerce\PluginFramework\v5_15_12\Payment_Gateway\Dynamic_Props; +use SkyVerge\WooCommerce\PluginFramework\v6_0_0\Payment_Gateway\Dynamic_Props; defined( 'ABSPATH' ) or exit; diff --git a/woocommerce/payment-gateway/payment-tokens/class-sv-wc-payment-gateway-payment-tokens-handler.php b/woocommerce/payment-gateway/payment-tokens/class-sv-wc-payment-gateway-payment-tokens-handler.php index 1f4721743..20c21a6fe 100644 --- a/woocommerce/payment-gateway/payment-tokens/class-sv-wc-payment-gateway-payment-tokens-handler.php +++ b/woocommerce/payment-gateway/payment-tokens/class-sv-wc-payment-gateway-payment-tokens-handler.php @@ -24,7 +24,7 @@ namespace SkyVerge\WooCommerce\PluginFramework\v6_0_0; -use SkyVerge\WooCommerce\PluginFramework\v5_15_12\Payment_Gateway\Dynamic_Props; +use SkyVerge\WooCommerce\PluginFramework\v6_0_0\Payment_Gateway\Dynamic_Props; defined( 'ABSPATH' ) or exit; From 1070f1c75446bb985f621013765bb603f2180169 Mon Sep 17 00:00:00 2001 From: Dharmesh Patel Date: Wed, 27 Aug 2025 16:27:42 +0530 Subject: [PATCH 6/8] Added "sv_wc_plugin_framework_use_dynamic_props_class" filter to make use of Dynamic_Props class opt-in only. --- woocommerce/payment-gateway/Dynamic_Props.php | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/woocommerce/payment-gateway/Dynamic_Props.php b/woocommerce/payment-gateway/Dynamic_Props.php index f7b53e4da..609ed2107 100644 --- a/woocommerce/payment-gateway/Dynamic_Props.php +++ b/woocommerce/payment-gateway/Dynamic_Props.php @@ -134,6 +134,26 @@ public static function unset( \WC_Order &$order, string $key ): void { } } + /** + * Checks if Dynamic_Props class should be used based on the filter. + * + * @return bool True if Dynamic_Props class should be used, false otherwise. + */ + private static function use_dynamic_props_class(): bool { + static $use_dynamic_props_class = null; + if ( null === $use_dynamic_props_class ) { + /** + * Filters whether to use Dynamic_Props class for storing order data. + * + * @since x.x.x + * + * @var bool Whether to Dynamic_Props class for storing order data. + */ + $use_dynamic_props_class = apply_filters( 'sv_wc_plugin_framework_use_dynamic_props_class', false ); + } + return $use_dynamic_props_class; + } + /** * Checks if WeakMap should be used based on PHP version. * @@ -147,7 +167,7 @@ private static function use_weak_map(): bool { static $use_weak_map = null; if ( null === $use_weak_map ) { - $use_weak_map = version_compare( PHP_VERSION, '8.0', '>=' ) && class_exists( '\WeakMap' ); + $use_weak_map = version_compare( PHP_VERSION, '8.0', '>=' ) && self::use_dynamic_props_class(); } return $use_weak_map; From 4aa65dd54a79ac1eb4992c29643afcb1aacdebbc Mon Sep 17 00:00:00 2001 From: Dharmesh Patel Date: Thu, 28 Aug 2025 13:02:33 +0530 Subject: [PATCH 7/8] Add OrderHelper Class to simplify property get/set on order object. --- woocommerce/Helpers/OrderHelper.php | 145 ++++++++++++++++++ .../Abstract_Hosted_Payment_Handler.php | 6 +- .../class-sv-wc-payment-gateway-direct.php | 21 +-- .../class-sv-wc-payment-gateway-hosted.php | 13 +- .../class-sv-wc-payment-gateway.php | 31 ++-- ...payment-gateway-integration-pre-orders.php | 16 +- ...ment-gateway-integration-subscriptions.php | 19 +-- ...payment-gateway-payment-tokens-handler.php | 6 +- 8 files changed, 204 insertions(+), 53 deletions(-) create mode 100644 woocommerce/Helpers/OrderHelper.php diff --git a/woocommerce/Helpers/OrderHelper.php b/woocommerce/Helpers/OrderHelper.php new file mode 100644 index 000000000..8f0f41df1 --- /dev/null +++ b/woocommerce/Helpers/OrderHelper.php @@ -0,0 +1,145 @@ +get_gateway()->get_order( $order ); - $payment = Dynamic_Props::get( $order, 'payment', null, new \stdClass() ); + $payment = OrderHelper::getPayment( $order ); $payment->account_number = $response->get_account_number(); @@ -343,7 +343,7 @@ protected function get_order_from_response( FrameworkBase\SV_WC_Payment_Gateway_ } // Set payment info on the order object. - Dynamic_Props::set( $order, 'payment', $payment ); + OrderHelper::setPayment( $order, $payment ); return $order; } diff --git a/woocommerce/payment-gateway/class-sv-wc-payment-gateway-direct.php b/woocommerce/payment-gateway/class-sv-wc-payment-gateway-direct.php index 2fb2a9f8b..0b65a3899 100644 --- a/woocommerce/payment-gateway/class-sv-wc-payment-gateway-direct.php +++ b/woocommerce/payment-gateway/class-sv-wc-payment-gateway-direct.php @@ -25,6 +25,7 @@ namespace SkyVerge\WooCommerce\PluginFramework\v6_0_0; use SkyVerge\WooCommerce\PluginFramework\v6_0_0\Blocks\Blocks_Handler; +use SkyVerge\WooCommerce\PluginFramework\v6_0_0\Helpers\OrderHelper; use SkyVerge\WooCommerce\PluginFramework\v6_0_0\Payment_Gateway\Dynamic_Props; defined( 'ABSPATH' ) or exit; @@ -389,7 +390,7 @@ public function process_payment( $order_id ) { if ( $this->should_skip_transaction( $order ) || $this->do_transaction( $order ) ) { // add transaction data for zero-dollar "orders" - if ( '0.00' === Dynamic_Props::get( $order, 'payment_total' ) ) { + if ( '0.00' === OrderHelper::getPaymentTotal( $order ) ) { $this->add_transaction_data( $order ); } @@ -604,7 +605,7 @@ public function get_order( $order_id ) { $order = parent::get_order( $order_id ); // Get payment info from the order object. - $payment = Dynamic_Props::get( $order, 'payment', null, new \stdClass() ); + $payment = OrderHelper::getPayment( $order ); // payment info if ( SV_WC_Helper::get_posted_value( 'wc-' . $this->get_id_dasherized() . '-account-number' ) && ! SV_WC_Helper::get_posted_value( 'wc-' . $this->get_id_dasherized() . '-payment-token' ) ) { @@ -682,7 +683,7 @@ public function get_order( $order_id ) { } // Set payment info on the order object. - Dynamic_Props::set( $order, 'payment', $payment ); + OrderHelper::setPayment( $order, $payment ); /** * Direct Gateway Get Order Filter. @@ -1141,14 +1142,14 @@ protected function get_order_for_add_payment_method() { $order->set_props( $properties ); // other default info - Dynamic_Props::set( $order, 'customer_id', $this->get_customer_id( $order->get_user_id() ) ); + OrderHelper::setCustomerId( $order, $this->get_customer_id( $order->get_user_id() ) ); /* translators: Placeholders: %1$s - site title, %2$s - customer email. Payment method as in a specific credit card, e-check or bank account */ $description = sprintf( esc_html__( '%1$s - Add Payment Method for %2$s', 'woocommerce-plugin-framework' ), sanitize_text_field( SV_WC_Helper::get_site_name() ), $properties['billing_email'] ); Dynamic_Props::set( $order, 'description', $description ); // force zero amount - Dynamic_Props::set( $order, 'payment_total', '0.00' ); + OrderHelper::setPaymentTotal( $order, '0.00' ); /** * Direct Gateway Get Order for Add Payment Method Filter. @@ -1179,12 +1180,12 @@ protected function add_add_payment_method_customer_data( $order, $response ) { // set customer ID from response if available if ( $this->supports_customer_id() && method_exists( $response, 'get_customer_id' ) && $response->get_customer_id() ) { - Dynamic_Props::set( $order, 'customer_id', $customer_id = $response->get_customer_id() ); + OrderHelper::setCustomerId( $order, $customer_id = $response->get_customer_id() ); } else { // default to the customer ID on "order" - $customer_id = Dynamic_Props::get( $order, 'customer_id' ); + $customer_id = OrderHelper::getCustomerId( $order ); } // update the user @@ -1294,7 +1295,7 @@ public function transaction_forced() { */ protected function should_tokenize_before_sale( \WC_Order $order ): bool { - $result = $this->get_payment_tokens_handler()->should_tokenize() && ( '0.00' === Dynamic_Props::get( $order, 'payment_total' ) || $this->tokenize_before_sale() ); + $result = $this->get_payment_tokens_handler()->should_tokenize() && ( '0.00' === OrderHelper::getPaymentTotal( $order ) || $this->tokenize_before_sale() ); /** * Filters whether tokenization should be performed before the sale, for a given order. @@ -1385,7 +1386,7 @@ protected function can_tokenize_with_or_after_sale( \WC_Order $order ): bool { */ return apply_filters( "wc_payment_gateway_{$this->get_id()}_can_tokenize_with_or_after_sale", - Dynamic_Props::get( $order, 'payment_total' ) > 0, + OrderHelper::getPaymentTotal( $order ) > 0, $order, $this ); @@ -1422,7 +1423,7 @@ protected function should_skip_transaction( \WC_Order $order ): bool { return apply_filters( "wc_payment_gateway_{$this->get_id()}_should_skip_transaction", // the order amount will be $0 if a WooCommerce Subscriptions free trial product is being processed - ( '0.00' === Dynamic_Props::get( $order, 'payment_total' ) && ! $this->transaction_forced() ), + ( '0.00' === OrderHelper::getPaymentTotal( $order ) && ! $this->transaction_forced() ), $order, $this ); diff --git a/woocommerce/payment-gateway/class-sv-wc-payment-gateway-hosted.php b/woocommerce/payment-gateway/class-sv-wc-payment-gateway-hosted.php index e091618b3..c671d233c 100644 --- a/woocommerce/payment-gateway/class-sv-wc-payment-gateway-hosted.php +++ b/woocommerce/payment-gateway/class-sv-wc-payment-gateway-hosted.php @@ -24,7 +24,8 @@ namespace SkyVerge\WooCommerce\PluginFramework\v6_0_0; -use SkyVerge\WooCommerce\PluginFramework\v6_0_0\Payment_Gateway\Dynamic_Props; +use SkyVerge\WooCommerce\PluginFramework\v6_0_0\Helpers\OrderHelper; + defined( 'ABSPATH' ) or exit; @@ -467,7 +468,7 @@ protected function get_order_from_response( $response ) { $order = $this->get_order( $order ); - $payment = Dynamic_Props::get( $order, 'payment', null, new \stdClass() ); + $payment = OrderHelper::getPayment( $order ); $payment->account_number = $response->get_account_number(); @@ -484,7 +485,7 @@ protected function get_order_from_response( $response ) { } // Set payment info on the order object. - Dynamic_Props::set( $order, 'payment', $payment ); + OrderHelper::setPayment( $order, $payment ); return $order; } @@ -603,7 +604,7 @@ protected function process_transaction_response( $order, $response ) { protected function process_tokenization_response( \WC_Order $order, $response ) { if ( is_callable( array( $response, 'get_customer_id' ) ) && $response->get_customer_id() ) { - Dynamic_Props::set( $order, 'customer_id', $response->get_customer_id() ); + OrderHelper::setCustomerId( $order, $response->get_customer_id() ); } $token = $response->get_payment_token(); @@ -662,7 +663,7 @@ protected function process_tokenization_response( \WC_Order $order, $response ) // add the payment method order data if ( $token ) { - $payment = Dynamic_Props::get( $order, 'payment', null, new \stdClass() ); + $payment = OrderHelper::getPayment( $order ); $payment->token = $token->get_id(); $payment->account_number = $token->get_last_four(); @@ -681,7 +682,7 @@ protected function process_tokenization_response( \WC_Order $order, $response ) } // Set payment info on the order object - Dynamic_Props::set( $order, 'payment', $payment ); + OrderHelper::setPayment( $order, $payment ); } // remove any tokens that were deleted on the hosted pay page diff --git a/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php b/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php index bbbc90bfe..91299e108 100755 --- a/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php +++ b/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php @@ -26,6 +26,7 @@ use Automattic\WooCommerce\Blocks\Integrations\IntegrationInterface; use SkyVerge\WooCommerce\PluginFramework\v6_0_0\Blocks\Blocks_Handler; +use SkyVerge\WooCommerce\PluginFramework\v6_0_0\Helpers\OrderHelper; use SkyVerge\WooCommerce\PluginFramework\v6_0_0\Payment_Gateway\Blocks\Gateway_Checkout_Block_Integration; use SkyVerge\WooCommerce\PluginFramework\v6_0_0\Payment_Gateway\Dynamic_Props; use stdClass; @@ -1282,13 +1283,13 @@ public function get_apple_pay_currencies() { */ public function get_order_for_apple_pay( \WC_Order $order, SV_WC_Payment_Gateway_Apple_Pay_Payment_Response $response ) { - $payment = Dynamic_Props::get( $order, 'payment', null, new \stdClass() ); + $payment = OrderHelper::getPayment( $order ); $payment->account_number = $response->get_last_four(); $payment->last_four = $response->get_last_four(); $payment->card_type = $response->get_card_type(); - Dynamic_Props::set( $order, 'payment', $payment ); + OrderHelper::setPayment( $order, $payment ); return $order; } @@ -1341,7 +1342,7 @@ public function get_order_for_google_pay( \WC_Order $order, $response_data ) { $payment_method_data = $response_data['paymentMethodData']; - $payment = Dynamic_Props::get( $order, 'payment', null, new \stdClass() ); + $payment = OrderHelper::getPayment( $order ); $payment->google_pay = base64_encode( $payment_method_data['tokenizationData']['token'] ); @@ -1350,7 +1351,7 @@ public function get_order_for_google_pay( \WC_Order $order, $response_data ) { $payment->card_type = SV_WC_Payment_Gateway_Helper::normalize_card_type( $payment_method_data['info']['cardNetwork'] ); // Set payment info on the order object. - Dynamic_Props::set( $order, 'payment', $payment ); + OrderHelper::setPayment( $order, $payment ); return $order; } @@ -1947,13 +1948,13 @@ public function get_order( $order ) { // set payment total here, so it can be modified for later by add-ons like subscriptions which may need to charge an amount different than the get_total() $payment_total = number_format( $order->get_total(), 2, '.', '' ); - Dynamic_Props::set( $order, 'payment_total', $payment_total ); + OrderHelper::setPaymentTotal( $order, $payment_total ); - Dynamic_Props::set( $order, 'customer_id', '' ); + OrderHelper::setCustomerId( $order, '' ); // logged in customer? if ( 0 != $order->get_user_id() && false !== ( $customer_id = $this->get_customer_id( $order->get_user_id(), array( 'order' => $order ) ) ) ) { - Dynamic_Props::set( $order, 'customer_id', $customer_id ); + OrderHelper::setCustomerId( $order, $customer_id ); } // add payment info @@ -1963,7 +1964,7 @@ public function get_order( $order ) { $payment->type = str_replace( '-', '_', $this->get_payment_type() ); // Set payment info on the order object - Dynamic_Props::set( $order, 'payment', $payment ); + OrderHelper::setPayment( $order, $payment ); /* translators: Placeholders: %1$s - site title, %2$s - order number */ $description = sprintf( esc_html__( '%1$s - Order %2$s', 'woocommerce-plugin-framework' ), wp_specialchars_decode( SV_WC_Helper::get_site_name(), ENT_QUOTES ), $order->get_order_number() ); @@ -2706,7 +2707,7 @@ public function add_transaction_data( $order, $response = null ) { $this->add_customer_data( $order, $response ); } - $payment = Dynamic_Props::get( $order, 'payment', null, new \stdClass() ); + $payment = OrderHelper::getPayment( $order ); if ( isset( $payment->token ) && $payment->token ) { $this->update_order_meta( $order, 'payment_token', $payment->token ); @@ -2722,13 +2723,13 @@ public function add_transaction_data( $order, $response = null ) { // credit card gateway data if ( $response instanceof SV_WC_Payment_Gateway_API_Authorization_Response ) { - $this->update_order_meta( $order, 'authorization_amount', Dynamic_Props::get( $order, 'payment_total' ) ); + $this->update_order_meta( $order, 'authorization_amount', OrderHelper::getPaymentTotal( $order ) ); if ( $response->get_authorization_code() ) { $this->update_order_meta( $order, 'authorization_code', $response->get_authorization_code() ); } - if ( Dynamic_Props::get( $order, 'payment_total' ) > 0 ) { + if ( OrderHelper::getPaymentTotal( $order ) > 0 ) { // mark as captured if ( $this->perform_credit_card_charge( $order ) ) { @@ -2812,12 +2813,12 @@ protected function add_customer_data( $order, $response = null ) { if ( $response && method_exists( $response, 'get_customer_id' ) && $response->get_customer_id() ) { $customer_id = $response->get_customer_id(); - Dynamic_Props::set( $order, 'customer_id', $customer_id ); + OrderHelper::setCustomerId( $order, $customer_id ); } else { // default to the customer ID set on the order - $customer_id = Dynamic_Props::get( $order, 'customer_id' ); + $customer_id = OrderHelper::getCustomerId( $order ); } // update the order with the customer ID, note environment is not appended here because it's already available @@ -2843,7 +2844,7 @@ protected function add_customer_data( $order, $response = null ) { */ public function get_credit_card_transaction_approved_message( \WC_Order $order, $response ) { - $payment = Dynamic_Props::get( $order, 'payment', null, new \stdClass() ); + $payment = OrderHelper::getPayment( $order ); $last_four = ! empty( $payment->last_four ) ? $payment->last_four : substr( $payment->account_number, -4 ); @@ -2918,7 +2919,7 @@ public function get_credit_card_transaction_approved_message( \WC_Order $order, */ public function get_echeck_transaction_approved_message( \WC_Order $order, SV_WC_Payment_Gateway_API_Response $response ) { - $payment = Dynamic_Props::get( $order, 'payment', null, new \stdClass() ); + $payment = OrderHelper::getPayment( $order ); $last_four = ! empty( $payment->last_four ) ? $payment->last_four : substr( $payment->account_number, -4 ); diff --git a/woocommerce/payment-gateway/integrations/class-sv-wc-payment-gateway-integration-pre-orders.php b/woocommerce/payment-gateway/integrations/class-sv-wc-payment-gateway-integration-pre-orders.php index 51a568e49..1743813a5 100644 --- a/woocommerce/payment-gateway/integrations/class-sv-wc-payment-gateway-integration-pre-orders.php +++ b/woocommerce/payment-gateway/integrations/class-sv-wc-payment-gateway-integration-pre-orders.php @@ -24,6 +24,7 @@ namespace SkyVerge\WooCommerce\PluginFramework\v6_0_0; +use SkyVerge\WooCommerce\PluginFramework\v6_0_0\Helpers\OrderHelper; use SkyVerge\WooCommerce\PluginFramework\v6_0_0\Payment_Gateway\Dynamic_Props; defined( 'ABSPATH' ) or exit; @@ -141,22 +142,23 @@ public function get_order( $order ) { // normally a guest user wouldn't be assigned a customer id, but for a pre-order requiring tokenization, it might be if ( 0 == $order->get_user_id() && false !== ( $customer_id = $this->get_gateway()->get_guest_customer_id( $order ) ) ) { - Dynamic_Props::set( $order, 'customer_id', $customer_id ); + OrderHelper::setCustomerId( $order, $customer_id ); + } // zero out the payment total since we're just tokenizing the payment method - Dynamic_Props::set( $order, 'payment_total', '0.00' ); + OrderHelper::setPaymentTotal( $order, '0.00' ); } elseif ( \WC_Pre_Orders_Order::order_has_payment_token( $order ) && ! is_checkout_pay_page() ) { // if this is a pre-order release payment with a tokenized payment method, get the payment token to complete the order - $payment = Dynamic_Props::get( $order, 'payment', null, new \stdClass() ); + $payment = OrderHelper::getPayment( $order ); // retrieve the payment token $payment->token = $this->get_gateway()->get_order_meta( $order, 'payment_token' ); // retrieve the optional customer id - Dynamic_Props::set( $order, 'customer_id', $this->get_gateway()->get_order_meta( $order, 'customer_id' ) ); + OrderHelper::setCustomerId( $order, $this->get_gateway()->get_order_meta( $order, 'customer_id' ) ); // set token data on order if ( $this->get_gateway()->get_payment_tokens_handler()->user_has_token( $order->get_user_id(), $payment->token ) ) { @@ -211,7 +213,7 @@ public function get_order( $order ) { } // Set payment info on the order object - Dynamic_Props::set( $order, 'payment', $payment ); + OrderHelper::setPayment( $order, $payment ); } return $order; @@ -239,7 +241,7 @@ public function process_payment( $result, $order_id ) { try { - $payment = Dynamic_Props::get( $order, 'payment', null, new \stdClass() ); + $payment = OrderHelper::getPayment( $order ); // using an existing tokenized payment method if ( isset( $payment->token ) && $payment->token ) { @@ -311,7 +313,7 @@ public function process_release_payment( $order ) { // set order defaults $order = $this->get_gateway()->get_order( $order ); - $payment = Dynamic_Props::get( $order, 'payment', null, new \stdClass() ); + $payment = OrderHelper::getPayment( $order ); // order description $description = sprintf( diff --git a/woocommerce/payment-gateway/integrations/class-sv-wc-payment-gateway-integration-subscriptions.php b/woocommerce/payment-gateway/integrations/class-sv-wc-payment-gateway-integration-subscriptions.php index f9b10e53e..106763d94 100644 --- a/woocommerce/payment-gateway/integrations/class-sv-wc-payment-gateway-integration-subscriptions.php +++ b/woocommerce/payment-gateway/integrations/class-sv-wc-payment-gateway-integration-subscriptions.php @@ -24,6 +24,7 @@ namespace SkyVerge\WooCommerce\PluginFramework\v6_0_0; +use SkyVerge\WooCommerce\PluginFramework\v6_0_0\Helpers\OrderHelper; use SkyVerge\WooCommerce\PluginFramework\v6_0_0\Payment_Gateway\Dynamic_Props; defined( 'ABSPATH' ) or exit; @@ -224,8 +225,8 @@ public function save_payment_meta( $order ) { } // customer ID - if ( ! empty( Dynamic_Props::get( $order, 'customer_id' ) ) ) { - $subscription->update_meta_data( $this->get_gateway()->get_order_meta_prefix() . 'customer_id', Dynamic_Props::get( $order, 'customer_id' ) ); + if ( ! empty( OrderHelper::getCustomerId( $order ) ) ) { + $subscription->update_meta_data( $this->get_gateway()->get_order_meta_prefix() . 'customer_id', OrderHelper::getCustomerId( $order ) ); $updated = true; } @@ -251,7 +252,7 @@ public function save_payment_meta( $order ) { */ public function add_subscriptions_details_to_order( $order, $gateway ) { - $payment = Dynamic_Props::get( $order, 'payment' ); + $payment = OrderHelper::getPayment( $order ); if ( $payment ) { @@ -300,7 +301,7 @@ public function add_subscriptions_details_to_order( $order, $gateway ) { } } - Dynamic_Props::set( $order, 'payment', $payment ); + OrderHelper::setPayment( $order, $payment ); } return $order; @@ -406,9 +407,9 @@ public function get_order( $order ) { Dynamic_Props::set( $order, 'description', $description ); // override the payment total with the amount to charge given by Subscriptions - Dynamic_Props::set( $order, 'payment_total', $this->renewal_payment_total ); + OrderHelper::setPaymentTotal( $order, $this->renewal_payment_total ); - $payment = Dynamic_Props::get( $order, 'payment', null, new \stdClass() ); + $payment = OrderHelper::getPayment( $order ); // set payment token $payment->token = $this->get_gateway()->get_order_meta( $order, 'payment_token' ); @@ -418,7 +419,7 @@ public function get_order( $order ) { // only if a customer ID exists in order meta, otherwise this will default to the previously set value from user meta if ( ! empty( $customer_id ) ) { - Dynamic_Props::set( $order, 'customer_id', $customer_id ); + OrderHelper::setCustomerId( $order, $customer_id ); } // get the token object @@ -440,7 +441,7 @@ public function get_order( $order ) { } // Set payment info on the order object - Dynamic_Props::set( $order, 'payment', $payment ); + OrderHelper::setPayment( $order, $payment ); return $order; } @@ -521,7 +522,7 @@ public function process_change_payment( $result, $order_id, $gateway ) { $subscription = $gateway->get_order( $order_id ); - $payment = Dynamic_Props::get( $subscription, 'payment', null, new \stdClass() ); + $payment = OrderHelper::getPayment( $subscription ); try { diff --git a/woocommerce/payment-gateway/payment-tokens/class-sv-wc-payment-gateway-payment-tokens-handler.php b/woocommerce/payment-gateway/payment-tokens/class-sv-wc-payment-gateway-payment-tokens-handler.php index 20c21a6fe..bd82bff60 100644 --- a/woocommerce/payment-gateway/payment-tokens/class-sv-wc-payment-gateway-payment-tokens-handler.php +++ b/woocommerce/payment-gateway/payment-tokens/class-sv-wc-payment-gateway-payment-tokens-handler.php @@ -24,7 +24,7 @@ namespace SkyVerge\WooCommerce\PluginFramework\v6_0_0; -use SkyVerge\WooCommerce\PluginFramework\v6_0_0\Payment_Gateway\Dynamic_Props; +use SkyVerge\WooCommerce\PluginFramework\v6_0_0\Helpers\OrderHelper; defined( 'ABSPATH' ) or exit; @@ -146,7 +146,7 @@ public function create_token( \WC_Order $order, $response = null, $environment_i // store the billing hash on the token for later use in case it needs to be updated $token->set_billing_hash( $address->get_hash() ); - $payment = Dynamic_Props::get( $order, 'payment', null, new \stdClass() ); + $payment = OrderHelper::getPayment( $order ); // set the resulting token on the order $payment->token = $token->get_id(); @@ -167,7 +167,7 @@ public function create_token( \WC_Order $order, $response = null, $environment_i } // Set payment info on the order object. - Dynamic_Props::set( $order, 'payment', $payment ); + OrderHelper::setPayment( $order, $payment ); $order->add_order_note( $this->get_order_note( $token ) ); From 4ab31b922c38dcf4793d9a040452d566b28fd0cb Mon Sep 17 00:00:00 2001 From: Dharmesh Patel Date: Thu, 28 Aug 2025 13:27:00 +0530 Subject: [PATCH 8/8] Update OrderHelper methods to follow the WP case. --- woocommerce/Helpers/OrderHelper.php | 16 +++++----- .../Abstract_Hosted_Payment_Handler.php | 4 +-- .../class-sv-wc-payment-gateway-direct.php | 20 ++++++------- .../class-sv-wc-payment-gateway-hosted.php | 10 +++---- .../class-sv-wc-payment-gateway.php | 30 +++++++++---------- ...payment-gateway-integration-pre-orders.php | 14 ++++----- ...ment-gateway-integration-subscriptions.php | 18 +++++------ ...payment-gateway-payment-tokens-handler.php | 4 +-- 8 files changed, 58 insertions(+), 58 deletions(-) diff --git a/woocommerce/Helpers/OrderHelper.php b/woocommerce/Helpers/OrderHelper.php index 8f0f41df1..52f7a36a8 100644 --- a/woocommerce/Helpers/OrderHelper.php +++ b/woocommerce/Helpers/OrderHelper.php @@ -32,7 +32,7 @@ class OrderHelper { * @param \WC_Order $order The order object. * @return \stdClass The payment object containing payment details. */ - public static function getPayment( \WC_Order $order ) { + public static function get_payment( \WC_Order $order ) { return Dynamic_Props::get( $order, 'payment', null, new \stdClass() ); } @@ -46,7 +46,7 @@ public static function getPayment( \WC_Order $order ) { * @param \WC_Order $order The order object. * @return mixed The payment total amount, or null if not set. */ - public static function getPaymentTotal( \WC_Order $order ) { + public static function get_payment_total( \WC_Order $order ) { return Dynamic_Props::get( $order, 'payment_total' ); } @@ -60,7 +60,7 @@ public static function getPaymentTotal( \WC_Order $order ) { * @param \WC_Order $order The order object. * @return mixed The customer ID, or null if not set. */ - public static function getCustomerId( \WC_Order $order ) { + public static function get_customer_id( \WC_Order $order ) { return Dynamic_Props::get( $order, 'customer_id' ); } @@ -78,7 +78,7 @@ public static function getCustomerId( \WC_Order $order ) { * @param mixed $default Optional. The default value if the property doesn't exist. Default null. * @return mixed The property value if found, or the default value if not found. */ - public static function getProperty( \WC_Order $order, string $key, $nested_key = null, $default = null ): mixed { + public static function get_property( \WC_Order $order, string $key, $nested_key = null, $default = null ): mixed { return Dynamic_Props::get( $order, $key, $nested_key, $default ); } @@ -93,7 +93,7 @@ public static function getProperty( \WC_Order $order, string $key, $nested_key = * @param \WC_Order $order The order object (passed by reference). * @param \stdClass $payment The payment object containing payment details. */ - public static function setPayment( \WC_Order &$order, \stdClass $payment ) { + public static function set_payment( \WC_Order &$order, \stdClass $payment ) { Dynamic_Props::set( $order, 'payment', $payment ); } @@ -108,7 +108,7 @@ public static function setPayment( \WC_Order &$order, \stdClass $payment ) { * @param \WC_Order $order The order object (passed by reference). * @param float|string $payment_total The payment total amount. */ - public static function setPaymentTotal( \WC_Order &$order, $payment_total ) { + public static function set_payment_total( \WC_Order &$order, $payment_total ) { Dynamic_Props::set( $order, 'payment_total', $payment_total ); } @@ -123,7 +123,7 @@ public static function setPaymentTotal( \WC_Order &$order, $payment_total ) { * @param \WC_Order $order The order object (passed by reference). * @param mixed $customer_id The customer ID to set. */ - public static function setCustomerId( \WC_Order &$order, $customer_id ) { + public static function set_customer_id( \WC_Order &$order, $customer_id ) { Dynamic_Props::set( $order, 'customer_id', $customer_id ); } @@ -139,7 +139,7 @@ public static function setCustomerId( \WC_Order &$order, $customer_id ) { * @param string $key The property key to set. * @param mixed $value The value to set for the property. */ - public static function setProperty( \WC_Order &$order, string $key, $value ) { + public static function set_property( \WC_Order &$order, string $key, $value ) { Dynamic_Props::set( $order, $key, $value ); } } diff --git a/woocommerce/payment-gateway/Handlers/Abstract_Hosted_Payment_Handler.php b/woocommerce/payment-gateway/Handlers/Abstract_Hosted_Payment_Handler.php index cd086cf95..216388310 100644 --- a/woocommerce/payment-gateway/Handlers/Abstract_Hosted_Payment_Handler.php +++ b/woocommerce/payment-gateway/Handlers/Abstract_Hosted_Payment_Handler.php @@ -326,7 +326,7 @@ protected function get_order_from_response( FrameworkBase\SV_WC_Payment_Gateway_ $order = $this->get_gateway()->get_order( $order ); - $payment = OrderHelper::getPayment( $order ); + $payment = OrderHelper::get_payment( $order ); $payment->account_number = $response->get_account_number(); @@ -343,7 +343,7 @@ protected function get_order_from_response( FrameworkBase\SV_WC_Payment_Gateway_ } // Set payment info on the order object. - OrderHelper::setPayment( $order, $payment ); + OrderHelper::set_payment( $order, $payment ); return $order; } diff --git a/woocommerce/payment-gateway/class-sv-wc-payment-gateway-direct.php b/woocommerce/payment-gateway/class-sv-wc-payment-gateway-direct.php index 0b65a3899..8cb03e3ca 100644 --- a/woocommerce/payment-gateway/class-sv-wc-payment-gateway-direct.php +++ b/woocommerce/payment-gateway/class-sv-wc-payment-gateway-direct.php @@ -390,7 +390,7 @@ public function process_payment( $order_id ) { if ( $this->should_skip_transaction( $order ) || $this->do_transaction( $order ) ) { // add transaction data for zero-dollar "orders" - if ( '0.00' === OrderHelper::getPaymentTotal( $order ) ) { + if ( '0.00' === OrderHelper::get_payment_total( $order ) ) { $this->add_transaction_data( $order ); } @@ -605,7 +605,7 @@ public function get_order( $order_id ) { $order = parent::get_order( $order_id ); // Get payment info from the order object. - $payment = OrderHelper::getPayment( $order ); + $payment = OrderHelper::get_payment( $order ); // payment info if ( SV_WC_Helper::get_posted_value( 'wc-' . $this->get_id_dasherized() . '-account-number' ) && ! SV_WC_Helper::get_posted_value( 'wc-' . $this->get_id_dasherized() . '-payment-token' ) ) { @@ -683,7 +683,7 @@ public function get_order( $order_id ) { } // Set payment info on the order object. - OrderHelper::setPayment( $order, $payment ); + OrderHelper::set_payment( $order, $payment ); /** * Direct Gateway Get Order Filter. @@ -1142,14 +1142,14 @@ protected function get_order_for_add_payment_method() { $order->set_props( $properties ); // other default info - OrderHelper::setCustomerId( $order, $this->get_customer_id( $order->get_user_id() ) ); + OrderHelper::set_customer_id( $order, $this->get_customer_id( $order->get_user_id() ) ); /* translators: Placeholders: %1$s - site title, %2$s - customer email. Payment method as in a specific credit card, e-check or bank account */ $description = sprintf( esc_html__( '%1$s - Add Payment Method for %2$s', 'woocommerce-plugin-framework' ), sanitize_text_field( SV_WC_Helper::get_site_name() ), $properties['billing_email'] ); Dynamic_Props::set( $order, 'description', $description ); // force zero amount - OrderHelper::setPaymentTotal( $order, '0.00' ); + OrderHelper::set_payment_total( $order, '0.00' ); /** * Direct Gateway Get Order for Add Payment Method Filter. @@ -1180,12 +1180,12 @@ protected function add_add_payment_method_customer_data( $order, $response ) { // set customer ID from response if available if ( $this->supports_customer_id() && method_exists( $response, 'get_customer_id' ) && $response->get_customer_id() ) { - OrderHelper::setCustomerId( $order, $customer_id = $response->get_customer_id() ); + OrderHelper::set_customer_id( $order, $customer_id = $response->get_customer_id() ); } else { // default to the customer ID on "order" - $customer_id = OrderHelper::getCustomerId( $order ); + $customer_id = OrderHelper::get_customer_id( $order ); } // update the user @@ -1295,7 +1295,7 @@ public function transaction_forced() { */ protected function should_tokenize_before_sale( \WC_Order $order ): bool { - $result = $this->get_payment_tokens_handler()->should_tokenize() && ( '0.00' === OrderHelper::getPaymentTotal( $order ) || $this->tokenize_before_sale() ); + $result = $this->get_payment_tokens_handler()->should_tokenize() && ( '0.00' === OrderHelper::get_payment_total( $order ) || $this->tokenize_before_sale() ); /** * Filters whether tokenization should be performed before the sale, for a given order. @@ -1386,7 +1386,7 @@ protected function can_tokenize_with_or_after_sale( \WC_Order $order ): bool { */ return apply_filters( "wc_payment_gateway_{$this->get_id()}_can_tokenize_with_or_after_sale", - OrderHelper::getPaymentTotal( $order ) > 0, + OrderHelper::get_payment_total( $order ) > 0, $order, $this ); @@ -1423,7 +1423,7 @@ protected function should_skip_transaction( \WC_Order $order ): bool { return apply_filters( "wc_payment_gateway_{$this->get_id()}_should_skip_transaction", // the order amount will be $0 if a WooCommerce Subscriptions free trial product is being processed - ( '0.00' === OrderHelper::getPaymentTotal( $order ) && ! $this->transaction_forced() ), + ( '0.00' === OrderHelper::get_payment_total( $order ) && ! $this->transaction_forced() ), $order, $this ); diff --git a/woocommerce/payment-gateway/class-sv-wc-payment-gateway-hosted.php b/woocommerce/payment-gateway/class-sv-wc-payment-gateway-hosted.php index c671d233c..e37a2496b 100644 --- a/woocommerce/payment-gateway/class-sv-wc-payment-gateway-hosted.php +++ b/woocommerce/payment-gateway/class-sv-wc-payment-gateway-hosted.php @@ -468,7 +468,7 @@ protected function get_order_from_response( $response ) { $order = $this->get_order( $order ); - $payment = OrderHelper::getPayment( $order ); + $payment = OrderHelper::get_payment( $order ); $payment->account_number = $response->get_account_number(); @@ -485,7 +485,7 @@ protected function get_order_from_response( $response ) { } // Set payment info on the order object. - OrderHelper::setPayment( $order, $payment ); + OrderHelper::set_payment( $order, $payment ); return $order; } @@ -604,7 +604,7 @@ protected function process_transaction_response( $order, $response ) { protected function process_tokenization_response( \WC_Order $order, $response ) { if ( is_callable( array( $response, 'get_customer_id' ) ) && $response->get_customer_id() ) { - OrderHelper::setCustomerId( $order, $response->get_customer_id() ); + OrderHelper::set_customer_id( $order, $response->get_customer_id() ); } $token = $response->get_payment_token(); @@ -663,7 +663,7 @@ protected function process_tokenization_response( \WC_Order $order, $response ) // add the payment method order data if ( $token ) { - $payment = OrderHelper::getPayment( $order ); + $payment = OrderHelper::get_payment( $order ); $payment->token = $token->get_id(); $payment->account_number = $token->get_last_four(); @@ -682,7 +682,7 @@ protected function process_tokenization_response( \WC_Order $order, $response ) } // Set payment info on the order object - OrderHelper::setPayment( $order, $payment ); + OrderHelper::set_payment( $order, $payment ); } // remove any tokens that were deleted on the hosted pay page diff --git a/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php b/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php index 91299e108..7b6942040 100755 --- a/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php +++ b/woocommerce/payment-gateway/class-sv-wc-payment-gateway.php @@ -1283,13 +1283,13 @@ public function get_apple_pay_currencies() { */ public function get_order_for_apple_pay( \WC_Order $order, SV_WC_Payment_Gateway_Apple_Pay_Payment_Response $response ) { - $payment = OrderHelper::getPayment( $order ); + $payment = OrderHelper::get_payment( $order ); $payment->account_number = $response->get_last_four(); $payment->last_four = $response->get_last_four(); $payment->card_type = $response->get_card_type(); - OrderHelper::setPayment( $order, $payment ); + OrderHelper::set_payment( $order, $payment ); return $order; } @@ -1342,7 +1342,7 @@ public function get_order_for_google_pay( \WC_Order $order, $response_data ) { $payment_method_data = $response_data['paymentMethodData']; - $payment = OrderHelper::getPayment( $order ); + $payment = OrderHelper::get_payment( $order ); $payment->google_pay = base64_encode( $payment_method_data['tokenizationData']['token'] ); @@ -1351,7 +1351,7 @@ public function get_order_for_google_pay( \WC_Order $order, $response_data ) { $payment->card_type = SV_WC_Payment_Gateway_Helper::normalize_card_type( $payment_method_data['info']['cardNetwork'] ); // Set payment info on the order object. - OrderHelper::setPayment( $order, $payment ); + OrderHelper::set_payment( $order, $payment ); return $order; } @@ -1948,13 +1948,13 @@ public function get_order( $order ) { // set payment total here, so it can be modified for later by add-ons like subscriptions which may need to charge an amount different than the get_total() $payment_total = number_format( $order->get_total(), 2, '.', '' ); - OrderHelper::setPaymentTotal( $order, $payment_total ); + OrderHelper::set_payment_total( $order, $payment_total ); - OrderHelper::setCustomerId( $order, '' ); + OrderHelper::set_customer_id( $order, '' ); // logged in customer? if ( 0 != $order->get_user_id() && false !== ( $customer_id = $this->get_customer_id( $order->get_user_id(), array( 'order' => $order ) ) ) ) { - OrderHelper::setCustomerId( $order, $customer_id ); + OrderHelper::set_customer_id( $order, $customer_id ); } // add payment info @@ -1964,7 +1964,7 @@ public function get_order( $order ) { $payment->type = str_replace( '-', '_', $this->get_payment_type() ); // Set payment info on the order object - OrderHelper::setPayment( $order, $payment ); + OrderHelper::set_payment( $order, $payment ); /* translators: Placeholders: %1$s - site title, %2$s - order number */ $description = sprintf( esc_html__( '%1$s - Order %2$s', 'woocommerce-plugin-framework' ), wp_specialchars_decode( SV_WC_Helper::get_site_name(), ENT_QUOTES ), $order->get_order_number() ); @@ -2707,7 +2707,7 @@ public function add_transaction_data( $order, $response = null ) { $this->add_customer_data( $order, $response ); } - $payment = OrderHelper::getPayment( $order ); + $payment = OrderHelper::get_payment( $order ); if ( isset( $payment->token ) && $payment->token ) { $this->update_order_meta( $order, 'payment_token', $payment->token ); @@ -2723,13 +2723,13 @@ public function add_transaction_data( $order, $response = null ) { // credit card gateway data if ( $response instanceof SV_WC_Payment_Gateway_API_Authorization_Response ) { - $this->update_order_meta( $order, 'authorization_amount', OrderHelper::getPaymentTotal( $order ) ); + $this->update_order_meta( $order, 'authorization_amount', OrderHelper::get_payment_total( $order ) ); if ( $response->get_authorization_code() ) { $this->update_order_meta( $order, 'authorization_code', $response->get_authorization_code() ); } - if ( OrderHelper::getPaymentTotal( $order ) > 0 ) { + if ( OrderHelper::get_payment_total( $order ) > 0 ) { // mark as captured if ( $this->perform_credit_card_charge( $order ) ) { @@ -2813,12 +2813,12 @@ protected function add_customer_data( $order, $response = null ) { if ( $response && method_exists( $response, 'get_customer_id' ) && $response->get_customer_id() ) { $customer_id = $response->get_customer_id(); - OrderHelper::setCustomerId( $order, $customer_id ); + OrderHelper::set_customer_id( $order, $customer_id ); } else { // default to the customer ID set on the order - $customer_id = OrderHelper::getCustomerId( $order ); + $customer_id = OrderHelper::get_customer_id( $order ); } // update the order with the customer ID, note environment is not appended here because it's already available @@ -2844,7 +2844,7 @@ protected function add_customer_data( $order, $response = null ) { */ public function get_credit_card_transaction_approved_message( \WC_Order $order, $response ) { - $payment = OrderHelper::getPayment( $order ); + $payment = OrderHelper::get_payment( $order ); $last_four = ! empty( $payment->last_four ) ? $payment->last_four : substr( $payment->account_number, -4 ); @@ -2919,7 +2919,7 @@ public function get_credit_card_transaction_approved_message( \WC_Order $order, */ public function get_echeck_transaction_approved_message( \WC_Order $order, SV_WC_Payment_Gateway_API_Response $response ) { - $payment = OrderHelper::getPayment( $order ); + $payment = OrderHelper::get_payment( $order ); $last_four = ! empty( $payment->last_four ) ? $payment->last_four : substr( $payment->account_number, -4 ); diff --git a/woocommerce/payment-gateway/integrations/class-sv-wc-payment-gateway-integration-pre-orders.php b/woocommerce/payment-gateway/integrations/class-sv-wc-payment-gateway-integration-pre-orders.php index 1743813a5..bdfb9afe8 100644 --- a/woocommerce/payment-gateway/integrations/class-sv-wc-payment-gateway-integration-pre-orders.php +++ b/woocommerce/payment-gateway/integrations/class-sv-wc-payment-gateway-integration-pre-orders.php @@ -142,23 +142,23 @@ public function get_order( $order ) { // normally a guest user wouldn't be assigned a customer id, but for a pre-order requiring tokenization, it might be if ( 0 == $order->get_user_id() && false !== ( $customer_id = $this->get_gateway()->get_guest_customer_id( $order ) ) ) { - OrderHelper::setCustomerId( $order, $customer_id ); + OrderHelper::set_customer_id( $order, $customer_id ); } // zero out the payment total since we're just tokenizing the payment method - OrderHelper::setPaymentTotal( $order, '0.00' ); + OrderHelper::set_payment_total( $order, '0.00' ); } elseif ( \WC_Pre_Orders_Order::order_has_payment_token( $order ) && ! is_checkout_pay_page() ) { // if this is a pre-order release payment with a tokenized payment method, get the payment token to complete the order - $payment = OrderHelper::getPayment( $order ); + $payment = OrderHelper::get_payment( $order ); // retrieve the payment token $payment->token = $this->get_gateway()->get_order_meta( $order, 'payment_token' ); // retrieve the optional customer id - OrderHelper::setCustomerId( $order, $this->get_gateway()->get_order_meta( $order, 'customer_id' ) ); + OrderHelper::set_customer_id( $order, $this->get_gateway()->get_order_meta( $order, 'customer_id' ) ); // set token data on order if ( $this->get_gateway()->get_payment_tokens_handler()->user_has_token( $order->get_user_id(), $payment->token ) ) { @@ -213,7 +213,7 @@ public function get_order( $order ) { } // Set payment info on the order object - OrderHelper::setPayment( $order, $payment ); + OrderHelper::set_payment( $order, $payment ); } return $order; @@ -241,7 +241,7 @@ public function process_payment( $result, $order_id ) { try { - $payment = OrderHelper::getPayment( $order ); + $payment = OrderHelper::get_payment( $order ); // using an existing tokenized payment method if ( isset( $payment->token ) && $payment->token ) { @@ -313,7 +313,7 @@ public function process_release_payment( $order ) { // set order defaults $order = $this->get_gateway()->get_order( $order ); - $payment = OrderHelper::getPayment( $order ); + $payment = OrderHelper::get_payment( $order ); // order description $description = sprintf( diff --git a/woocommerce/payment-gateway/integrations/class-sv-wc-payment-gateway-integration-subscriptions.php b/woocommerce/payment-gateway/integrations/class-sv-wc-payment-gateway-integration-subscriptions.php index 106763d94..b832f78ed 100644 --- a/woocommerce/payment-gateway/integrations/class-sv-wc-payment-gateway-integration-subscriptions.php +++ b/woocommerce/payment-gateway/integrations/class-sv-wc-payment-gateway-integration-subscriptions.php @@ -225,8 +225,8 @@ public function save_payment_meta( $order ) { } // customer ID - if ( ! empty( OrderHelper::getCustomerId( $order ) ) ) { - $subscription->update_meta_data( $this->get_gateway()->get_order_meta_prefix() . 'customer_id', OrderHelper::getCustomerId( $order ) ); + if ( ! empty( OrderHelper::get_customer_id( $order ) ) ) { + $subscription->update_meta_data( $this->get_gateway()->get_order_meta_prefix() . 'customer_id', OrderHelper::get_customer_id( $order ) ); $updated = true; } @@ -252,7 +252,7 @@ public function save_payment_meta( $order ) { */ public function add_subscriptions_details_to_order( $order, $gateway ) { - $payment = OrderHelper::getPayment( $order ); + $payment = OrderHelper::get_payment( $order ); if ( $payment ) { @@ -301,7 +301,7 @@ public function add_subscriptions_details_to_order( $order, $gateway ) { } } - OrderHelper::setPayment( $order, $payment ); + OrderHelper::set_payment( $order, $payment ); } return $order; @@ -407,9 +407,9 @@ public function get_order( $order ) { Dynamic_Props::set( $order, 'description', $description ); // override the payment total with the amount to charge given by Subscriptions - OrderHelper::setPaymentTotal( $order, $this->renewal_payment_total ); + OrderHelper::set_payment_total( $order, $this->renewal_payment_total ); - $payment = OrderHelper::getPayment( $order ); + $payment = OrderHelper::get_payment( $order ); // set payment token $payment->token = $this->get_gateway()->get_order_meta( $order, 'payment_token' ); @@ -419,7 +419,7 @@ public function get_order( $order ) { // only if a customer ID exists in order meta, otherwise this will default to the previously set value from user meta if ( ! empty( $customer_id ) ) { - OrderHelper::setCustomerId( $order, $customer_id ); + OrderHelper::set_customer_id( $order, $customer_id ); } // get the token object @@ -441,7 +441,7 @@ public function get_order( $order ) { } // Set payment info on the order object - OrderHelper::setPayment( $order, $payment ); + OrderHelper::set_payment( $order, $payment ); return $order; } @@ -522,7 +522,7 @@ public function process_change_payment( $result, $order_id, $gateway ) { $subscription = $gateway->get_order( $order_id ); - $payment = OrderHelper::getPayment( $subscription ); + $payment = OrderHelper::get_payment( $subscription ); try { diff --git a/woocommerce/payment-gateway/payment-tokens/class-sv-wc-payment-gateway-payment-tokens-handler.php b/woocommerce/payment-gateway/payment-tokens/class-sv-wc-payment-gateway-payment-tokens-handler.php index bd82bff60..f67c70b9a 100644 --- a/woocommerce/payment-gateway/payment-tokens/class-sv-wc-payment-gateway-payment-tokens-handler.php +++ b/woocommerce/payment-gateway/payment-tokens/class-sv-wc-payment-gateway-payment-tokens-handler.php @@ -146,7 +146,7 @@ public function create_token( \WC_Order $order, $response = null, $environment_i // store the billing hash on the token for later use in case it needs to be updated $token->set_billing_hash( $address->get_hash() ); - $payment = OrderHelper::getPayment( $order ); + $payment = OrderHelper::get_payment( $order ); // set the resulting token on the order $payment->token = $token->get_id(); @@ -167,7 +167,7 @@ public function create_token( \WC_Order $order, $response = null, $environment_i } // Set payment info on the order object. - OrderHelper::setPayment( $order, $payment ); + OrderHelper::set_payment( $order, $payment ); $order->add_order_note( $this->get_order_note( $token ) );