Fix psalm

This commit is contained in:
Emili Castells Guasch 2023-05-02 12:35:46 +02:00
parent e1d84af7f0
commit eca8a3b09c
21 changed files with 357 additions and 203 deletions

View file

@ -120,8 +120,8 @@ class BillingAgreementsEndpoint {
*/ */
public function reference_transaction_enabled(): bool { public function reference_transaction_enabled(): bool {
try { try {
$reference_transaction_enabled = get_transient('ppcp_reference_transaction_enabled') ?? ''; $reference_transaction_enabled = get_transient( 'ppcp_reference_transaction_enabled' ) ?? '';
if($reference_transaction_enabled === true) { if ( $reference_transaction_enabled === true ) {
return true; return true;
} }
@ -135,12 +135,12 @@ class BillingAgreementsEndpoint {
); );
} finally { } finally {
$this->is_request_logging_enabled = true; $this->is_request_logging_enabled = true;
set_transient('ppcp_reference_transaction_enabled', true, 3 * MONTH_IN_SECONDS); set_transient( 'ppcp_reference_transaction_enabled', true, 3 * MONTH_IN_SECONDS );
} }
return true; return true;
} catch ( PayPalApiException $exception ) { } catch ( PayPalApiException $exception ) {
delete_transient('ppcp_reference_transaction_enabled'); delete_transient( 'ppcp_reference_transaction_enabled' );
return false; return false;
} }
} }

View file

@ -70,11 +70,11 @@ class BillingPlans {
PlanFactory $plan_factory, PlanFactory $plan_factory,
LoggerInterface $logger LoggerInterface $logger
) { ) {
$this->host = $host; $this->host = $host;
$this->bearer = $bearer; $this->bearer = $bearer;
$this->billing_cycle_factory = $billing_cycle_factory; $this->billing_cycle_factory = $billing_cycle_factory;
$this->plan_factory = $plan_factory; $this->plan_factory = $plan_factory;
$this->logger = $logger; $this->logger = $logger;
} }
/** /**
@ -95,10 +95,10 @@ class BillingPlans {
): Plan { ): Plan {
$data = array( $data = array(
'name' => $name, 'name' => $name,
'product_id' => $product_id, 'product_id' => $product_id,
'billing_cycles' => $billing_cycles, 'billing_cycles' => $billing_cycles,
'payment_preferences' => $payment_preferences 'payment_preferences' => $payment_preferences,
); );
$bearer = $this->bearer->bearer(); $bearer = $this->bearer->bearer();
@ -108,7 +108,7 @@ class BillingPlans {
'headers' => array( 'headers' => array(
'Authorization' => 'Bearer ' . $bearer->token(), 'Authorization' => 'Bearer ' . $bearer->token(),
'Content-Type' => 'application/json', 'Content-Type' => 'application/json',
'Prefer' => 'return=representation' 'Prefer' => 'return=representation',
), ),
'body' => wp_json_encode( $data ), 'body' => wp_json_encode( $data ),
); );
@ -128,17 +128,17 @@ class BillingPlans {
); );
} }
return $this->plan_factory->from_paypal_response($json); return $this->plan_factory->from_paypal_response( $json );
} }
public function plan(string $id): Plan { public function plan( string $id ): Plan {
$bearer = $this->bearer->bearer(); $bearer = $this->bearer->bearer();
$url = trailingslashit( $this->host ) . 'v1/billing/plans/' . $id; $url = trailingslashit( $this->host ) . 'v1/billing/plans/' . $id;
$args = array( $args = array(
'headers' => array( 'headers' => array(
'Authorization' => 'Bearer ' . $bearer->token(), 'Authorization' => 'Bearer ' . $bearer->token(),
'Content-Type' => 'application/json', 'Content-Type' => 'application/json',
'Prefer' => 'return=representation' 'Prefer' => 'return=representation',
), ),
); );
@ -156,15 +156,15 @@ class BillingPlans {
); );
} }
return $this->plan_factory->from_paypal_response($json); return $this->plan_factory->from_paypal_response( $json );
} }
public function update_pricing(string $id, BillingCycle $billing_cycle): void { public function update_pricing( string $id, BillingCycle $billing_cycle ): void {
$data = array( $data = array(
"pricing_schemes" => array( 'pricing_schemes' => array(
(object)array( (object) array(
"billing_cycle_sequence" => 1, 'billing_cycle_sequence' => 1,
"pricing_scheme" => $billing_cycle->pricing_scheme(), 'pricing_scheme' => $billing_cycle->pricing_scheme(),
), ),
), ),
); );

View file

@ -179,14 +179,14 @@ class BillingSubscriptions {
* @param string $id Subscription ID. * @param string $id Subscription ID.
* @return stdClass * @return stdClass
*/ */
public function subscription(string $id): stdClass { public function subscription( string $id ): stdClass {
$bearer = $this->bearer->bearer(); $bearer = $this->bearer->bearer();
$url = trailingslashit( $this->host ) . 'v1/billing/subscriptions/' . $id; $url = trailingslashit( $this->host ) . 'v1/billing/subscriptions/' . $id;
$args = array( $args = array(
'headers' => array( 'headers' => array(
'Authorization' => 'Bearer ' . $bearer->token(), 'Authorization' => 'Bearer ' . $bearer->token(),
'Content-Type' => 'application/json', 'Content-Type' => 'application/json',
'Prefer' => 'return=representation' 'Prefer' => 'return=representation',
), ),
); );

View file

@ -60,10 +60,10 @@ class CatalogProducts {
ProductFactory $product_factory, ProductFactory $product_factory,
LoggerInterface $logger LoggerInterface $logger
) { ) {
$this->host = $host; $this->host = $host;
$this->bearer = $bearer; $this->bearer = $bearer;
$this->product_factory = $product_factory; $this->product_factory = $product_factory;
$this->logger = $logger; $this->logger = $logger;
} }
/** /**
@ -77,12 +77,12 @@ class CatalogProducts {
* @throws RuntimeException If the request fails. * @throws RuntimeException If the request fails.
* @throws PayPalApiException If the request fails. * @throws PayPalApiException If the request fails.
*/ */
public function create(string $name, string $description): Product { public function create( string $name, string $description ): Product {
$data = array( $data = array(
'name' => $name, 'name' => $name,
); );
if($description) { if ( $description ) {
$data['description'] = $description; $data['description'] = $description;
} }
@ -93,7 +93,7 @@ class CatalogProducts {
'headers' => array( 'headers' => array(
'Authorization' => 'Bearer ' . $bearer->token(), 'Authorization' => 'Bearer ' . $bearer->token(),
'Content-Type' => 'application/json', 'Content-Type' => 'application/json',
'Prefer' => 'return=representation' 'Prefer' => 'return=representation',
), ),
'body' => wp_json_encode( $data ), 'body' => wp_json_encode( $data ),
); );
@ -113,17 +113,17 @@ class CatalogProducts {
); );
} }
return $this->product_factory->from_paypal_response($json); return $this->product_factory->from_paypal_response( $json );
} }
/** /**
* Updates a Product. * Updates a Product.
* *
* @param string $id Product ID. * @param string $id Product ID.
* @param array $data Data to update. * @param array $data Data to update.
* @return void * @return void
*/ */
public function update(string $id, array $data): void { public function update( string $id, array $data ): void {
$bearer = $this->bearer->bearer(); $bearer = $this->bearer->bearer();
$url = trailingslashit( $this->host ) . 'v1/catalogs/products/' . $id; $url = trailingslashit( $this->host ) . 'v1/catalogs/products/' . $id;
$args = array( $args = array(
@ -131,7 +131,7 @@ class CatalogProducts {
'headers' => array( 'headers' => array(
'Authorization' => 'Bearer ' . $bearer->token(), 'Authorization' => 'Bearer ' . $bearer->token(),
'Content-Type' => 'application/json', 'Content-Type' => 'application/json',
'Prefer' => 'return=representation' 'Prefer' => 'return=representation',
), ),
'body' => wp_json_encode( $data ), 'body' => wp_json_encode( $data ),
); );
@ -157,14 +157,14 @@ class CatalogProducts {
* @param string $id Product ID. * @param string $id Product ID.
* @return Product * @return Product
*/ */
public function product(string $id): Product { public function product( string $id ): Product {
$bearer = $this->bearer->bearer(); $bearer = $this->bearer->bearer();
$url = trailingslashit( $this->host ) . 'v1/catalogs/products/' . $id; $url = trailingslashit( $this->host ) . 'v1/catalogs/products/' . $id;
$args = array( $args = array(
'headers' => array( 'headers' => array(
'Authorization' => 'Bearer ' . $bearer->token(), 'Authorization' => 'Bearer ' . $bearer->token(),
'Content-Type' => 'application/json', 'Content-Type' => 'application/json',
'Prefer' => 'return=representation' 'Prefer' => 'return=representation',
), ),
); );
@ -182,6 +182,6 @@ class CatalogProducts {
); );
} }
return $this->product_factory->from_paypal_response($json); return $this->product_factory->from_paypal_response( $json );
} }
} }

