Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Infinite loop when activating subscription with past expiry date #26

Closed
rvdsteege opened this issue Sep 11, 2024 · 1 comment · Fixed by #27
Closed

Infinite loop when activating subscription with past expiry date #26

rvdsteege opened this issue Sep 11, 2024 · 1 comment · Fixed by #27
Assignees
Labels

Comments

@rvdsteege
Copy link
Member

rvdsteege commented Sep 11, 2024

Updating the RCP membership status can result in an infinite loop. The way I was able to reproduce this is by manually activating an expired RCP membership without changing the expiration date (so that the expiration date is in the past).

Internal Help Scout ticket: https://secure.helpscout.net/conversation/2703692673/27702

@rvdsteege
Copy link
Member Author

Culprit seems to be a recursion conflict caused by our Extension::rcp_transition_membership_status() which hooks into rcp_transition_membership_status and an rcp_set_customer_trialing_flag() in RCP hooking into rcp_transition_membership_status_active (the $membership->is_trialing() results in the membership status being updated from active to expired again, while we're still processing the update from expired to active).

Changing the priority to < 10 with which we hook into rcp_transition_membership_status seems to resolve the issue.

  • /**
    * Restrict Content Pro transition membership status.
    *
    * @link https://gitlab.com/pronamic-plugins/restrict-content-pro/blob/master/includes/memberships/class-rcp-membership.php#L673-683
    * @link https://gitlab.com/pronamic-plugins/restrict-content-pro/blob/master/includes/database/engine/class-query.php#L2061-2070
    *
    * @param string $old_status Old membership status.
    * @param string $new_status New membership status.
    * @param int $membership_id ID of the membership.
    * @return void
    */
    public function rcp_transition_membership_status( $old_status, $new_status, $membership_id ) {
    $rcp_membership = \rcp_get_membership( (int) $membership_id );
    if ( false === $rcp_membership ) {
    return;
    }
    $gateway_subscription_id = $rcp_membership->get_gateway_subscription_id();
    if ( '' === $gateway_subscription_id ) {
    return;
    }
    $pronamic_subscription = \get_pronamic_subscription( (int) $gateway_subscription_id );
    if ( null === $pronamic_subscription ) {
    return;
    }
    $core_status = MembershipStatus::to_core_subscription_status( $new_status );
    $note = null;
    switch ( $new_status ) {
    case MembershipStatus::ACTIVE:
    $note = sprintf(
    /* translators: %s: Restrict Content Pro */
    __( 'Subscription activated by %s.', 'pronamic_ideal' ),
    __( 'Restrict Content Pro', 'pronamic_ideal' )
    );
    break;
    case MembershipStatus::CANCELLED:
    $note = sprintf(
    /* translators: %s: Restrict Content Pro */
    __( 'Subscription canceled by %s.', 'pronamic_ideal' ),
    __( 'Restrict Content Pro', 'pronamic_ideal' )
    );
    break;
    case MembershipStatus::EXPIRED:
    $note = sprintf(
    /* translators: %s: Restrict Content Pro */
    __( 'Subscription expired by %s.', 'pronamic_ideal' ),
    __( 'Restrict Content Pro', 'pronamic_ideal' )
    );
    break;
    case MembershipStatus::PENDING:
    $note = sprintf(
    /* translators: %s: Restrict Content Pro */
    __( 'Subscription pending by %s.', 'pronamic_ideal' ),
    __( 'Restrict Content Pro', 'pronamic_ideal' )
    );
    break;
    }
    if ( null === $core_status ) {
    return;
    }
    $pronamic_subscription->set_status( $core_status );
    if ( null !== $note ) {
    $pronamic_subscription->add_note( $note );
    }
    $pronamic_subscription->save();
    }
  • https://github.com/stellarwp/restrict-content/blob/1b7914806e9703b6820d9073f0e6d965ebee7337/core/includes/memberships/membership-actions.php#L231-L266
  • https://github.com/stellarwp/restrict-content/blob/1b7914806e9703b6820d9073f0e6d965ebee7337/core/includes/customers/customer-actions.php#L15-L37
  • https://github.com/stellarwp/restrict-content/blob/1b7914806e9703b6820d9073f0e6d965ebee7337/core/includes/memberships/class-rcp-membership.php#L1321-L1333
  • /**
    * Update RCP membership status on subscription status update.
    *
    * @param Subscription $pronamic_subscription Subscription.
    * @return void
    */
    public function subscription_status_update( Subscription $pronamic_subscription ) {
    $membership_id = (int) $pronamic_subscription->get_source_id();
    $rcp_membership = \rcp_get_membership( $membership_id );
    if ( false === $rcp_membership ) {
    return;
    }
    $status = MembershipStatus::transform_from_pronamic( $pronamic_subscription->get_status() );
    if ( null !== $status ) {
    $rcp_membership->set_status( $status );

@rvdsteege rvdsteege moved this from Todo to In Progress in Pronamic Pay Sep 11, 2024
rvdsteege added a commit that referenced this issue Sep 17, 2024
…-subscription-with-past-expiry-date

Fix recursion conflict with RCP `rcp_set_customer_trialing_flag` (#26).
@github-project-automation github-project-automation bot moved this from In Progress to Done in Pronamic Pay Sep 17, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
Status: Done
1 participant