diff --git a/.psalm/wcs.php b/.psalm/wcs.php index a35088c88..cc33e0103 100644 --- a/.psalm/wcs.php +++ b/.psalm/wcs.php @@ -2093,3 +2093,17 @@ function wcs_order_contains_product($order, $product) * @return string Page ID. Empty string if resource not found. */ function wc_get_page_screen_id( $for ) {} + +/** + * Subscription Product Variation Class + * + * The subscription product variation class extends the WC_Product_Variation product class + * to create subscription product variations. + * + * @class WC_Product_Subscription + * @package WooCommerce Subscriptions + * @category Class + * @since 1.0.0 - Migrated from WooCommerce Subscriptions v1.3 + * + */ +class WC_Product_Subscription_Variation extends WC_Product_Variation {} diff --git a/modules/ppcp-subscription/src/Helper/SubscriptionHelper.php b/modules/ppcp-subscription/src/Helper/SubscriptionHelper.php index 619fbc658..635e66cc1 100644 --- a/modules/ppcp-subscription/src/Helper/SubscriptionHelper.php +++ b/modules/ppcp-subscription/src/Helper/SubscriptionHelper.php @@ -219,6 +219,11 @@ class SubscriptionHelper { return ''; } + /** + * Returns variations for variable PayPal subscription product. + * + * @return array + */ public function variable_paypal_subscription_variations(): array { $variations = array(); if ( ! $this->current_product_is_subscription() ) { @@ -232,16 +237,16 @@ class SubscriptionHelper { } $variation_ids = $product->get_children(); - foreach ($variation_ids as $id) { - $product = wc_get_product($id); - if(! is_a($product, WC_Product_Subscription_Variation::class )) { + foreach ( $variation_ids as $id ) { + $product = wc_get_product( $id ); + if ( ! is_a( $product, WC_Product_Subscription_Variation::class ) ) { continue; } - $subscription_plan = $product->get_meta('ppcp_subscription_plan') ?? ''; - $variations[] = array( - 'id' => $product->get_id(), - 'attributes' => $product->get_attributes(), + $subscription_plan = $product->get_meta( 'ppcp_subscription_plan' ) ?? array(); + $variations[] = array( + 'id' => $product->get_id(), + 'attributes' => $product->get_attributes(), 'subscription_plan' => $subscription_plan['id'] ?? '', ); } diff --git a/modules/ppcp-subscription/src/SubscriptionModule.php b/modules/ppcp-subscription/src/SubscriptionModule.php index d2077db06..5fe6f1dc1 100644 --- a/modules/ppcp-subscription/src/SubscriptionModule.php +++ b/modules/ppcp-subscription/src/SubscriptionModule.php @@ -12,6 +12,7 @@ namespace WooCommerce\PayPalCommerce\Subscription; use Exception; use WC_Product; use WC_Product_Subscription_Variation; +use WC_Product_Variable; use WC_Product_Variable_Subscription; use WC_Subscriptions_Product; use WooCommerce\PayPalCommerce\ApiClient\Endpoint\BillingSubscriptions; @@ -195,9 +196,15 @@ class SubscriptionModule implements ModuleInterface { $products = array( $this->set_product_config( $product ) ); if ( $product->get_type() === 'variable-subscription' ) { - $products = array(); + $products = array(); + assert( $product instanceof WC_Product_Variable ); $available_variations = $product->get_available_variations(); foreach ( $available_variations as $variation ) { + /** + * The method is defined in WooCommerce. + * + * @psalm-suppress UndefinedMethod + */ $variation = wc_get_product_object( 'variation', $variation['variation_id'] ); $products[] = $this->set_product_config( $variation ); } @@ -472,9 +479,18 @@ class SubscriptionModule implements ModuleInterface { add_action( 'woocommerce_save_product_variation', + /** + * Param types removed to avoid third-party issues. + * + * @psalm-suppress MissingClosureParamType + */ function( $variation_id ) use ( $c ) { $wcsnonce_save_variations = wc_clean( wp_unslash( $_POST['_wcsnonce_save_variations'] ?? '' ) ); - if ( ! WC_Subscriptions_Product::is_subscription( $variation_id ) || empty( $wcsnonce_save_variations ) || ! wp_verify_nonce( $wcsnonce_save_variations, 'wcs_subscription_variations' ) ) { + if ( + ! WC_Subscriptions_Product::is_subscription( $variation_id ) + || ! is_string( $wcsnonce_save_variations ) + || ! wp_verify_nonce( $wcsnonce_save_variations, 'wcs_subscription_variations' ) + ) { return; } @@ -808,6 +824,11 @@ class SubscriptionModule implements ModuleInterface { add_action( 'woocommerce_variation_options_pricing', + /** + * Param types removed to avoid third-party issues. + * + * @psalm-suppress MissingClosureParamType + */ function( $loop, $variation_data, $variation ) use ( $c ) { $settings = $c->get( 'wcgateway.settings' ); assert( $settings instanceof Settings );