View file

@ -92,11 +92,11 @@ class BillingCycle {
*/ */
public function to_array(): array { public function to_array(): array {
return array( return array(
'frequency' => $this->frequency(), 'frequency' => $this->frequency(),
'sequence' => $this->sequence(), 'sequence' => $this->sequence(),
'tenure_type' => $this->tenure_type(), 'tenure_type' => $this->tenure_type(),
'pricing_scheme' => $this->pricing_scheme(), 'pricing_scheme' => $this->pricing_scheme(),
'total_cycles' => $this->total_cycles(), 'total_cycles' => $this->total_cycles(),
); );
} }
} }

View file

@ -101,12 +101,12 @@ class Plan {
public function to_array():array { public function to_array():array {
return array( return array(
'id' => $this->id(), 'id' => $this->id(),
'name' => $this->name(), 'name' => $this->name(),
'product_id' => $this->product_id(), 'product_id' => $this->product_id(),
'billing_cycles' => $this->billing_cycles(), 'billing_cycles' => $this->billing_cycles(),
'payment_preferences' => $this->payment_preferences(), 'payment_preferences' => $this->payment_preferences(),
'status' => $this->status(), 'status' => $this->status(),
); );
} }
} }

View file

@ -6,8 +6,8 @@ use stdClass;
use WooCommerce\PayPalCommerce\ApiClient\Entity\Plan; use WooCommerce\PayPalCommerce\ApiClient\Entity\Plan;
use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException; use WooCommerce\PayPalCommerce\ApiClient\Exception\RuntimeException;
class PlanFactory class PlanFactory {
{
/** /**
* @var BillingCycleFactory * @var BillingCycleFactory
*/ */
@ -20,12 +20,12 @@ class PlanFactory
public function __construct( public function __construct(
BillingCycleFactory $billing_cycle_factory, BillingCycleFactory $billing_cycle_factory,
PaymentPreferencesFactory $payment_preferences_factory PaymentPreferencesFactory $payment_preferences_factory
){ ) {
$this->billing_cycle_factory = $billing_cycle_factory; $this->billing_cycle_factory = $billing_cycle_factory;
$this->payment_preferences_factory = $payment_preferences_factory; $this->payment_preferences_factory = $payment_preferences_factory;
} }
public function from_paypal_response(stdClass $data): Plan { public function from_paypal_response( stdClass $data ): Plan {
if ( ! isset( $data->id ) ) { if ( ! isset( $data->id ) ) {
throw new RuntimeException( throw new RuntimeException(
__( 'No id for given plan', 'woocommerce-paypal-payments' ) __( 'No id for given plan', 'woocommerce-paypal-payments' )
@ -48,11 +48,11 @@ class PlanFactory
} }
$billing_cycles = array(); $billing_cycles = array();
foreach ($data->billing_cycles as $billing_cycle) { foreach ( $data->billing_cycles as $billing_cycle ) {
$billing_cycles[] = $this->billing_cycle_factory->from_paypal_response($billing_cycle); $billing_cycles[] = $this->billing_cycle_factory->from_paypal_response( $billing_cycle );
} }
$payment_preferences = $this->payment_preferences_factory->from_paypal_response($data->payment_preferences); $payment_preferences = $this->payment_preferences_factory->from_paypal_response( $data->payment_preferences );
return new Plan( return new Plan(
$data->id, $data->id,

View file

@ -23,7 +23,7 @@ class ProductFactory {
* @return Product * @return Product
* @throws RuntimeException When JSON object is malformed. * @throws RuntimeException When JSON object is malformed.
*/ */
public function from_paypal_response(stdClass $data): Product { public function from_paypal_response( stdClass $data ): Product {
if ( ! isset( $data->id ) ) { if ( ! isset( $data->id ) ) {
throw new RuntimeException( throw new RuntimeException(
__( 'No id for product given', 'woocommerce-paypal-payments' ) __( 'No id for product given', 'woocommerce-paypal-payments' )

View file

@ -257,7 +257,7 @@ class SmartButton implements SmartButtonInterface {
$this->module_url = $module_url; $this->module_url = $module_url;
$this->version = $version; $this->version = $version;
$this->session_handler = $session_handler; $this->session_handler = $session_handler;
$this->settings = $settings; $this->settings = $settings;
$this->payer_factory = $payer_factory; $this->payer_factory = $payer_factory;
$this->client_id = $client_id; $this->client_id = $client_id;
@ -826,15 +826,15 @@ class SmartButton implements SmartButtonInterface {
'endpoint' => \WC_AJAX::get_endpoint( StartPayPalVaultingEndpoint::ENDPOINT ), 'endpoint' => \WC_AJAX::get_endpoint( StartPayPalVaultingEndpoint::ENDPOINT ),
'nonce' => wp_create_nonce( StartPayPalVaultingEndpoint::nonce() ), 'nonce' => wp_create_nonce( StartPayPalVaultingEndpoint::nonce() ),
), ),
'save_checkout_form' => array( 'save_checkout_form' => array(
'endpoint' => \WC_AJAX::get_endpoint( SaveCheckoutFormEndpoint::ENDPOINT ), 'endpoint' => \WC_AJAX::get_endpoint( SaveCheckoutFormEndpoint::ENDPOINT ),
'nonce' => wp_create_nonce( SaveCheckoutFormEndpoint::nonce() ), 'nonce' => wp_create_nonce( SaveCheckoutFormEndpoint::nonce() ),
), ),
'validate_checkout' => array( 'validate_checkout' => array(
'endpoint' => \WC_AJAX::get_endpoint( ValidateCheckoutEndpoint::ENDPOINT ), 'endpoint' => \WC_AJAX::get_endpoint( ValidateCheckoutEndpoint::ENDPOINT ),
'nonce' => wp_create_nonce( ValidateCheckoutEndpoint::nonce() ), 'nonce' => wp_create_nonce( ValidateCheckoutEndpoint::nonce() ),
), ),
'cart_script_params' => array( 'cart_script_params' => array(
'endpoint' => \WC_AJAX::get_endpoint( CartScriptParamsEndpoint::ENDPOINT ), 'endpoint' => \WC_AJAX::get_endpoint( CartScriptParamsEndpoint::ENDPOINT ),
), ),
), ),
@ -1380,14 +1380,13 @@ class SmartButton implements SmartButtonInterface {
* @return string * @return string
*/ */
private function paypal_subscription_id(): string { private function paypal_subscription_id(): string {
if($this->subscription_helper->current_product_is_subscription() ) { if ( $this->subscription_helper->current_product_is_subscription() ) {
$product = wc_get_product(); $product = wc_get_product();
assert( $product instanceof WC_Product ); assert( $product instanceof WC_Product );
if ( $product->get_type() === 'subscription' && $product->meta_exists( 'ppcp_subscription_plan' ) ) { if ( $product->get_type() === 'subscription' && $product->meta_exists( 'ppcp_subscription_plan' ) ) {
return $product->get_meta( 'ppcp_subscription_plan' )['id']; return $product->get_meta( 'ppcp_subscription_plan' )['id'];
} }
} }
$items = WC()->cart->get_cart_contents(); $items = WC()->cart->get_cart_contents();

View file

@ -44,8 +44,8 @@ class ApproveSubscriptionEndpoint implements EndpointInterface {
/** /**
* ApproveSubscriptionEndpoint constructor. * ApproveSubscriptionEndpoint constructor.
* *
* @param RequestData $request_data The request data helper. * @param RequestData $request_data The request data helper.
* @param OrderEndpoint $order_endpoint The order endpoint. * @param OrderEndpoint $order_endpoint The order endpoint.
* @param SessionHandler $session_handler The session handler. * @param SessionHandler $session_handler The session handler.
*/ */
public function __construct( public function __construct(

View file

@ -43,14 +43,14 @@ return array(
$endpoint = $container->get( 'api.endpoint.payment-token' ); $endpoint = $container->get( 'api.endpoint.payment-token' );
return new PaymentTokenRepository( $factory, $endpoint ); return new PaymentTokenRepository( $factory, $endpoint );
}, },
'subscription.api-handler' => static function(ContainerInterface $container): SubscriptionsApiHandler { 'subscription.api-handler' => static function( ContainerInterface $container ): SubscriptionsApiHandler {
return new SubscriptionsApiHandler( return new SubscriptionsApiHandler(
$container->get('api.endpoint.catalog-products'), $container->get( 'api.endpoint.catalog-products' ),
$container->get('api.factory.product'), $container->get( 'api.factory.product' ),
$container->get('api.endpoint.billing-plans'), $container->get( 'api.endpoint.billing-plans' ),
$container->get('api.factory.billing-cycle'), $container->get( 'api.factory.billing-cycle' ),
$container->get('api.factory.payment-preferences'), $container->get( 'api.factory.payment-preferences' ),
$container->get( 'woocommerce.logger.woocommerce' ) $container->get( 'woocommerce.logger.woocommerce' )
); );
} },
); );

View file

@ -9,6 +9,7 @@ declare(strict_types=1);
namespace WooCommerce\PayPalCommerce\Subscription; namespace WooCommerce\PayPalCommerce\Subscription;
use WC_Product;
use WC_Product_Subscription; use WC_Product_Subscription;
use WooCommerce\PayPalCommerce\ApiClient\Endpoint\BillingSubscriptions; use WooCommerce\PayPalCommerce\ApiClient\Endpoint\BillingSubscriptions;
use WooCommerce\PayPalCommerce\ApiClient\Exception\PayPalApiException; use WooCommerce\PayPalCommerce\ApiClient\Exception\PayPalApiException;
@ -142,6 +143,11 @@ class SubscriptionModule implements ModuleInterface {
add_action( add_action(
'save_post', 'save_post',
/**
* Param types removed to avoid third-party issues.
*
* @psalm-suppress MissingClosureParamType
*/
function( $product_id ) use ( $c ) { function( $product_id ) use ( $c ) {
$settings = $c->get( 'wcgateway.settings' ); $settings = $c->get( 'wcgateway.settings' );
assert( $settings instanceof Settings ); assert( $settings instanceof Settings );
@ -152,14 +158,19 @@ class SubscriptionModule implements ModuleInterface {
return; return;
} }
$nonce = wc_clean(wp_unslash($_POST['_wcsnonce'])) ?? ''; $nonce = wc_clean( wp_unslash( $_POST['_wcsnonce'] ?? '' ) );
if ( if (
$subscriptions_mode !== 'subscriptions_api' $subscriptions_mode !== 'subscriptions_api'
|| ! is_string( $nonce )
|| ! wp_verify_nonce( $nonce, 'wcs_subscription_meta' ) ) { || ! wp_verify_nonce( $nonce, 'wcs_subscription_meta' ) ) {
return; return;
} }
$product = wc_get_product( $product_id ); $product = wc_get_product( $product_id );
if ( ! is_a( $product, WC_Product::class ) ) {
return;
}
$enable_subscription_product = wc_clean( wp_unslash( $_POST['_ppcp_enable_subscription_product'] ?? '' ) ); $enable_subscription_product = wc_clean( wp_unslash( $_POST['_ppcp_enable_subscription_product'] ?? '' ) );
$product->update_meta_data( '_ppcp_enable_subscription_product', $enable_subscription_product ); $product->update_meta_data( '_ppcp_enable_subscription_product', $enable_subscription_product );
$product->save(); $product->save();
@ -180,6 +191,10 @@ class SubscriptionModule implements ModuleInterface {
if ( $product->meta_exists( 'ppcp_subscription_product' ) && ! $product->meta_exists( 'ppcp_subscription_plan' ) ) { if ( $product->meta_exists( 'ppcp_subscription_product' ) && ! $product->meta_exists( 'ppcp_subscription_plan' ) ) {
$subscription_plan_name = wc_clean( wp_unslash( $_POST['_ppcp_subscription_plan_name'] ?? '' ) ); $subscription_plan_name = wc_clean( wp_unslash( $_POST['_ppcp_subscription_plan_name'] ?? '' ) );
if ( ! is_string( $subscription_plan_name ) ) {
return;
}
$product->update_meta_data( '_ppcp_subscription_plan_name', $subscription_plan_name ); $product->update_meta_data( '_ppcp_subscription_plan_name', $subscription_plan_name );
$product->save(); $product->save();
@ -192,7 +207,12 @@ class SubscriptionModule implements ModuleInterface {
add_filter( add_filter(
'woocommerce_order_data_store_cpt_get_orders_query', 'woocommerce_order_data_store_cpt_get_orders_query',
function( $query, $query_vars ) { /**
* Param types removed to avoid third-party issues.
*
* @psalm-suppress MissingClosureParamType
*/
function( $query, $query_vars ): array {
if ( ! empty( $query_vars['ppcp_subscription'] ) ) { if ( ! empty( $query_vars['ppcp_subscription'] ) ) {
$query['meta_query'][] = array( $query['meta_query'][] = array(
'key' => 'ppcp_subscription', 'key' => 'ppcp_subscription',
@ -208,6 +228,11 @@ class SubscriptionModule implements ModuleInterface {
add_action( add_action(
'woocommerce_customer_changed_subscription_to_cancelled', 'woocommerce_customer_changed_subscription_to_cancelled',
/**
* Param types removed to avoid third-party issues.
*
* @psalm-suppress MissingClosureParamType
*/
function( $subscription ) use ( $c ) { function( $subscription ) use ( $c ) {
$subscription_id = $subscription->get_meta( 'ppcp_subscription' ) ?? ''; $subscription_id = $subscription->get_meta( 'ppcp_subscription' ) ?? '';
if ( $subscription_id ) { if ( $subscription_id ) {
@ -231,6 +256,11 @@ class SubscriptionModule implements ModuleInterface {
add_action( add_action(
'woocommerce_customer_changed_subscription_to_active', 'woocommerce_customer_changed_subscription_to_active',
/**
* Param types removed to avoid third-party issues.
*
* @psalm-suppress MissingClosureParamType
*/
function( $subscription ) use ( $c ) { function( $subscription ) use ( $c ) {
$subscription_id = $subscription->get_meta( 'ppcp_subscription' ) ?? ''; $subscription_id = $subscription->get_meta( 'ppcp_subscription' ) ?? '';
if ( $subscription_id ) { if ( $subscription_id ) {
@ -261,8 +291,17 @@ class SubscriptionModule implements ModuleInterface {
try { try {
$subscriptions_mode = $settings->get( 'subscriptions_mode' ); $subscriptions_mode = $settings->get( 'subscriptions_mode' );
if ( $subscriptions_mode === 'subscriptions_api' ) { if ( $subscriptions_mode === 'subscriptions_api' ) {
/**
* Needed for getting global post object.
*
* @psalm-suppress InvalidGlobal
*/
global $post; global $post;
$product = wc_get_product( $post->ID ); $product = wc_get_product( $post->ID );
if ( ! is_a( $product, WC_Product::class ) ) {
return;
}
$enable_subscription_product = $product->get_meta( '_ppcp_enable_subscription_product' ); $enable_subscription_product = $product->get_meta( '_ppcp_enable_subscription_product' );
$subscription_plan_name = $product->get_meta( '_ppcp_subscription_plan_name' ); $subscription_plan_name = $product->get_meta( '_ppcp_subscription_plan_name' );
@ -289,6 +328,11 @@ class SubscriptionModule implements ModuleInterface {
add_action( add_action(
'woocommerce_subscription_before_actions', 'woocommerce_subscription_before_actions',
/**
* Param types removed to avoid third-party issues.
*
* @psalm-suppress MissingClosureParamType
*/
function( $subscription ) use ( $c ) { function( $subscription ) use ( $c ) {
$subscription_id = $subscription->get_meta( 'ppcp_subscription' ) ?? ''; $subscription_id = $subscription->get_meta( 'ppcp_subscription' ) ?? '';
if ( $subscription_id ) { if ( $subscription_id ) {
@ -308,7 +352,16 @@ class SubscriptionModule implements ModuleInterface {
add_filter( add_filter(
'wcs_view_subscription_actions', 'wcs_view_subscription_actions',
function( $actions, $subscription ) { /**
* Param types removed to avoid third-party issues.
*
* @psalm-suppress MissingClosureParamType
*/
function( $actions, $subscription ): array {
if ( ! is_a( $subscription, WC_Subscription::class ) ) {
return $actions;
}
$subscription_id = $subscription->get_meta( 'ppcp_subscription' ) ?? ''; $subscription_id = $subscription->get_meta( 'ppcp_subscription' ) ?? '';
if ( $subscription_id && $subscription->get_status() === 'active' ) { if ( $subscription_id && $subscription->get_status() === 'active' ) {
$url = wp_nonce_url( $url = wp_nonce_url(
@ -342,18 +395,22 @@ class SubscriptionModule implements ModuleInterface {
add_action( add_action(
'wp_loaded', 'wp_loaded',
function() use ( $c ) { function() use ( $c ) {
if(! function_exists('wcs_get_subscription')) { if ( ! function_exists( 'wcs_get_subscription' ) ) {
return; return;
} }
$cancel_subscription_id = wc_clean( wp_unslash( $_GET['ppcp_cancel_subscription'] ?? '' ) ); $cancel_subscription_id = wc_clean( wp_unslash( $_GET['ppcp_cancel_subscription'] ?? '' ) );
$subscription = wcs_get_subscription( absint( $cancel_subscription_id ) ); $subscription = wcs_get_subscription( absint( $cancel_subscription_id ) );
if ( ! wcs_is_subscription( $subscription ) ) { if ( ! wcs_is_subscription( $subscription ) || $subscription === false ) {
return; return;
} }
$subscription_id = $subscription->get_meta( 'ppcp_subscription' ) ?? ''; $subscription_id = $subscription->get_meta( 'ppcp_subscription' ) ?? '';
$nonce = wc_clean( wp_unslash( $_GET['_wpnonce'] ?? '' ) ); $nonce = wc_clean( wp_unslash( $_GET['_wpnonce'] ?? '' ) );
if ( ! is_string( $nonce ) ) {
return;
}
if ( if (
$subscription_id $subscription_id
&& $cancel_subscription_id && $cancel_subscription_id
@ -393,7 +450,16 @@ class SubscriptionModule implements ModuleInterface {
add_filter( add_filter(
'woocommerce_order_actions', 'woocommerce_order_actions',
function( $actions, $subscription ) { /**
* Param types removed to avoid third-party issues.
*
* @psalm-suppress MissingClosureParamType
*/
function( $actions, $subscription ): array {
if ( ! is_a( $subscription, WC_Subscription::class ) ) {
return $actions;
}
$subscription_id = $subscription->get_meta( 'ppcp_subscription' ) ?? ''; $subscription_id = $subscription->get_meta( 'ppcp_subscription' ) ?? '';
if ( $subscription_id && isset( $actions['wcs_process_renewal'] ) ) { if ( $subscription_id && isset( $actions['wcs_process_renewal'] ) ) {
unset( $actions['wcs_process_renewal'] ); unset( $actions['wcs_process_renewal'] );
@ -407,6 +473,11 @@ class SubscriptionModule implements ModuleInterface {
add_action( add_action(
'woocommerce_process_shop_subscription_meta', 'woocommerce_process_shop_subscription_meta',
/**
* Param types removed to avoid third-party issues.
*
* @psalm-suppress MissingClosureParamType
*/
function( $id, $subscription ) use ( $c ) { function( $id, $subscription ) use ( $c ) {
$subscription_id = $subscription->get_meta( 'ppcp_subscription' ) ?? ''; $subscription_id = $subscription->get_meta( 'ppcp_subscription' ) ?? '';
if ( $subscription_id ) { if ( $subscription_id ) {

View file

@ -1,4 +1,11 @@
<?php <?php
/**
* The subscription module.
*
* @package WooCommerce\PayPalCommerce\Subscription
*/
declare(strict_types=1);
namespace WooCommerce\PayPalCommerce\Subscription; namespace WooCommerce\PayPalCommerce\Subscription;
@ -12,63 +19,88 @@ use WooCommerce\PayPalCommerce\ApiClient\Factory\BillingCycleFactory;
use WooCommerce\PayPalCommerce\ApiClient\Factory\PaymentPreferencesFactory; use WooCommerce\PayPalCommerce\ApiClient\Factory\PaymentPreferencesFactory;
use WooCommerce\PayPalCommerce\ApiClient\Factory\ProductFactory; use WooCommerce\PayPalCommerce\ApiClient\Factory\ProductFactory;
/**
* Class SubscriptionsApiHandler
*/
class SubscriptionsApiHandler { class SubscriptionsApiHandler {
/** /**
* Catalog products.
*
* @var CatalogProducts * @var CatalogProducts
*/ */
private $products_endpoint; private $products_endpoint;
/** /**
* @var ProductFactory * Product factory.
*/ *
private $product_factory; * @var ProductFactory
*/
private $product_factory;
/** /**
* Billing plans.
*
* @var BillingPlans * @var BillingPlans
*/ */
private $billing_plans_endpoint; private $billing_plans_endpoint;
/** /**
* Billing cycle factory.
*
* @var BillingCycleFactory * @var BillingCycleFactory
*/ */
private $billing_cycle_factory; private $billing_cycle_factory;
/** /**
* Payment preferences factory.
*
* @var PaymentPreferencesFactory * @var PaymentPreferencesFactory
*/ */
private $payment_preferences_factory; private $payment_preferences_factory;
/** /**
* The logger.
*
* @var LoggerInterface * @var LoggerInterface
*/ */
private $logger; private $logger;
public function __construct( /**
* SubscriptionsApiHandler constructor.
*
* @param CatalogProducts $products_endpoint Products endpoint.
* @param ProductFactory $product_factory Product factory.
* @param BillingPlans $billing_plans_endpoint Billing plans endpoint.
* @param BillingCycleFactory $billing_cycle_factory Billing cycle factory.
* @param PaymentPreferencesFactory $payment_preferences_factory Payment preferences factory.
* @param LoggerInterface $logger The logger.
*/
public function __construct(
CatalogProducts $products_endpoint, CatalogProducts $products_endpoint,
ProductFactory $product_factory, ProductFactory $product_factory,
BillingPlans $billing_plans_endpoint, BillingPlans $billing_plans_endpoint,
BillingCycleFactory $billing_cycle_factory, BillingCycleFactory $billing_cycle_factory,
PaymentPreferencesFactory $payment_preferences_factory, PaymentPreferencesFactory $payment_preferences_factory,
LoggerInterface $logger LoggerInterface $logger
) { ) {
$this->products_endpoint = $products_endpoint; $this->products_endpoint = $products_endpoint;
$this->product_factory = $product_factory; $this->product_factory = $product_factory;
$this->billing_plans_endpoint = $billing_plans_endpoint; $this->billing_plans_endpoint = $billing_plans_endpoint;
$this->billing_cycle_factory = $billing_cycle_factory; $this->billing_cycle_factory = $billing_cycle_factory;
$this->payment_preferences_factory = $payment_preferences_factory; $this->payment_preferences_factory = $payment_preferences_factory;
$this->logger = $logger; $this->logger = $logger;
} }
/** /**
* Creates a Catalog Product and adds it as WC product meta. * Creates a Catalog Product and adds it as WC product meta.
* *
* @param WC_Product $product * @param WC_Product $product The WC product.
* @return void * @return void
*/ */
public function create_product( WC_Product $product ) { public function create_product( WC_Product $product ) {
try { try {
$subscription_product = $this->products_endpoint->create( $product->get_title(), $product->get_description()); $subscription_product = $this->products_endpoint->create( $product->get_title(), $product->get_description() );
$product->update_meta_data( 'ppcp_subscription_product', $subscription_product->to_array() ); $product->update_meta_data( 'ppcp_subscription_product', $subscription_product->to_array() );
$product->save(); $product->save();
} catch ( RuntimeException $exception ) { } catch ( RuntimeException $exception ) {
@ -81,13 +113,20 @@ class SubscriptionsApiHandler {
} }
} }
public function create_plan( string $plan_name, WC_Product $product ) { /**
* Creates a subscription plan.
*
* @param string $plan_name The plan name.
* @param WC_Product $product The WC product.
* @return void
*/
public function create_plan( string $plan_name, WC_Product $product ): void {
try { try {
$subscription_plan = $this->billing_plans_endpoint->create( $subscription_plan = $this->billing_plans_endpoint->create(
$plan_name, $plan_name,
$product->get_meta( 'ppcp_subscription_product' )['id'] ?? '', $product->get_meta( 'ppcp_subscription_product' )['id'] ?? '',
array($this->billing_cycle_factory->from_wc_product($product)->to_array()), array( $this->billing_cycle_factory->from_wc_product( $product )->to_array() ),
$this->payment_preferences_factory->from_wc_product($product)->to_array() $this->payment_preferences_factory->from_wc_product( $product )->to_array()
); );
$product->update_meta_data( 'ppcp_subscription_plan', $subscription_plan->to_array() ); $product->update_meta_data( 'ppcp_subscription_plan', $subscription_plan->to_array() );
@ -102,65 +141,76 @@ class SubscriptionsApiHandler {
} }
} }
public function update_product(WC_Product $product) { /**
try { * Updates a product.
$catalog_product_id = $product->get_meta( 'ppcp_subscription_product' )['id'] ?? ''; *
if($catalog_product_id) { * @param WC_Product $product The WC product.
$catalog_product = $this->products_endpoint->product($catalog_product_id); * @return void
$catalog_product_name = $catalog_product->name() ?? ''; */
$catalog_product_description = $catalog_product->description() ?? ''; public function update_product( WC_Product $product ): void {
if($catalog_product_name !== $product->get_title() || $catalog_product_description !== $product->get_description()) { try {
$data = array(); $catalog_product_id = $product->get_meta( 'ppcp_subscription_product' )['id'] ?? '';
if($catalog_product_name !== $product->get_title()) { if ( $catalog_product_id ) {
$data[] = (object) array( $catalog_product = $this->products_endpoint->product( $catalog_product_id );
'op' => 'replace', $catalog_product_name = $catalog_product->name() ?: '';
'path' => '/name', $catalog_product_description = $catalog_product->description() ?: '';
'value' => $product->get_title(), if ( $catalog_product_name !== $product->get_title() || $catalog_product_description !== $product->get_description() ) {
); $data = array();
} if ( $catalog_product_name !== $product->get_title() ) {
if($catalog_product_description !== $product->get_description()) { $data[] = (object) array(
$data[] = (object) array( 'op' => 'replace',
'op' => 'replace', 'path' => '/name',
'path' => '/description', 'value' => $product->get_title(),
'value' => $product->get_description(), );
); }
} if ( $catalog_product_description !== $product->get_description() ) {
$data[] = (object) array(
'op' => 'replace',
'path' => '/description',
'value' => $product->get_description(),
);
}
$this->products_endpoint->update($catalog_product_id, $data); $this->products_endpoint->update( $catalog_product_id, $data );
} }
} }
} catch ( RuntimeException $exception ) {
$error = $exception->getMessage();
if ( is_a( $exception, PayPalApiException::class ) ) {
$error = $exception->get_details( $error );
}
} catch (RuntimeException $exception) { $this->logger->error( 'Could not update catalog product on PayPal. ' . $error );
$error = $exception->getMessage(); }
if ( is_a( $exception, PayPalApiException::class ) ) {
$error = $exception->get_details( $error );
}
$this->logger->error( 'Could not update catalog product on PayPal. ' . $error );
}
} }
public function update_plan(WC_Product $product) { /**
try { * Updates a plan.
$subscription_plan_id = $product->get_meta('ppcp_subscription_plan')['id'] ?? ''; *
if ($subscription_plan_id) { * @param WC_Product $product The WC product.
$subscription_plan = $this->billing_plans_endpoint->plan($subscription_plan_id); * @return void
*/
public function update_plan( WC_Product $product ): void {
try {
$subscription_plan_id = $product->get_meta( 'ppcp_subscription_plan' )['id'] ?? '';
if ( $subscription_plan_id ) {
$subscription_plan = $this->billing_plans_endpoint->plan( $subscription_plan_id );
$price = $subscription_plan->billing_cycles()[0]->pricing_scheme()['fixed_price']['value'] ?? ''; $price = $subscription_plan->billing_cycles()[0]->pricing_scheme()['fixed_price']['value'] ?? '';
if($price && round($price, 2) !== round($product->get_price(), 2)) { if ( $price && round( $price, 2 ) !== round( (float) $product->get_price(), 2 ) ) {
$this->billing_plans_endpoint->update_pricing( $this->billing_plans_endpoint->update_pricing(
$subscription_plan_id, $subscription_plan_id,
$this->billing_cycle_factory->from_wc_product($product) $this->billing_cycle_factory->from_wc_product( $product )
); );
} }
} }
} catch (RuntimeException $exception) { } catch ( RuntimeException $exception ) {
$error = $exception->getMessage(); $error = $exception->getMessage();
if ( is_a( $exception, PayPalApiException::class ) ) { if ( is_a( $exception, PayPalApiException::class ) ) {
$error = $exception->get_details( $error ); $error = $exception->get_details( $error );
} }
$this->logger->error( 'Could not update subscription plan on PayPal. ' . $error ); $this->logger->error( 'Could not update subscription plan on PayPal. ' . $error );
} }
} }
} }

View file

@ -798,8 +798,8 @@ return array(
'description' => '', 'description' => '',
'default' => 'vaulting_api', 'default' => 'vaulting_api',
'options' => array( 'options' => array(
'vaulting_api' => __( 'PayPal Vaulting', 'woocommerce-paypal-payments' ), 'vaulting_api' => __( 'PayPal Vaulting', 'woocommerce-paypal-payments' ),
'subscriptions_api' => __( 'PayPal Subscriptions', 'woocommerce-paypal-payments' ), 'subscriptions_api' => __( 'PayPal Subscriptions', 'woocommerce-paypal-payments' ),
'disable_paypal_subscriptions' => __( 'Disable PayPal for subscriptions', 'woocommerce-paypal-payments' ), 'disable_paypal_subscriptions' => __( 'Disable PayPal for subscriptions', 'woocommerce-paypal-payments' ),
), ),
'screens' => array( 'screens' => array(

View file

@ -338,9 +338,9 @@ class SettingsListener {
$this->dcc_status_cache->delete( DCCProductStatus::DCC_STATUS_CACHE_KEY ); $this->dcc_status_cache->delete( DCCProductStatus::DCC_STATUS_CACHE_KEY );
} }
$ppcp_reference_transaction_enabled = get_transient('ppcp_reference_transaction_enabled') ?? ''; $ppcp_reference_transaction_enabled = get_transient( 'ppcp_reference_transaction_enabled' ) ?? '';
if($ppcp_reference_transaction_enabled) { if ( $ppcp_reference_transaction_enabled ) {
delete_transient('ppcp_reference_transaction_enabled'); delete_transient( 'ppcp_reference_transaction_enabled' );
} }
$redirect_url = false; $redirect_url = false;

View file

@ -92,8 +92,8 @@ return array(
new PaymentSaleCompleted( $logger ), new PaymentSaleCompleted( $logger ),
new BillingSubscriptionCancelled( $logger ), new BillingSubscriptionCancelled( $logger ),
new BillingPlanPricingChangeActivated( $logger ), new BillingPlanPricingChangeActivated( $logger ),
new CatalogProductUpdated($logger), new CatalogProductUpdated( $logger ),
new BillingPlanUpdated($logger), new BillingPlanUpdated( $logger ),
); );
}, },

View file

@ -65,19 +65,24 @@ class BillingPlanPricingChangeActivated implements RequestHandler {
*/ */
public function handle_request( WP_REST_Request $request ): WP_REST_Response { public function handle_request( WP_REST_Request $request ): WP_REST_Response {
$response = array( 'success' => false ); $response = array( 'success' => false );
if ( is_null( $request['resource'] ) ) {
return new WP_REST_Response( $response );
}
$plan_id = wc_clean( wp_unslash( $request['resource']['id'] ?? '' ) ); $plan_id = wc_clean( wp_unslash( $request['resource']['id'] ?? '' ) );
$price = wc_clean( wp_unslash( $request['resource']['billing_cycles'][0]['pricing_scheme']['fixed_price']['value'] ?? '' ) ); $price = wc_clean( wp_unslash( $request['resource']['billing_cycles'][0]['pricing_scheme']['fixed_price']['value'] ?? '' ) );
if ( $plan_id && $price ) { if ( $plan_id && $price ) {
$args = array( $args = array(
'meta_key' => 'ppcp_subscription_plan', 'meta_key' => 'ppcp_subscription_plan',
); );
$products = wc_get_products( $args );
foreach ( $products as $product ) { $products = wc_get_products( $args );
if ( $product->get_meta( 'ppcp_subscription_plan' )->id === $plan_id ) { if ( is_array( $products ) ) {
$product->update_meta_data( '_subscription_price', $price ); foreach ( $products as $product ) {
$product->save(); if ( $product->get_meta( 'ppcp_subscription_plan' )->id === $plan_id ) {
$product->update_meta_data( '_subscription_price', $price );
$product->save();
}
} }
} }
} }

View file

@ -64,6 +64,11 @@ class BillingPlanUpdated implements RequestHandler {
* @return WP_REST_Response * @return WP_REST_Response
*/ */
public function handle_request( WP_REST_Request $request ): WP_REST_Response { public function handle_request( WP_REST_Request $request ): WP_REST_Response {
$response = array( 'success' => false );
if ( is_null( $request['resource'] ) ) {
return new WP_REST_Response( $response );
}
$plan_id = wc_clean( wp_unslash( $request['resource']['id'] ?? '' ) ); $plan_id = wc_clean( wp_unslash( $request['resource']['id'] ?? '' ) );
if ( $plan_id ) { if ( $plan_id ) {
$products = wc_get_products( $products = wc_get_products(
@ -72,29 +77,31 @@ class BillingPlanUpdated implements RequestHandler {
) )
); );
foreach ( $products as $product ) { if ( is_array( $products ) ) {
if ( $product->meta_exists( 'ppcp_subscription_plan' ) ) { foreach ( $products as $product ) {
$plan_name = wc_clean( wp_unslash( $request['resource']['name'] ?? '' ) ); if ( $product->meta_exists( 'ppcp_subscription_plan' ) ) {
if ( $plan_name !== $product->get_meta( '_ppcp_subscription_plan_name' ) ) { $plan_name = wc_clean( wp_unslash( $request['resource']['name'] ?? '' ) );
$product->update_meta_data( '_ppcp_subscription_plan_name', $plan_name ); if ( $plan_name !== $product->get_meta( '_ppcp_subscription_plan_name' ) ) {
$product->save(); $product->update_meta_data( '_ppcp_subscription_plan_name', $plan_name );
}
$billing_cycles = wc_clean( wp_unslash( $request['resource']['billing_cycles'] ?? array() ) );
if ( $billing_cycles ) {
$price = $billing_cycles[0]['pricing_scheme']['fixed_price']['value'] ?? '';
if ( $price && round( $price, 2 ) !== round( $product->get_meta( '_subscription_price' ), 2 ) ) {
$product->update_meta_data( '_subscription_price', $price );
$product->save(); $product->save();
} }
}
$payment_preferences = wc_clean( wp_unslash( $request['resource']['payment_preferences'] ?? array() ) ); $billing_cycles = wc_clean( wp_unslash( $request['resource']['billing_cycles'] ?? array() ) );
if ( $payment_preferences ) { if ( $billing_cycles ) {
$setup_fee = $payment_preferences['setup_fee']['value'] ?? ''; $price = $billing_cycles[0]['pricing_scheme']['fixed_price']['value'] ?? '';
if ( $setup_fee && round( $setup_fee, 2 ) !== round( $product->get_meta( '_subscription_sign_up_fee' ), 2 ) ) { if ( $price && round( $price, 2 ) !== round( $product->get_meta( '_subscription_price' ), 2 ) ) {
$product->update_meta_data( '_subscription_sign_up_fee', $setup_fee ); $product->update_meta_data( '_subscription_price', $price );
$product->save(); $product->save();
}
}
$payment_preferences = wc_clean( wp_unslash( $request['resource']['payment_preferences'] ?? array() ) );
if ( $payment_preferences ) {
$setup_fee = $payment_preferences['setup_fee']['value'] ?? '';
if ( $setup_fee && round( $setup_fee, 2 ) !== round( $product->get_meta( '_subscription_sign_up_fee' ), 2 ) ) {
$product->update_meta_data( '_subscription_sign_up_fee', $setup_fee );
$product->save();
}
} }
} }
} }

View file

@ -65,6 +65,9 @@ class BillingSubscriptionCancelled implements RequestHandler {
*/ */
public function handle_request( WP_REST_Request $request ): WP_REST_Response { public function handle_request( WP_REST_Request $request ): WP_REST_Response {
$response = array( 'success' => false ); $response = array( 'success' => false );
if ( is_null( $request['resource'] ) ) {
return new WP_REST_Response( $response );
}
$subscription_id = wc_clean( wp_unslash( $request['resource']['id'] ?? '' ) ); $subscription_id = wc_clean( wp_unslash( $request['resource']['id'] ?? '' ) );
if ( $subscription_id ) { if ( $subscription_id ) {

View file

@ -64,6 +64,11 @@ class CatalogProductUpdated implements RequestHandler {
* @return WP_REST_Response * @return WP_REST_Response
*/ */
public function handle_request( WP_REST_Request $request ): WP_REST_Response { public function handle_request( WP_REST_Request $request ): WP_REST_Response {
$response = array( 'success' => false );
if ( is_null( $request['resource'] ) ) {
return new WP_REST_Response( $response );
}
$product_id = wc_clean( wp_unslash( $request['resource']['id'] ?? '' ) ); $product_id = wc_clean( wp_unslash( $request['resource']['id'] ?? '' ) );
$name = wc_clean( wp_unslash( $request['resource']['name'] ?? '' ) ); $name = wc_clean( wp_unslash( $request['resource']['name'] ?? '' ) );
if ( $product_id && $name ) { if ( $product_id && $name ) {
@ -72,21 +77,28 @@ class CatalogProductUpdated implements RequestHandler {
); );
$products = wc_get_products( $args ); $products = wc_get_products( $args );
foreach ( $products as $product ) { if ( is_array( $products ) ) {
if ( foreach ( $products as $product ) {
$product->meta_exists( 'ppcp_subscription_product' ) if (
&& isset( $product->get_meta( 'ppcp_subscription_product' )['id'] ) $product->meta_exists( 'ppcp_subscription_product' )
&& $product->get_meta( 'ppcp_subscription_product' )['id'] === $product_id && isset( $product->get_meta( 'ppcp_subscription_product' )['id'] )
&& $product->get_title() !== $name && $product->get_meta( 'ppcp_subscription_product' )['id'] === $product_id
) { && $product->get_title() !== $name
wp_update_post( ) {
array( /**
'ID' => $product->get_id(), * Suppress ArgumentTypeCoercion
'post_title' => $name, *
) * @psalm-suppress ArgumentTypeCoercion
); */
wp_update_post(
array(
'ID' => $product->get_id(),
'post_title' => $name,
)
);
break; break;
}
} }
} }
} }

View file

@ -10,6 +10,7 @@ declare(strict_types=1);
namespace WooCommerce\PayPalCommerce\Webhooks\Handler; namespace WooCommerce\PayPalCommerce\Webhooks\Handler;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
use WC_Order;
use WooCommerce\PayPalCommerce\WcGateway\Processor\TransactionIdHandlingTrait; use WooCommerce\PayPalCommerce\WcGateway\Processor\TransactionIdHandlingTrait;
use WP_REST_Request; use WP_REST_Request;
use WP_REST_Response; use WP_REST_Response;
@ -67,8 +68,11 @@ class PaymentSaleCompleted implements RequestHandler {
*/ */
public function handle_request( WP_REST_Request $request ): WP_REST_Response { public function handle_request( WP_REST_Request $request ): WP_REST_Response {
$response = array( 'success' => false ); $response = array( 'success' => false );
if ( is_null( $request['resource'] ) ) {
return new WP_REST_Response( $response );
}
$billing_agreement_id = wc_clean( wp_unslash( $request['resource']['billing_agreement_id'] ) ) ?? ''; $billing_agreement_id = wc_clean( wp_unslash( $request['resource']['billing_agreement_id'] ?? '' ) );
if ( ! $billing_agreement_id ) { if ( ! $billing_agreement_id ) {
$message = 'Could not retrieve billing agreement id for subscription.'; $message = 'Could not retrieve billing agreement id for subscription.';
$this->logger->warning( $message, array( 'request' => $request ) ); $this->logger->warning( $message, array( 'request' => $request ) );
@ -88,7 +92,8 @@ class PaymentSaleCompleted implements RequestHandler {
$subscriptions = wcs_get_subscriptions( $args ); $subscriptions = wcs_get_subscriptions( $args );
if ( ! $subscriptions ) { if ( ! $subscriptions ) {
$message = "Could not retrieve WC subscriptions for billing agreement: {$billing_agreement_id}"; $billing_agreement_id = is_string( $billing_agreement_id ) ? $billing_agreement_id : '';
$message = "Could not retrieve WC subscriptions for billing agreement: {$billing_agreement_id}";
$this->logger->warning( $message, array( 'request' => $request ) ); $this->logger->warning( $message, array( 'request' => $request ) );
$response['message'] = $message; $response['message'] = $message;
return new WP_REST_Response( $response ); return new WP_REST_Response( $response );
@ -96,11 +101,13 @@ class PaymentSaleCompleted implements RequestHandler {
foreach ( $subscriptions as $subscription ) { foreach ( $subscriptions as $subscription ) {
$renewal_order = wcs_create_renewal_order( $subscription ); $renewal_order = wcs_create_renewal_order( $subscription );
$renewal_order->payment_complete(); if ( is_a( $renewal_order, WC_Order::class ) ) {
$renewal_order->payment_complete();
$transaction_id = wc_clean( wp_unslash( $request['resource']['id'] ) ) ?? ''; $transaction_id = wc_clean( wp_unslash( $request['resource']['id'] ?? '' ) );
if ( $transaction_id ) { if ( $transaction_id && is_string( $transaction_id ) ) {
$this->update_transaction_id( $transaction_id, $renewal_order ); $this->update_transaction_id( $transaction_id, $renewal_order );
}
} }
} }