Files
roi-theme/wp-content/plugins/restrict-content-pro/core/includes/registration-functions.php
root a22573bf0b Commit inicial - WordPress Análisis de Precios Unitarios
- WordPress core y plugins
- Tema Twenty Twenty-Four configurado
- Plugin allow-unfiltered-html.php simplificado
- .gitignore configurado para excluir wp-config.php y uploads

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-03 21:04:30 -06:00

2027 lines
67 KiB
PHP

<?php
/**
* Registration Functions
*
* Processes the registration form
*
* @package Restrict Content Pro
* @subpackage Registration Functions
* @copyright Copyright (c) 2017, Pippin Williamson
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
* @since 1.5
*/
// Exit if accessed directly
use RCP\Membership_Level;
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Register a new user
*
* @access public
* @since 1.0
* @return void
*/
function rcp_process_registration() {
// check nonce
if ( ! ( isset( $_POST['rcp_register_nonce'] ) && wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['rcp_register_nonce'] ) ), 'rcp-register-nonce' ) ) ) {
rcp_errors()->add( 'invalid_nonce', __( 'An authentication error occurred. Please try again.', 'rcp' ), 'register' );
wp_send_json_error(
array(
'success' => false,
'errors' => rcp_get_error_messages_html( 'register' ),
'nonce' => wp_create_nonce( 'rcp-register-nonce' ),
)
);
}
global $rcp_options;
$membership_level = rcp_get_membership_level( rcp_get_registration()->get_membership_level_id() );
// We are already sanitizing, but PHPCS keep complaining about the isset function.
// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
$discount = isset( $_POST['rcp_discount'] ) ? sanitize_text_field( strtolower( wp_unslash( $_POST['rcp_discount'] ) ) ) : '';
$price = number_format( $membership_level->get_price(), 2, '.', '' );
$initial_amount = rcp_get_registration()->get_total();
$auto_renew = rcp_registration_is_recurring();
// if both today's total and the recurring total are 0, the there is a full discount
// if this is not a recurring membership only check today's total
$full_discount = ( $auto_renew ) ? ( rcp_get_registration()->get_total() == 0 && rcp_get_registration()->get_recurring_total() == 0 ) : ( rcp_get_registration()->get_total() == 0 );
$customer = rcp_get_customer_by_user_id();
$has_trialed = ! empty( $customer ) ? $customer->has_trialed() : false;
$registration_type = rcp_get_registration()->get_registration_type(); // Whether this is a `new` membership, `renewal`, `upgrade`, or `downgrade`.
$recovered_payment = rcp_get_registration()->get_recovered_payment();
// get the selected payment method/gateway
if ( ! isset( $_POST['rcp_gateway'] ) ) {
$gateway = 'paypal';
} else {
$gateway = sanitize_text_field( wp_unslash( $_POST['rcp_gateway'] ) );
}
// Change gateway to "free" if this membership doesn't require payment.
if ( empty( $initial_amount ) && ! $auto_renew ) {
$gateway = 'free';
}
rcp_log( sprintf( 'Started new registration for membership level #%d via %s.', $membership_level->get_id(), $gateway ) );
/***********************
* validate the form
*/
do_action( 'rcp_before_form_errors', $_POST, $customer );
$validate_only = isset( $_POST['validate_only'] );
$user_data = rcp_validate_user_data();
if ( ! rcp_is_registration() ) {
// no membership level was chosen
rcp_errors()->add( 'no_level', __( 'Please choose a membership level', 'rcp' ), 'register' );
}
if ( $membership_level->is_free() && ! $membership_level->is_lifetime() && $has_trialed ) {
// this ensures that users only sign up for a free trial once
rcp_errors()->add( 'free_trial_used', __( 'You may only sign up for a free trial once', 'rcp' ), 'register' );
}
if ( ! empty( $discount ) ) {
// make sure we have a valid discount
if ( rcp_validate_discount( $discount, $membership_level->get_id() ) ) {
// check if the user has already used this discount
if ( $price > 0 && ! $user_data['need_new'] && rcp_user_has_used_discount( $user_data['id'], $discount ) && apply_filters( 'rcp_discounts_once_per_user', false, $discount, $membership_level->get_id() ) ) {
rcp_errors()->add( 'discount_already_used', __( 'You can only use the discount code once', 'rcp' ), 'register' );
}
} else {
// the entered discount code is incorrect
rcp_errors()->add( 'invalid_discount', __( 'The discount you entered is invalid', 'rcp' ), 'register' );
}
}
// Validate extra fields in gateways with the 2.1+ gateway API
if ( ! has_action( 'rcp_gateway_' . $gateway ) && $price > 0 && ! $full_discount ) {
$gateways = new RCP_Payment_Gateways();
$gateway_var = $gateways->get_gateway( $gateway );
$gateway_obj = new $gateway_var['class']();
$gateway_obj->validate_fields();
}
// If enabled, terms agreement must be checked.
if ( ! empty( $rcp_options['enable_terms'] ) && ! isset( $_POST['rcp_agree_to_terms'] ) ) {
rcp_errors()->add( 'terms_not_agreed', __( 'You must agree to the terms and conditions', 'rcp' ), 'register' );
}
// If enabled, privacy policy agreement must be checked.
if ( ! empty( $rcp_options['enable_privacy_policy'] ) && ! isset( $_POST['rcp_agree_to_privacy_policy'] ) ) {
rcp_errors()->add( 'privacy_policy_not_agreed', __( 'You must agree to the privacy policy', 'rcp' ), 'register' );
}
do_action( 'rcp_form_errors', $_POST, $customer );
// retrieve all error messages, if any
$errors = rcp_errors()->get_error_messages();
if ( ! empty( $errors ) ) {
rcp_log( sprintf( 'Registration cancelled with the following errors: %s.', implode( ', ', $errors ) ) );
wp_send_json_error(
array(
'success' => false,
'errors' => rcp_get_error_messages_html( 'register' ),
'nonce' => wp_create_nonce( 'rcp-register-nonce' ),
'gateway' => array(
'slug' => $gateway,
'supports' => ! empty( $gateway_obj->supports ) ? $gateway_obj->supports : false,
),
)
);
} elseif ( $validate_only ) {
wp_send_json_success(
array(
'success' => true,
'nonce' => wp_create_nonce( 'rcp-register-nonce' ),
'total' => rcp_get_registration()->get_total(),
'total_formatted' => rcp_currency_filter( rcp_get_registration()->get_total() ),
'recurring_total' => rcp_get_registration()->get_recurring_total(),
'auto_renew' => $auto_renew,
'gateway' => array(
'slug' => $gateway,
'supports' => ! empty( $gateway_obj->supports ) ? $gateway_obj->supports : false,
),
'level' => array(
'id' => $membership_level->get_id(),
'name' => $membership_level->get_name(),
'description' => $membership_level->get_description(),
'trial' => $membership_level->has_trial(),
),
)
);
}
if ( $user_data['need_new'] ) {
$display_name = trim( $user_data['first_name'] . ' ' . $user_data['last_name'] );
$user_data['id'] = wp_insert_user(
array(
'user_login' => $user_data['login'],
'user_pass' => $user_data['password'],
'user_email' => $user_data['email'],
'first_name' => $user_data['first_name'],
'last_name' => $user_data['last_name'],
'display_name' => ! empty( $display_name ) ? $display_name : $user_data['login'],
'user_registered' => date( 'Y-m-d H:i:s' ),
)
);
if ( ! is_wp_error( $user_data['id'] ) ) {
wp_set_auth_cookie( $user_data['id'] );
wp_set_current_user( $user_data['id'] );
if ( ! isset( $rcp_options['disable_new_user_notices'] ) ) {
// Send an email to the admin alerting them of the registration.
wp_new_user_notification( absint( $user_data['id'] ) );
}
}
}
if ( is_wp_error( $user_data['id'] ) ) {
rcp_errors()->add( $user_data['id']->get_error_code(), $user_data['id']->get_error_message(), 'register' );
} elseif ( ! empty( $user_data['id'] ) && ! is_wp_error( $user_data['id'] ) && empty( $customer ) ) {
// Create the customer record if it doesn't already exist.
$customer_id = rcp_add_customer( array( 'user_id' => absint( $user_data['id'] ) ) );
$customer = ! empty( $customer_id ) ? rcp_get_customer( $customer_id ) : false;
if ( empty( $customer ) ) {
rcp_errors()->add( 'customer_creation_failed', __( 'Failed to create customer record', 'rcp' ), 'register' );
}
}
// Refresh error messages to account for any user creation errors.
$errors = rcp_errors()->get_error_messages();
if ( ! empty( $errors ) ) {
rcp_log( sprintf( 'Registration cancelled with the following errors: %s.', implode( ', ', $errors ) ) );
wp_send_json_error(
array(
'success' => false,
'errors' => rcp_get_error_messages_html( 'register' ),
'nonce' => wp_create_nonce( 'rcp-register-nonce' ),
'gateway' => array(
'slug' => $gateway,
'supports' => ! empty( $gateway_obj->supports ) ? $gateway_obj->supports : false,
),
)
);
}
$user_id = $user_data['id'];
// Save agreement to terms and privacy policy.
if ( ! empty( $_POST['rcp_agree_to_terms'] ) ) {
$terms_agreed = get_user_meta( $user_id, 'rcp_terms_agreed', true );
if ( ! is_array( $terms_agreed ) ) {
$terms_agreed = array();
}
$terms_agreed[] = current_time( 'timestamp' );
update_user_meta( $user_id, 'rcp_terms_agreed', $terms_agreed );
}
if ( ! empty( $_POST['rcp_agree_to_privacy_policy'] ) ) {
$privacy_policy_agreed = get_user_meta( $user_id, 'rcp_privacy_policy_agreed', true );
if ( ! is_array( $privacy_policy_agreed ) ) {
$privacy_policy_agreed = array();
}
$privacy_policy_agreed[] = current_time( 'timestamp' );
update_user_meta( $user_id, 'rcp_privacy_policy_agreed', $privacy_policy_agreed );
}
update_user_meta( $user_id, '_rcp_new_subscription', '1' );
$subscription_key = rcp_generate_subscription_key();
// If we're recovering a payment, then let's recover the associated membership as well.
if ( ! empty( $recovered_payment ) && ! empty( $recovered_payment->membership_id ) && $recovered_payment->object_id == $membership_level->get_id() ) {
$previous_membership = rcp_get_membership( $recovered_payment->membership_id );
// Re-enable this membership if it's been disabled.
if ( $previous_membership->is_disabled() ) {
$previous_membership->enable();
}
rcp_log( sprintf( 'Using recovered membership #%d for registration.', $previous_membership->get_id() ) );
} else {
$previous_membership = rcp_get_registration()->get_membership();
}
$previous_membership_level = ! empty( $previous_membership ) ? rcp_get_membership_level( $previous_membership->get_object_id() ) : false;
if ( $previous_membership instanceof Membership_Level ) {
// Backwards compat.
update_user_meta( $user_id, '_rcp_old_subscription_id', $previous_membership->get_object_id() );
// If the current user isn't the "owner" of the previous membership, something is wrong...
if ( $previous_membership->get_user_id() != get_current_user_id() ) {
wp_die( __( 'You do not have permission to perform this action.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 403 ) );
}
// If this is an upgrade/downgrade but the membership isn't allowed to be changed, something is wrong...
if ( in_array( $registration_type, array( 'upgrade', 'downgrade' ) ) && ! $previous_membership->upgrade_possible() ) {
wp_die( __( 'You do not have permission to perform this action.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 403 ) );
}
// If this is a renewal, but the membership isn't allowed to be renewed, something is wrong...
if ( 'renewal' == $registration_type && ! $previous_membership->can_renew() ) {
wp_die( __( 'You do not have permission to perform this action.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 403 ) );
}
}
rcp_log( sprintf( 'Registration type: %s.', $registration_type ) );
// Delete pending payment ID. A new one may be created for paid membership.
delete_user_meta( $user_id, 'rcp_pending_payment_id' );
// Delete old pending data that may have been added in previous versions.
delete_user_meta( $user_id, 'rcp_pending_expiration_date' );
delete_user_meta( $user_id, 'rcp_pending_subscription_key' );
// Backwards compatibility pre-2.9: set pending subscription key.
update_user_meta( $user_id, 'rcp_pending_subscription_key', $subscription_key );
// Backwards compatibility: we still need to set this for Hard-set Expiration dates.
update_user_meta( $user_id, 'rcp_pending_subscription_level', $membership_level->get_id() );
$amount = ( $membership_level->has_trial() && ! $has_trialed ) ? 0.00 : rcp_get_registration()->get_total();
/**
* Create a pending membership if this is not a manual renewal.
*/
if ( 'renewal' != $registration_type && empty( $recovered_payment ) ) {
$membership_data = array(
'customer_id' => $customer->get_id(),
'object_id' => $membership_level->get_id(),
'object_type' => 'membership',
'initial_amount' => $amount,
'recurring_amount' => $membership_level->is_lifetime() ? 0.00 : rcp_get_registration()->get_recurring_total( true, true ),
'auto_renew' => $auto_renew,
'maximum_renewals' => $membership_level->get_maximum_renewals(),
'status' => 'pending',
'gateway' => $gateway,
'subscription_key' => $subscription_key,
);
if ( in_array( $registration_type, array( 'upgrade', 'downgrade' ) ) && ! empty( $previous_membership ) ) {
$membership_data['upgraded_from'] = $previous_membership->get_id();
}
$membership_id = $customer->add_membership( $membership_data );
if ( in_array( $registration_type, array( 'upgrade', 'downgrade' ) ) ) {
$membership = rcp_get_membership( $membership_id );
$membership->add_note( sprintf( __( 'Upgraded from %1$s (membership #%2$d).', 'rcp' ), $previous_membership_level->get_name(), $previous_membership->get_id() ) );
}
} elseif ( ! empty( $previous_membership ) ) {
/**
* Use the existing membership record if this is a renewal and we have a previous membership to work with.
*/
$membership_id = $previous_membership->get_id();
$new_membership_data = array(
'auto_renew' => $auto_renew,
'gateway' => $gateway,
'recurring_amount' => $membership_level->is_lifetime() ? 0.00 : rcp_get_registration()->get_recurring_total( true, true ),
);
if ( $auto_renew || ! $previous_membership->get_subscription_key() ) {
// Use new generated subscription key if auto renewing, or if the existing subscription key is blank.
$new_membership_data['subscription_key'] = $subscription_key;
} else {
// Keep the same subscription key if not auto renew.
$subscription_key = $previous_membership->get_subscription_key();
}
if ( ! $previous_membership->is_active() ) {
$new_membership_data['status'] = 'pending';
$new_membership_data['expiration_date'] = $previous_membership->calculate_expiration( true, ! $has_trialed );
// Maybe re-calculate trialing period.
if ( $membership_level->has_trial() && ! $has_trialed ) {
$new_membership_data['trial_end_date'] = $new_membership_data['expiration_date'];
}
}
rcp_update_membership( $membership_id, $new_membership_data );
rcp_log( sprintf( 'Using existing membership #%d for payment.', $membership_id ) );
}
if ( rcp_get_registration()->get_total() == 0 && rcp_get_registration()->get_recurring_total() == 0 && ! empty( $discount ) && '2' != rcp_get_auto_renew_behavior() ) {
rcp_update_membership( $membership_id, array( 'expiration_date' => null ) );
}
// Create a pending payment
$credits = ! empty( $previous_membership ) && in_array( $registration_type, array( 'upgrade', 'downgrade' ) ) ? $previous_membership->get_prorate_credit_amount() : 0;
$payment_data = array(
'date' => date( 'Y-m-d H:i:s', current_time( 'timestamp' ) ),
'subscription' => $membership_level->get_name(),
'object_id' => $membership_level->get_id(),
'object_type' => 'subscription',
'gateway' => $gateway,
'subscription_key' => $subscription_key,
'amount' => $amount,
'user_id' => $user_id,
'customer_id' => $customer->get_id(),
'membership_id' => $membership_id,
'status' => 'pending',
'subtotal' => $membership_level->get_price(),
'credits' => $credits,
'fees' => rcp_get_registration()->get_total_fees() + $credits,
'discount_amount' => rcp_get_registration()->get_total_discounts(),
'discount_code' => $discount,
'transaction_type' => $registration_type,
);
$rcp_payments = new RCP_Payments();
if ( ! empty( $recovered_payment ) ) {
// Update the recovered payment.
rcp_log( sprintf( 'Updating recovered payment #%d with new data.', $recovered_payment->id ) );
$rcp_payments->update( $recovered_payment->id, $payment_data );
$payment_id = $recovered_payment->id;
} else {
// Insert a new payment record.
$payment_id = $rcp_payments->insert( $payment_data );
}
// Store the pending payment ID. This is so we know which payment is responsible for activating the membership.
rcp_update_membership_meta( $membership_id, 'pending_payment_id', $payment_id );
// This is for backwards compatibility only. We now use membership meta (see above).
update_user_meta( $user_data['id'], 'rcp_pending_payment_id', $payment_id );
if ( in_array( $registration_type, array( 'upgrade', 'downgrade' ) ) ) {
// Flag the member as having just upgraded
update_user_meta( $user_id, '_rcp_just_upgraded', current_time( 'timestamp' ) );
}
/**
* Triggers after all the form data has been processed, but before the user is sent to the payment gateway.
* The user's membership is pending at this point.
*
* @param array $_POST Posted data.
* @param int $user_id ID of the user registering.
* @param float $price Price of the membership.
* @param int $payment_id ID of the pending payment associated with this registration.
* @param RCP_Customer $customer Customer object.
* @param int $membership_id ID of the new pending membership.
* @param RCP_Membership|false $previous_membership Previous membership object, or false if none.
* @param string $registration_type Type of registration: 'new', 'renewal', or 'upgrade'.
*/
do_action( 'rcp_form_processing', $_POST, $user_id, $price, $payment_id, $customer, $membership_id, $previous_membership, $registration_type );
$success_data = array(
'success' => true,
'nonce' => wp_create_nonce( 'rcp-register-nonce' ),
'total' => rcp_get_registration()->get_total(),
'recurring_total' => rcp_get_registration()->get_recurring_total(),
'auto_renew' => $auto_renew,
'gateway' => array(
'slug' => $gateway,
'supports' => ! empty( $gateway_obj->supports ) ? $gateway_obj->supports : false,
),
'level' => array(
'trial' => $membership_level->has_trial(),
),
'payment_id' => $payment_id,
);
// Handle gateway ajax processing.
if ( 'free' != $gateway && rcp_gateway_supports( $gateway, 'ajax-payment' ) ) {
// send all of the membership data off for processing by the gateway
$result = rcp_handle_gateway_ajax_processing( $gateway, rcp_get_payment_registration_details( $payment_id ) );
if ( is_wp_error( $result ) ) {
rcp_errors()->add( $result->get_error_code(), $result->get_error_message(), 'register' );
wp_send_json_error(
array(
'success' => false,
'errors' => rcp_get_error_messages_html( 'register' ),
'nonce' => wp_create_nonce( 'rcp-register-nonce' ),
'gateway' => array(
'slug' => $gateway,
'supports' => ! empty( $gateway_obj->supports ) ? $gateway_obj->supports : false,
),
)
);
} elseif ( is_array( $result ) ) {
$success_data['gateway']['data'] = $result;
}
}
wp_send_json_success( $success_data );
exit;
}
add_action( 'wp_ajax_rcp_process_register_form', 'rcp_process_registration', 100 );
add_action( 'wp_ajax_nopriv_rcp_process_register_form', 'rcp_process_registration', 100 );
/**
* Generate a new nonce for registration
*
* We have to do this via ajax after the form processing step because we log in new users, which means
* nonce generations done in the same request after log in will fail (due to the new logged in cookies not
* being properly set in PHP yet). We have to do a whole new request to get a properly validated nonce.
*
* Annoying, but it's the price we pay for not doing a full page refresh.
*
* @since 3.2
* @return void
*/
function rcp_generate_registration_nonce() {
wp_send_json_success( wp_create_nonce( 'rcp-register-nonce' ) );
}
add_action( 'wp_ajax_rcp_generate_registration_nonce', 'rcp_generate_registration_nonce', 100 );
add_action( 'wp_ajax_nopriv_rcp_generate_registration_nonce', 'rcp_generate_registration_nonce', 100 );
/**
* Send registration payment to the gateway for processing.
*
* @since 3.2
* @return void
*/
function rcp_send_registration_to_gateway() {
// Don't listen if we're doing ajax processes.
if ( ! empty( $_POST['rcp_ajax'] ) ) {
return;
}
// Check nonce
if ( ! ( isset( $_POST['rcp_register_nonce'] ) && wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['rcp_register_nonce'] ) ), 'rcp-register-nonce' ) ) ) {
return;
}
if ( empty( $_POST['rcp_registration_payment_id'] ) ) {
rcp_errors()->add( 'missing_payment_id', __( 'Missing payment ID.', 'rcp' ), 'register' );
return;
}
/**
* @var RCP_Payments $rcp_payments_db
*/
global $rcp_payments_db;
$payment = $rcp_payments_db->get_payment( absint( sanitize_text_field( wp_unslash( $_POST['rcp_registration_payment_id'] ) ) ) );
if ( empty( $payment ) ) {
rcp_errors()->add( 'invalid_payment', __( 'Invalid payment. Please try again.', 'rcp' ), 'register' );
return;
}
// Process a paid membership.
if ( 'free' != $payment->gateway ) {
// Send all of the membership data off for processing by the gateway.
rcp_send_to_gateway( $payment->gateway, rcp_get_payment_registration_details( $payment->id ) );
} else {
// Process a free or trial membership.
// Complete payment. This also activates the membership.
$rcp_payments_db->update( $payment->id, array( 'status' => 'complete' ) );
rcp_log( sprintf( 'Completed free registration to membership level #%d for customer #%d.', $payment->object_id, $payment->customer_id ) );
// send the newly created user to the redirect page after logging them in
wp_redirect( rcp_get_return_url( absint( $payment->user_id ) ) );
exit;
}
}
add_action( 'init', 'rcp_send_registration_to_gateway', 100 );
/**
* Get all the registration information associated with a payment. This is used when sending the
* payment to the gateway for processing.
*
* @param int $payment_id
*
* @since 3.2
* @return array
*/
function rcp_get_payment_registration_details( $payment_id ) {
/**
* @var RCP_Payments $rcp_payments_db
*/
global $rcp_payments_db;
$payment = $rcp_payments_db->get_payment( absint( $payment_id ) );
if ( empty( $payment ) ) {
return array();
}
$user = get_userdata( absint( $payment->user_id ) );
$membership_level = rcp_get_membership_level( $payment->object_id );
$customer = rcp_get_customer( $payment->customer_id );
/*
* At this point we can't know for sure if this was a brand new user, so we will assume they were if their account was created today.
*/
$new_user = date( 'Y-m-d', strtotime( $user->user_registered, current_time( 'timestamp' ) ) ) === date( 'Y-m-d', current_time( 'timestamp' ) );
$registration_data = array(
'price' => rcp_get_registration()->get_total( true, false ), // get total without the fee
'initial_price' => rcp_get_registration()->get_total( true, true ),
'recurring_price' => rcp_get_registration()->get_recurring_total( true, true ),
'discount' => rcp_get_registration()->get_total_discounts(),
'discount_code' => ! empty( $payment->discount_code ) ? $payment->discount_code : '',
'fee' => rcp_get_registration()->get_total_fees(),
'length' => $membership_level instanceof Membership_Level ? $membership_level->get_duration() : 0,
'length_unit' => $membership_level instanceof Membership_Level ? strtolower( $membership_level->get_duration_unit() ) : 'day',
'subscription_id' => $membership_level instanceof Membership_Level ? $membership_level->get_id() : 0,
'subscription_name' => $membership_level instanceof Membership_Level ? $membership_level->get_name() : '',
'key' => $payment->subscription_key,
'user_id' => $user->ID,
'user_name' => $user->user_login,
'user_email' => $user->user_email,
'currency' => rcp_get_currency(),
'auto_renew' => rcp_registration_is_recurring(),
'return_url' => rcp_get_return_url( $user->ID ),
'new_user' => $new_user,
'trial_duration' => $membership_level instanceof Membership_Level ? $membership_level->get_trial_duration() : 0,
'trial_duration_unit' => $membership_level instanceof Membership_Level ? $membership_level->get_trial_duration_unit() : 'day',
'trial_eligible' => ! $customer->has_trialed(),
'post_data' => $_POST,
'payment_id' => $payment_id,
'membership_id' => absint( $payment->membership_id ),
'customer' => $customer,
'subscription_start_date' => '', // Empty means it starts today.
);
// if giving the user a credit, make sure the credit does not exceed the first payment
if ( $registration_data['fee'] < 0 && abs( $registration_data['fee'] ) > $registration_data['price'] ) {
$registration_data['fee'] = -1 * $registration_data['price'];
}
/*
* Delay the subscription start date if this is a free trial OR the amount due today is $0,
* the recurring amount is greater than $0, and auto renew is enabled.
*/
if ( $registration_data['trial_eligible'] && ! empty( $registration_data['trial_duration'] ) ) {
// Subscription start date is the end of the trial.
$registration_data['subscription_start_date'] = date( 'Y-m-d H:i:s', strtotime( $registration_data['trial_duration'] . ' ' . $registration_data['trial_duration_unit'], current_time( 'timestamp' ) ) );
// Set the amount due today to $0.
$registration_data['price'] = 0;
$registration_data['fee'] = 0;
} elseif ( empty( $registration_data['price'] + $registration_data['fee'] ) && ! empty( $registration_data['recurring_price'] ) && rcp_registration_is_recurring() ) {
// Start date is delayed due to discounts, negative signup fees, or credits.
$registration_data['subscription_start_date'] = date( 'Y-m-d H:i:s', strtotime( $registration_data['length'] . ' ' . $registration_data['length_unit'], current_time( 'timestamp' ) ) );
}
update_user_meta( $user->ID, 'rcp_pending_subscription_amount', round( $registration_data['price'] + $registration_data['fee'], 2 ) );
/**
* Filters the registration data.
*
* @param array $registration_data
*/
return apply_filters( 'rcp_subscription_data', $registration_data );
}
/**
* Provide the default registration values when checking out with Stripe Checkout.
*
* @return void
*/
function rcp_handle_stripe_checkout() {
if ( empty( $_POST['rcp_stripe_checkout'] ) || empty( $_POST['rcp_gateway'] ) || empty( $_POST['rcp_user_email'] ) || 'stripe' !== $_POST['rcp_gateway'] ) {
return;
}
if ( empty( $_POST['rcp_user_login'] ) ) {
$_POST['rcp_user_login'] = sanitize_text_field( wp_unslash( $_POST['rcp_user_email'] ) );
}
if ( empty( $_POST['rcp_user_first'] ) ) {
$user_email = explode( '@', sanitize_text_field( wp_unslash( $_POST['rcp_user_email'] ) ) );
$_POST['rcp_user_first'] = $user_email[0];
}
if ( empty( $_POST['rcp_user_last'] ) ) {
$_POST['rcp_user_last'] = '';
}
if ( empty( $_POST['rcp_user_pass'] ) ) {
$_POST['rcp_user_pass'] = wp_generate_password();
}
if ( empty( $_POST['rcp_user_pass_confirm'] ) ) {
$_POST['rcp_user_pass_confirm'] = sanitize_text_field( wp_unslash( $_POST['rcp_user_pass'] ) );
}
}
add_action( 'rcp_before_form_errors', 'rcp_handle_stripe_checkout' );
/**
* Validate and set up the user data for registration
*
* @access public
* @since 1.5
* @return array
*/
function rcp_validate_user_data() {
$user = array();
if ( ! is_user_logged_in() ) {
$user['id'] = 0;
$user['login'] = sanitize_text_field( wp_unslash( isset( $_POST['rcp_user_login'] ) ? $_POST['rcp_user_login'] : '' ) );
$user['email'] = sanitize_text_field( wp_unslash( isset( $_POST['rcp_user_email'] ) ? $_POST['rcp_user_email'] : '' ) );
$user['first_name'] = sanitize_text_field( wp_unslash( isset( $_POST['rcp_user_first'] ) ? $_POST['rcp_user_first'] : '' ) );
$user['last_name'] = sanitize_text_field( wp_unslash( isset( $_POST['rcp_user_last'] ) ? $_POST['rcp_user_last'] : '' ) );
$user['password'] = sanitize_text_field( wp_unslash( isset( $_POST['rcp_user_pass'] ) ? $_POST['rcp_user_pass'] : '' ) );
$user['password_confirm'] = sanitize_text_field( wp_unslash( isset( $_POST['rcp_user_pass_confirm'] ) ? $_POST['rcp_user_pass_confirm'] : '' ) );
$user['need_new'] = true;
} else {
$userdata = get_userdata( get_current_user_id() );
$user['id'] = $userdata->ID;
$user['login'] = $userdata->user_login;
$user['email'] = $userdata->user_email;
$user['need_new'] = false;
}
if ( $user['need_new'] ) {
if ( username_exists( $user['login'] ) ) {
// Username already registered
rcp_errors()->add(
'username_unavailable',
sprintf(
__( 'This username is already in use. If this is your username, please <a href="%s">log in</a> and try again.', 'rcp' ),
esc_url( rcp_get_login_url() )
),
'register'
);
}
if ( ! rcp_validate_username( $user['login'] ) ) {
// invalid username
rcp_errors()->add( 'username_invalid', __( 'Invalid username', 'rcp' ), 'register' );
}
if ( empty( $user['login'] ) ) {
// empty username
rcp_errors()->add( 'username_empty', __( 'Please enter a username', 'rcp' ), 'register' );
}
if ( ! is_email( $user['email'] ) ) {
// invalid email
rcp_errors()->add( 'email_invalid', __( 'Invalid email', 'rcp' ), 'register' );
}
if ( email_exists( $user['email'] ) ) {
// Email address already registered
rcp_errors()->add(
'email_used',
sprintf(
__( 'This email address is already in use. If this is your email address, please <a href="%s">log in</a> and try again.', 'rcp' ),
esc_url( rcp_get_login_url() )
),
'register'
);
}
if ( empty( $user['password'] ) ) {
// passwords do not match
rcp_errors()->add( 'password_empty', __( 'Please enter a password', 'rcp' ), 'register' );
}
if ( $user['password'] !== $user['password_confirm'] ) {
// passwords do not match
rcp_errors()->add( 'password_mismatch', __( 'Passwords do not match', 'rcp' ), 'register' );
}
}
return apply_filters( 'rcp_user_registration_data', $user );
}
/**
* Get the registration success/return URL
*
* @param $user_id int The user ID we have just registered
*
* @access public
* @since 1.5
* @since 3.5.8 Looking inside the $_POST for the content_upgrade_redirect block
* @return string
*/
function rcp_get_return_url( $user_id = 0 ) {
if ( empty( $user_id ) ) {
$user_id = get_current_user_id();
}
// Redirect coming from Content Upgrade Redirect block
if ( ! empty( $_POST['rcp_redirect'] ) ) {
$validated_rcp_redirect = wp_validate_redirect( sanitize_text_field( wp_unslash( $_POST['rcp_redirect'] ) ) );
if ( ! empty( $validated_rcp_redirect ) ) {
return apply_filters( 'rcp_return_url', $validated_rcp_redirect, $user_id );
}
}
global $rcp_options;
if ( isset( $rcp_options['redirect'] ) ) {
$redirect = get_permalink( $rcp_options['redirect'] );
} else {
$redirect = home_url();
}
return apply_filters( 'rcp_return_url', $redirect, $user_id );
}
/**
* Determine if the current page is a registration page
*
* @access public
* @since 2.0
* @return bool
*/
function rcp_is_registration_page() {
global $rcp_options, $post;
$ret = false;
if ( isset( $rcp_options['registration_page'] ) ) {
$ret = is_page( $rcp_options['registration_page'] );
}
if ( ! empty( $post ) && has_shortcode( $post->post_content, 'register_form' ) ) {
$ret = true;
}
return apply_filters( 'rcp_is_registration_page', $ret );
}
/**
* Get the auto renew behavior
*
* 1 == All memberships auto renew
* 2 == No memberships auto renew
* 3 == Customer chooses whether to auto renew
*
* @access public
* @since 2.0
* @return int
*/
function rcp_get_auto_renew_behavior() {
global $rcp_options, $rcp_level;
// Check for old disable auto renew option
if ( isset( $rcp_options['disable_auto_renew'] ) ) {
$rcp_options['auto_renew'] = '2';
unset( $rcp_options['disable_auto_renew'] );
update_option( 'rcp_settings', $rcp_options );
}
$behavior = isset( $rcp_options['auto_renew'] ) ? $rcp_options['auto_renew'] : '3';
if ( $rcp_level ) {
$level = rcp_get_membership_level( $rcp_level );
if ( $level instanceof Membership_Level && $level->is_free() ) {
$behavior = '2';
}
}
return apply_filters( 'rcp_auto_renew_behavior', $behavior );
}
/**
* When new memberships are registered, a flag is set
*
* This removes the flag as late as possible so other systems can hook into
* rcp_set_status and perform actions on new memberships
*
* @deprecated 3.0 Still here for backwards compatibility.
*
* @param string $status User's membership status.
* @param int $user_id ID of the member.
*
* @access public
* @since 2.3.6
* @return void
*/
function rcp_remove_new_subscription_flag( $status, $user_id ) {
if ( ! in_array( $status, array( 'active', 'free' ) ) ) {
return;
}
delete_user_meta( $user_id, '_rcp_old_subscription_id' );
delete_user_meta( $user_id, '_rcp_new_subscription' );
}
add_action( 'rcp_set_status', 'rcp_remove_new_subscription_flag', 9999999, 2 );
/**
* When upgrading memberships, the new level / key are stored as pending. Once payment is received, the pending
* values are set as the permanent values.
*
* See https://github.com/restrictcontentpro/restrict-content-pro/issues/294
*
* @deprecated 3.0 Still here for backwards compatibility.
*
* @param string $status User's membership status.
* @param int $user_id ID of the user.
* @param string $old_status Previous membership status.
* @param RCP_Member $member Member object.
*
* @access public
* @since 2.4.3
* @return void
*/
function rcp_set_pending_subscription_on_upgrade( $status, $user_id, $old_status, $member ) {
if ( 'active' !== $status ) {
return;
}
$subscription_id = get_user_meta( $user_id, 'rcp_pending_subscription_level', true );
$subscription_key = get_user_meta( $user_id, 'rcp_pending_subscription_key', true );
if ( ! empty( $subscription_id ) && ! empty( $subscription_key ) ) {
delete_user_meta( $user_id, 'rcp_pending_subscription_level' );
delete_user_meta( $user_id, 'rcp_pending_subscription_key' );
}
}
add_action( 'rcp_set_status', 'rcp_set_pending_subscription_on_upgrade', 10, 4 );
/**
* Determine if this registration is recurring
*
* @since 2.5
* @return bool
*/
function rcp_registration_is_recurring() {
$auto_renew = false;
if ( '3' == rcp_get_auto_renew_behavior() ) {
$auto_renew = ! empty( $_POST['rcp_auto_renew'] );
}
if ( '1' == rcp_get_auto_renew_behavior() ) {
$auto_renew = true;
}
// make sure this gateway supports recurring payments
if ( $auto_renew && ! empty( $_POST['rcp_gateway'] ) ) {
$auto_renew = rcp_gateway_supports( sanitize_text_field( wp_unslash( $_POST['rcp_gateway'] ) ), 'recurring' );
}
if ( $auto_renew && ! empty( $_POST['rcp_level'] ) ) {
$membership_level = rcp_get_membership_level( sanitize_text_field( wp_unslash( $_POST['rcp_level'] ) ) );
if ( $membership_level instanceof Membership_Level ) {
// check if this is an unlimited or free membership
if ( $membership_level->is_lifetime() || $membership_level->is_free() ) {
$auto_renew = false;
}
// Disable auto renew if this is a free trial but the gateway doesn't support them built into subscriptions.
if ( $auto_renew && $membership_level->has_trial() ) {
$customer = rcp_get_customer();
$trial_eligible = empty( $customer ) || ( ! empty( $customer ) && ! $customer->has_trialed() );
if ( $trial_eligible && ! rcp_gateway_supports( sanitize_text_field( wp_unslash( $_POST['rcp_gateway'] ) ), 'trial' ) ) {
$auto_renew = false;
}
}
}
}
if ( ! rcp_get_registration_recurring_total() > 0 ) {
$auto_renew = false;
}
return apply_filters( 'rcp_registration_is_recurring', $auto_renew );
}
/**
* Add the registration total before the gateway fields
*
* @since 2.5
* @return void
*/
function rcp_registration_total_field() {
?>
<div class="rcp_registration_total"></div>
<?php
}
add_action( 'rcp_after_register_form_fields', 'rcp_registration_total_field' );
/**
* Get formatted total for this registration
*
* @param bool $echo Whether or not to echo the value.
*
* @since 2.5
* @return string|bool
*/
function rcp_registration_total( $echo = true ) {
$total = rcp_get_registration_total();
// the registration has not been setup yet
if ( false === $total ) {
return false;
}
if ( 0 < $total ) {
$total = rcp_currency_filter( $total );
} else {
$total = __( 'free', 'rcp' );
}
$level = rcp_get_membership_level( rcp_get_registration()->get_membership_level_id() );
if ( $level instanceof Membership_Level && $level->has_trial() && ! rcp_customer_has_trialed() ) {
$total = sprintf(
__( 'Free trial - %s', 'rcp' ),
$level->get_trial_duration() . ' ' . rcp_filter_duration_unit( $level->get_trial_duration_unit(), $level->get_trial_duration() )
);
}
$total = apply_filters( 'rcp_registration_total', $total );
if ( $echo ) {
echo $total;
}
return $total;
}
/**
* Get the total for this registration
*
* @since 2.5
* @return float|false
*/
function rcp_get_registration_total() {
if ( ! rcp_is_registration() ) {
return false;
}
return rcp_get_registration()->get_total();
}
/**
* Get formatted recurring total for this registration
*
* @param bool $echo Whether or not to echo the value.
*
* @since 2.5
* @return string|bool
*/
function rcp_registration_recurring_total( $echo = true ) {
$total = rcp_get_registration_recurring_total();
// the registration has not been setup yet
if ( false === $total ) {
return false;
}
if ( 0 < $total ) {
$total = rcp_currency_filter( $total );
$membership_level = rcp_get_membership_level( rcp_get_registration()->get_membership_level_id() );
if ( $membership_level instanceof Membership_Level ) {
if ( $membership_level->get_duration() == 1 ) {
$total .= '/' . rcp_filter_duration_unit( $membership_level->get_duration_unit(), 1 );
} else {
$total .= sprintf(
__( ' every %1$s %2$s', 'rcp' ),
$membership_level->get_duration(),
rcp_filter_duration_unit( $membership_level->get_duration_unit(), $membership_level->get_duration() )
);
}
}
} else {
$total = __( 'free', 'rcp' );
}
$total = apply_filters( 'rcp_registration_recurring_total', $total );
if ( $echo ) {
echo $total;
}
return $total;
}
/**
* Get the recurring total payment
*
* @since 2.5
* @return bool|int
*/
function rcp_get_registration_recurring_total() {
if ( ! rcp_is_registration() ) {
return false;
}
return rcp_get_registration()->get_recurring_total();
}
/**
* Is the registration object setup?
*
* @since 2.5
* @return bool
*/
function rcp_is_registration() {
return (bool) rcp_get_registration()->get_membership_level_id();
}
/**
* Get the registration object. If it hasn't been setup, setup an empty
* registration object.
*
* @return RCP_Registration
*/
function rcp_get_registration() {
global $rcp_registration;
// setup empty registration object if one doesn't exist
if ( ! is_a( $rcp_registration, 'RCP_Registration' ) ) {
rcp_setup_registration();
}
return $rcp_registration;
}
/**
* Setup the registration object
*
* Auto setup cart on page load if $_POST parameters are found
*
* @param int|null $level_id ID of the membership level for this registration.
* @param string|null $discount Discount code to apply to this registration.
*
* @since 2.5
* @return void
*/
function rcp_setup_registration( $level_id = null, $discount = null ) {
global $rcp_registration;
$rcp_registration = new RCP_Registration( $level_id, $discount );
do_action( 'rcp_setup_registration', $level_id, $discount );
}
/**
* Automatically setup the registration object
*
* @uses rcp_setup_registration()
*
* @return void
*/
function rcp_setup_registration_init() {
if ( empty( $_POST['rcp_level'] ) ) {
return;
}
$level_id = abs( sanitize_text_field( wp_unslash( $_POST['rcp_level'] ) ) );
$discount = ! empty( $_REQUEST['discount'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['discount'] ) ) : null;
$discount = ! empty( $_POST['rcp_discount'] ) ? sanitize_text_field( wp_unslash( $_POST['rcp_discount'] ) ) : $discount;
rcp_setup_registration( $level_id, $discount );
}
add_action( 'init', 'rcp_setup_registration_init' );
/**
* Filter levels to only show valid upgrade levels
*
* @param array $levels Array of membership levels.
*
* @since 2.5
* @return array Array of membership levels.
*/
function rcp_filter_registration_upgrade_levels( $levels = array() ) {
global $rcp_payments_db;
remove_filter( 'rcp_get_levels', 'rcp_filter_registration_upgrade_levels' );
// Filter available levels based on query args.
$type = rcp_get_registration()->get_registration_type();
$membership = rcp_get_registration()->get_membership();
$payment_id = ! empty( $_GET['rcp_registration_payment_id'] ) ? absint( $_GET['rcp_registration_payment_id'] ) : 0;
if ( ! empty( $payment_id ) && $payment = $rcp_payments_db->get_payment( $payment_id ) ) {
// We're recovering a payment -- only show the level associated with that payment.
$levels = array( rcp_get_membership_level( $payment->object_id ) );
} else {
// Renewals / upgrades / normal.
if ( 'renewal' == $type && ! empty( $membership ) ) {
$level_id = $membership->get_object_id();
$levels = $membership->can_renew() ? array( rcp_get_membership_level( $level_id ) ) : array();
} elseif ( in_array( $type, array( 'upgrade', 'downgrade' ) ) && ! empty( $membership ) ) {
$levels = $membership->upgrade_possible() ? $membership->get_upgrade_paths() : array();
} elseif ( 'new' == $type && ! rcp_multiple_memberships_enabled() ) {
$levels = rcp_get_upgrade_paths();
}
}
add_filter( 'rcp_get_levels', 'rcp_filter_registration_upgrade_levels' );
return $levels;
}
/**
* Hook into registration page and filter upgrade path
*/
add_action( 'rcp_before_subscription_form_fields', 'rcp_filter_registration_upgrade_levels' );
/**
* Display "new membership" message.
*
* Adds a notice to the registration form if a user is signing up for a new membership but they
* already have existing memberships that could be renewed or upgraded instead. This is to help
* avoid confusion if someone thinks they're renewing a membership but actually they're signing
* up for a second one instead.
*
* This message is not displayed if multiple memberships is disabled.
*
* @since 3.1
* @return void
*/
function rcp_display_new_membership_message() {
// Bail if multiple memberships aren't enabled.
if ( ! rcp_multiple_memberships_enabled() ) {
return;
}
// Bail if we're already renewing or upgrading.
if ( 'new' != rcp_get_registration()->get_registration_type() ) {
return;
}
$customer = rcp_get_customer(); // current customer
// Bail if this user isn't already a customer.
if ( empty( $customer ) ) {
return;
}
// Bail if this customer doesn't have any memberships.
$memberships = $customer->get_memberships(
array(
'status__in' => array( 'active', 'cancelled', 'expired' ),
)
);
// Final array of filtered memberships.
$membership_array = array();
/**
* @var RCP_Membership $membership
*/
foreach ( $memberships as $membership ) {
if ( ! $membership->can_renew() && ! $membership->upgrade_possible() ) {
continue;
}
$actions = array();
if ( $membership->can_renew() ) {
$actions[] = '<a href="' . esc_url( rcp_get_membership_renewal_url( $membership->get_id() ) ) . '">' . __( 'Renew', 'rcp' ) . '</a>';
}
if ( $membership->upgrade_possible() ) {
$actions[] = '<a href="' . esc_url( rcp_get_membership_upgrade_url( $membership->get_id() ) ) . '">' . __( 'Change', 'rcp' ) . '</a>';
}
$membership_array[ $membership->get_id() ] = array(
'name' => sprintf( '%s (%s)', $membership->get_membership_level_name(), $membership->get_status() ),
'actions' => implode( sprintf( ' %s ', __( 'or', 'rcp' ) ), $actions ),
);
}
if ( empty( $membership_array ) ) {
return;
}
?>
<div id="rcp-membership-new-signup-notice">
<p>
<?php printf( '%s <a href="#" id="rcp-membership-renew-upgrade-toggle">%s</a>', __( 'You are signing up for a new membership.', 'rcp' ), __( 'Click here to renew or change an existing membership instead.', 'rcp' ) ); ?>
</p>
<div id="rcp-membership-renew-upgrade-choice" style="display:none;">
<ul>
<?php
/**
* @var RCP_Membership $membership
*/
foreach ( $membership_array as $id => $this_membership ) :
?>
<li>
<?php printf( '%s - %s', $this_membership['name'], $this_membership['actions'] ); ?>
</li>
<?php endforeach; ?>
</ul>
</div>
</div>
<?php
}
add_action( 'rcp_before_subscription_form_fields', 'rcp_display_new_membership_message' );
/**
* Display "change membership" message.
*
* Adds a notice to the registration form if a user is changing their membership but they have
* the option of signing up for an additional membership instead. This is to help avoid
* confusion if someone thinks they're signing up for a second membership, but actually they're
* changing an existing one.
*
* This message is not displayed if multiple memberships is disabled.
*
* @since 3.1
* @return void
*/
function rcp_display_change_membership_message() {
// Bail if multiple memberships aren't enabled.
if ( ! rcp_multiple_memberships_enabled() ) {
return;
}
// Bail if this isn't an upgrade/downgrade.
if ( ! in_array( rcp_get_registration()->get_registration_type(), array( 'upgrade', 'downgrade' ) ) ) {
return;
}
$membership = rcp_get_registration()->get_membership();
if ( empty( $membership ) ) {
return;
}
?>
<div id="rcp-membership-renew-upgrade-notice">
<p>
<?php printf( __( 'You are changing your "%1$s" membership. <a href="%2$s">Click here to sign up for an additional membership instead.</a>', 'rcp' ), $membership->get_membership_level_name(), esc_url( rcp_get_registration_page_url() ) ); ?>
</p>
</div>
<?php
}
add_action( 'rcp_before_subscription_form_fields', 'rcp_display_change_membership_message' );
/**
* Add prorate credit to member registration
*
* @param RCP_Registration $registration
*
* @since 2.5
* @return void
*/
function rcp_add_prorate_fee( $registration ) {
// If this isn't an upgrade, don't show the message.
if ( ! in_array( $registration->get_registration_type(), array( 'upgrade', 'downgrade' ) ) ) {
return;
}
if ( $membership = $registration->get_membership() ) {
$amount = $membership->get_prorate_credit_amount();
} else {
$amount = rcp_get_member_prorate_credit();
}
if ( empty( $amount ) ) {
return;
}
$registration->add_fee( -1 * $amount, __( 'Proration Credit', 'rcp' ), false, true );
rcp_log( sprintf( 'Adding %.2f proration credits to registration for user #%d.', $amount, get_current_user_id() ) );
}
add_action( 'rcp_registration_init', 'rcp_add_prorate_fee' );
/**
* Add message to checkout specifying proration credit
*
* @since 2.5
* @return void
*/
function rcp_add_prorate_message() {
// If this isn't an upgrade, don't show the message.
if ( ! in_array( rcp_get_registration()->get_registration_type(), array( 'upgrade', 'downgrade' ) ) ) {
return;
}
$upgrade_paths = rcp_get_upgrade_paths( get_current_user_id() );
$has_upgrade = false;
/*
* The proration message should only be shown if the user has at least one upgrade
* option available where the price is greater than $0.
*/
if ( ! empty( $upgrade_paths ) ) {
foreach ( $upgrade_paths as $subscription_level ) {
if ( ( $subscription_level->price > 0 || $subscription_level->fee > 0 ) ) {
$has_upgrade = true;
break;
}
}
}
if ( $membership = rcp_get_registration()->get_membership() ) {
$amount = $membership->get_prorate_credit_amount();
} else {
$amount = rcp_get_member_prorate_credit();
}
if ( empty( $amount ) || ( ! $has_upgrade ) ) {
return;
}
$prorate_message = sprintf( '<p>%s</p>', __( 'If you upgrade or downgrade your account, the new membership will be prorated up to %s for the first payment. Prorated prices are shown below.', 'rcp' ) );
printf( apply_filters( 'rcp_registration_prorate_message', $prorate_message ), esc_html( rcp_currency_filter( $amount ) ) );
}
add_action( 'rcp_before_subscription_form_fields', 'rcp_add_prorate_message' );
/**
* Add the registration type to the form.
*
* @since 3.1
* @return void
*/
function rcp_add_registration_type_field() {
$reg_type = ! empty( $_GET['registration_type'] ) ? sanitize_text_field( wp_unslash( $_GET['registration_type'] ) ) : '';
$membership_id = ! empty( $_GET['membership_id'] ) ? sanitize_text_field( wp_unslash( $_GET['membership_id'] ) ) : 0;
$payment_id = ! empty( $_GET['rcp_registration_payment_id'] ) ? sanitize_text_field( wp_unslash( $_GET['rcp_registration_payment_id'] ) ) : 0;
?>
<input type="hidden" id="rcp-registration-type" name="registration_type" value="<?php echo esc_attr( $reg_type ); ?>" />
<input type="hidden" id="rcp-membership-id" name="membership_id" value="<?php echo absint( $membership_id ); ?>" />
<input type="hidden" id="rcp-payment-id" name="rcp_registration_payment_id" value="<?php echo absint( $payment_id ); ?>" />
<?php
}
add_action( 'rcp_before_registration_submit_field', 'rcp_add_registration_type_field' );
/**
* Removes the reminder sent flags when the member's status is set to active.
* This allows the reminders to be re-sent for the next membership period.
*
* @deprecated 3.0 In favour of `rcp_remove_membership_reminder_flags()`.
* @see rcp_remove_membership_reminder_flags()
*
* @param string $status User's membership status.
* @param int $user_id ID of the user.
* @param string $old_status Old status from before the update.
* @param RCP_Member $member Member object.
*
* @since 2.5.5
* @return void
*/
function rcp_remove_expiring_soon_email_sent_flag( $status, $user_id, $old_status, $member ) {
if ( 'active' !== $status ) {
return;
}
global $wpdb;
$query = $wpdb->prepare( "DELETE FROM {$wpdb->usermeta} WHERE user_id = %d AND meta_key LIKE %s", $user_id, '_rcp_reminder_sent_' . absint( $member->get_subscription_id() ) . '_%' );
$wpdb->query( $query );
}
// add_action( 'rcp_set_status', 'rcp_remove_expiring_soon_email_sent_flag', 10, 4 );
/**
* Trigger email verification during registration.
*
* @uses rcp_send_email_verification()
*
* @param array $posted Posted form data.
* @param int $user_id ID of the user making this registration.
* @param float $price Price of the membership level.
* @param int $payment_id ID of the pending payment associated with this registration.
* @param RCP_Customer $customer Customer object.
* @param int $membership_id ID of the new pending membership.
* @param RCP_Membership|false $previous_membership Previous membership object, or false if none.
* @param string $registration_type Type of registration: 'new', 'renewal', or 'upgrade'.
*
* @return void
*/
function rcp_set_email_verification_flag( $posted, $user_id, $price, $payment_id, $customer, $membership_id, $previous_membership, $registration_type ) {
global $rcp_options;
$require_verification = isset( $rcp_options['email_verification'] ) ? $rcp_options['email_verification'] : 'off';
$required = in_array( $require_verification, array( 'free', 'all' ) );
// Not required if this is a paid registration and email verification is required for free only.
if ( $price > 0 && 'free' == $require_verification ) {
$required = false;
}
// Not required if they've already had a membership level.
// This prevents email verification from popping up for old users on upgrades/downgrades/renewals.
if ( $previous_membership ) {
$required = false;
}
// Bail if verification not required.
if ( ! apply_filters( 'rcp_require_email_verification', $required, $posted, $user_id, $price ) ) {
return;
}
// Email verification already completed.
if ( 'verified' === $customer->get_email_verification_status() ) {
return;
}
// Add meta flag to indicate they're pending email verification. This also sends the email.
$customer->update(
array(
'email_verification' => 'pending',
)
);
}
add_action( 'rcp_form_processing', 'rcp_set_email_verification_flag', 10, 8 );
/**
* Remove membership data if registration payment fails. Includes:
*
* - Update pending payment status to "Failed"
* - If this is a brand new registration, disable the associated membership. @todo Maybe this could be improved.
*
* @param RCP_Payment_Gateway $gateway
*
* @since 2.8
* @return void
*/
function rcp_remove_subscription_data_on_failure( $gateway ) {
if ( ! empty( $gateway->user_id ) && is_object( $gateway->payment ) ) {
/**
* @var RCP_Payments $rcp_payments_db
*/
global $rcp_payments_db;
// Mark the pending payment as failed.
$rcp_payments_db->update( $gateway->payment->id, array( 'status' => 'failed' ) );
// Disable the membership.
$transaction_type = ! empty( $gateway->payment->transaction_type ) ? $gateway->payment->transaction_type : 'new';
if ( is_object( $gateway->membership ) && ! $gateway->membership->is_active() && 'renewal' != $transaction_type ) {
$gateway->membership->disable();
}
if ( is_object( $gateway->membership ) ) {
$pending_payment_id = rcp_get_membership_meta( $gateway->membership->get_id(), 'pending_payment_id', true );
if ( $pending_payment_id == $gateway->payment->id ) {
rcp_delete_membership_meta( $gateway->membership->get_id(), 'pending_payment_id' );
}
}
// Delete the pending payment ID meta value if that matches this payment.
// This is for backwards compatibility only; we now use membership meta.
$customer = rcp_get_customer_by_user_id( $gateway->user_id );
if ( ! empty( $customer ) ) {
$pending_payment_id = $customer->get_pending_payment_id();
if ( $pending_payment_id == $gateway->payment->id ) {
delete_user_meta( $customer->get_user_id(), 'rcp_pending_payment_id' );
}
}
}
// Log error.
rcp_log( sprintf( '%s registration failed for user #%d. Error message: %s', rcp_get_gateway_name_from_object( $gateway ), $gateway->user_id, $gateway->error_message ), true );
}
add_action( 'rcp_registration_failed', 'rcp_remove_subscription_data_on_failure' );
/**
* Complete a registration when a payment is completed by updating the following:
*
* - Add discount code to member's profile (if applicable).
* - Increase discount code usage (if applicable).
* - Mark as trialing (if applicable).
* - Remove the role granted by the previous membership level and apply new one.
*
* @param int $payment_id ID of the payment being completed.
*
* @since 2.9
* @return void
*/
function rcp_complete_registration( $payment_id ) {
/**
* @var RCP_Payments $rcp_payments_db
*/
global $rcp_payments_db;
$payment = $rcp_payments_db->get_payment( $payment_id );
if ( ! empty( $payment->customer_id ) ) {
$customer = rcp_get_customer( $payment->customer_id );
} else {
$customer = false;
}
// No customer - bail.
if ( empty( $customer ) ) {
return;
}
$membership_id = ! empty( $payment->membership_id ) ? $payment->membership_id : 0;
$membership = ! empty( $membership_id ) ? rcp_get_membership( $membership_id ) : false;
if ( empty( $membership ) ) {
return;
}
$pending_payment_id = rcp_get_membership_meta( $membership_id, 'pending_payment_id', true );
// If this payment doesn't correspond to the initial signup ID, bail.
if ( empty( $pending_payment_id ) || $pending_payment_id != $payment_id ) {
return;
}
rcp_log( sprintf( 'Completing registration for customer #%d via payment #%d.', $customer->get_id(), $pending_payment_id ) );
if ( ! empty( $payment->transaction_type ) && 'renewal' != $payment->transaction_type ) {
// If this is a brand new membership, activate it.
$membership->activate();
} else {
// Otherwise this is a manual renewal, so let's renew it.
$expiration = '';
if ( 'pending' == $membership->get_status() ) {
// If membership is pending, use existing expiration date. This would have been set during registration.
$expiration = $membership->get_expiration_date( false );
}
$membership->renew( $membership->is_recurring(), 'active', $expiration );
}
// Increase the number of uses for this discount code.
if ( ! empty( $payment->discount_code ) ) {
$discount = rcp_get_discount_by( 'code', $payment->discount_code );
if ( ! empty( $discount ) ) {
rcp_log( sprintf( 'Recording usage of discount code #%d.', $discount->get_id() ) );
// Record the usage of this discount code
$discount->store_for_user( $customer->get_user_id() );
// Increase the usage count for the code
$discount->increment_use_count();
}
}
// Delete the pending payment record.
rcp_delete_membership_meta( $membership_id, 'pending_payment_id' );
// Backwards compatibility.
if ( ! empty( $payment->user_id ) ) {
delete_user_meta( $payment->user_id, 'rcp_pending_payment_id' );
}
$member = new RCP_Member( $customer->get_user_id() ); // for backwards compatibility in the below action
/**
* Registration successful! Hook into this action if you need to execute code
* after a successful registration, but not during an automatic renewal.
*
* @var RCP_Member $member
* @var RCP_Customer $customer
* @var RCP_Membership $membership
* @since 2.9
*/
do_action( 'rcp_successful_registration', $member, $customer, $membership );
}
add_action( 'rcp_update_payment_status_complete', 'rcp_complete_registration' );
/**
* Register a user account as an RCP member, assign a membership level,
* calculate the expiration date, etc.
*
* @deprecated 3.0 Use `RCP_Customer::add_membership()` instead.
* @see RCP_Customer::add_membership()
*
* @param int $user_id ID of the user to add the membership to.
* @param array $args {
* Array of membership arguments. Only `subscription_id` is required.
*
* @type string $status Optional. Status to set: free, active, cancelled, or expired. If omitted, set
* to free or active.
* @type int $subscription_id Required. ID number of the membership level to give the user.
* @type string $expiration Optional. Expiration date to give the user in MySQL format. If omitted,
* calculated automatically.
* @type string $discount_code Optional. Name of a discount code to add to the user's profile and increment
* usage count.
* @type string $subscription_key Optional. Subscription key to add to the user's profile.
* @type int|bool $trial_duration Optional. Only supply this to give the user a free trial.
* @type string $trial_duration_unit Optional. `day`, `month`, or `year`.
* @type bool $recurring Optional. Whether or not the membership is automatically recurring. Default is
* `false`.
* @type string $payment_profile_id Optional. Payment profile ID to add to the user's profile.
* }
*
* @since 2.9
* @return bool
*/
function rcp_add_user_to_subscription( $user_id, $args = array() ) {
$defaults = array(
'status' => '',
'subscription_id' => 0,
'expiration' => '', // Calculated automatically if not provided.
'discount_code' => '', // To add to their profile and increase usage.
'subscription_key' => '',
'trial_duration' => false, // To set as trialing.
'trial_duration_unit' => 'day',
'recurring' => false,
'payment_profile_id' => '',
);
$args = wp_parse_args( $args, $defaults );
// Membership level ID is required.
if ( empty( $args['subscription_id'] ) ) {
return false;
}
// Check to see if a customer exists, and if not, create one.
$customer = rcp_get_customer_by_user_id( $user_id );
if ( empty( $customer ) ) {
$customer_id = rcp_add_customer(
array(
'user_id' => $user_id,
)
);
if ( empty( $customer_id ) ) {
return false;
}
$customer = rcp_get_customer( $customer_id );
}
$member = new RCP_Member( $user_id );
$previous_membership = rcp_get_customer_single_membership( $customer->get_id() );
$old_membership_id = ! empty( $previous_membership ) ? $previous_membership->get_object_id() : false;
$membership_level = rcp_get_membership_level( $args['subscription_id'] );
// Invalid membership level - bail.
if ( ! $membership_level instanceof Membership_Level ) {
return false;
}
if ( ! empty( $previous_membership ) && $previous_membership->get_object_id() == $args['subscription_id'] ) {
/**
* If the previous membership is the same as this new one, renew it instead of adding a new one.
*/
$expiration = ! empty( $args['expiration'] ) ? $args['expiration'] : '';
$previous_membership->renew( false, 'active', $expiration );
if ( ! empty( $args['subscription_key'] ) ) {
$previous_membership->set_subscription_key( $args['subscription_key'] );
}
if ( ! empty( $args['payment_profile_id'] ) ) {
$previous_membership->set_gateway_customer_id( $args['payment_profile_id'] );
}
} else {
/**
* Gather all the membership data for a brand new membership.
*/
$membership_data = array(
'object_id' => $membership_level->get_id(),
);
if ( ! empty( $args['subscription_key'] ) ) {
$membership_data['subscription_key'] = $args['subscription_key'];
}
/*
* Initial and recurring amounts.
*/
$membership_data['initial_amount'] = $membership_level->get_price() + $membership_level->get_fee();
$membership_data['recurring_amount'] = $membership_level->get_price();
/*
* Expiration date
* Calculate it if not provided.
*/
$expiration = $args['expiration'];
if ( empty( $expiration ) ) {
$expiration = rcp_calculate_subscription_expiration( $membership_level->get_id(), ! $member->has_trialed() );
}
$membership_data['expiration_date'] = $expiration;
/*
* Discount code
* Increase the number of uses.
*/
if ( ! empty( $args['discount_code'] ) ) {
$discount = rcp_get_discount_by( 'code', $args['discount_code'] );
if ( ! empty( $discount ) ) {
// Record the usage of this discount code
$discount->store_for_user( $user_id );
// Increase the usage count for the code
$discount->increment_use_count();
}
}
/*
* Set the status
*/
$status = $args['status'];
if ( empty( $status ) || 'free' == $status ) {
$status = 'active';
}
$membership_data['status'] = $status;
// Recurring
$membership_data['auto_renew'] = ! empty( $args['recurring'] ) ? 1 : 0;
// Payment profile ID
if ( ! empty( $args['payment_profile_id'] ) ) {
$membership_data['gateway_subscription_id'] = $args['payment_profile_id'];
}
/**
* Now actually insert or update the membership.
*/
$membership_id = $customer->add_membership( $membership_data );
if ( empty( $membership_id ) ) {
return false;
}
}
/**
* Registration successful! Hook into this action if you need to execute code
* after a successful registration, but not during an automatic renewal.
*
* @var RCP_Member $member
* @since 2.9
*/
do_action( 'rcp_successful_registration', $member );
return true;
}
/**
* Automatically add new users to a membership level if enabled
*
* @param int $user_id ID of the newly created user.
*
* @since 2.9
* @return void
*/
function rcp_user_register_add_subscription_level( $user_id ) {
global $rcp_options;
if ( empty( $rcp_options['auto_add_users'] ) ) {
return;
}
$level_id = absint( $rcp_options['auto_add_users_level'] );
if ( empty( $level_id ) ) {
return;
}
// Don't run if we're on the registration form.
if ( did_action( 'rcp_form_errors' ) ) {
return;
}
rcp_log( sprintf( 'Auto adding membership level to user #%d.', $user_id ) );
$customer = rcp_get_customer_by_user_id( $user_id );
if ( empty( $customer ) ) {
$customer_id = rcp_add_customer( array( 'user_id' => $user_id ) );
if ( empty( $customer_id ) ) {
rcp_log( sprintf( 'Error creating customer record for user #%d.', $user_id ) );
return;
}
$customer = rcp_get_customer( $customer_id );
}
if ( empty( $customer ) ) {
rcp_log( sprintf( 'Error retrieving customer record for user #%d.', $user_id ) );
return;
}
$customer->add_membership(
array(
'object_id' => $level_id,
'status' => 'active', // Note: this bypasses RCP_Membership::activate(). Not sure if desired.
'signup_method' => 'manual',
)
);
}
add_action( 'user_register', 'rcp_user_register_add_subscription_level' );
/**
* Returns the URL to the designated registration page.
*
* @since 3.1
* @return string
*/
function rcp_get_registration_page_url() {
global $rcp_options;
$url = get_permalink( $rcp_options['registration_page'] );
/**
* Filters the registration page URL.
*
* @param string $url
*
* @since 3.3.5
*/
return apply_filters( 'rcp_registration_page_url', $url );
}
/**
* Adds the membership "Next Renewal Due" date to the registration "Total Details" table.
*
* @since 3.3
* @return void
*/
function rcp_add_membership_renewal_date_to_total_details() {
$renewal_date = false;
$registration = rcp_get_registration();
$membership = $registration->get_membership();
$membership_level_id = $registration->get_membership_level_id();
// Bail if we have a discount code and the initial & recurring amounts are 0.
if ( $registration->get_total() == 0 && $registration->get_recurring_total() == 0 && $registration->get_discounts() && '2' != rcp_get_auto_renew_behavior() ) {
return;
}
if ( ! empty( $membership ) && 'renewal' == $registration->get_registration_type() ) {
/*
* @link https://github.com/restrictcontentpro/restrict-content-pro/issues/1259
*
* Not all gateways currently support extending the expiration date another full billing cycle during
* renewals while auto renew is selected.
*/
$from_today = false;
if ( ! empty( $_POST['rcp_gateway'] ) ) {
$from_today = rcp_gateway_supports( sanitize_text_field( wp_unslash( $_POST['rcp_gateway'] ) ), 'expiration-extension-on-renewals' ) ? false : rcp_registration_is_recurring();
}
$renewal_date = $membership->calculate_expiration( $from_today );
}
if ( empty( $renewal_date ) && ! empty( $membership_level_id ) ) {
$membership_level = rcp_get_membership_level( $membership_level_id );
// Bail if duration is `0` or price is `0`.
if ( ! $membership_level instanceof Membership_Level || $membership_level->is_free() || $membership_level->is_lifetime() ) {
return;
}
$renewal_date = rcp_calculate_subscription_expiration( $membership_level_id, $registration->is_trial() );
}
if ( empty( $renewal_date ) || 'none' == $renewal_date ) {
return;
}
?>
<tr class="row rcp-renewal-date">
<td class="cell" scope="col"><?php _e( 'Next Renewal Due', 'rcp' ); ?></td>
<td class="cell" data-th="<?php esc_attr_e( 'Next Renewal Due', 'rcp' ); ?>"><?php echo date_i18n( get_option( 'date_format' ), strtotime( $renewal_date, current_time( 'timestamp' ) ) ); ?></td>
</tr>
<?php
}
add_action( 'rcp_register_total_details_footer_bottom', 'rcp_add_membership_renewal_date_to_total_details' );