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>
This commit is contained in:
root
2025-11-03 21:04:30 -06:00
commit a22573bf0b
24068 changed files with 4993111 additions and 0 deletions

View File

@@ -0,0 +1,52 @@
<?php
namespace RCP;
use RCP\lucatume\DI52\Container as DI52Container;
use RCP\StellarWP\ContainerContract\ContainerInterface;
class Container implements ContainerInterface {
protected $container;
/**
* Container constructor.
*/
public function __construct() {
$this->container = new DI52Container();
}
/**
* @inheritDoc
*/
public function bind( string $id, $implementation = null, array $afterBuildMethods = null ) {
return $this->container->bind( $id, $implementation, $afterBuildMethods );
}
/**
* @inheritDoc
*/
public function get( string $id ) {
return $this->container->get( $id );
}
/**
* @inheritDoc
*/
public function has( string $id ) {
return $this->container->has( $id );
}
/**
* @inheritDoc
*/
public function singleton( string $id, $implementation = null, array $afterBuildMethods = null ) {
$this->container->singleton( $id, $implementation, $afterBuildMethods );
}
/**
* Defer all other calls to the container object.
*/
public function __call( $name, $args ) {
return $this->container->{$name}( ...$args );
}
}

View File

@@ -0,0 +1,109 @@
<?php
/**
* Admin Add-Ons
*
* @package Restrict Content Pro
* @subpackage Admin/Add-Ons
* @copyright Copyright (c) 2017, Restrict Content Pro
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
*/
// Exit if accessed directly
if ( ! defined( 'ABSPATH' ) ) exit;
/**
* Add-ons Page
*
* Renders the add-ons page content.
*
* @return void
*/
function rcp_add_ons_admin() {
$add_ons_tabs = apply_filters( 'rcp_add_ons_tabs', array( 'pro' => 'Pro', 'official-free' => 'Official Free' ) );
$active_tab = isset( $_GET['tab'] ) && array_key_exists( $_GET['tab'], $add_ons_tabs ) ? $_GET['tab'] : 'pro';
ob_start();
?>
<div class="wrap" id="rcp-add-ons">
<h1>
<?php _e( 'Add-ons for Restrict Content Pro', 'rcp' ); ?>
<span>
&nbsp;&nbsp;<a href="https://restrictcontentpro.com/add-ons/?utm_source=plugin-add-ons-page&utm_medium=plugin&utm_campaign=Restrict%20Content%20Pro%20Add-ons%20Page&utm_content=All%20Add-ons" class="button-primary" title="<?php _e( 'Browse all add-ons', 'rcp' ); ?>" target="_blank"><?php _e( 'Browse all add-ons', 'rcp' ); ?></a>
</span>
</h1>
<p><?php _e( 'These add-ons <em><strong>add functionality</strong></em> to your Restrict Content Pro-powered site.', 'rcp' ); ?></p>
<h2 class="nav-tab-wrapper">
<?php
foreach( $add_ons_tabs as $tab_id => $tab_name ) {
$tab_url = add_query_arg( array(
'settings-updated' => false,
'tab' => urlencode( $tab_id )
) );
$active = $active_tab == $tab_id ? ' nav-tab-active' : '';
echo '<a href="' . esc_url( $tab_url ) . '" title="' . esc_attr( $tab_name ) . '" class="nav-tab' . $active . '">';
echo esc_html( $tab_name );
echo '</a>';
}
?>
</h2>
<div id="tab_container">
<?php if ( 'pro' === $active_tab ) : ?>
<p><?php printf( __( 'Pro add-ons are only available with a Professional or Ultimate license. If you already have one of these licenses, simply <a href="%s">log in to your account</a> to download any of these add-ons.', 'rcp' ), 'https://restrictcontentpro.com/account/?utm_source=plugin-add-ons-page&utm_medium=plugin&utm_campaign=Restrict%20Content%20Pro%20Add-ons%20Page&utm_content=Account' ); ?></p>
<p><?php printf( __( 'If you have a Personal or Plus license, you can easily upgrade from your account page to <a href="%s">get access to all of these add-ons</a>!', 'rcp' ), 'https://restrictcontentpro.com/account/?utm_source=plugin-add-ons-page&utm_medium=plugin&utm_campaign=Restrict%20Content%20Pro%20Add-ons%20Page&utm_content=Account' ); ?></p>
<?php else : ?>
<p><?php _e( 'Our official free add-ons are available to all license holders!', 'rcp' ); ?></p>
<?php endif; ?>
<?php echo rcp_add_ons_get_feed( $active_tab ); ?>
<div class="rcp-add-ons-footer">
<a href="https://restrictcontentpro.com/add-ons/?utm_source=plugin-add-ons-page&utm_medium=plugin&utm_campaign=Restrict%20Content%20Pro%20Add-ons%20Page&utm_content=All%20Add-ons" class="button-primary" title="<?php _e( 'Browse all add-ons', 'rcp' ); ?>" target="_blank"><?php _e( 'Browse all add-ons', 'rcp' ); ?></a>
</div>
</div>
</div>
<?php
echo ob_get_clean();
}
/**
* Add-ons Get Feed
*
* Gets the add-ons page feed.
*
* @param string $tab Which type of add-ons to retrieve.
*
* @return string
*/
function rcp_add_ons_get_feed( $tab = 'pro' ) {
$cache = get_transient( 'rcp_add_ons_feed_' . $tab );
if ( false === $cache ) {
$url = 'https://restrictcontentpro.com/?feed=feed-add-ons';
if ( 'pro' !== $tab ) {
$url = add_query_arg( array( 'display' => urlencode( $tab ) ), $url );
}
$feed = wp_remote_get( esc_url_raw( $url ) );
if ( ! is_wp_error( $feed ) ) {
if ( isset( $feed['body'] ) && strlen( $feed['body'] ) > 0 ) {
$cache = wp_remote_retrieve_body( $feed );
set_transient( 'rcp_add_ons_feed_' . $tab, $cache, HOUR_IN_SECONDS );
}
} else {
$cache = '<div class="error"><p>' . __( 'There was an error retrieving the add-ons list from the server. Please try again later.', 'rcp' ) . '</div>';
}
}
return $cache;
}

View File

@@ -0,0 +1,58 @@
<?php
/**
* Admin Actions
*
* @package restrict-content-pro
* @subpackage Admin/Admin Actions
* @copyright Copyright (c) 2017, Restrict Content Pro
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
* @since 2.9
*/
// Exit if accessed directly
if ( ! defined( 'ABSPATH' ) ) exit;
/**
* Process all RCP actions sent via POST and GET
*
* @since 2.9
* @return void
*/
function rcp_process_actions() {
if ( isset( $_POST['rcp-action'] ) ) {
do_action( 'rcp_action_' . $_POST['rcp-action'], $_POST );
}
if ( isset( $_GET['rcp-action'] ) ) {
do_action( 'rcp_action_' . $_GET['rcp-action'], $_GET );
}
}
add_action( 'admin_init', 'rcp_process_actions' );
/**
* Denotes the various RCP pages as such in the pages list table.
*
* @param array $post_states An array of post display states.
* @param WP_Post $post The current post object.
* @return array An array of post display states.
*/
function rcp_display_post_states( $post_states, $post ) {
$rcp_options = get_option( 'rcp_settings' );
$pages = array(
'registration_page' => __( 'Registration Page', 'rcp' ),
'redirect' => __( 'Registration Success Page', 'rcp' ),
'account_page' => __( 'Account Page', 'rcp' ),
'edit_profile' => __( 'Edit Profile Page', 'rcp' ),
'update_card' => __( 'Update Card Page', 'rcp' )
);
foreach( $pages as $key => $value ) {
if( isset( $rcp_options[$key] ) && ( $post->ID === (int) $rcp_options[$key] ) ) {
$post_states['rcp_'.$key] = $pages[$key];
}
}
return $post_states;
}
add_filter( 'display_post_states', 'rcp_display_post_states', 10, 2 );

View File

@@ -0,0 +1,141 @@
<?php
/**
* Admin Ajax Actions
*
* @package Restrict Content Pro
* @subpackage Admin/Ajax Actions
* @copyright Copyright (c) 2017, Restrict Content Pro
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
*/
use RCP\Membership_Level;
/**
* Retrieves the expiration date of a membership level
*
* @uses rcp_calculate_subscription_expiration()
*
* @return void
*/
function rcp_ajax_get_subscription_expiration() {
if ( current_user_can( 'rcp_view_members' ) ) {
if( isset( $_POST['subscription_level'] ) ) {
$level_id = absint( $_POST['subscription_level'] );
$expiration = rcp_calculate_subscription_expiration( $level_id );
echo $expiration;
}
}
die();
}
add_action( 'wp_ajax_rcp_get_subscription_expiration', 'rcp_ajax_get_subscription_expiration' );
/**
* Processes the ajax re-ordering request
*
* @return void
*/
function rcp_update_subscription_order() {
if ( current_user_can( 'rcp_view_levels' ) ) {
if( isset( $_POST['recordsArray'] ) ) {
global $wpdb, $rcp_db_name;
$subscription_levels = $_POST['recordsArray'];
$counter = 1;
foreach ( $subscription_levels as $level ) {
$new_order = $wpdb->update(
$rcp_db_name,
array('list_order' => $counter ),
array('id' => $level),
array('%d')
);
$counter++;
}
// clear the cache
delete_transient('rcp_subscription_levels');
}
}
die();
}
add_action( 'wp_ajax_update-subscription-order', 'rcp_update_subscription_order' );
/**
* Retrieves a list of users via live search
*
* @return void
*/
function rcp_search_users() {
if ( current_user_can( 'rcp_view_members' ) ) {
if( wp_verify_nonce( $_POST['rcp_nonce'], 'rcp_member_nonce' ) ) {
$search_query = trim( $_POST['user_name'] );
$return_field = ! empty( $_POST['return_field'] ) ? sanitize_text_field( $_POST['return_field'] ) : 'user_login';
$found_users = get_users( array(
'number' => 9999,
'search' => $search_query . '*'
)
);
if( $found_users ) {
$user_list = '<ul>';
foreach( $found_users as $user ) {
$user_list .= '<li><a href="#" data-login="' . esc_attr( $user->$return_field ) . '">' . esc_html( $user->$return_field ) . '</a></li>';
}
$user_list .= '</ul>';
echo json_encode( array( 'results' => $user_list, 'id' => 'found' ) );
} else {
echo json_encode( array( 'msg' => '<ul><li>' . __( 'No users found', 'rcp' ) . '</li></ul>', 'results' => 'none', 'id' => 'fail' ) );
}
}
}
die();
}
add_action( 'wp_ajax_rcp_search_users', 'rcp_search_users' );
/**
* Retrieve the initial and recurring amounts for a membership level.
*
* @since 3.0
* @return void
*/
function rcp_get_membership_billing_cycle_ajax() {
if ( current_user_can( 'rcp_view_levels' ) ) {
check_ajax_referer( 'rcp_member_nonce', 'rcp_nonce' );
$object_id = $_POST['object_id'];
if ( empty( $object_id ) ) {
wp_send_json_error();
}
$cycle = array(
'initial_amount' => 0.00,
'recurring_amount' => 0.00
);
$membership_level = rcp_get_membership_level( $object_id );
if ( ! $membership_level instanceof Membership_Level ) {
wp_send_json_error();
}
if ( $membership_level->is_free() ) {
$cycle = 'free';
} else {
$cycle['initial_amount'] = $membership_level->get_price() + $membership_level->get_fee();
$cycle['recurring_amount'] = $membership_level->is_lifetime() ? 0 : $membership_level->get_price();
}
wp_send_json_success( $cycle );
}
exit;
}
add_action( 'wp_ajax_rcp_get_membership_billing_cycle', 'rcp_get_membership_billing_cycle_ajax' );

View File

@@ -0,0 +1,485 @@
<?php
/**
* Admin Notices
*
* @package Restrict Content Pro
* @subpackage Admin/Notices
* @copyright Copyright (c) 2017, Restrict Content Pro
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
*/
/**
* Display admin notices
*
* @return void
*/
function rcp_admin_notices() {
global $rcp_options;
$message = ! empty( $_GET['rcp_message'] ) ? urldecode( $_GET['rcp_message'] ) : false;
$class = 'updated';
$text = '';
if( current_user_can( 'rcp_manage_settings' ) ) {
// only show notice if settings have never been saved
if ( ! is_array( $rcp_options ) || empty( $rcp_options ) ) {
echo '<div class="notice notice-info"><p><a href="' . admin_url( "admin.php?page=rcp-settings" ) . '">' . __( 'You should now configure your Restrict Content Pro settings', 'rcp' ) . '</a></p></div>';
}
if ( rcp_check_if_upgrade_needed() ) {
echo '<div class="error"><p>' . __( 'The Restrict Content Pro database needs to be updated: ', 'rcp' ) . ' ' . '<a href="' . esc_url( add_query_arg( 'rcp-action', 'upgrade', admin_url() ) ) . '">' . __( 'upgrade now', 'rcp' ) . '</a></p></div>';
}
if ( isset( $_GET['rcp-db'] ) && $_GET['rcp-db'] == 'updated' ) {
echo '<div class="updated fade"><p>' . __( 'The Restrict Content Pro database has been updated', 'rcp' ) . '</p></div>';
}
if ( false !== get_transient( 'rcp_login_redirect_invalid' ) ) {
echo '<div class="error"><p>' . __( 'The page selected for log in redirect does not appear to contain a log in form. Please add [login_form] to the page then re-enable the log in redirect option.', 'rcp' ) . '</p></div>';
}
if ( ( ! empty( $rcp_options['paid_message'] ) || ! empty( $rcp_options['free_message'] ) ) && empty( $rcp_options['restriction_message'] ) && ! get_user_meta( get_current_user_id(), '_rcp_content_restriction_message_missing_dismissed', true ) ) {
echo '<div class="notice notice-info">';
echo '<p>' . __( 'The Restrict Content Pro "Free Content Message" and "Premium Content Message" settings have been merged into one "Restricted Content Message" setting field. Please visit the', 'rcp' ) . ' <a href="' . esc_url( admin_url( "admin.php?page=rcp-settings" ) ) . '">' . __( 'settings page', 'rcp' ) . '</a> ' . __( 'to confirm your new message.', 'rcp' ) . '</p>';
echo '<p>' . __( 'For more information, view our version 3.0 release post on the Restrict Content Pro blog: ', 'rcp' ) . '<a href="https://restrictcontentpro.com/?p=102444#restriction-message" target="_blank">https://restrictcontentpro.com/blog</a></p>';
echo '<p><a href="' . esc_url( wp_nonce_url( add_query_arg( array( 'rcp_notice' => 'content_restriction_message_missing' ) ), 'rcp_dismiss_notice', 'rcp_dismiss_notice_nonce' ) ) . '">' . __( 'Dismiss Notice', 'rcp' ) . '</a></p>';
echo '</div>';
}
$stripe_user_id = get_option( 'rcp_stripe_connect_account_id' );
if( empty( $stripe_user_id ) && ( rcp_is_gateway_enabled( 'stripe' ) || rcp_is_gateway_enabled( 'stripe_checkout' ) ) && ! get_user_meta( get_current_user_id(), '_rcp_stripe_connect_dismissed', true ) ) {
echo '<div class="notice notice-info">';
echo '<p>' . sprintf( __( 'Restrict Content Pro now supports Stripe Connect for easier setup and improved security. <a href="%s">Click here</a> to learn more about connecting your Stripe account.', 'rcp' ), esc_url( admin_url( 'admin.php?page=rcp-settings#payments' ) ) ) . '</p>';
echo '<p><a href="' . wp_nonce_url( add_query_arg( array( 'rcp_notice' => 'stripe_connect' ) ), 'rcp_dismiss_notice', 'rcp_dismiss_notice_nonce' ) . '">' . _x( 'Dismiss Notice', 'Stripe Connect', 'rcp' ) . '</a></p>';
echo '</div>';
}
}
if( current_user_can( 'activate_plugins' ) ) {
if ( version_compare( PHP_VERSION, '5.6', '<' ) ) {
echo '<div class="error">';
echo '<p><strong>' . __( 'Restrict Content Pro is increasing its PHP version requirement', 'rcp' ) . '</strong></p>';
echo '<p>' . sprintf( __( 'Restrict Content Pro will be increasing its PHP requirement to version 5.6 or higher in version 3.0. It looks like you\'re using version %s, which means you will need to upgrade your version of PHP before upgrading to Restrict Content Pro 3.0. Newer versions of PHP are both faster and more secure. The version you\'re using <a href="%s" target="_blank">no longer receives security updates</a>, which is another great reason to update.', 'rcp' ), PHP_VERSION, 'http://php.net/eol.php' ) . '</p>';
echo '<p><strong>' . __( 'Which version should I upgrade to?', 'rcp' ) . '</strong></p>';
echo '<p>' . __( 'In order to be compatible with future versions of Restrict Content Pro, you should update your PHP version to 5.6, 7.0, 7.1, or 7.2. On a normal WordPress site, switching to PHP 5.6 should never cause issues. We would however actually recommend you switch to PHP 7.1 or higher to receive the full speed and security benefits provided to more modern and fully supported versions of PHP. However, some plugins may not be fully compatible with PHP 7+, so more testing may be required.', 'rcp' ) . '</p>';
echo '<p><strong>' . __( 'Need help upgrading? Ask your web host!', 'rcp' ) . '</strong></p>';
echo '<p>' . sprintf( __( 'Many web hosts can give you instructions on how/where to upgrade your version of PHP through their control panel, or may even be able to do it for you. If they do not want to upgrade your PHP version then we would suggest you switch hosts. All of the <a href="%s" target="_blank">WordPress hosting partners</a> support PHP 7.0 and higher.', 'rcp' ), 'https://wordpress.org/hosting/' ) . '</p>';
echo '</div>';
}
if ( function_exists( 'rcp_register_stripe_gateway' ) ) {
$deactivate_url = add_query_arg( array( 's' => 'restrict+content+pro+-+stripe' ), admin_url( 'plugins.php' ) );
echo '<div class="error"><p>' . sprintf( __( 'You are using an outdated version of the Stripe integration for Restrict Content Pro. Please <a href="%s">deactivate</a> the add-on version to configure the new version.', 'rcp' ), $deactivate_url ) . '</p></div>';
}
if ( function_exists( 'rcp_register_paypal_pro_express_gateway' ) ) {
$deactivate_url = add_query_arg( array( 's' => 'restrict+content+pro+-+paypal+pro' ), admin_url( 'plugins.php' ) );
echo '<div class="error"><p>' . sprintf( __( 'You are using an outdated version of the PayPal Pro / Express integration for Restrict Content Pro. Please <a href="%s">deactivate</a> the add-on version to configure the new version.', 'rcp' ), $deactivate_url ) . '</p></div>';
}
// Show notice about installing new Authorize.net add-on.
if ( rcp_is_gateway_enabled( 'authorizenet' ) && ! defined( 'RCP_ANET_VERSION' ) ) {
echo '<div class="error">';
echo '<p><strong>' . __( 'ACTION REQUIRED: You need to update your Authorize.net payment gateway for Restrict Content Pro' ) . '</strong></p>';
echo '<p>' . sprintf( __( 'The Authorize.net payment gateway has been removed from the main Restrict Content Pro plugin. To continue processing payments with this gateway you need to install the new Authorize.net add-on. Once installed, please follow the instructions to <a href="%s" target="_blank">enter your signature key</a> and <a href="%s" target="_blank">set up a webhook</a>.' ), 'https://docs.restrictcontentpro.com/article/1765-authorize-net#api-credentials', 'https://docs.restrictcontentpro.com/article/1765-authorize-net#webhook' ) . '</p>';
echo '<p><a href="' . esc_url( wp_nonce_url( self_admin_url( 'update.php?action=install-plugin&plugin=rcp-authorize-net' ), 'install-plugin_rcp-authorize-net' ) ) . '" class="button button-primary">' . __( 'Install', 'rcp' ) . '</a></p>';
echo '</div>';
}
// Show notice about ending support for Stripe Checkout.
if ( rcp_is_gateway_enabled( 'stripe_checkout' ) ) {
echo '<div class="error">';
echo '<p><strong>' . __( 'Restrict Content Pro: Support for Stripe Checkout is ending in version 3.2' ) . '</strong></p>';
echo '<p>' . sprintf( __( 'Stripe will not be updating the Stripe Checkout modal to comply with Strong Customer Authentication (SCA) and as a result, the Stripe Checkout gateway will be removed from Restrict Content Pro in version 3.2. You will automatically be switched over to our Stripe Elements gateway instead. This will affect the appearance of your registration form, but will not impact payment processing or renewals. <a href="%s" target="_blank">Click here to learn more.</a>' ), 'https://docs.restrictcontentpro.com/article/1552-stripe-checkout' ) . '</p>';
echo '</div>';
}
}
$screen = get_current_screen();
// Message on settings page if email sending is disabled by RCP_DISABLE_EMAILS
if( $screen->id === 'restrict_page_rcp-settings' && defined( 'RCP_DISABLE_EMAILS' ) && RCP_DISABLE_EMAILS ) {
echo '<div class="notice notice-info"><p>' . sprintf( __( 'Restrict Content Pro will not send emails because the %s constant is active. Remove it from your code to re-enable email notifications. (Emails generated by other plugins or WordPress core are not affected.)', 'rcp' ), '<code>RCP_DISABLE_EMAILS</code>' ) . '</p></div>';
}
// Payment messages.
if( current_user_can( 'rcp_manage_payments' ) ) {
switch( $message ) {
case 'payment_deleted' :
$text = __( 'Payment deleted', 'rcp' );
break;
case 'payment_added' :
$text = __( 'Payment added', 'rcp' );
break;
case 'payment_not_added' :
$text = __( 'Payment creation failed', 'rcp' );
$class = 'error';
break;
case 'payment_updated' :
$text = __( 'Payment updated', 'rcp' );
break;
case 'payment_not_updated' :
$text = __( 'Payment update failed', 'rcp' );
break;
}
}
// Upgrade messages.
if( current_user_can( 'rcp_manage_settings' ) ) {
switch( $message ) {
case 'upgrade-complete' :
$text = __( 'Database upgrade complete', 'rcp' );
break;
}
}
// Member messages.
if( current_user_can( 'rcp_manage_members' ) ) {
switch( $message ) {
case 'user_added' :
$text = __( 'The user\'s membership has been added', 'rcp' );
break;
case 'user_not_added' :
$text = __( 'The user\'s membership could not be added', 'rcp' );
$class = 'error';
break;
case 'members_updated' :
$text = __( 'Member accounts updated', 'rcp' );
break;
case 'member_cancelled' :
$text = __( 'Member\'s payment profile cancelled successfully', 'rcp' );
break;
case 'member_cancelled_error' :
$text = __( 'The member\'s payment profile could not be cancelled. Please see the member\'s user notes for details.', 'rcp' );
$class = 'error';
break;
case 'verification_sent' :
$text = __( 'Verification email sent successfully.', 'rcp' );
break;
case 'email_verified' :
$text = __( 'The user\'s email has been verified successfully', 'rcp' );
break;
}
}
// Customer messages.
if ( current_user_can( 'rcp_manage_members' ) ) {
switch ( $message ) {
case 'customer_added' :
$text = __( 'Customer added', 'rcp' );
break;
case 'user_updated' :
$text = __( 'Customer updated', 'rcp' );
break;
case 'customer_note_added' :
$text = __( 'Note added', 'rcp' );
break;
case 'customer_deleted' :
$text = __( 'Customer deleted', 'rcp' );
break;
}
}
// Membership messages.
if ( current_user_can( 'rcp_manage_members' ) ) {
switch( $message ) {
case 'membership_added' :
$text = __( 'Membership added', 'rcp' );
break;
case 'membership_updated' :
$text = __( 'Membership updated', 'rcp' );
break;
case 'membership_level_changed' :
$text = __( 'Membership level changed', 'rcp' );
break;
case 'membership_expired' :
$text = __( 'Membership has been expired. The customer no longer has access to associated content.', 'rcp' );
break;
case 'membership_cancelled' :
$text = __( 'Membership cancelled. The customer will retain access until they reach their expiration date.', 'rcp' );
break;
case 'membership_cancellation_failed' :
$text = ! empty( $_GET['rcp_cancel_failure_message'] ) ? sprintf( __( 'Membership cancellation failed: %s', 'rcp' ), esc_html( urldecode( $_GET['rcp_cancel_failure_message'] ) ) ) : __( 'Membership cancellation failed', 'rcp' );
$class = 'error';
break;
case 'membership_note_added' :
$text = __( 'Note added', 'rcp' );
break;
case 'membership_deleted' :
$text = __( 'Membership deleted', 'rcp' );
break;
}
// Extra message for auto renew toggle.
if ( ! empty( $_GET['rcp_auto_renew_toggle_error'] ) ) {
?>
<div class="notice notice-error">
<p>
<strong><?php _e( 'Failed to change auto renew settings.', 'rcp' ); ?></strong>
<?php echo esc_html( urldecode( $_GET['rcp_auto_renew_toggle_error'] ) ); ?>
</p>
</div>
<?php
}
}
// Level messages.
if( current_user_can( 'rcp_manage_levels' ) ) {
switch( $message ) {
case 'level_added' :
$text = __( 'Membership level added', 'rcp' );
break;
case 'level_updated' :
$text = __( 'Membership level updated', 'rcp' );
break;
case 'invalid_level_price' :
$text = __( 'Invalid price: the membership level price must be a valid positive number.', 'rcp' );
$class = 'error';
break;
case 'invalid_level_fee' :
$text = __( 'Invalid fee: the membership level price must be a valid positive number.', 'rcp' );
$class = 'error';
break;
case 'invalid_level_trial' :
$text = sprintf( __( 'Invalid trial: a membership level with a trial must have a price and duration greater than zero. Please see <a href="%s">the documentation article on creating trials</a> for further instructions.', 'rcp' ), 'http://docs.restrictcontentpro.com/article/1764-creating-free-trials' );
$class = 'error';
break;
case 'invalid_maximum_renewals' :
$text = __( 'Invalid Maximum Renewals: A one-time payment cannot include a payment plan.', 'rcp' );
$class = 'error';
break;
case 'level_not_added' :
$text = __( 'An unexpected error occurred while trying to add the membership level.', 'rcp' );
$class = 'error';
break;
case 'level_not_updated' :
$text = __( 'An unexpected error occurred while trying to update the membership level.', 'rcp' );
$class = 'error';
break;
case 'level_missing_fields' :
$text = __( 'Membership level fields are required', 'rcp' );
$class = 'error';
break;
case 'level_deleted' :
$text = __( 'Membership level deleted', 'rcp' );
break;
case 'level_activated' :
$text = __( 'Membership level activated', 'rcp' );
break;
case 'level_deactivated' :
$text = __( 'Membership level deactivated', 'rcp' );
break;
}
}
// Discount messages.
if( current_user_can( 'rcp_manage_discounts' ) ) {
switch ( $message ) {
case 'discount_added' :
$text = __( 'Discount code created', 'rcp' );
break;
case 'discount_not_added' :
$text = __( 'The discount code could not be created due to an error', 'rcp' );
$class = 'error';
break;
case 'discount_code_already_exists' :
if ( ! empty( $_GET['discount_code'] ) ) {
$text = sprintf( __( 'A discount with the code %s already exists.', 'rcp' ), '<code>' . esc_html( urldecode( $_GET['discount_code'] ) ) . '</code>' );
} else {
$text = __( 'A discount with this code already exists.', 'rcp' );
}
$class = 'error';
break;
case 'discount_amount_missing' :
$text = __( 'Please enter a discount amount containing numbers only.', 'rcp' );
$class = 'error';
break;
case 'discount_invalid_percent' :
$text = __( 'Percentage discounts must be whole numbers between 1 and 100.', 'rcp' );
$class = 'error';
break;
case 'discount_deleted' :
$text = __( 'Discount code successfully deleted', 'rcp' );
break;
case 'discount_activated' :
$text = __( 'Discount code activated', 'rcp' );
break;
case 'discount_deactivated' :
$text = __( 'Discount code deactivated', 'rcp' );
break;
}
}
// Post type restriction messages.
if( current_user_can( 'edit_posts' ) || current_user_can( 'edit_pages' ) ) {
switch ( $message ) {
case 'post-type-updated' :
$text = __( 'Post type restrictions updated.', 'rcp' );
break;
}
}
// Telemetry Notices.
if( current_user_can( 'rcp_manage_settings' ) ) {
switch( $message ) {
case 'opt_in_message' :
$text = __('Telemetry status changed to Opt In', 'rcp');
break;
case 'opt_out_message' :
$text = __('Telemetry status changed to Opt Out', 'rcp');
break;
}
}
// Membership reminder messages.
if( current_user_can( 'rcp_manage_settings' ) ) {
switch( $message ) {
case 'reminder_added' :
$text = __( 'Membership reminder added', 'rcp' );
break;
case 'reminder_updated' :
$text = __( 'Membership reminder updated', 'rcp' );
break;
case 'reminder_deleted' :
$text = __( 'Membership reminder deleted', 'rcp' );
break;
case 'test_reminder_sent' :
$text = __( 'Test reminder sent successfully', 'rcp' );
break;
case 'test_email_sent' :
$current_user = wp_get_current_user();
$text = sprintf( __( 'Test email sent successfully to %s', 'rcp' ), $current_user->user_email );
break;
case 'test_email_not_sent' :
$text = __( 'Test email failed to send.', 'rcp' );
$class = 'error';
break;
}
if( $message ) {
echo '<div class="' . $class . '"><p>' . $text . '</p></div>';
}
}
}
add_action( 'admin_notices', 'rcp_admin_notices' );
/**
* Dismiss an admin notice for current user
*
* @access private
* @return void
*/
function rcp_dismiss_notices() {
if( empty( $_GET['rcp_dismiss_notice_nonce'] ) || empty( $_GET['rcp_notice'] ) ) {
return;
}
if( ! wp_verify_nonce( $_GET['rcp_dismiss_notice_nonce'], 'rcp_dismiss_notice') ) {
wp_die( __( 'Security check failed', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 403 ) );
}
$notice = sanitize_key( $_GET['rcp_notice'] );
update_user_meta( get_current_user_id(), "_rcp_{$notice}_dismissed", 1 );
do_action( 'rcp_dismiss_notices', $notice );
wp_redirect( remove_query_arg( array( 'rcp_notice' ) ) );
exit;
}
add_action( 'admin_init', 'rcp_dismiss_notices' );

View File

@@ -0,0 +1,892 @@
<?php
/**
* Admin Pages
*
* @package Restrict Content Pro
* @subpackage Admin/Pages
* @copyright Copyright (c) 2017, Restrict Content Pro
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
*/
/**
* Create admin menus and sub-menus
*
* @return void
*/
function rcp_settings_menu() {
global $rcp_members_page, $rcp_customers_page, $rcp_subscriptions_page, $rcp_payments_page,
$rcp_settings_page, $rcp_export_page, $rcp_tools_page, $rcp_reminders_page, $restrict_content_pro_why_go_pro,
$restrict_content_pro_help_page, $restrict_content_pro_welcome_page, $restrict_content_pro_addons;
$restrict_content = restrict_content_pro();
// add settings page
add_menu_page( __( 'Restrict Content Pro Settings', 'rcp' ), __( 'Restrict', 'rcp' ), 'rcp_view_members', 'rcp-members', 'rcp_members_page', 'dashicons-lock' );
$rcp_members_page = add_submenu_page( 'rcp-members', __( 'Memberships', 'rcp' ), __( 'Memberships', 'rcp' ), 'rcp_view_members', 'rcp-members', 'rcp_members_page', 1 );
$rcp_customers_page = add_submenu_page( 'rcp-members', __( 'Customers', 'rcp' ), __( 'Customers', 'rcp' ), 'rcp_view_members', 'rcp-customers', 'rcp_customers_page', 2 );
$rcp_subscriptions_page = add_submenu_page( 'rcp-members', __( 'Membership Levels', 'rcp' ), __( 'Membership Levels', 'rcp' ), 'rcp_view_levels', 'rcp-member-levels', 'rcp_member_levels_page', 3 );
$rcp_payments_page = add_submenu_page( 'rcp-members', __( 'Payments', 'rcp' ), __( 'Payments', 'rcp' ), 'rcp_view_payments', 'rcp-payments', 'rcp_payments_page', 5 );
$rcp_settings_page = add_submenu_page( 'rcp-members', __( 'Restrict Content Pro Settings', 'rcp' ), __( 'Settings', 'rcp' ),'rcp_manage_settings', 'rcp-settings', 'rcp_settings_page', 7 );
$rcp_tools_page = add_submenu_page( 'rcp-members', __( 'Tools', 'rcp' ), __( 'Tools', 'rcp' ), 'rcp_manage_settings', 'rcp-tools', 'rcp_tools_page', 8 );
$rcp_reminders_page = add_submenu_page( 'rcp-members', __( 'Subscription Reminder', 'rcp' ), __( 'Subscription Reminder', 'rcp' ), 'rcp_manage_settings', 'rcp-reminder', 'rcp_subscription_reminder_page', 11 );
$restrict_content_pro_help_page = add_submenu_page( 'rcp-members', __( 'Help', 'rcp' ), __( 'Help', 'rcp' ), 'manage_options', 'rcp-need-help', 'rc_need_help_page_redesign' );
$restrict_content_pro_addons = add_submenu_page( 'rcp-members', __( 'RCP Addons', 'rcp' ), __( 'RCP Addons', 'rcp' ), 'manage_options', 'rcp-addons', 'rc_pro_addons' );
// If we are not in PRO include the Free menus.
if( false === $restrict_content->is_pro() ) {
$restrict_content_pro_why_go_pro = add_submenu_page( 'rcp-members', __( 'Why Go Pro', 'rcp' ), __( 'Why Go Pro', 'rcp' ), 'manage_options', 'rcp-why-go-pro', 'rc_why_go_pro_page_redesign' );
$restrict_content_pro_welcome_page = add_submenu_page( 'rcp-none', __( 'rcp-members', 'rcp' ), __( 'RCP Welcome', 'rcp' ), 'manage_options', 'restrict-content-welcome', 'rc_welcome_page_redesign' );
}
else {
$restrict_content_pro_welcome_page = add_submenu_page( 'rcp-none', __( 'RCP Welcome', 'rcp' ), __( 'RCP Welcome', 'rcp' ), 'manage_options', 'restrict-content-pro-welcome', 'rcp_welcome_page_redesign' );
}
// Backwards compatibility - link the old export page to the tools page.
$rcp_export_page = $rcp_tools_page;
// Remove the reminders page from the menu.
add_action( 'admin_head', 'rcp_hide_reminder_page' );
// Add "Restrict" submenu under each post type.
foreach ( rcp_get_metabox_post_types() as $post_type ) {
$post_type_details = get_post_type_object( $post_type );
$url = ( 'post' == $post_type ) ? 'edit.php' : 'edit.php?post_type=' . $post_type;
$slug = ( 'post' == $post_type ) ? 'rcp-restrict-post-type' : 'rcp-restrict-post-type-' . $post_type;
$capability = isset( $post_type_details->cap->edit_posts ) ? $post_type_details->cap->edit_posts : 'edit_posts';
add_submenu_page( $url, __( 'Restrict Access', 'rcp' ), __( 'Restrict Access', 'rcp' ), $capability, $slug, 'rcp_restrict_post_type_page' );
}
if ( get_bloginfo('version') >= 3.3 ) {
// load each of the help tabs
add_action( "load-$rcp_members_page", "rcp_help_tabs" );
add_action( "load-$rcp_customers_page", "rcp_help_tabs" );
add_action( "load-$rcp_subscriptions_page", "rcp_help_tabs" );
add_action( "load-$rcp_settings_page", "rcp_help_tabs" );
}
add_action( "load-$rcp_members_page", "rcp_screen_options" );
add_action( "load-$rcp_customers_page", "rcp_screen_options" );
add_action( "load-$rcp_subscriptions_page", "rcp_screen_options" );
add_action( "load-$rcp_payments_page", "rcp_screen_options" );
add_action( "load-$rcp_settings_page", "rcp_screen_options" );
add_action( "load-$rcp_tools_page", "rcp_screen_options" );
}
add_action( 'admin_menu', 'rcp_settings_menu', 10, 2 );
/**
* Determines whether or not the current page is an RCP admin page.
*
* @since 3.3.7
* @return bool
*/
function rcp_is_rcp_admin_page() {
$screen = get_current_screen();
global $rcp_members_page, $rcp_customers_page, $rcp_subscriptions_page, $rcp_discounts_page, $rcp_payments_page, $rcp_reports_page, $rcp_settings_page, $rcp_help_page, $rcp_tools_page, $restrict_content_pro_welcome_page, $restrict_content_pro_help_page, $restrict_content_pro_addons;
$pages = array( $rcp_members_page, $rcp_customers_page, $rcp_subscriptions_page, $rcp_discounts_page, $rcp_payments_page, $rcp_reports_page, $rcp_settings_page, $rcp_tools_page, $rcp_help_page, $restrict_content_pro_welcome_page, $restrict_content_pro_help_page, $restrict_content_pro_addons );
// Include post types that support restrictions.
if ( 'post' === $screen->base && ! empty( $screen->post_type ) && in_array( $screen->post_type, rcp_get_metabox_post_types() ) ) {
$pages[] = $screen->id;
}
if( false !== strpos( $screen->id, 'rcp-restrict-post-type' ) ) {
$pages[] = $screen->id;
}
$is_admin = in_array( $screen->id, $pages );
/**
* Filters whether or not the current page is an RCP admin page.
*
* @param bool $is_admin
* @param WP_Screen $screen
*
* @since 3.3.7
*/
return apply_filters( 'rcp_is_rcp_admin_page', $is_admin, $screen );
}
/**
* Returns the URL to the memberships page.
*
* @param array $args Query args to add.
*
* @since 3.0
* @return string
*/
function rcp_get_memberships_admin_page( $args = array() ) {
$args = wp_parse_args( $args, array(
'page' => 'rcp-members'
) );
$sanitized_args = array();
foreach ($args as $key => $value) {
$sanitized_key = urlencode( $key );
$sanitized_value = urlencode( $value );
$sanitized_args[ $sanitized_key ] = $sanitized_value;
}
$memberships_page = add_query_arg( $sanitized_args, admin_url( 'admin.php' ) );
return $memberships_page;
}
/**
* Returns the URL to the customers page.
*
* @param array $args Query args to add.
*
* @since 3.0
* @return string
*/
function rcp_get_customers_admin_page( $args = array() ) {
$args = wp_parse_args( $args, array(
'page' => 'rcp-customers'
) );
$customers_page = add_query_arg( $args, admin_url( 'admin.php' ) );
return $customers_page;
}
/**
* Displays the must used add-ons used by RCP.
*
* @return void
*/
function rc_pro_addons() {
do_action( 'stellarwp/telemetry/restrict-content-pro/optin' );
do_action( 'stellarwp/telemetry/restrict-content/optin' );
$restrict_content = restrict_content_pro();
$hidegrid = "";
if ( $restrict_content->is_pro() ) {
$hidegrid = "hide-grid";
}
?>
<div class="restrict-content-welcome-header">
<img class="restrict-content-logo" src="<?php echo esc_url( RCP_PLUGIN_URL . 'core/includes/images/rc_logo_horizontal_black.svg' ); ?>" >
</div>
<div class="restrict-content-addons-top-container <?php echo $hidegrid; ?>">
<div class="restrict-content-addons-left-container">
<h1 class="restrict-content-addons-user"><?php _e( 'Pro Add-ons', 'rcp' ); ?></h1>
<p>
<?php
printf(
__('Below are just a few of our <a href="%s">pro-only addons.</a> ', 'rcp' ),
'https://restrictcontentpro.com/add-ons/pro/'
);
?>
</p>
<div class="addons-flex-container">
<div class="addon-card">
<div class="addon-card-header">
<img src="<?php echo esc_url( RCP_PLUGIN_URL . 'core/includes/images/WooCommerce-addon.png' ); ?>" >
</div>
<div class="addon-card-body">
<h2 class="addon-card-title">WooCommerce Member Discounts</h2>
<p class="addon-card-text">Give members automatic discounts on purchases in your WooCommerce store.</p>
<?php
printf(
__('<a class="addon-card-cta" href="%s" target="_blank">Learn More</a>', 'rcp' ),
'https://restrictcontentpro.com/add-on/woocommerce-member-discounts/'
);
?>
</div>
</div>
<div class="addon-card">
<div class="addon-card-header">
<img src="<?php echo esc_url( RCP_PLUGIN_URL . 'core/includes/images/Per-Level-Email-addon.png' ); ?>" >
</div>
<div class="addon-card-body">
<h2 class="addon-card-title">Per-Level Emails</h2>
<p class="addon-card-text">Restrict Content Pro allows you to set up notification email templates, but the contents are the same for each membership.</p>
<?php
printf(
__('<a class="addon-card-cta" href="%s" target="_blank">Learn More</a>', 'rcp' ),
'https://restrictcontentpro.com/add-on/per-level-emails/'
);
?>
</div>
</div>
<div class="addon-card">
<div class="addon-card-header">
<img src="<?php echo esc_url( RCP_PLUGIN_URL . 'core/includes/images/drip-content-addon.png' ); ?>" >
</div>
<div class="addon-card-body">
<h2 class="addon-card-title">Drip Content</h2>
<p class="addon-card-text">Schedule the release of member content.</p>
<?php
printf(
__('<a class="addon-card-cta" href="%s" target="_blank">Learn More</a>', 'rcp' ),
'https://restrictcontentpro.com/add-on/drip-content/'
);
?>
</div>
</div>
<div class="addon-card">
<div class="addon-card-header">
<img src="<?php echo esc_url( RCP_PLUGIN_URL . 'core/includes/images/Ultimate-Member-addon.png' ); ?>" >
</div>
<div class="addon-card-body">
<h2 class="addon-card-title">Ultimate Member Integration</h2>
<p class="addon-card-text">Seamlessly integrates RCP's powerful subscriptions functionality with the advanced member management provided by Ultimate Member.</p>
<?php
printf(
__('<a class="addon-card-cta" href="%s" target="_blank">Learn More</a>', 'rcp' ),
'https://restrictcontentpro.com/add-on/ultimate-member-integration/'
);
?>
</div>
</div>
<div class="addon-card">
<div class="addon-card-header">
<img src="<?php echo esc_url( RCP_PLUGIN_URL . 'core/includes/images/Download-Monitor-addon.png' ); ?>" >
</div>
<div class="addon-card-body">
<h2 class="addon-card-title">Download Monitor</h2>
<p class="addon-card-text">Protect file downloads.</p>
<?php
printf(
__('<a class="addon-card-cta" href="%s" target="_blank">Learn More</a>', 'rcp' ),
'https://restrictcontentpro.com/add-on/download-monitor/'
);
?>
</div>
</div>
<div class="addon-card">
<div class="addon-card-header">
<img src="<?php echo esc_url( RCP_PLUGIN_URL . 'core/includes/images/BuddyPress-addon.png' ); ?>" >
</div>
<div class="addon-card-body">
<h2 class="addon-card-title">BuddyPress Integration</h2>
<p class="addon-card-text">Make your community profitable.</p>
<?php
printf(
__('<a class="addon-card-cta" href="%s" target="_blank">Learn More</a>', 'rcp' ),
'https://restrictcontentpro.com/add-on/buddypress-integration/'
);
?>
</div>
</div>
<div class="addon-card">
<div class="addon-card-header">
<img src="<?php echo esc_url( RCP_PLUGIN_URL . 'core/includes/images/Group-Account-addon.png' ); ?>" >
</div>
<div class="addon-card-body">
<h2 class="addon-card-title">Group Accounts</h2>
<p class="addon-card-text">Sell multi-member group memberships through Restrict Content Pro.</p>
<?php
printf(
__('<a class="addon-card-cta" href="%s" target="_blank">Learn More</a>', 'rcp' ),
'https://restrictcontentpro.com/add-on/group-accounts/'
);
?>
</div>
</div>
</div>
<div class="addons-cta"><a href="https://restrictcontentpro.com/add-ons/pro/" target="_blank">View all Pro add-ons</a></div>
</div>
<div class="restrict-content-welcome-right-container">
<?php
$restrict_content = restrict_content_pro();
if ( ! $restrict_content->is_pro() ) {
?>
<div class="restrict-content-welcome-advertisement">
<div class="logo">
<img class="restrict-content-welcome-advertisement-logo" src="<?php echo esc_url( RCP_PLUGIN_URL . 'core/includes/images/Stacked_Logo_V2.svg' ); ?>" >
</div>
<div class="restrict-content-welcome-try-for-free">
<p><?php _e( 'Try For Free!', 'rcp' ); ?></p>
</div>
<div class="restrict-content-welcome-advertisement-content">
<p><?php _e( 'Lock away your exclusive content. Give access to valued members.', 'rcp' ); ?></p>
<p class="rcp-highlight"><?php _e( 'A Full-Featured Powerful Membership Solution for WordPress.', 'rcp' ); ?></p>
<p><?php _e( 'Give Restrict Content Pro a spin, along with the full suite of add-ons. Enter your email and well automatically send you a link to a personal WordPress demo site, no strings attached!', 'rcp' ); ?></p>
</div>
<div class="restrict-content-welcome-advertisement-form">
<form action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>" method="post" id="restrict_content_try_free">
<input type="hidden" name="action" value="restrict_content_try_free">
<input type="hidden" name="rc_welcome_try_free_meta_nonce" value="<?php echo wp_create_nonce( 'rc_welcome_try_free_meta_nonce' ); ?>" >
<input type="hidden" name="source_page" value="help_page">
<input type="email" name="try_email_address" id="try_email_address" placeholder="Email Address">
<input type="submit" class="restrict-content-welcome-button" value="<?php _e( 'Try Now, Free!', 'rcp' ); ?>">
</form>
</div>
</div>
<div class="restrict-content-unlock-premium-features">
<h3><?php _e( 'Unlock Premium Features', 'rcp' ); ?></h3>
<p><?php _e( 'Go beyond the basics with premium features & support.', 'rcp' ); ?></p>
<div class="tabs">
<div class="tablist" role="tablist" aria-label="<?php esc_attr_e( 'Pricing Plans', 'rcp' ); ?>">
<button role="tab" aria-selected="true" aria-controls="1sitetab" id="1site">
<?php _e( '1 Site', 'rcp' ); ?>
</button>
<button role="tab" aria-selected="false" aria-controls="10sitetab" id="10site" tabindex="-1">
<?php _e( '10 Sites', 'rcp' ); ?>
</button>
<button role="tab" aria-selected="false" aria-controls="unlimitedtab" id="unlimited" tabindex="-1">
<?php _e( 'Unlimited', 'rcp' ); ?>
</button>
</div>
<div class="tabpanel" tabindex="0" role="tabpanel" id="1sitetab" aria-labelledby="1site">
<h4><?php _e( '$99', 'rcp' ); ?></h4>
<p><?php _e( 'Includes updates & support for one year.', 'rcp' ); ?></p>
</div>
<div class="tabpanel" tabindex="0" role="tabpanel" id="10sitetab" aria-labelledby="10site" hidden="">
<h4><?php _e( '$149', 'rcp' ); ?></h4>
<p><?php _e( 'Includes updates & support for one year.', 'rcp' ); ?></p>
</div>
<div class="tabpanel" tabindex="0" role="tabpanel" id="unlimitedtab" aria-labelledby="unlimited" hidden="">
<h4><?php _e( '$249', 'rcp' ); ?></h4>
<p><?php _e( 'Includes updates & support for one year.', 'rcp' ); ?></p>
</div>
</div>
<a href="https://restrictcontentpro.com/pricing/" class="go-pro-now"><?php _e( 'Go Pro Now', 'rcp' ); ?></a>
<p class="whats-included"><a href="https://restrictcontentpro.com/why-go-pro/"><?php _e( "What's included with Pro?", 'rcp' ); ?></a></p>
</div>
<?php } ?>
</div>
</div>
<?php
}
function rc_why_go_pro_page_redesign() {
do_action( 'stellarwp/telemetry/restrict-content-pro/optin' );
do_action( 'stellarwp/telemetry/restrict-content/optin' );
?>
<div class="wrap">
<div class="rcp-why-go-pro-wrap">
<img class="restrict-content-logo" src="<?php echo esc_url( RCP_PLUGIN_URL . 'core/includes/images/rc_logo_horizontal_black.svg' ); ?>" >
<div class="rcp-go-pro-color-container">
<div class="rcp-why-go-pro-inner-wrapper">
<div class="rcp-top-header">
<h1>
<?php _e( 'Why Go Pro?', 'rcp' ); ?></h1>
</div>
<h2><?php _e( 'Grow Your Sales with Premium Features and Add-ons in Restrict Content PRO', 'rcp' ); ?></h2>
<div class="rcp-pro-features-container">
<!-- LIMIT NUMBER OF CONNECTIONS FEATURE -->
<a href="https://restrictcontentpro.com/pricing/">
<div class="rcp-limit-number-of-connections feature">
<img src="<?php echo esc_url( RCP_PLUGIN_URL . 'core/includes/images/memb-levels.svg' ); ?>" >
<div class="feature-text">
<h3><?php _e( 'Limit Number of Connections', 'rcp' ); ?></h3>
<p><?php _e( 'Prevent password sharing by limiting the number of simultaneous connections for each member.', 'rcp' ); ?></p>
</div>
</div>
</a>
<!-- REMOVE STRIPE FEE FEATURE -->
<a href="https://restrictcontentpro.com/pricing">
<div class="rcp-remove-stripe-fee feature">
<img src="<?php echo esc_url( RCP_PLUGIN_URL . 'core/includes/images/collect-payments.svg' ); ?>" >
<div class="feature-text">
<h3><?php _e( 'Remove Stripe Fee', 'rcp' ); ?></h3>
<p><?php _e( "Remove the 2% fee for processing Stripe payments by upgrading to Restrict Content Pro.", 'rcp' ); ?></p>
</div>
</div>
</a>
<!-- PRO EMAILS FEATURE -->
<a href="https://restrictcontentpro.com/tour/features/member-emails/">
<div class="rcp-pro-emails feature">
<img src="<?php echo esc_url( RCP_PLUGIN_URL . 'core/includes/images/customer-dash.svg' ); ?>" >
<div class="feature-text">
<h3><?php _e( 'Pro Emails', 'rcp' ); ?></h3>
<p><?php _e( 'Unlock email personalization and automatically member expiration & renewal email reminders.', 'rcp' ); ?></p>
</div>
</div>
</a>
<!-- MARKETING INTEGRATION FEATURE -->
<a href="https://restrictcontentpro.com/add-ons/pro/">
<div class="rcp-marketing-integration feature">
<img src="<?php echo esc_url( RCP_PLUGIN_URL . 'core/includes/images/mkt-integration.svg' ); ?>" >
<div class="feature-text">
<h3><?php _e( 'Marketing Integration', 'rcp' ); ?></h3>
<p><?php _e( 'Subscribe members to your Mailchimp, AWeber, ConvertKit, etc., mailing lists.', 'rcp' ); ?></p>
</div>
</div>
</a>
<!-- GROUP ACCOUNTS FEATURE -->
<a href="https://restrictcontentpro.com/downloads/group-accounts/">
<div class="rcp-group-accounts feature">
<img src="<?php echo esc_url( RCP_PLUGIN_URL . 'core/includes/images/group-acct.svg' ); ?>" >
<div class="feature-text">
<h3><?php _e( 'Group Accounts', 'rcp' ); ?></h3>
<p><?php _e( 'Sell enterprise or group memberships with multiple sub accounts.', 'rcp' ); ?></p>
</div>
</div>
</a>
<!-- DRIP CONTENT FEATURE -->
<a href="https://restrictcontentpro.com/downloads/drip-content/">
<div class="rcp-drip-content feature">
<img src="<?php echo esc_url( RCP_PLUGIN_URL . 'core/includes/images/drip-content.svg' ); ?>" >
<div class="feature-text">
<h3><?php _e( 'Drip Content', 'rcp' ); ?></h3>
<p><?php _e( 'Time-release content to new members based on their start date.', 'rcp' ); ?></p>
</div>
</div>
</a>
<!-- OFFER DISCOUNTS FEATURE -->
<a href="https://restrictcontentpro.com/tour/features/discount-codes/">
<div class="rcp-offer-discounts feature">
<img src="<?php echo esc_url( RCP_PLUGIN_URL . 'core/includes/images/offer-discounts.svg' ); ?>" >
<div class="feature-text">
<h3><?php _e( 'Offer Discounts', 'rcp' ); ?></h3>
<p><?php _e( 'Attract new customers with special promotional codes that give them a discount on the purchase of a membership.', 'rcp' ); ?></p>
</div>
</div>
</a>
<!-- RESTRICT PAST CONTENT FEATURE -->
<a href="https://restrictcontentpro.com/downloads/restrict-past-content/">
<div class="rcp-restrict-past-content feature">
<img src="<?php echo esc_url( RCP_PLUGIN_URL . 'core/includes/images/restrict-content.svg' ); ?>" >
<div class="feature-text">
<h3><?php _e( 'Restrict Past Content', 'rcp' ); ?></h3>
<p><?php _e( "Restrict content published before a member's join date.", 'rcp' ); ?></p>
</div>
</div>
</a>
<!-- PREMIUM SUPPORT FEATURE -->
<div class="rcp-premium-support feature">
<img src="<?php echo esc_url( RCP_PLUGIN_URL . 'core/includes/images/premium-support.svg' ); ?>" >
<div class="feature-text">
<h3><?php _e( 'Premium Support', 'rcp' ); ?></h3>
<p><?php _e( 'Get help from our team of membership experts.', 'rcp' ); ?></p>
</div>
</div>
</div>
<div class="rcp-why-go-pro-buttons-container">
<a class="try-before-you-buy" href="https://restrictcontentpro.com/demo/">
<?php _e( 'Try Before You Buy', 'rcp' ); ?>
</a>
<a class="rcp-unlock-pro-features-add-ons" href="https://restrictcontentpro.com/pricing/">
<?php _e( 'Unlock Pro Features & Add-Ons', 'rcp' ); ?>
</a>
</div>
</div>
</div>
</div>
</div>
<?php
}
function rc_need_help_page_redesign() {
do_action( 'stellarwp/telemetry/restrict-content-pro/optin' );
do_action( 'stellarwp/telemetry/restrict-content/optin' );
?>
<div class="restrict-content-welcome-header">
<img class="restrict-content-logo" src="<?php echo esc_url( RCP_PLUGIN_URL . 'core/includes/images/rc_logo_horizontal_black.svg' ); ?>" >
</div>
<div class="restrict-content-welcome-top-container">
<div class="restrict-content-welcome-left-container">
<h1 class="restrict-content-welcome-user"><?php _e( 'Need Help?', 'rcp' ); ?></h1>
<p>
<?php
printf(
__('Are you new to Restrict Content? Check out the Getting Started with <a href="%s">Restrict Content guide.</a>', 'rcp' ),
'https://help.ithemes.com/hc/en-us/sections/360008799334-Getting-Started'
);
?>
</p>
<div class="restrict-content-inner-container">
<a class="restrict-content-section-link" href="https://restrictcontentpro.com/knowledgebase" target="_blank">
<div class="restrict-content-help-section">
<div class="restrict-content-help-section-icon">
<div id="restrict-content-help-center" class="restrict-content-help-section-trouble-shooting-image"></div>
</div>
<div class="restrict-content-help-section-content">
<h3><?php _e( 'Help Center', 'rcp' ); ?></h3>
<p><?php _e( 'Our Help Center is filled with articles to help you learn more about using Restrict Content and Restrict Content Pro.', 'rcp' ); ?></p>
</div>
<img class="restrict-content-help-section-arrow hidden" style="display: none;" src="<?php echo esc_url( RCP_PLUGIN_URL . 'core/includes/images/purple-arrow-right.svg' ); ?>" >
</div>
</a>
<a class="restrict-content-section-link" href="https://restrictcontentpro.com/knowledgebase/testing-for-conflicts-with-themes-and-other-plugins/" target="_blank">
<div id="restrict-content-troubleshooting-link" class="restrict-content-help-section">
<div class="restrict-content-help-section-icon">
<div id="restrict-content-trouble-shooting" class="restrict-content-help-section-trouble-shooting-image"></div>
</div>
<div class="restrict-content-help-section-content">
<h3><?php _e( 'Troubleshooting', 'rcp' ); ?></h3>
<p><?php _e( 'If you run into any errors or things arent working as expected, the first step in troubleshooting is to check for a plugin or theme conflict.', 'rcp' ); ?></p>
</div>
<img class="restrict-content-help-section-arrow hidden" style="display: none;" src="<?php echo esc_url( RCP_PLUGIN_URL . 'core/includes/images/purple-arrow-right.svg' ); ?>" >
</div>
</a>
<?php if( false === has_action('admin_menu','include_pro_pages') ) { ?>
<a class="restrict-content-section-link" href="https://wordpress.org/support/plugin/restrict-content/" target="_blank">
<div id="restrict-content-support-link" class="restrict-content-help-section">
<div class="restrict-content-help-section-icon">
<div id="restrict-content-support-forum" class="restrict-content-help-section-trouble-shooting-image"></div>
</div>
<div class="restrict-content-help-section-content">
<h3><?php _e( 'Support Forum', 'rcp' ); ?></h3>
<p><?php _e( 'If you are still having trouble after checking for a conflict, feel free to start a new thread on the Restrict Content support forum.', 'rcp' ); ?></p>
</div>
<img class="restrict-content-help-section-arrow hidden" style="display:none;" src="<?php echo esc_url( RCP_PLUGIN_URL . 'core/includes/images/purple-arrow-right.svg' ); ?>" >
</div>
</a>
<?php } else { ?>
<a class="restrict-content-section-link" href="https://restrictcontentpro.com/support/" target="_blank">
<div id="restrict-content-support-link" class="restrict-content-help-section">
<div class="restrict-content-help-section-icon">
<div id="restrict-content-support-forum" class="restrict-content-help-section-trouble-shooting-image"></div>
</div>
<div class="restrict-content-help-section-content">
<h3><?php _e( 'Submit Support Ticket', 'rcp' ); ?></h3>
<p><?php _e( 'If you are still having trouble after checking for a conflict, feel free to start a new thread on the Restrict Content support forum.', 'rcp' ); ?></p>
</div>
<img class="restrict-content-help-section-arrow hidden" style="display:none;" src="<?php echo esc_url( RCP_PLUGIN_URL . 'core/includes/images/purple-arrow-right.svg' ); ?>" >
</div>
</a>
<?php } ?>
<?php if( false === has_action('admin_menu','include_pro_pages') ) { ?>
<div class="restrict-content-premium-support">
<div class="premium-support-content">
<h3><?php _e( 'Get Premium Support', 'rcp' ); ?></h3>
<p>
<?php
printf(
__( 'Purchase any <a href="%s">Restrict Content Pro subscription</a> and get access to our ticketed support system. Our team of experts is ready to help!', 'rcp' ),
'https://restrictcontentpro.com/pricing/'
);
?>
</p>
</div>
</div>
<?php } ?>
</div>
</div>
<div class="restrict-content-welcome-right-container">
<div class="restrict-content-welcome-advertisement">
<div class="logo">
<img class="restrict-content-welcome-advertisement-logo" src="<?php echo esc_url( RCP_PLUGIN_URL . 'core/includes/images/Stacked_Logo_V2.svg' ); ?>" >
</div>
<div class="restrict-content-welcome-try-for-free">
<p><?php _e( 'Try For Free!', 'rcp' ); ?></p>
</div>
<div class="restrict-content-welcome-advertisement-content">
<p><?php _e( 'Lock away your exclusive content. Give access to valued members.', 'rcp' ); ?></p>
<p class="rcp-highlight"><?php _e( 'A Full-Featured Powerful Membership Solution for WordPress.', 'rcp' ); ?></p>
<p><?php _e( 'Give Restrict Content Pro a spin, along with the full suite of add-ons. Enter your email and well automatically send you a link to a personal WordPress demo site, no strings attached!', 'rcp' ); ?></p>
</div>
<div class="restrict-content-welcome-advertisement-form">
<form action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>" method="post" id="restrict_content_try_free">
<input type="hidden" name="action" value="restrict_content_try_free">
<input type="hidden" name="rc_welcome_try_free_meta_nonce" value="<?php echo wp_create_nonce( 'rc_welcome_try_free_meta_nonce' ); ?>" >
<input type="hidden" name="source_page" value="help_page">
<input type="email" name="try_email_address" id="try_email_address" placeholder="Email Address">
<input type="submit" class="restrict-content-welcome-button" value="<?php _e( 'Try Now, Free!', 'rcp' ); ?>">
</form>
</div>
</div>
<div class="restrict-content-unlock-premium-features">
<h3><?php _e( 'Unlock Premium Features', 'rcp' ); ?></h3>
<p><?php _e( 'Go beyond the basics with premium features & support.', 'rcp' ); ?></p>
<div class="tabs">
<div class="tablist" role="tablist" aria-label="<?php esc_attr_e( 'Pricing Plans', 'rcp' ); ?>">
<button role="tab" aria-selected="true" aria-controls="1sitetab" id="1site">
<?php _e( '1 Site', 'rcp' ); ?>
</button>
<button role="tab" aria-selected="false" aria-controls="10sitetab" id="10site" tabindex="-1">
<?php _e( '10 Sites', 'rcp' ); ?>
</button>
<button role="tab" aria-selected="false" aria-controls="unlimitedtab" id="unlimited" tabindex="-1">
<?php _e( 'Unlimited', 'rcp' ); ?>
</button>
</div>
<div class="tabpanel" tabindex="0" role="tabpanel" id="1sitetab" aria-labelledby="1site">
<h4><?php _e( '$99', 'rcp' ); ?></h4>
<p><?php _e( 'Includes updates & support for one year.', 'rcp' ); ?></p>
</div>
<div class="tabpanel" tabindex="0" role="tabpanel" id="10sitetab" aria-labelledby="10site" hidden="">
<h4><?php _e( '$149', 'rcp' ); ?></h4>
<p><?php _e( 'Includes updates & support for one year.', 'rcp' ); ?></p>
</div>
<div class="tabpanel" tabindex="0" role="tabpanel" id="unlimitedtab" aria-labelledby="unlimited" hidden="">
<h4><?php _e( '$249', 'rcp' ); ?></h4>
<p><?php _e( 'Includes updates & support for one year.', 'rcp' ); ?></p>
</div>
</div>
<a href="https://restrictcontentpro.com/pricing/" class="go-pro-now"><?php _e( 'Go Pro Now', 'rcp' ); ?></a>
<p class="whats-included"><a href="https://restrictcontentpro.com/why-go-pro/"><?php _e( "What's included with Pro?", 'rcp' ); ?></a></p>
</div>
</div>
</div>
<?php
}
/**
* Build out the Welcome page for Restrict Content 3.0 and Restrict Content Pro
*
* @since 3.6
*/
function rcp_welcome_page_redesign() {
$current_user = wp_get_current_user();
do_action( 'stellarwp/telemetry/restrict-content-pro/optin' );
// $rc_welcome_try_free_meta_nonce = wp_create_nonce( 'rc_welcome_try_free_meta_nonce' );
?>
<div class="restrict-content-welcome-header">
<img class="restrict-content-logo" src="<?php echo esc_url( RCP_PLUGIN_URL . 'core/includes/images/Full-Logo-1.svg' ); ?>" >
</div>
<div class="restrict-content-welcome-top-container">
<div class="restrict-content-welcome-left-container">
<h1 class="restrict-content-welcome-user">
<?php
printf( __( 'Welcome %s!', 'rcp' ),
$current_user->first_name ?: $current_user->display_name
);
?>
</h1>
<div class="restrict-content-inner-container">
<div class="restrict-content-welcome-body-container">
<div class="restrict-content-welcome-body restrict-content-container-section">
<h2 class="restrict-content-thanks-header"><?php _e( 'Thanks for installing Restrict Content Pro!', 'rcp' ); ?></h2>
<p class="restrict-content-thanks-message"><?php _e( 'Restrict Content Pro is a simple, yet powerful WordPress membership plugin that gives you full control over who can and cannot view content on your WordPress site.', 'rcp' ); ?></p>
<p class="restrict-content-thanks-message"><?php _e( 'Start your membership site and create multiple Membership Levels and collect payments with Stripe, PayPal, Braintree or Authorize.net.', 'rcp' ); ?></p>
</div>
</div>
<div class="restrict-content-welcome-body-container">
<div class="restrict-content-how-to-body restrict-content-container-section">
<h2><?php _e( 'Collect Payments with Stripe, PayPal, Braintree or Authorize.net', 'rcp' ); ?></h2>
<p class="restrict-content-how-to-message">
<?php
printf(
__( 'With Pro you can use several popular payment gateways to collect payments. We even have an <a href="%s" target="_blank">API</a> that you can use to integrate RCP with additional payment gateways. ', 'rcp' ),
'https://help.ithemes.com/hc/en-us/articles/360052351054-Payment-Gateway-API'
);
?>
</p>
</div>
</div>
<div class="restrict-content-welcome-body-container">
<div class="restrict-content-helpful-resources restrict-content-container-section">
<h2><?php _e( 'Helpful Resources', 'rcp' ); ?></h2>
<div class="restrict-content-resource-container">
<!-- <h3><?php _e( 'Knowledgebase', 'rcp' ); ?></h3> -->
<p>
<?php
printf(
__( 'Our <a href="%s">Knowledgebase</a> will help you become a Restrict Content & Restrict Content Pro expert.', 'rcp' ),
'https://restrictcontentpro.com/knowledgebase'
);
?>
</p>
</div>
<div class="restrict-content-resource-container">
<!-- <h3><?php _e( 'Need More Control Over Your Content & Memberships?', 'rcp' ); ?></h3> -->
<p>
<?php
printf(
__( 'Check out our <a href="%s">suite of add-ons</a> for building awesome membership websites.', 'rcp' ),
'https://restrictcontentpro.com/add-ons/'
);
?>
</p>
</div>
<div class="restrict-content-resource-container">
<!-- <h3><?php _e( 'Introduction to Restrict Content Pro', 'rcp' ); ?></h3> -->
<p>
<?php
printf(
__( 'Get a <a href="%s">full overview of Restrict Content Pro</a> and dive into several of its key features.', 'rcp' ),
'https://training.ithemes.com/webinar/introduction-to-restrict-content-pro/'
);
?>
</p>
</div>
</div>
</div>
</div>
</div>
</div>
<?php
}
function rc_welcome_page_redesign() {
$current_user = wp_get_current_user();
$rc_welcome_try_free_meta_nonce = wp_create_nonce( 'rc_welcome_try_free_meta_nonce' );
?>
<div class="restrict-content-welcome-header">
<img class="restrict-content-logo" src="<?php echo esc_url( RCP_PLUGIN_URL . 'core/includes/images/rc_logo_horizontal_black.svg' ); ?>" >
</div>
<div class="restrict-content-welcome-top-container">
<div class="restrict-content-welcome-left-container">
<h1 class="restrict-content-welcome-user">
<?php
printf( __( 'Welcome %s!', 'rcp' ),
$current_user->first_name ?: $current_user->display_name
);
?>
</h1>
<div class="restrict-content-inner-container">
<div class="restrict-content-welcome-body-container">
<div class="restrict-content-welcome-body restrict-content-container-section">
<h2 class="restrict-content-thanks-header"><?php _e( 'Thanks For Installing Restrict Content!', 'rcp' ); ?></h2>
<p class="restrict-content-thanks-message"><?php _e( 'Restrict Content is a simple WordPress membership plugin that gives you full control over who can and cannot view content on your WordPress site.', 'rcp' ); ?></p>
<p class="restrict-content-thanks-message"><?php _e( 'Start your membership site and create multiple Membership Levels and collect payments with Stripe.', 'rcp' ); ?></p>
</div>
</div>
<div class="restrict-content-welcome-body-container">
<div class="restrict-content-how-to-body restrict-content-container-section">
<h2><?php _e( 'Collect Payments with Stripe', 'rcp' ); ?></h2>
<p class="restrict-content-how-to-message"><?php _e( "Install the free Restrict Content Stripe add-on to start accepting credit and debit card payments.", 'rcp' ); ?></p>
<p class="restrict-content-how-to-message"><?php _e( 'Stripe is an excellent payment gateway with a simple setup process and exceptional reliability.', 'rcp' ); ?></p>
<p class="restrict-content-how-to-message"><?php _e( "Placeholder text for Stripe add-on sign-up link.", 'rcp' ); ?></p>
</div>
</div>
<div class="restrict-content-welcome-body-container">
<div class="restrict-content-helpful-resources restrict-content-container-section">
<h2><?php _e( 'Helpful Resources', 'rcp' ); ?></h2>
<div class="restrict-content-resource-container">
<h3><?php _e( 'Help Center', 'rcp' ); ?></h3>
<p>
<?php
printf(
__( 'Our <a href="%s">Help Center</a> will help you become a Restrict Content & Restrict Content Pro expert.', 'rcp' ),
'https://help.ithemes.com'
);
?>
</p>
</div>
<div class="restrict-content-resource-container">
<h3><?php _e( 'Need More Control Over Your Content & Memberships?', 'rcp' ); ?></h3>
<p>
<?php
printf(
__( 'Check out Restrict Content Pro and our <a href="%s">suite of add-ons</a> for building awesome membership websites.', 'rcp' ),
'https://restrictcontentpro.com/add-ons/'
);
?>
</p>
</div>
<div class="restrict-content-resource-container">
<h3><?php _e( 'Introduction to Restrict Content Pro', 'rcp' ); ?></h3>
<p>
<?php
printf(
__( 'Get a <a href="%s">full overview of Restrict Content Pro</a> and dive into several of its key features.', 'rcp' ),
'https://training.ithemes.com/webinar/introduction-to-restrict-content-pro/'
);
?>
</p>
</div>
</div>
</div>
</div>
</div>
<div class="restrict-content-welcome-right-container">
<div class="restrict-content-welcome-advertisement">
<div class="logo">
<img class="restrict-content-welcome-advertisement-logo" src="<?php echo esc_url( RCP_PLUGIN_URL . 'core/includes/images/Stacked_Logo_V2.svg' ); ?>" >
</div>
<div class="restrict-content-welcome-try-for-free">
<p><?php _e( 'Try For Free!', 'rcp' ); ?></p>
</div>
<div class="restrict-content-welcome-advertisement-content">
<p><?php _e( 'Lock away your exclusive content. Give access to valued members.', 'rcp' ); ?></p>
<p class="rcp-highlight"><?php _e( 'A Full-Featured Powerful Membership Solution for WordPress.', 'rcp' ); ?></p>
<p><?php _e( 'Give Restrict Content Pro a spin, along with the full suite of add-ons. Enter your email and well automatically send you a link to a personal WordPress demo site, no strings attached!', 'rcp' ); ?></p>
</div>
<div class="restrict-content-welcome-advertisement-form">
<form action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>" method="post" id="restrict_content_try_free">
<input type="hidden" name="action" value="restrict_content_try_free">
<input type="hidden" name="rc_welcome_try_free_meta_nonce" value="<?php echo $rc_welcome_try_free_meta_nonce; ?>" >
<input type="hidden" name="source_page" value="welcome_page">
<input type="email" name="try_email_address" id="try_email_address" placeholder="Email Address">
<input type="submit" class="restrict-content-welcome-button" value="<?php _e( 'Try Now, Free!', 'rcp' ); ?>">
</form>
</div>
</div>
</div>
</div>
<?php
}
function restrict_content_admin_try_free_success() {
if ( ! empty( $_GET['message'] ) && ! empty( $_GET['page'] ) && $_GET['page'] === 'rcp-need-help') {
if ( $_GET['message'] === 'success' ) {
?>
<div class="notice notice-success is-dismissible">
<p><?php _e( 'Email Sent Successfully.', 'rcp' ); ?></p>
</div>
<?php
} else if ( $_GET['message'] === 'failed' ) {
?>
<div class="notice notice-error is-dismissible">
<p><?php _e( 'Unable to send email.', 'rcp' ); ?></p>
</div>
<?php
}
} else if ( ! empty( $_GET['message'] ) && ! empty( $_GET['page'] ) && $_GET['page'] === 'restrict-content-welcome' ) {
if ( $_GET['message'] === 'success' ) {
?>
<div class="notice notice-success is-dismissible">
<p><?php _e( 'Email Sent Successfully.', 'rcp' ); ?></p>
</div>
<?php
} else if ( $_GET['message'] === 'failed' ) {
?>
<div class="notice notice-error is-dismissible">
<p><?php _e( 'Unable to send email.', 'rcp' ); ?></p>
</div>
<?php
}
}
}
add_action( 'admin_notices', 'restrict_content_admin_try_free_success' );
function restrict_content_admin_try_free () {
if( isset( $_POST['rc_welcome_try_free_meta_nonce'] ) && wp_verify_nonce( $_POST['rc_welcome_try_free_meta_nonce'], 'rc_welcome_try_free_meta_nonce') ) {
$body = array(
'template_name' => 'rcp-demo-delivery',
'email' => $_POST['try_email_address']
);
$fields = array(
'method' => 'POST',
'body' => json_encode( $body )
);
$response = wp_remote_request( 'https://api.ithemes.com/email/send', $fields );
if ( ! is_wp_error( $response ) && $_POST['source_page'] === 'welcome_page' ) {
wp_redirect( add_query_arg( 'message', 'success', admin_url( 'admin.php?page=restrict-content-welcome' ) ) );
} else if ( ! is_wp_error( $response ) && $_POST['source_page'] === 'help_page' ) {
wp_redirect( add_query_arg( 'message', 'success', admin_url( 'admin.php?page=rcp-need-help' ) ) );
} else {
wp_redirect( add_query_arg( 'message', 'failed', admin_url( 'admin.php?page=rcp-need-help' ) ) );
}
}
}
add_action( 'admin_post_restrict_content_try_free', 'restrict_content_admin_try_free' );

View File

@@ -0,0 +1,92 @@
<?php
/**
* Batch Ajax Functions
*
* @package restrict-content-pro
* @copyright Copyright (c) 2018, Restrict Content Pro team
* @license GPL2+
* @since 3.0
*/
namespace RCP\Utils\Batch;
/**
* Processes ajax batch jobs.
*
* @since 3.0
*/
function ajax_process_batch() {
if ( ! current_user_can( 'rcp_manage_settings' ) ) {
wp_die();
}
check_ajax_referer( 'rcp_batch_nonce', 'rcp_batch_nonce' );
$step = ! empty( $_POST['step'] ) ? absint( $_POST['step'] ) : 0;
$job_id = ! empty( $_POST['job_id'] ) ? sanitize_text_field( $_POST['job_id'] ) : false;
$job = get_job( $job_id );
if ( ! $job_id || empty( $job ) ) {
wp_send_json_error( array(
'message' => __( 'Invalid job ID provided.', 'rcp' )
) );
}
/**
* Use this hook to include the job callback class file.
*
* @param string $job_callback Name of the class file.
*/
do_action( 'rcp_batch_processing_class_include', $job->get_callback() );
if ( ! class_exists( $job->get_callback() ) ) {
wp_send_json_error( array(
'message' => __( 'Job callback doesn\'t exist.', 'rcp' )
) );
}
if ( $job->get_step() != $step ) {
$job->set_step( $step );
}
$result = $job->process_batch();
if ( true === $result ) {
wp_send_json_success( array(
'step' => $step,
'next_step' => $job->is_completed() ? false : ++$step,
'job_name' => $job->get_name(),
'job_description' => $job->get_description(),
'percent_complete' => $job->is_completed() ? 100 : $job->get_percent_complete(),
'items_processed' => $job->get_current_count(),
'complete' => $job->is_completed(),
'complete_message' => $job->get_callback_object()->get_complete_message(),
'has_errors' => $job->has_errors(),
'errors' => '<p><strong>' . __( 'Errors', 'rcp' ) . '</strong></p>' . implode( '<br>', $job->get_errors() )
) );
}
// An error occurred during process. Return the error message.
if ( is_wp_error( $result ) ) {
// TODO: what to do with failed jobs?
wp_send_json_error( array(
'message' => $result->get_error_message(),
'step' => $step,
'job_name' => $job->get_name(),
'job_description' => $job->get_description()
) );
}
// We didn't get an expected return.
wp_send_json_error( array(
'message' => sprintf( __( 'An unknown error occurred processing %s.', 'rcp' ), $job->get_name() ),
'step' => $step,
'job_name' => $job->get_name(),
'job_description' => $job->get_description()
) );
}
add_action( 'wp_ajax_rcp_process_batch', __NAMESPACE__ . '\ajax_process_batch' );

View File

@@ -0,0 +1 @@
<?php // Silence is golden.

View File

@@ -0,0 +1,296 @@
<?php
/**
* List Table Base Class
*
* @package restrict-content-pro
* @copyright Copyright (c) 2018, Restrict Content Pro team
* @license GPL2+
* @since 3.0
*/
namespace RCP\Admin;
// Exit if accessed directly
defined( 'ABSPATH' ) || exit;
// Load WP_List_Table if not loaded
if ( ! class_exists( 'WP_List_Table' ) ) {
require_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php';
}
/**
* Class List_Table
*
* @since 3.0
* @package RCP\Admin
*/
abstract class List_Table extends \WP_List_Table {
/**
* Number of results to show per page.
*
* @since 3.0
* @var int
*/
public $per_page = 30;
/**
* Counts.
*
* @since 3.0
* @var array
*/
public $counts = array(
'total' => 0
);
/**
* List_Table constructor.
*
* @param $args
*
* @since 3.0.3
*/
public function __construct( $args ) {
parent::__construct( $args );
$this->set_per_page();
add_filter( 'removable_query_args', array( $this, 'removable_query_args' ) );
}
/**
* Set number of results per page
*
* This uses the screen options setting if available. Otherwise it defaults to 30.
*
* @since 3.0.3
* @access protected
*/
protected function set_per_page() {
$per_page = 30;
$user_id = get_current_user_id();
$screen = get_current_screen();
$screen_option = $screen->get_option( 'per_page', 'option' );
if ( ! empty( $screen_option ) ) {
$per_page = get_user_meta( $user_id, $screen_option, true );
if ( empty( $per_page ) || $per_page < 1 ) {
$per_page = $screen->get_option( 'per_page', 'default' );
}
}
$this->per_page = $per_page;
}
/**
* Get a request var, or return the default if not set.
*
* @param string $var
* @param mixed $default
*
* @since 3.0
* @return mixed Un-sanitized request var
*/
public function get_request_var( $var = '', $default = false ) {
return isset( $_REQUEST[$var] )
? $_REQUEST[$var]
: $default;
}
/**
* Get a status request var, if set.
*
* @param mixed $default
*
* @since 3.0
* @return string
*/
protected function get_status( $default = '' ) {
return sanitize_key( $this->get_request_var( 'status', $default ) );
}
/**
* Retrieve the current page number.
*
* @since 3.0
* @return int Current page number.
*/
protected function get_paged() {
return absint( $this->get_request_var( 'paged', 1 ) );
}
/**
* Retrieve the offset to use for the query.
*
* @since 3.0
* @return int Offset.
*/
protected function get_offset() {
$offset = ( $this->get_paged() - 1 ) * $this->per_page;
return absint( $offset );
}
/**
* Retrieve the current page number.
*
* @since 3.0
* @return int Current page number.
*/
protected function get_search() {
return rawurldecode( trim( $this->get_request_var( 's', '' ) ) );
}
/**
* Generate the table navigation above or below the table.
*
* We're overriding this to turn off the referer param in `wp_nonce_field()`.
*
* @param string $which
*
* @since 3.1
*/
protected function display_tablenav( $which ) {
if ( 'top' === $which ) {
wp_nonce_field( 'bulk-' . $this->_args['plural'], '_wpnonce', false );
}
?>
<div class="tablenav <?php echo esc_attr( $which ); ?>">
<?php if ( $this->has_items() ) : ?>
<div class="alignleft actions bulkactions">
<?php $this->bulk_actions( $which ); ?>
</div>
<?php
endif;
$this->extra_tablenav( $which );
$this->pagination( $which );
?>
<br class="clear"/>
</div>
<?php
}
/**
* Show the search field.
*
* @param string $text Label for the search box
* @param string $input_id ID of the search box
*
* @since 3.0
*/
public function search_box( $text, $input_id ) {
// Bail if no items and no search
if ( ! $this->get_search() && ! $this->has_items() ) {
return;
}
$orderby = $this->get_request_var( 'orderby' );
$order = $this->get_request_var( 'order' );
$input_id = $input_id . '-search-input';
if ( ! empty( $orderby ) ) {
echo '<input type="hidden" name="orderby" value="' . esc_attr( $orderby ) . '" />';
}
if ( ! empty( $order ) ) {
echo '<input type="hidden" name="order" value="' . esc_attr( $order ) . '" />';
}
?>
<p class="search-box">
<label class="screen-reader-text" for="<?php echo esc_attr( $input_id ); ?>"><?php echo esc_html( $text ); ?>:</label>
<input type="search" id="<?php echo esc_attr( $input_id ); ?>" name="s" value="<?php _admin_search_query(); ?>"/>
<?php submit_button( esc_html( $text ), 'button', false, false, array( 'ID' => 'search-submit' ) ); ?>
</p>
<?php
}
/**
* Get the base URL for this list table.
*
* @since 3.0
* @return string Base URL.
*/
public function get_base_url() {
return admin_url();
}
/**
* Retrieve the view types
*
* @since 3.0
* @return array $views All the views available
*/
public function get_views() {
// Get the current status
$current = $this->get_status();
// Args to remove
$remove = array( 'rcp_message', 'status', 'paged', '_wpnonce' );
// Base URL
$url = remove_query_arg( $remove, $this->get_base_url() );
// Is all selected?
$class = in_array( $current, array( '', 'all' ), true )
? ' class="current"'
: '';
// All
$count = '&nbsp;<span class="count">(' . esc_attr( $this->counts['total'] ) . ')</span>';
$label = __( 'All', 'rcp' ) . $count;
$views = array(
'all' => sprintf( '<a href="%s"%s>%s</a>', $url, $class, $label ),
);
// Remove total from counts array
$counts = $this->counts;
unset( $counts['total'] );
// Loop through statuses.
if ( ! empty( $counts ) ) {
foreach ( $counts as $status => $count ) {
$count_url = add_query_arg( array(
'status' => urlencode( $status ),
'paged' => false,
), $url );
$class = ( $current === $status )
? ' class="current"'
: '';
$count = '&nbsp;<span class="count">(' . absint( $this->counts[$status] ) . ')</span>';
$label = rcp_get_status_label( $status ) . $count;
$views[$status] = sprintf( '<a href="%s"%s>%s</a>', $count_url, $class, $label );
}
}
return $views;
}
/**
* Remove "action" query arg. This prevents the bulk action admin notice from persisting across page views.
*
* @param array $query_args
*
* @since 3.1
* @return array
*/
public function removable_query_args( $query_args ) {
$query_args[] = 'action';
return $query_args;
}
}

View File

@@ -0,0 +1,300 @@
<?php
/**
* RCP Add-On Updater
*
* @package Restrict Content Pro
* @subpackage Admin/Add-On Updater
* @copyright Copyright (c) 2017, Restrict Content Pro
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
*/
//set_site_transient( 'update_plugins', null );
class RCP_Add_On_Updater {
private $api_url = '';
private $api_data = array();
private $addon_id = '';
private $name = '';
private $slug = '';
private $version = '';
/**
* Class constructor.
*
* @uses plugin_basename()
* @uses hook()
*
* @param string $_api_url The URL pointing to the custom API endpoint.
* @param string $_plugin_file Path to the plugin file.
* @param array $_api_data Optional data to send with API calls.
* @return void
*/
function __construct( $_addon_id, $_plugin_file, $_version ) {
$this->api_url = 'https://restrictcontentpro.com';
$this->addon_id = $_addon_id;
$this->name = plugin_basename( $_plugin_file );
$this->slug = basename( $_plugin_file, '.php');
$this->version = $_version;
// Set up hooks.
$this->hook();
}
/**
* Set up Wordpress filters to hook into WP's update process.
*
* @uses add_filter()
*
* @return void
*/
private function hook() {
add_filter( 'pre_set_site_transient_update_plugins', array( $this, 'check_update' ) );
add_filter( 'plugins_api', array( $this, 'plugins_api_filter' ), 10, 3 );
add_action( 'after_plugin_row_' . $this->name, array( $this, 'show_update_notification' ), 10, 2 );
add_action( 'admin_init', array( $this, 'show_changelog' ) );
}
/**
* Check for Updates at the defined API endpoint and modify the update array.
*
* This function dives into the update api just when Wordpress creates its update array,
* then adds a custom API call and injects the custom plugin data retrieved from the API.
* It is reassembled from parts of the native Wordpress plugin update code.
* See wp-includes/update.php line 121 for the original wp_update_plugins() function.
*
* @uses api_request()
*
* @param array $_transient_data Update array build by Wordpress.
* @return array Modified update array with custom plugin data.
*/
function check_update( $_transient_data ) {
global $pagenow;
if( 'plugins.php' == $pagenow && is_multisite() ) {
return $_transient_data;
}
if( ! is_object( $_transient_data ) ) {
$_transient_data = new stdClass;
}
if ( empty( $_transient_data->response ) || empty( $_transient_data->response[ $this->name ] ) ) {
$api_response = $this->api_request( 'plugin_latest_version', array( 'slug' => $this->slug ) );
if( false !== $api_response && is_object( $api_response ) && isset( $api_response->new_version ) ) {
if( version_compare( $this->version, $api_response->new_version, '<' ) ) {
$_transient_data->response[ $this->name ] = $api_response;
}
}
$_transient_data->last_checked = time();
$_transient_data->checked[ $this->name ] = $this->version;
}
return $_transient_data;
}
/**
* Updates information on the "View version x.x details" page with custom data.
*
* @uses api_request()
*
* @param mixed $_data
* @param string $_action
* @param object $_args
* @return object $_data
*/
function plugins_api_filter( $_data, $_action = '', $_args = null ) {
if ( ( $_action != 'plugin_information' ) || !isset( $_args->slug ) || ( $_args->slug != $this->slug ) ) {
return $_data;
}
$to_send = array( 'slug' => $this->slug );
$api_response = $this->api_request( 'plugin_information', $to_send );
if ( false !== $api_response ) {
$_data = $api_response;
}
return $_data;
}
/**
* show update nofication row -- needed for multisite subsites, because WP won't tell you otherwise!
*
* @param string $file
* @param array $plugin
*/
public function show_update_notification( $file, $plugin ) {
if( ! current_user_can( 'update_plugins' ) ) {
return;
}
if( ! is_multisite() || is_network_admin() ) {
return;
}
if ( $this->name != $file ) {
return;
}
// Remove our filter on the site transient
remove_filter( 'pre_set_site_transient_update_plugins', array( $this, 'check_update' ), 10 );
$update_cache = get_site_transient( 'update_plugins' );
if ( ! is_object( $update_cache ) || empty( $update_cache->response ) || empty( $update_cache->response[ $this->name ] ) ) {
$cache_key = md5( 'rcp_plugin_' . sanitize_key( $this->name ) . '_version_info' );
$version_info = get_transient( $cache_key );
if( false === $version_info ) {
$version_info = $this->api_request( 'plugin_latest_version', array( 'slug' => $this->slug ) );
set_transient( $cache_key, $version_info, 3600 );
}
if( ! is_object( $version_info ) ) {
return;
}
if( version_compare( $this->version, $version_info->new_version, '<' ) ) {
$update_cache->response[ $this->name ] = $version_info;
}
$update_cache->last_checked = time();
$update_cache->checked[ $this->name ] = $this->version;
set_site_transient( 'update_plugins', $update_cache );
} else {
$version_info = $update_cache->response[ $this->name ];
}
if ( ! empty( $update_cache->response[ $this->name ] ) && version_compare( $this->version, $update_cache->response[ $this->name ]->new_version, '<' ) ) {
// build a plugin list row, with update notification
$wp_list_table = _get_list_table( 'WP_Plugins_List_Table' );
echo '<tr class="plugin-update-tr"><td colspan="' . $wp_list_table->get_column_count() . '" class="plugin-update colspanchange"><div class="update-message">';
$changelog_link = self_admin_url( 'index.php?rcp_action=view_plugin_changelog&plugin=' . $this->name . '&slug=' . $this->slug . '&addon_id=' . $this->addon_id . '&TB_iframe=true&width=772&height=911' );
if ( empty( $version_info->download_link ) ) {
printf(
__( 'There is a new version of %1$s available. <a target="_blank" class="thickbox" href="%2$s">View version %3$s details</a>.', 'rcp' ),
esc_html( $version_info->name ),
esc_url( $changelog_link ),
esc_html( $version_info->new_version )
);
} else {
printf(
__( 'There is a new version of %1$s available. <a target="_blank" class="thickbox" href="%2$s">View version %3$s details</a> or <a href="%4$s">update now</a>.', 'rcp' ),
esc_html( $version_info->name ),
esc_url( $changelog_link ),
esc_html( $version_info->new_version ),
esc_url( wp_nonce_url( self_admin_url( 'update.php?action=upgrade-plugin&plugin=' ) . $this->name, 'upgrade-plugin_' . $this->name ) )
);
}
echo '</div></td></tr>';
}
// Restore our filter
add_filter( 'pre_set_site_transient_update_plugins', array( $this, 'check_update' ) );
}
/**
* Calls the API and, if successful, returns the object delivered by the API.
*
* @uses get_bloginfo()
* @uses wp_remote_post()
* @uses is_wp_error()
*
* @param string $_action The requested action.
* @param array $_data Parameters for the API action.
* @return false||object
*/
private function api_request( $_action, $_data ) {
global $rcp_options;
$data = $_data;
$data['license'] = ! empty( $rcp_options['license_key'] ) ? trim( $rcp_options['license_key'] ) : '';
if( empty( $data['addon_id'] ) ) {
$data['addon_id'] = $this->addon_id;
}
if( empty( $data['addon_id'] ) ) {
return;
}
$api_params = array(
'rcp_action' => 'get_version',
'license' => $data['license'],
'id' => $data['addon_id'],
'slug' => $data['slug'],
'url' => home_url()
);
$request = wp_remote_post( $this->api_url, array(
'timeout' => 15,
'body' => $api_params
) );
if ( ! is_wp_error( $request ) ) {
$request = json_decode( wp_remote_retrieve_body( $request ) );
if( $request && isset( $request->sections ) ) {
$request->sections = maybe_unserialize( $request->sections );
}
return $request;
} else {
return false;
}
}
public function show_changelog() {
if( empty( $_REQUEST['rcp_action'] ) || 'view_plugin_changelog' != $_REQUEST['rcp_action'] ) {
return;
}
if( empty( $_REQUEST['plugin'] ) ) {
return;
}
if( empty( $_REQUEST['slug'] ) ) {
return;
}
if( ! current_user_can( 'update_plugins' ) ) {
wp_die( __( 'You do not have permission to install plugin updates', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 403 ) );
}
$response = $this->api_request( 'plugin_latest_version', array( 'slug' => $_REQUEST['slug'], 'addon_id' => $_REQUEST['addon_id'] ) );
if( $response && isset( $response->sections['changelog'] ) ) {
echo '<div style="background:#fff;padding:10px;height:100%;">' . $response->sections['changelog'] . '</div>';
}
exit;
}
}

View File

@@ -0,0 +1,332 @@
<?php
/**
* Upgrade class
*
* This class handles database upgrade routines between versions
*
* @package Restrict Content Pro
* @copyright Copyright (c) 2017, Pippin Williamson
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
* @since 2.6
*/
class RCP_Upgrades {
private $version = '';
private $upgraded = false;
/**
* RCP_Upgrades constructor.
*
* @access public
* @return void
*/
public function __construct() {
$this->version = preg_replace( '/[^0-9.].*/', '', get_option( 'rcp_version' ) );
add_action( 'admin_init', array( $this, 'init' ), -9999 );
// This uses a lower priority because we need it to run before BerlinDB's upgrade checks.
add_action( 'admin_init', array( $this, 'maybe_set_db_upgrade_flags' ), -999999 );
}
/**
* Trigger updates and maybe update the RCP version number
*
* @access public
* @return void
*/
public function init() {
$this->v26_upgrades();
$this->v27_upgrades();
$this->v29_upgrades();
$this->v30_upgrades();
$this->v304_upgrades();
$this->v31_upgrades();
$this->v32_upgrades();
$this->v35_upgrades();
// If upgrades have occurred or the DB version is different from the version constant
if ( $this->upgraded || $this->version <> RCP_PLUGIN_VERSION ) {
rcp_log( sprintf( 'RCP upgraded from version %s to %s.', $this->version, RCP_PLUGIN_VERSION ), true );
update_option( 'rcp_version_upgraded_from', $this->version );
update_option( 'rcp_version', RCP_PLUGIN_VERSION );
update_option( 'rcp_version_upgraded_on', current_time( 'mysql', true ) );
}
}
/**
* Maybe set BerlinDB upgrade flags
*
* This has to run before BerlinDB checks for table upgrades/installations. We might need to set a flag
* when moving an "old" database table to BerlinDB's API so we can ensure BerlinDB runs through table
* upgrades on existing installs.
*
* @access private
* @return void
*/
public function maybe_set_db_upgrade_flags() {
if ( version_compare( $this->version, '3.4', '<' ) ) {
update_option( 'rcp_membership_level_db', 1 );
}
}
/**
* Process 2.6 upgrades
*
* @access private
* @return void
*/
private function v26_upgrades() {
if( version_compare( $this->version, '2.6', '<' ) ) {
rcp_log( 'Performing version 2.6 upgrades: options install.', true );
@rcp_options_install();
}
}
/**
* Process 2.7 upgrades
*
* @access private
* @return void
*/
private function v27_upgrades() {
if( version_compare( $this->version, '2.7', '<' ) ) {
rcp_log( 'Performing version 2.7 upgrades: options install and updating discounts database.', true );
global $wpdb, $rcp_discounts_db_name;
$wpdb->query( "UPDATE $rcp_discounts_db_name SET code = LOWER(code)" );
@rcp_options_install();
$this->upgraded = true;
}
}
/**
* Process 2.9 upgrades
*
* @access private
* @since 2.9
* @return void
*/
private function v29_upgrades() {
if( version_compare( $this->version, '2.9', '<' ) ) {
global $rcp_options;
// Migrate expiring soon email to new reminders.
$period = rcp_get_renewal_reminder_period();
$subject = isset( $rcp_options['renewal_subject'] ) ? $rcp_options['renewal_subject'] : '';
$message = isset( $rcp_options['renew_notice_email'] ) ? $rcp_options['renew_notice_email'] : '';
$reminders = new RCP_Reminders();
$reminders_to_add = array();
if ( 'none' != $period && ! empty( $subject ) && ! empty( $message ) ) {
$allowed_periods = $reminders->get_notice_periods();
$period = str_replace( ' ', '', $period );
$new_notice = array(
'subject' => sanitize_text_field( $subject ),
'message' => wp_kses( $message, wp_kses_allowed_html( 'post' ) ),
'send_period' => array_key_exists( $period, $allowed_periods ) ? $period : '+1month',
'type' => 'expiration',
'enabled' => true
);
$reminders_to_add[] = $new_notice;
}
// Insert default renewal notice.
$renewal_notices = $reminders->get_notices( 'renewal' );
if ( empty( $renewal_notices ) ) {
$reminders_to_add[] = $reminders->get_default_notice( 'renewal' );
}
// Update notices.
if ( ! empty( $reminders_to_add ) ) {
update_option( 'rcp_reminder_notices', $reminders_to_add );
}
@rcp_options_install();
$this->upgraded = true;
}
}
/**
* Process 3.0 upgrades.
* Renames the payment_id column to rcp_payment_id in the payment meta table.
*
* @since 3.0
*/
private function v30_upgrades() {
if( version_compare( $this->version, '3.0', '<' ) ) {
global $wpdb;
/**
* Run options install to add new tables, add payment plan settings to subscription level table, etc.
*/
@rcp_options_install();
/**
* Rename "payment_id" column in payment meta table to "rcp_payment_id".
*/
$payment_meta_table_name = rcp_get_payment_meta_db_name();
rcp_log( sprintf( 'Performing version 3.0 upgrade: Renaming payment_id column to rcp_payment_id in the %s table.', $payment_meta_table_name ), true );
$payment_meta_cols = $wpdb->get_col( "DESC " . $payment_meta_table_name, 0 );
$column_renamed = in_array( 'rcp_payment_id', $payment_meta_cols );
// Only attempt to rename the column if it hasn't already been done.
if ( ! $column_renamed ) {
$updated = $wpdb->query( "ALTER TABLE {$payment_meta_table_name} CHANGE payment_id rcp_payment_id BIGINT(20) NOT NULL DEFAULT '0';" );
if ( false === $updated ) {
rcp_log( sprintf( 'Error renaming the payment_id column in %s.', $payment_meta_table_name ), true );
return;
} else {
rcp_log( sprintf( 'Renaming payment_id to rcp_payment_id in %s was successful.', $payment_meta_table_name ), true );
}
} else {
rcp_log( sprintf( 'payment_id column already renamed to rcp_payment_id in %s.', $payment_meta_table_name ), true );
}
/**
* Upgrade discounts table.
*
* Discounts migration moved to BerlinDB
* @see \RCP\Database\Tables\Discounts::__202002101()
*/
/**
* Change column types in rcp_payments.
*/
$payment_table_name = rcp_get_payments_db_name();
rcp_log( sprintf( 'Performing version 3.0 upgrade: Changing column types in %s table.', $payment_table_name ), true );
$wpdb->query( "ALTER TABLE {$payment_table_name} MODIFY id bigint(9) unsigned NOT NULL AUTO_INCREMENT" );
$wpdb->query( "ALTER TABLE {$payment_table_name} MODIFY object_id bigint(9) unsigned NOT NULL" );
$wpdb->query( "ALTER TABLE {$payment_table_name} MODIFY user_id bigint(20) unsigned NOT NULL" );
/**
* Add batch processing job for migrating memberships to custom table.
*/
$registered = \RCP\Utils\Batch\add_batch_job( array(
'name' => 'Memberships Migration',
'description' => __( 'Migrate members and their memberships from user meta to a custom table.', 'rcp' ),
'callback' => 'RCP_Batch_Callback_Migrate_Memberships_v3'
) );
if ( is_wp_error( $registered ) ) {
rcp_log( sprintf( 'Batch: Error adding memberships migration job: %s', $registered->get_error_message() ), true );
} else {
rcp_log( 'Batch: Successfully initiated memberships migration job.', true );
}
$this->upgraded = true;
}
}
/**
* Process 3.0.4 upgrades.
*
* @access private
* @return void
*/
private function v304_upgrades() {
if( version_compare( $this->version, '3.0.4', '<' ) ) {
rcp_log( 'Performing version 3.0.4 upgrades: options install.', true );
@rcp_options_install();
}
}
/**
* Process 3.1 upgrades.
*
* @access private
* @return void
*/
private function v31_upgrades() {
if( version_compare( $this->version, '3.1', '<' ) ) {
rcp_log( 'Performing version 3.1 upgrades: options install.', true );
@rcp_options_install();
/**
* Database upgrade to add `one_time` column to discounts table has been moved to:
* @see \RCP\Database\Tables\Discounts::__202002101()
*/
}
}
/**
* Process 3.2 upgrades.
* - Remove Stripe Checkout gateway.
*
* @access private
* @return void
*/
private function v32_upgrades() {
if( version_compare( $this->version, '3.2', '<' ) ) {
global $rcp_options;
$enabled_gateways = isset( $rcp_options['gateways'] ) ? array_map( 'trim', $rcp_options['gateways'] ) : array();
if ( ! empty( $enabled_gateways ) && is_array( $enabled_gateways ) && array_key_exists( 'stripe_checkout', $enabled_gateways ) ) {
rcp_log( 'Performing version 3.2 upgrades: removing Stripe Checkout gateway.', true );
unset( $enabled_gateways[ 'stripe_checkout' ] );
// If Stripe doesn't exist, add it.
if ( ! array_key_exists( 'stripe', $enabled_gateways ) ) {
rcp_log( 'Performing version 3.2 upgrades: adding Stripe Elements gateway.', true );
$enabled_gateways['stripe'] = 1;
}
$rcp_options['gateways'] = $enabled_gateways;
update_option( 'rcp_settings', $rcp_options );
}
}
}
/**
* Process 3.5 upgrades.
* - Remove License Key Option
*
* @access private
* @return void
*/
private function v35_upgrades() {
if ( version_compare( $this->version, '3.5', '<' ) ) {
global $rcp_options;
// Setting license_key to empty string before we eventually remove completely.
$rcp_options['license_key'] = '';
update_option( 'rcp_settings', $rcp_options );
}
}
}
new RCP_Upgrades;

View File

@@ -0,0 +1,110 @@
<?php
/**
* Add Customer
*
* @package restrict-content-pro
* @copyright Copyright (c) 2019, Restrict Content Pro team
* @license GPL2+
* @since 3.0
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
if ( ! isset( $_GET['view'] ) || 'add' != $_GET['view'] ) {
wp_die( __( 'Something went wrong.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 400 ) );
}
?>
<div class="wrap">
<h1><?php _e( 'Customers Details', 'rcp' ); ?></h1>
<div id="rcp-item-card-wrapper">
<div class="rcp-info-wrapper rcp-item-section rcp-customer-card-wrapper">
<form id="rcp-edit-customer-info" method="POST">
<div class="rcp-item-info">
<div id="rcp-new-customer-details">
<table class="widefat striped">
<tbody>
<tr>
<th scope="row" class="row-title">
<label for="tablecell"><?php _e( 'User Account:', 'rcp' ); ?></label>
</th>
<td>
<input type="radio" id="rcp-customer-account-new" name="rcp_customer_user_account" value="new" checked="checked"/> <label for="rcp-customer-account-new"><?php _e( 'New Account', 'rcp' ); ?></label>
<input type="radio" id="rcp-customer-account-existing" name="rcp_customer_user_account" value="existing"/> <label for="rcp-customer-account-existing"><?php _e( 'Existing Account', 'rcp' ); ?></label> <br/>
</td>
</tr>
<tr class="rcp-customer-new-user-field">
<th scope="row" class="row-title">
<label for="tablecell"><?php _e( 'Name:', 'rcp' ); ?></label>
</th>
<td>
<label for="rcp-customer-first-name" class="screen-reader-text"><?php _e( 'First Name', 'rcp' ); ?></label>
<input type="text" id="rcp-customer-first-name" name="first_name" value="" placeholder="<?php esc_attr_e( 'First name', 'rcp' ); ?>"/>
<label for="rcp-customer-last-name" class="screen-reader-text"><?php _e( 'Last Name', 'rcp' ); ?></label>
<input type="text" id="rcp-customer-last-name" name="last_name" value="" placeholder="<?php esc_attr_e( 'Last name', 'rcp' ); ?>"/>
</td>
</tr>
<tr>
<th scope="row" class="row-title">
<label for="rcp-customer-email"><?php _e( 'Email:', 'rcp' ); ?></label>
</th>
<td>
<input type="text" id="rcp-customer-email" class="rcp-user-search" data-return-field="user_email" name="user_email" value=""/>
<div id="rcp_user_search_results"></div>
</td>
</tr>
<tr class="rcp-customer-new-user-field">
<th scope="row" class="row-title">
<label for="rcp-customer-username"><?php _e( 'Username:', 'rcp' ); ?></label>
</th>
<td>
<input type="text" id="rcp-customer-username" name="user_login" value=""/>
</td>
</tr>
<tr class="user-pass1-wrap rcp-customer-new-user-field">
<th scope="row" class="row-title">
<label for="pass1"><?php _e( 'Password:', 'rcp' ); ?></label>
</th>
<td>
<button type="button" class="button wp-generate-pw hide-if-no-js"><?php _e( 'Show password', 'rcp' ); ?></button>
<div class="wp-pwd hide-if-js">
<?php $initial_password = wp_generate_password( 24 ); ?>
<span class="password-input-wrapper">
<input type="password" name="user_password" id="pass1" autocomplete="off" data-reveal="1" data-pw="<?php echo esc_attr( $initial_password ); ?>" aria-describedby="pass-strength-result" />
</span>
<button type="button" class="button wp-hide-pw hide-if-no-js" data-toggle="0" aria-label="<?php esc_attr_e( 'Hide password', 'rcp' ); ?>">
<span class="dashicons dashicons-hidden"></span>
<span class="text"><?php _e( 'Hide', 'rcp-group-accounts' ); ?></span>
</button>
<button type="button" class="button wp-cancel-pw hide-if-no-js" data-toggle="0" aria-label="<?php esc_attr_e( 'Cancel password change', 'rcp' ); ?>">
<span class="text"><?php _e( 'Cancel', 'rcp-group-accounts' ); ?></span>
</button>
<div style="display:none" id="pass-strength-result" aria-live="polite"></div>
</div>
</td>
</tr>
<tr>
<th scope="row" class="row-title">
<label for="rcp-customer-since"><?php _e( 'Customer Since:', 'rcp' ); ?></label>
</th>
<td>
<input type="text" id="rcp-customer-since" name="date_registered" value="<?php echo esc_attr( current_time( 'mysql' ) ); ?>"/>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<div id="rcp-item-edit-actions" class="edit-item">
<input type="hidden" name="rcp-action" value="add_customer"/>
<?php wp_nonce_field( 'rcp_add_customer_nonce', 'rcp_add_customer_nonce' ); ?>
<input type="submit" name="rcp_update_customer" id="rcp_update_customer" class="button button-primary" value="<?php _e( 'Add Customer', 'rcp' ); ?>"/>
</div>
</form>
</div>
</div>
</div>

View File

@@ -0,0 +1,438 @@
<?php
/**
* Customers List Table
*
* @package restrict-content-pro
* @copyright Copyright (c) 2018, Restrict Content Pro
* @license GPL2+
* @since 3.0
*/
namespace RCP\Admin;
/**
* Class Customers_Table
*
* @since 3.0
* @package RCP\Admin
*/
class Customers_Table extends List_Table {
/**
* Constructor.
*
* @since 3.0
* @see WP_List_Table::__construct()
*/
public function __construct() {
parent::__construct( [
'singular' => 'Customer',
'plural' => 'Customers',
'ajax' => false,
] );
$this->process_bulk_action();
$this->get_counts();
}
/**
* Get the base URL for the customers list table.
*
* @since 3.0
* @return string Base URL.
*/
public function get_base_url() {
return rcp_get_customers_admin_page();
}
/**
* Retrieve the table columns.
*
* @since 3.0
* @return array
*/
public function get_columns() {
$columns = array(
'cb' => '<input type="checkbox" />',
'name' => __( 'Name', 'rcp' ),
'email' => __( 'Email', 'rcp' ),
'date_registered' => __( 'Date Registered', 'rcp' ),
'last_login' => __( 'Last Login', 'rcp' ),
);
/*
* Backwards compatibility: add an "extra" column if someone is hooking into the old action to add
* their own column. Everything gets bundled into one column because this is the only way we can realistically
* do it.
*/
if ( has_action( 'rcp_members_page_table_header' ) ) {
$columns['custom'] = __( 'Extra', 'rcp' );
}
$columns = apply_filters( 'rcp_customers_list_table_columns', $columns );
return $columns;
}
/**
* Retrieve the sortable columns.
*
* @since 3.0
* @return array
*/
public function get_sortable_columns() {
return array(
'date_registered' => array( 'date_registered', false ),
'last_login' => array( 'last_login', false )
);
}
/**
* Gets the name of the primary column.
*
* @since 3.0
* @return string
*/
protected function get_primary_column_name() {
return 'name';
}
/**
* This function renders any other columns in the list table.
*
* @param \RCP_Customer $customer Customer object.
* @param string $column_name The name of the column
*
* @since 3.0
* @return string Column Name
*/
public function column_default( $customer, $column_name ) {
$value = '';
/*
* Backwards compatibility: show content of custom columns from old action hook.
*/
if ( 'custom' == $column_name && has_action( 'rcp_members_page_table_column' ) ) {
ob_start();
do_action( 'rcp_members_page_table_column', $customer->get_user_id() );
$column_content = ob_get_clean();
$value = wp_strip_all_tags( $column_content );
}
/**
* Filters the column value.
*
* @param string $value Column value.
* @param \RCP_Customer $customer Customer object.
*
* @since 3.0
*/
$value = apply_filters( 'rcp_customers_list_table_column_' . $column_name, $value, $customer );
return $value;
}
/**
* Render the checkbox column.
*
* @param \RCP_Customer $customer
*
* @since 3.0
* @return string
*/
public function column_cb( $customer ) {
return sprintf(
'<input type="checkbox" name="%1$s[]" value="%2$s" />',
'customer_id',
$customer->get_id()
);
}
/**
* Render the "Name" column.
*
* @param \RCP_Customer $customer
*
* @since 3.0
* @return string
*/
public function column_name( $customer ) {
$customer_id = $customer->get_id();
$user_id = $customer->get_user_id();
$user = get_userdata( $user_id );
$display_name = ! empty( $user->display_name ) ? $user->display_name : $user->user_login;
$edit_customer_url = rcp_get_customers_admin_page( array(
'customer_id' => $customer_id,
'view' => 'edit'
) );
$delete_customer_url = wp_nonce_url( rcp_get_customers_admin_page( array(
'rcp-action' => 'delete_customer',
'customer_id' => $customer_id
) ), 'rcp_delete_customer' );
$actions = array(
'edit_customer' => '<a href="' . esc_url( $edit_customer_url ) . '">' . __( 'Edit Customer', 'rcp' ) . '</a>',
'delete_customer' => '<span class="trash"><a href="' . esc_url( $delete_customer_url ) . '" class="rcp-delete-customer">' . __( 'Delete', 'rcp' ) . '</a></span>',
'customer_id' => '<span class="rcp-id-col">' . sprintf( __( 'ID: %d', 'rcp' ), $customer_id ) . '</span>'
);
ob_start();
/**
* @deprecated 3.0 Use `rcp_customers_list_table_row_actions` instead.
*/
do_action( 'rcp_member_row_actions', $customer->get_user_id() );
$custom_row_actions = ob_get_clean();
if ( $custom_row_actions ) {
$actions['custom_row_actions'] = $custom_row_actions;
}
/**
* Filters the row actions.
*
* @param array $actions Default actions.
* @param \RCP_Customer $membership Membership object.
*
* @since 3.0
*/
$actions = apply_filters( 'rcp_customers_list_table_row_actions', $actions, $customer );
return '<strong><a class="row-title" href="' . esc_url( $edit_customer_url ) . '">' . esc_html( $display_name ) . '</a></strong>' . $this->row_actions( $actions );
}
/**
* Render the "Email" column.
*
* @param \RCP_Customer $customer
*
* @since 3.0
* @return string
*/
public function column_email( $customer ) {
$user = get_userdata( $customer->get_user_id() );
return esc_html( $user->user_email );
}
/**
* Render the "Date Registered" column.
*
* @param \RCP_Customer $customer
*
* @since 3.0
* @return string
*/
public function column_date_registered( $customer ) {
return $customer->get_date_registered();
}
/**
* Render the "Last Login" column.
*
* @param \RCP_Customer $customer
*
* @since 3.0
* @return string
*/
public function column_last_login( $customer ) {
$last_login = $customer->get_last_login();
if ( empty( $last_login ) ) {
$last_login = __( 'Unknown', 'rcp' );
}
return $last_login;
}
/**
* Message to be displayed when there are no customers.
*
* @since 3.0
* @return void
*/
public function no_items() {
esc_html_e( 'No customers found.', 'rcp' );
}
/**
* Retrieve the bulk actions.
*
* @since 3.0
* @return array
*/
public function get_bulk_actions() {
return array(
'delete' => __( 'Permanently Delete', 'rcp' )
);
}
/**
* Process bulk actions.
*
* @since 3.0
* @return void
*/
public function process_bulk_action() {
// Bail if a nonce was not supplied.
if ( ! isset( $_REQUEST['_wpnonce'] ) ) {
return;
}
if ( ! wp_verify_nonce( $_REQUEST['_wpnonce'], 'bulk-customers' ) ) {
return;
}
$ids = wp_parse_id_list( (array) $this->get_request_var( 'customer_id', false ) );
// Bail if no IDs
if ( empty( $ids ) ) {
return;
}
$current_user = wp_get_current_user();
rcp_log( sprintf( '%s is performing the %s bulk action on customers: %s.', $current_user->user_login, $this->current_action(), implode( ', ', $ids ) ) );
foreach ( $ids as $id ) {
$customer = rcp_get_customer( absint( $id ) );
if ( empty( $customer ) ) {
continue;
}
switch ( $this->current_action() ) {
case 'delete':
rcp_delete_customer( $customer->get_id() );
break;
}
}
$this->show_admin_notice( $this->current_action() );
}
/**
* Show admin notice for bulk actions.
*
* @param string $action The action to show the notice for.
*
* @access private
* @since 3.0.8
* @return void
*/
private function show_admin_notice( $action ) {
$message = '';
switch ( $action ) {
case 'delete' :
$message = __( 'Customer(s) deleted.', 'rcp' );
break;
}
if ( empty( $message ) ) {
return;
}
echo '<div class="updated"><p>' . $message . '</p></div>';
}
/**
* Retrieve the customer counts.
*
* @since 3.0
* @return void
*/
public function get_counts() {
$this->counts = array(
'total' => rcp_count_customers(),
'pending' => rcp_count_customers( array(
'email_verification' => 'pending'
) )
);
}
/**
* Retrieve customers data.
*
* @param bool $count Whether or not to get customer objects (false) or just count the total number (true).
*
* @since 3.0
* @return array|int
*/
public function customers_data( $count = false ) {
$args = array(
'number' => $this->per_page,
'offset' => $this->get_offset(),
'orderby' => sanitize_text_field( $this->get_request_var( 'orderby', 'id' ) ),
'order' => sanitize_text_field( $this->get_request_var( 'order', 'DESC' ) ),
'email_verification' => $this->get_status(),
);
$search = $this->get_search();
if ( ! empty( $search ) ) {
/*
* Search by user account
* This process sucks because our query class doesn't do joins.
* @todo first name and last name
*/
// First we have to search for user accounts.
$user_ids = get_users( array(
'number' => -1,
'search' => '*' . $this->get_search() . '*',
'fields' => 'ids'
) );
// No user results - bail.
if ( empty( $user_ids ) ) {
return $count ? 0 : array();
}
// Finally, include these user IDs in the customers query.
$args['user_id__in'] = $user_ids;
}
if ( $count ) {
return rcp_count_customers( $args );
}
return rcp_get_customers( $args );
}
/**
* Setup the final data for the table.
*
* @since 3.0
* @return void
*/
public function prepare_items() {
$columns = $this->get_columns();
$hidden = array();
$sortable = $this->get_sortable_columns();
$this->_column_headers = array( $columns, $hidden, $sortable );
$this->items = $this->customers_data();
$total = $this->customers_data( true );
// Setup pagination
$this->set_pagination_args( array(
'total_items' => $total,
'per_page' => $this->per_page,
'total_pages' => ceil( $total / $this->per_page )
) );
}
}

View File

@@ -0,0 +1,293 @@
<?php
/**
* Customer Actions
*
* @package restrict-content-pro
* @copyright Copyright (c) 2018, Restrict Content Pro team
* @license GPL2+
* @since 3.0
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Add a new customer
*
* @since 3.0
* @return void
*/
function rcp_process_add_customer() {
if ( ! wp_verify_nonce( $_POST['rcp_add_customer_nonce'], 'rcp_add_customer_nonce' ) ) {
wp_die( __( 'Nonce verification failed.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 403 ) );
}
if ( ! current_user_can( 'rcp_manage_members' ) ) {
wp_die( __( 'You do not have permission to perform this action.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 403 ) );
}
$current_user = wp_get_current_user();
rcp_log( sprintf( '%s has started adding a new customer.', $current_user->display_name ) );
$type = ! empty( $_POST['rcp_customer_user_account'] ) ? $_POST['rcp_customer_user_account'] : 'new';
$customer_email = ! empty( $_POST['user_email'] ) ? $_POST['user_email'] : false;
if ( empty( $customer_email ) ) {
wp_die( __( 'Please enter a valid customer email.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 400 ) );
}
// Create new user account.
if ( 'new' == $type ) {
rcp_log( 'Creating new user account.' );
$user_login = ! empty( $_POST['user_login'] ) ? $_POST['user_login'] : $customer_email;
$existing_user = get_user_by( 'login', $user_login );
if ( ! empty( $existing_user ) ) {
wp_die( sprintf( __( 'A user account already exists with the login %s.', 'rcp' ), esc_html( $user_login ) ), __( 'Error', 'rcp' ), array( 'response' => 500 ) );
}
$user_args = array(
'user_login' => sanitize_text_field( $user_login ),
'user_email' => sanitize_text_field( $customer_email ),
'user_pass' => ! empty( $_POST['user_password'] ) ? $_POST['user_password'] : wp_generate_password( 24 ),
'first_name' => ! empty( $_POST['first_name'] ) ? sanitize_text_field( $_POST['first_name'] ) : '',
'last_name' => ! empty( $_POST['last_name'] ) ? sanitize_text_field( $_POST['last_name'] ) : ''
);
$user_args['display_name'] = trim( $user_args['first_name'] . ' ' . $user_args['last_name'] );
if ( empty( $user_args['display_name'] ) ) {
$user_args['display_name'] = $user_args['user_login'];
}
$user_id = wp_insert_user( $user_args );
if ( empty( $user_id ) ) {
wp_die( __( 'Error creating customer account.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 500 ) );
}
$user = get_userdata( $user_id );
} else {
// Use existing user account.
$user = get_user_by( 'email', $customer_email );
if ( ! is_a( $user, 'WP_User' ) ) {
wp_die( sprintf( __( 'Unable to locate existing account with the email %s.', 'rcp' ), esc_html( $customer_email ) ), __( 'Error', 'rcp' ), array( 'response' => 500 ) );
}
}
// Check for a customer record.
$customer = rcp_get_customer_by_user_id( $user->ID );
if ( ! empty( $customer ) ) {
wp_die( sprintf( __( 'A customer with the ID %d already exists with this account.', 'rcp' ), $customer->get_id() ), __( 'Error', 'rcp' ), array( 'response' => 500 ) );
}
rcp_log( sprintf( 'Creating new customer record for user #%d.', $user->ID ) );
$customer_id = rcp_add_customer( array(
'user_id' => absint( $user->ID ),
'date_registered' => date( 'Y-m-d H:i:s', strtotime( $_POST['date_registered'], current_time( 'timestamp' ) ) )
) );
if ( empty( $customer_id ) ) {
wp_die( __( 'Error creating customer record.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 500 ) );
}
$redirect = add_query_arg( 'rcp_message', 'customer_added', rcp_get_customers_admin_page( array(
'customer_id' => urlencode( $customer_id ),
'view' => 'edit'
) ) );
wp_safe_redirect( $redirect );
exit;
}
add_action( 'rcp_action_add_customer', 'rcp_process_add_customer' );
/**
* Process editing a customer.
*
* Funnily enough, this actually only updates the user account.
*
* @since 3.0
* @return void
*/
function rcp_process_edit_customer() {
if ( ! wp_verify_nonce( $_POST['rcp_edit_member_nonce'], 'rcp_edit_member_nonce' ) ) {
wp_die( __( 'Nonce verification failed.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 403 ) );
}
if ( ! current_user_can( 'rcp_manage_members' ) ) {
wp_die( __( 'You do not have permission to perform this action.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 403 ) );
}
if ( empty( $_POST['customer_id'] ) ) {
wp_die( __( 'Invalid customer ID.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 400 ) );
}
$customer_id = absint( $_POST['customer_id'] );
$customer = rcp_get_customer( $customer_id );
if ( empty( $customer ) ) {
wp_die( __( 'Invalid customer.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 400 ) );
}
$user = get_userdata( $customer->get_user_id() );
$current_user = wp_get_current_user();
rcp_log( sprintf( '%s has started editing customer #%d.', $current_user->display_name, $customer_id ) );
/**
* Maybe update user account record.
*/
$user_args = array();
$first_name = ! empty( $_POST['first_name'] ) ? $_POST['first_name'] : '';
$last_name = ! empty( $_POST['last_name'] ) ? $_POST['last_name'] : '';
$email = ! empty( $_POST['user_email'] ) ? $_POST['user_email'] : '';
if ( $user->first_name != $first_name ) {
$user_args['first_name'] = sanitize_text_field( $first_name );
}
if ( $user->last_name != $last_name ) {
$user_args['last_name'] = sanitize_text_field( $last_name );
}
if ( $user->user_email != $email && is_email( $email ) ) {
$user_args['user_email'] = sanitize_text_field( $email );
rcp_log( sprintf( 'Changing email for user account #%d.', $user->ID ) );
}
$display_name = trim( $first_name . ' ' . $last_name );
if ( empty( $display_name ) ) {
$display_name = $user->user_login;
}
$user_args['display_name'] = sanitize_text_field( trim( $display_name ) );
if ( ! empty( $user_args ) ) {
$user_args['ID'] = $user->ID;
wp_update_user( $user_args );
}
/**
* @deprecated 3.0 Use `rcp_edit_customer` instead.
*/
do_action( 'rcp_edit_member', $customer->get_user_id() );
/**
* Triggers when a customer is edited.
*
* @param RCP_Customer $customer Customer object.
*
* @since 3.0
*/
do_action( 'rcp_edit_customer', $customer );
$redirect = add_query_arg( 'rcp_message', 'user_updated', rcp_get_customers_admin_page( array(
'customer_id' => urlencode( $customer_id ),
'view' => 'edit'
) ) );
wp_safe_redirect( $redirect );
exit;
}
add_action( 'rcp_action_edit_customer', 'rcp_process_edit_customer' );
/**
* Process deleting a customer.
*
* @since 3.0
* @return void
*/
function rcp_process_delete_customer() {
if ( ! wp_verify_nonce( $_GET['_wpnonce'], 'rcp_delete_customer' ) ) {
wp_die( __( 'Nonce verification failed.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 403 ) );
}
if ( ! current_user_can( 'rcp_manage_members' ) ) {
wp_die( __( 'You do not have permission to perform this action.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 403 ) );
}
if ( empty( $_GET['customer_id'] ) ) {
wp_die( __( 'Invalid customer ID.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 400 ) );
}
$current_user = wp_get_current_user();
rcp_log( sprintf( '%s is deleting customer #%d.', $current_user->user_login, absint( $_GET['customer_id'] ) ) );
$deleted = rcp_delete_customer( absint( $_GET['customer_id'] ) );
if ( ! $deleted ) {
wp_die( __( 'Failed to delete customer.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 400 ) );
}
$redirect = add_query_arg( 'rcp_message', 'customer_deleted', rcp_get_customers_admin_page() );
wp_safe_redirect( $redirect );
exit;
}
add_action( 'rcp_action_delete_customer', 'rcp_process_delete_customer' );
/**
* Process adding a new note to the customer.
*
* @todo ajaxify
*
* @since 3.0
* @return void
*/
function rcp_process_add_customer_note() {
if ( ! wp_verify_nonce( $_POST['rcp_add_customer_note_nonce'], 'rcp_add_customer_note' ) ) {
wp_die( __( 'Nonce verification failed.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 403 ) );
}
if ( ! current_user_can( 'rcp_manage_members' ) ) {
wp_die( __( 'You do not have permission to perform this action.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 403 ) );
}
if ( empty( $_POST['customer_id'] ) ) {
wp_die( __( 'Invalid customer ID.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 400 ) );
}
$customer_id = absint( $_POST['customer_id'] );
$customer = rcp_get_customer( $customer_id );
if ( empty( $customer ) ) {
wp_die( __( 'Invalid customer.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 400 ) );
}
$new_note = wp_unslash( $_POST['new_note'] );
if ( empty( $new_note ) ) {
wp_die( __( 'Please enter a note.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 400 ) );
}
$current_user = wp_get_current_user();
rcp_log( sprintf( '%s is adding a new note to customer #%d.', $current_user->user_login, $customer_id ) );
$customer->add_note( sanitize_text_field( $new_note ) );
$redirect = add_query_arg( 'rcp_message', 'customer_note_added', rcp_get_customers_admin_page( array( 'customer_id' => urlencode( $customer_id ), 'view' => 'edit' ) ) );
wp_safe_redirect( $redirect );
exit;
}
add_action( 'rcp_action_add_customer_note', 'rcp_process_add_customer_note' );

View File

@@ -0,0 +1,64 @@
<?php
/**
* Customers Page
*
* @package Restrict Content Pro
* @subpackage Admin/Customers Page
* @copyright Copyright (c) 2018, Restrict Content Pro
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
* @since 3.0
*/
/**
* Render customers table
*
* @return void
*/
function rcp_customers_page() {
do_action( 'stellarwp/telemetry/restrict-content-pro/optin' );
do_action( 'stellarwp/telemetry/restrict-content/optin' );
if ( ! empty( $_GET['view'] ) && 'edit' == $_GET['view'] && ! empty( $_GET['customer_id'] ) ) {
require_once RCP_PLUGIN_DIR . 'core/includes/admin/customers/edit-customer.php';
} elseif ( ! empty( $_GET['view'] ) && 'add' == $_GET['view'] ) {
require_once RCP_PLUGIN_DIR . 'core/includes/admin/customers/add-customer.php';
} else {
// List all customers.
rcp_customers_list();
}
return;
}
/**
* Display the list of customers.
*
* @since 3.0
* @return void
*/
function rcp_customers_list() {
include_once RCP_PLUGIN_DIR . 'core/includes/admin/customers/class-customers-table.php';
$table_class = new \RCP\Admin\Customers_Table();
$table_class->prepare_items();
?>
<div class="wrap">
<h1>
<?php _e( 'Customers', 'rcp' ); ?>
<a href="<?php echo esc_url( rcp_get_customers_admin_page( array( 'view' => 'add' ) ) ); ?>" class="page-title-action"><?php _e( 'Add New', 'rcp' ); ?></a>
</h1>
<form id="rcp-customers-filter" method="GET" action="<?php echo esc_url( rcp_get_customers_admin_page() ); ?>">
<input type="hidden" name="page" value="rcp-customers"/>
<?php
$table_class->views();
$table_class->search_box( __( 'Search customers', 'rcp' ), 'rcp-customers' );
$table_class->display();
?>
</form>
</div>
<?php
}

View File

@@ -0,0 +1,351 @@
<?php
/**
* Edit Customer
*
* @package restrict-content-pro
* @copyright Copyright (c) 2018, Restrict Content Pro team
* @license GPL2+
* @since 3.0
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
if ( ! isset( $_GET['customer_id'] ) || ! is_numeric( $_GET['customer_id'] ) ) {
wp_die( __( 'Something went wrong.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 400 ) );
}
$customer_id = $_GET['customer_id'];
$customer = rcp_get_customer( $customer_id );
if ( empty( $customer ) ) {
wp_die( __( 'Something went wrong.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 400 ) );
}
global $rcp_options;
$user = get_userdata( $customer->get_user_id() );
$memberships = $customer->get_memberships();
$payments = $customer->get_payments( array( 'number' => 5 ) );
$payments_db = new RCP_Payments();
$number_payments = $payments_db->count( array( 'user_id' => $user->ID ) );
$terms_agreed = get_user_meta( $user->ID, 'rcp_terms_agreed', true );
$privacy_policy_agreed = get_user_meta( $user->ID, 'rcp_privacy_policy_agreed', true );
$delete_customer_url = wp_nonce_url( rcp_get_customers_admin_page( array(
'rcp-action' => 'delete_customer',
'customer_id' => $customer->get_id()
) ), 'rcp_delete_customer' );
?>
<div class="wrap">
<h1><?php _e( 'Customers Details', 'rcp' ); ?></h1>
<div id="rcp-item-card-wrapper">
<div class="rcp-info-wrapper rcp-item-section rcp-customer-card-wrapper">
<form id="rcp-edit-customer-info" method="POST">
<div class="rcp-item-info">
<div id="rcp-customer-account">
<p class="rcp-customer-avatar">
<?php echo get_avatar( $user->user_email, 150 ); ?>
</p>
<p class="rcp-customer-account">
<a href="<?php echo esc_url( add_query_arg( 'user_id', urlencode( $user->ID ), admin_url( 'user-edit.php' ) ) ); ?>"><?php echo esc_html( $user->user_login ); ?></a>
<?php
$switch_to_url = $customer->get_switch_to_url();
if ( ! empty( $switch_to_url ) ) {
?>
<br/>
<a href="<?php echo esc_url( $switch_to_url ); ?>"><?php _e( 'Switch to User', 'rcp' ); ?></a>
<?php
}
?>
</p>
<p class="rcp-customer-lifetime-value">
<?php printf( __( '%s Lifetime Value', 'rcp' ), rcp_currency_filter( $customer->get_lifetime_value() ) ); ?>
</p>
</div>
<div id="rcp-customer-details">
<table class="widefat striped">
<tbody>
<?php do_action( 'rcp_edit_member_before', $customer->get_user_id() ); ?>
<tr>
<th scope="row" class="row-title">
<label for="tablecell"><?php _e( 'ID:', 'rcp' ); ?></label>
</th>
<td>
<?php echo $customer->get_id(); ?>
</td>
</tr>
<tr>
<th scope="row" class="row-title">
<label for="tablecell"><?php _e( 'Name:', 'rcp' ); ?></label>
</th>
<td>
<label for="rcp-customer-first-name" class="screen-reader-text"><?php _e( 'First Name', 'rcp' ); ?></label>
<input type="text" id="rcp-customer-first-name" name="first_name" value="<?php echo esc_attr( $user->first_name ); ?>" placeholder="<?php esc_attr_e( 'First name', 'rcp' ); ?>"/>
<label for="rcp-customer-last-name" class="screen-reader-text"><?php _e( 'Last Name', 'rcp' ); ?></label>
<input type="text" id="rcp-customer-last-name" name="last_name" value="<?php echo esc_attr( $user->last_name ); ?>" placeholder="<?php esc_attr_e( 'Last name', 'rcp' ); ?>"/>
</td>
</tr>
<tr>
<th scope="row" class="row-title">
<label for="rcp-customer-email"><?php _e( 'Email:', 'rcp' ); ?></label>
</th>
<td>
<input type="text" id="rcp-customer-email" name="user_email" value="<?php echo esc_attr( $user->user_email ); ?>"/>
</td>
</tr>
<tr>
<th scope="row" class="row-title">
<label for="tablecell"><?php _e( 'Customer Since:', 'rcp' ); ?></label>
</th>
<td>
<?php echo $customer->get_date_registered(); ?>
</td>
</tr>
<tr>
<th scope="row" class="row-title">
<label for="tablecell"><?php _e( 'Has Trialed:', 'rcp' ); ?></label>
</th>
<td>
<?php echo $customer->has_trialed() ? __( 'Yes', 'rcp' ) : __( 'No', 'rcp' ); ?>
<span alt="f223" class="rcp-help-tip dashicons dashicons-editor-help" title="<?php esc_attr_e( 'Each customer can only sign up for one free trial.', 'rcp' ); ?>"></span>
</td>
</tr>
<tr>
<th scope="row" class="row-title">
<label for="rcp-customer-date-registered"><?php _e( 'Last Login:', 'rcp' ); ?></label>
</th>
<td>
<?php
$last_login = $customer->get_last_login();
if ( ! empty( $last_login ) ) {
echo $last_login;
} else {
_e( 'Unknown', 'rcp' );
}
?>
</td>
</tr>
<tr>
<th scope="row" class="row-title">
<label for="tablecell"><?php _e( 'Email Verification:', 'rcp' ); ?></label>
</th>
<td>
<?php
$verification_status = $customer->get_email_verification_status();
switch ( $verification_status ) {
case 'verified' :
_e( 'Verified', 'rcp' );
break;
case 'pending' :
_e( 'Pending', 'rcp' );
$resend_url = rcp_get_customers_admin_page( array(
'customer_id' => $customer->get_id(),
'member_id' => $customer->get_user_id(),
'rcp-action' => 'send_verification'
) );
$verify_url = rcp_get_customers_admin_page( array(
'customer_id' => $customer->get_id(),
'member_id' => $customer->get_user_id(),
'rcp-action' => 'verify_email'
) );
echo '&nbsp;<a href="' . esc_url( wp_nonce_url( $resend_url, 'rcp-verification-nonce' ) ) . '" class="button" title="' . esc_attr__( 'Re-send the verification email to the customer', 'rcp' ) . '">' . __( 'Re-send Email', 'rcp' ) . '</a>&nbsp;<a href="' . esc_url( wp_nonce_url( $verify_url, 'rcp-manually-verify-email-nonce' ) ) . '" class="button" title="' . esc_attr__( 'Mark the customer as verified', 'rcp' ) . '">' . __( 'Mark Verified', 'rcp' ) . '</a>';
break;
default :
_e( 'Not required', 'rcp' );
break;
}
?>
</td>
</tr>
<tr>
<th scope="row" class="row-title">
<label for="tablecell"><?php _e( 'IP Address:', 'rcp' ); ?></label>
</th>
<td>
<?php
$ips = $customer->get_ips();
echo ! empty( $ips ) ? esc_html( implode( ', ', $ips ) ) : __( 'Unknown', 'rcp' );
?>
</td>
</tr>
<?php do_action( 'rcp_edit_member_after', $customer->get_user_id() ); ?>
</tbody>
</table>
</div>
</div>
<div id="rcp-item-edit-actions" class="edit-item">
<input type="hidden" name="rcp-action" value="edit_customer"/>
<input type="hidden" name="customer_id" value="<?php echo esc_attr( $customer->get_id() ); ?>"/>
<?php wp_nonce_field( 'rcp_edit_member_nonce', 'rcp_edit_member_nonce' ); ?>
<input type="submit" name="rcp_update_customer" id="rcp_update_customer" class="button button-primary" value="<?php _e( 'Update Customer', 'rcp' ); ?>"/>
&nbsp;<a href="<?php echo esc_url( $delete_customer_url ); ?>" class="rcp-delete-customer button"><?php _e( 'Delete Customer', 'rcp' ); ?></a>
</div>
</form>
</div>
<?php if ( ! empty( $rcp_options['enable_terms'] ) || ! empty( $rcp_options['enable_privacy_policy'] ) ) : ?>
<div id="rcp-customer-agreements-wrapper" class="rcp-item-section">
<h3><?php _e( 'Agreements', 'rcp' ); ?></h3>
<div id="rcp-customer-agreements-terms-wrapper">
<p><?php _e( 'Agreed to Terms:', 'rcp' ); ?></p>
<?php
if ( ! empty( $terms_agreed ) && is_array( $terms_agreed ) ) {
echo '<ul>';
foreach ( $terms_agreed as $terms_agreed_date ) {
echo '<li>' . date_i18n( get_option( 'date_format' ) . ' H:i:s', $terms_agreed_date ) . '</li>';
}
echo '</ul>';
} else {
echo '<p>' . __( 'None', 'rcp' ) . '</p>';
}
?>
</div>
<div id="rcp-customer-agreements-privacy-policy-wrapper">
<p><?php _e( 'Agreed to Privacy Policy:', 'rcp' ); ?></p>
<?php
if ( ! empty( $privacy_policy_agreed ) && is_array( $privacy_policy_agreed ) ) {
echo '<ul>';
foreach ( $privacy_policy_agreed as $privacy_policy_agreed_date ) {
echo '<li>' . date_i18n( get_option( 'date_format' ) . ' H:i:s', $privacy_policy_agreed_date ) . '</li>';
}
echo '</ul>';
} else {
echo '<p>' . __( 'None', 'rcp' ) . '</p>';
}
?>
</div>
</div>
<?php endif; ?>
<div id="rcp-customer-memberships-wrapper" class="rcp-item-section">
<h3><?php _e( 'Memberships:', 'rcp' ); ?></h3>
<table class="wp-list-table widefat striped payments">
<thead>
<tr>
<th class="column-primary"><?php _e( 'Membership', 'rcp' ); ?></th>
<th><?php _e( 'Amount', 'rcp' ); ?></th>
<th><?php _e( 'Status', 'rcp' ); ?></th>
<th><?php _e( 'Actions', 'rcp' ); ?></th>
</tr>
</thead>
<tbody>
<?php if ( ! empty( $memberships ) ) : ?>
<?php foreach ( $memberships as $membership ) :
/**
* @var RCP_Membership $membership
*/
?>
<tr>
<td class="column-primary" data-colname="<?php esc_attr_e( 'Membership', 'rcp' ); ?>">
<?php echo $membership->get_membership_level_name(); ?>
<button type="button" class="toggle-row">
<span class="screen-reader-text"><?php _e( 'Show more details', 'rcp' ); ?></span>
</button>
</td>
<td data-colname="<?php esc_attr_e( 'Amount', 'rcp' ); ?>"><?php echo $membership->get_formatted_billing_cycle(); ?></td>
<td data-colname="<?php esc_attr_e( 'Status', 'rcp' ); ?>"><?php echo rcp_get_status_label( $membership->get_status() ); ?></td>
<td data-colname="<?php esc_attr_e( 'Actions', 'rcp' ); ?>">
<a href="<?php echo esc_url( rcp_get_memberships_admin_page( array( 'view' => 'edit', 'membership_id' => $membership->get_id() ) ) ); ?>"><?php _e( 'View Details', 'rcp' ); ?></a>
</td>
</tr>
<?php endforeach; ?>
<?php else : ?>
<tr>
<td colspan="4"><?php printf( __( 'No memberships found. Would you like to <a href="%s">add one?</a>', 'rcp' ), esc_url( rcp_get_memberships_admin_page( array( 'view' => 'add', 'customer_id' => $customer->get_id() ) ) ) ); ?></td>
</tr>
<?php endif; ?>
</tbody>
</table>
<?php if ( rcp_multiple_memberships_enabled() ) : ?>
<div class="edit-item">
<a href="<?php echo esc_url( rcp_get_memberships_admin_page( array( 'view' => 'add', 'customer_id' => $customer->get_id() ) ) ); ?>" class="button"><?php _e( 'Add Membership', 'rcp' ); ?></a>
</div>
<?php endif; ?>
</div>
<?php
/**
* Insert content after the "Memberships" section.
*
* @param RCP_Customer $customer
*
* @since 3.1.1
*/
do_action( 'rcp_edit_customer_after_memberships_section', $customer );
?>
<div id="rcp-customer-recent-payments-wrapper" class="rcp-item-section">
<h3><?php _e( 'Recent Payments:', 'rcp' ); ?></h3>
<table class="wp-list-table widefat striped payments">
<thead>
<tr>
<th class="column-primary"><?php _e( 'ID', 'rcp' ); ?></th>
<th><?php _e( 'Date', 'rcp' ); ?></th>
<th><?php _e( 'Amount', 'rcp' ); ?></th>
<th><?php _e( 'Status', 'rcp' ); ?></th>
<th><?php _e( 'Transaction ID', 'rcp' ); ?></th>
<th><?php _e( 'Invoice', 'rcp' ); ?></th>
</tr>
</thead>
<tbody>
<?php if ( ! empty( $payments ) ) : ?>
<?php foreach ( $payments as $payment ) : ?>
<tr>
<td class="column-primary" data-colname="<?php esc_attr_e( 'ID', 'rcp' ); ?>">
<a href="<?php echo esc_url( add_query_arg( 'payment_id', urlencode( $payment->id ), admin_url( 'admin.php?page=rcp-payments&view=edit-payment' ) ) ); ?>"><?php echo $payment->id; ?></a>
<button type="button" class="toggle-row">
<span class="screen-reader-text"><?php _e( 'Show more details', 'rcp' ); ?></span>
</button>
</td>
<td data-colname="<?php esc_attr_e( 'Date', 'rcp' ); ?>"><?php echo $payment->date; ?></td>
<td data-colname="<?php esc_attr_e( 'Amount', 'rcp' ); ?>"><?php echo rcp_currency_filter( $payment->amount ); ?></td>
<td data-colname="<?php esc_attr_e( 'Status', 'rcp' ); ?>"><?php echo rcp_get_status_label( $payment->status ); ?></td>
<td data-colname="<?php esc_attr_e( 'Transaction ID', 'rcp' ); ?>"><?php echo rcp_get_merchant_transaction_id_link( $payment ); ?></td>
<td data-colname="<?php esc_attr_e( 'Invoice', 'rcp' ); ?>">
<a href="<?php echo esc_url( rcp_get_invoice_url( $payment->id ) ); ?>"><?php _e( 'View Invoice', 'rcp' ); ?></a>
</td>
</tr>
<?php endforeach; ?>
<?php if ( $number_payments > 5 ) : ?>
<tr>
<td colspan="6">
<a href="<?php echo esc_url( add_query_arg( 'user_id', urlencode( $customer->get_user_id() ), admin_url( 'admin.php?page=rcp-payments' ) ) ); ?>"><?php printf( __( 'View all %d payments', 'rcp' ), number_format_i18n( $number_payments ) ); ?></a>
</td>
</tr>
<?php endif; ?>
<?php else : ?>
<tr>
<td colspan="6"><?php _e( 'No payments found.', 'rcp' ); ?></td>
</tr>
<?php endif; ?>
</tbody>
</table>
</div>
<div id="rcp-customer-notes-wrapper" class="rcp-item-section">
<h3><?php _e( 'Notes:', 'rcp' ); ?></h3>
<div id="rcp-customer-notes" class="rcp-item-notes">
<?php echo wpautop( $customer->get_notes() ); ?>
</div>
<form id="rcp-edit-customer-notes" method="POST">
<label for="rcp-add-customer-note" class="screen-reader-text"><?php _e( 'Add Note', 'rcp' ); ?></label>
<textarea id="rcp-add-customer-note" class="rcp-add-item-note" name="new_note" placeholder="<?php esc_attr_e( 'Add a note...', 'rcp' ); ?>"></textarea>
<div class="edit-item">
<input type="hidden" name="rcp-action" value="add_customer_note"/>
<input type="hidden" name="customer_id" value="<?php echo esc_attr( $customer->get_id() ); ?>"/>
<?php wp_nonce_field( 'rcp_add_customer_note', 'rcp_add_customer_note_nonce' ); ?>
<input type="submit" class="button" value="<?php esc_attr_e( 'Add Note', 'rcp' ); ?>"/>
</div>
</form>
</div>
</div>
</div>

View File

@@ -0,0 +1 @@
<?php // Silence is golden.

View File

@@ -0,0 +1,47 @@
<?php
/**
* Deprecated Admin Functions
*
* @package restrict-content-pro
* @copyright Copyright (c) 2020, Sandhills Development, LLC
* @license GPL2+
* @since 3.4
*/
/**
* Process member export
*
* @deprecated 3.4
*
* @return void
*/
function rcp_export_members() {
if ( isset( $_POST['rcp-action'] ) && $_POST['rcp-action'] == 'export-members' ) {
_deprecated_function( __FUNCTION__, '3.4' );
include RCP_PLUGIN_DIR . 'core/includes/deprecated/class-rcp-export.php';
include RCP_PLUGIN_DIR . 'core/includes/deprecated/class-rcp-export-members.php';
$export = new RCP_Members_Export;
$export->export();
}
}
//add_action( 'admin_init', 'rcp_export_members' );
/**
* Process payment export
*
* @return void
*/
function rcp_export_payments() {
if( isset( $_POST['rcp-action'] ) && $_POST['rcp-action'] == 'export-payments' ) {
include RCP_PLUGIN_DIR . 'core/includes/class-rcp-export.php';
include RCP_PLUGIN_DIR . 'core/includes/class-rcp-export-payments.php';
$export = new RCP_Payments_Export;
$export->export();
}
}
//add_action( 'admin_init', 'rcp_export_payments' );

View File

@@ -0,0 +1,102 @@
<?php
/**
* Export Page
*
* @package Restrict Content Pro
* @subpackage Admin/Export
* @copyright Copyright (c) 2020, Restrict Content Pro
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
*/
/**
* Render the export page
*
* @deprecated 3.4
*
* @return void
*/
function rcp_export_page() {
_deprecated_function( __FUNCTION__, '3.4' );
global $rcp_options, $rcp_db_name, $wpdb;
$current_page = admin_url( '/admin.php?page=rcp-export' );
?>
<div class="wrap">
<h1><?php _e( 'Export', 'rcp' ); ?></h1>
<?php do_action( 'rcp_export_page_top' ); ?>
<h2><?php _e( 'Memberships Export', 'rcp' ); ?></h2>
<p><?php _e( 'Download membership data as a CSV file. This is useful for tasks such as importing batch users into MailChimp, or other systems.', 'rcp' ); ?></p>
<form id="rcp_export" action="<?php echo esc_attr( $current_page ); ?>" method="post">
<p>
<select name="rcp-subscription" id="rcp-subscription">
<option value="0"><?php _e( 'All', 'rcp' ); ?></option>
<?php
$levels = rcp_get_membership_levels( array( 'number' => 999 ) );
if ( $levels ) :
foreach ( $levels as $key => $level ) :
?>
<option value="<?php echo absint( $level->get_id() ); ?>"><?php echo esc_html( $level->get_name() ); ?></option>
<?php
endforeach;
endif;
?>
</select>
<label for="rcp-subscription"><?php _e( 'Choose the subscription to export memberships from', 'rcp' ); ?></label><br/>
<select name="rcp-status" id="rcp-status">
<option value="active"><?php _e( 'Active', 'rcp' ); ?></option>
<option value="pending"><?php _e( 'Pending', 'rcp' ); ?></option>
<option value="expired"><?php _e( 'Expired', 'rcp' ); ?></option>
<option value="cancelled"><?php _e( 'Cancelled', 'rcp' ); ?></option>
</select>
<label for="rcp-status"><?php _e( 'Choose the status to export', 'rcp' ); ?></label><br/>
<input type="number" id="rcp-number" name="rcp-number" class="small-text" value="500" />
<label for="rcp-number"><?php _e( 'Maximum number of memberships to export', 'rcp' ); ?><br/>
<input type="number" id="rcp-offset" name="rcp-offset" class="small-text" value="0" />
<label for="rcp-offset"><?php _e( 'The number of memberships to skip', 'rcp' ); ?>
</p>
<p><?php _e( 'If you need to export a large number of memberships, export them in batches using the max and offset options', 'rcp' ); ?></p>
<input type="hidden" name="rcp-action" value="export-members"/>
<input type="submit" class="button-secondary" value="<?php _e( 'Download Memberships CSV', 'rcp' ); ?>"/>
</form>
<!-- payments export -->
<h2><?php _e( 'Payments Export', 'rcp' ); ?></h2>
<p><?php _e( 'Download payment data as a CSV file. Use this file for your own record keeping or tracking.', 'rcp' ); ?></p>
<form id="rcp_export" action="<?php echo esc_url( $current_page ); ?>" method="post">
<p>
<select name="rcp-year" id="rcp-year">
<option value="0"><?php _e( 'All years', 'rcp' ); ?>
<?php
$current = date( 'Y' );
$year = $current;
$end = $current - 5;
while ( $year >= $end ) :
// phpcs:disable
?>
<option value="<?php echo $year; ?>"><?php echo $year; ?></option>
<?php
$year--;
endwhile;
// phpcs:enable
?>
</select>
<select name="rcp-month" id="rcp-month">
<option value="0"><?php _e( 'All months', 'rcp' ); ?>
<?php for ( $i = 1; $i <= 12; $i++ ) : ?>
<option value="<?php echo esc_attr( $i ); ?>"><?php echo esc_attr( rcp_get_month_name( $i ) ); ?></option>
<?php endfor; ?>
</select>
</p>
<p>
<input type="submit" class="button-secondary" value="<?php _e( 'Download Payments CSV', 'rcp' ); ?>"/>
<input type="hidden" name="rcp-action" value="export-payments"/>
</p>
</form>
<?php do_action( 'rcp_export_page_bottom' ); ?>
</div><!--end wrap-->
<?php
}

View File

@@ -0,0 +1,299 @@
<?php
/**
* Export Actions
*
* @package restrict-content-pro
* @copyright Copyright (c) 2020, Sandhills Development, LLC
* @license GPL2+
* @since 3.4
*/
namespace RCP\Admin\Export;
use RCP\Utils\Batch;
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Add an export job to the queue
*
* @since 3.4
*/
function add_export_job() {
if ( empty( $_POST['rcp_batch_export_nonce'] ) || ! wp_verify_nonce( $_POST['rcp_batch_export_nonce'], 'rcp_batch_export' ) ) {
wp_die( __( 'You do not have permission to perform this action.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 403 ) );
}
if ( ! rcp_current_user_can_export() ) {
wp_die( __( 'You do not have permission to perform this action.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 403 ) );
}
if ( empty( $_POST['exporter'] ) ) {
wp_die( __( 'Missing exporter.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 400 ) );
}
$exporter = rcp_get_csv_exporter( $_POST['exporter'] );
if ( empty( $exporter ) ) {
wp_die( __( 'This is not a registered exporter.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 400 ) );
}
// Sanitize export settings.
if ( ! empty( $_POST['export_settings'] ) && is_array( $_POST['export_settings'] ) ) {
$settings = array_map( 'sanitize_text_field', $_POST['export_settings'] );
} else {
$settings = array();
}
/**
* Use this hook to include the job callback class file.
*
* @param string $exporter ['callback'] Name of the class.
*/
do_action( 'rcp_batch_processing_class_include', $exporter['callback'] );
$job_name = sprintf( __( 'CSV %s Export - %s', 'rcp' ), $exporter['name'], date( 'Y-m-d H:i:s', current_time( 'timestamp' ) ) );
$job_id = Batch\add_batch_job( array(
'name' => $job_name,
'callback' => ( $exporter['callback'] ),
'queue' => 'rcp_csv_export',
'data' => array(
'filepath' => tempnam( get_temp_dir(), 'rcp-' ),
'settings' => $settings
)
) );
if ( is_wp_error( $job_id ) ) {
wp_die( $job_id->get_error_message(), __( 'Error', 'rcp' ), array( 'response' => 500 ) );
}
$job = Batch\get_job( $job_id );
if ( ! $job instanceof Batch\Job ) {
wp_die( __( 'Unable to retrieve job.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 500 ) );
}
$redirect_url = add_query_arg( array(
'rcp-job-id' => absint( $job->get_id() ),
'rcp-job-autostart' => 1
), admin_url( 'admin.php?page=rcp-tools&tab=batch' ) );
wp_safe_redirect( esc_url_raw( $redirect_url ) );
exit;
}
add_action( 'rcp_action_add_export_job', __NAMESPACE__ . '\add_export_job' );
/**
* Include batch CSV export class files.
*
* @param string $callback Export class name.
*
* @since 3.4
* @return void
*/
function include_batch_export_files( $callback ) {
$exporter = rcp_get_csv_exporter_by_callback( $callback );
if ( empty( $exporter ) ) {
return;
}
// Include the main file.
require_once RCP_PLUGIN_DIR . 'core/includes/batch/csv-exports/class-batch-csv-export-base.php';
// Include the file specifically for this importer.
if ( file_exists( $exporter['callback_file'] ) ) {
require_once $exporter['callback_file'];
}
}
add_action( 'rcp_batch_processing_class_include', __NAMESPACE__ . '\include_batch_export_files' );
/**
* Add extra settings to the Memberships Export
*
* @param array $exporter
*
* @since 3.4
*/
function memberships_settings( $exporter ) {
$levels = rcp_get_membership_levels( array( 'number' => 999 ) );
?>
<table class="form-table">
<tbody>
<?php if ( $levels ) : ?>
<tr>
<th>
<label for="rcp-membership-level"><?php _e( 'Memberships', 'rcp' ); ?></label>
</th>
<td>
<select id="rcp-membership-level" name="export_settings[level_id]">
<option value=""><?php _e( 'All Levels', 'rcp' ); ?></option>
<?php foreach ( $levels as $level ) : ?>
<option value="<?php echo esc_attr( $level->get_id() ); ?>"><?php echo esc_html( $level->get_name() ); ?></option>
<?php endforeach; ?>
</select>
<p class="description"><?php _e( 'Choose a membership level to only export memberships from that level.', 'rcp' ); ?></p>
</td>
</tr>
<?php endif; ?>
<tr>
<th>
<label for="rcp-membership-status"><?php _e( 'Membership Status', 'rcp' ); ?></label>
</th>
<td>
<select id="rcp-membership-status" name="export_settings[status]">
<option value="all"><?php _e( 'All', 'rcp' ); ?></option>
<option value="active"><?php _e( 'Active', 'rcp' ); ?></option>
<option value="pending"><?php _e( 'Pending', 'rcp' ); ?></option>
<option value="expired"><?php _e( 'Expired', 'rcp' ); ?></option>
<option value="cancelled"><?php _e( 'Cancelled', 'rcp' ); ?></option>
</select>
<p class="description"><?php _e( 'Choose a status to only export memberships with that status.', 'rcp' ); ?></p>
</td>
</tr>
<tr>
<th>
<label for="rcp-membership-number"><?php _e( 'Maximum Number', 'rcp' ); ?></label>
</th>
<td>
<input type="number" id="rcp-membership-number" name="export_settings[number]" class="small-text">
<p class="description"><?php _e( 'Maximum number of memberships to export. Leave blank to export all.', 'rcp' ); ?></p>
</td>
</tr>
</tbody>
</table>
<?php
}
add_action( 'rcp_csv_exporter_settings_memberships', __NAMESPACE__ . '\memberships_settings' );
/**
* Add extra settings to the Payments Export
*
* @param array $exporter
*
* @since 3.4
*/
function payments_settings( $exporter ) {
$current = date( 'Y' );
$year = $current;
$end = $current - 5;
?>
<table class="form-table">
<tbody>
<tr>
<th>
<?php _e( 'Payment Dates', 'rcp' ); ?>
</th>
<td>
<label for="rcp-year" class="screen-reader-text"><?php _e( 'Select a year to only export payments made in that year', 'rcp' ); ?></label>
<select id="rcp-year" name="export_settings[year]">
<option value="0"><?php _e( 'All years', 'rcp' ); ?></option>
<?php while ( $year >= $end ) : ?>
<option value="<?php echo esc_attr( $year ); ?>"><?php echo esc_html( $year ); ?></option>
<?php $year--; endwhile; ?>
</select>
<label for="rcp-month" class="screen-reader-text"><?php _e( 'Select a month to only export payments made in that month', 'rcp' ); ?></label>
<select id="rcp-month" name="export_settings[month]">
<option value="0"><?php _e( 'All months', 'rcp' ); ?></option>
<?php for ( $i = 1; $i <= 12; $i++ ) : ?>
<option value="<?php echo esc_attr( $i ); ?>"><?php echo esc_html( rcp_get_month_name( $i ) ); ?></option>
<?php endfor; ?>
</select>
</td>
</tr>
</tbody>
</table>
<?php
}
add_action( 'rcp_csv_exporter_settings_payments', __NAMESPACE__ . '\payments_settings' );
/**
* Downloads the export file and deletes the temp file from the system.
*
* @since 3.4
*/
function download_export_file() {
if ( ! wp_verify_nonce( $_GET['_wpnonce'], 'rcp_download_export_file' ) ) {
wp_die( __( 'Nonce verification failed.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 403 ) );
}
if ( ! rcp_current_user_can_export() ) {
wp_die( __( 'You do not have permission to perform this action.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 403 ) );
}
if ( empty( $_GET['export_id'] ) ) {
wp_die( __( 'Missing export ID.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 400 ) );
}
$job = Batch\get_job( absint( $_GET['export_id'] ) );
if ( ! $job instanceof Batch\Job || 'rcp_csv_export' !== $job->get_queue() ) {
wp_die( __( 'Invalid export.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 400 ) );
}
$data = $job->get_data();
$file_path = ! empty( $data['filepath'] ) ? $data['filepath'] : false;
$export_details = rcp_get_csv_exporter_by_callback( $job->get_callback() );
if ( empty( $file_path ) || ! file_exists( $file_path ) ) {
wp_die( __( 'Export file not found.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 400 ) );
}
ignore_user_abort( true );
if ( ! rcp_is_func_disabled( 'set_time_limit' ) && ! ini_get( 'safe_mode' ) ) {
set_time_limit( 0 );
}
nocache_headers();
header( 'Content-Type: text/csv; charset=utf-8' );
header( 'Content-Disposition: attachment; filename="rcp-' . $export_details['key'] . '-export-' . date( 'Y-m-d' ) . '.csv"' );
/**
* We need to append a BOM to the export so that Microsoft Excel knows
* that the file is in Unicode.
*/
echo "\xEF\xBB\xBF";
readfile( $file_path );
@unlink( $file_path );
die();
}
add_action( 'rcp_action_download_export_file', __NAMESPACE__ . '\download_export_file' );
/**
* Redirects the old separate export page to the tools page. Export now lives there in an Export tab.
*
* @since 3.4
*/
function redirect_old_export_page() {
if ( ! is_admin() || empty( $_GET['page'] ) || 'rcp-export' !== $_GET['page'] ) {
return;
}
wp_safe_redirect( esc_url_raw( admin_url( 'admin.php?page=rcp-tools&tab=export' ) ) );
exit;
}
add_action( 'init', __NAMESPACE__ . '\redirect_old_export_page', 1 );

View File

@@ -0,0 +1 @@
<?php // Silence is golden.

View File

@@ -0,0 +1,121 @@
<?php
/**
* Help Menus Setup (old)
*
* For WP version less than 3.3
*
* @package Restrict Content Pro
* @subpackage Admin/Help Menus Setup
* @copyright Copyright (c) 2017, Restrict Content Pro
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
*/
/**
* Setup help tabs
*
* @param $contextual_help
* @param $screen_id
* @param $screen
*
* @return string
*/
function rcp_help_tabs_old($contextual_help, $screen_id, $screen) {
global $rcp_members_page;
global $rcp_subscriptions_page;
global $rcp_discounts_page;
global $rcp_payments_page;
global $rcp_settings_page;
// replace edit with the base of the page you're adding the help info to
switch($screen->base) :
case $rcp_members_page:
$contextual_help = '<h3>' . __('General', 'rcp') . '</h3>';
$contextual_help .= rcp_render_members_tab_content('general');
$contextual_help .= '<h3>' . __('Adding Subscriptions', 'rcp') . '</h3>';
$contextual_help .= rcp_render_members_tab_content('adding_subs');
$contextual_help .= '<h3>' . __('Member Details', 'rcp') . '</h3>';
$contextual_help .= rcp_render_members_tab_content('member_details');
$contextual_help .= '<h3>' . __('Editing Members', 'rcp') . '</h3>';
$contextual_help .= rcp_render_members_tab_content('editing_member');
return $contextual_help;
break;
case $rcp_subscriptions_page:
$contextual_help = '<h3>' . __('General', 'rcp') . '</h3>';
$contextual_help .= rcp_render_subscriptions_tab_content('general');
$contextual_help .= '<h3>' . __('Adding Subscriptions', 'rcp') . '</h3>';
$contextual_help .= rcp_render_subscriptions_tab_content('adding_subscriptions');
$contextual_help .= '<h3>' . __('Editing Subscriptions', 'rcp') . '</h3>';
$contextual_help .= rcp_render_subscriptions_tab_content('editing_subscriptions');
$contextual_help .= '<h3>' . __('Deleting Subscriptions', 'rcp') . '</h3>';
$contextual_help .= rcp_render_subscriptions_tab_content('deleting_subscriptions');
return $contextual_help;
break;
case $rcp_discounts_page:
$contextual_help = '<h3>' . __('General', 'rcp') . '</h3>';
$contextual_help .= rcp_render_discounts_tab_content('general');
$contextual_help .= '<h3>' . __('Adding Discounts', 'rcp') . '</h3>';
$contextual_help .= rcp_render_discounts_tab_content('adding_discounts');
$contextual_help .= '<h3>' . __('Editing Discounts', 'rcp') . '</h3>';
$contextual_help .= rcp_render_discounts_tab_content('editing_discounts');
$contextual_help .= '<h3>' . __('Using Discounts', 'rcp') . '</h3>';
$contextual_help .= rcp_render_discounts_tab_content('using_discounts');
return $contextual_help;
break;
case $rcp_payments_page:
$contextual_help = '<h3>' . __('General', 'rcp') . '</h3>';
$contextual_help .= rcp_render_payments_tab_content('general');
return $contextual_help;
break;
case $rcp_settings_page:
$contextual_help = '<h3>' . __('General', 'rcp') . '</h3>';
$contextual_help .= rcp_render_settings_tab_content('general');
$contextual_help .= '<h3>' . __('Messages', 'rcp') . '</h3>';
$contextual_help .= rcp_render_settings_tab_content('messages');
$contextual_help .= '<h3>' . __('PayPal', 'rcp') . '</h3>';
$contextual_help .= rcp_render_settings_tab_content('paypal');
$contextual_help .= '<h3>' . __('Signup Forms', 'rcp') . '</h3>';
$contextual_help .= rcp_render_settings_tab_content('signup_forms');
$contextual_help .= '<h3>' . __('Emails', 'rcp') . '</h3>';
$contextual_help .= rcp_render_settings_tab_content('emails');
$contextual_help .= '<h3>' . __('Misc', 'rcp') . '</h3>';
$contextual_help .= rcp_render_settings_tab_content('misc');
$contextual_help .= '<h3>' . __('Logging', 'rcp') . '</h3>';
$contextual_help .= rcp_render_settings_tab_content('logging');
return $contextual_help;
break;
default:
// show the default WP help tab content
return $contextual_help;
break;
endswitch;
}
add_action('contextual_help', 'rcp_help_tabs_old', 100, 3);

View File

@@ -0,0 +1,220 @@
<?php
/**
* Help Menus Setup
*
* @package Restrict Content Pro
* @subpackage Admin/Help Menus Setup
* @copyright Copyright (c) 2017, Restrict Content Pro
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
*/
/**
* Setup help tabs
*/
function rcp_help_tabs() {
global $rcp_members_page;
global $rcp_customers_page;
global $rcp_subscriptions_page;
global $rcp_discounts_page;
global $rcp_payments_page;
global $rcp_settings_page;
$screen = get_current_screen();
if(!is_object($screen))
return;
switch($screen->id) :
case $rcp_members_page :
$screen->add_help_tab(
array(
'id' => 'general',
'title' => __( 'General', 'rcp' ),
'content' => rcp_render_members_tab_content( 'general' )
)
);
$screen->add_help_tab(
array(
'id' => 'adding_subs',
'title' => __( 'Adding Memberships', 'rcp' ),
'content' => rcp_render_members_tab_content( 'adding_subs' )
)
);
$screen->add_help_tab(
array(
'id' => 'member_details',
'title' => __( 'Membership Details', 'rcp' ),
'content' => rcp_render_members_tab_content( 'member_details' )
)
);
$screen->add_help_tab(
array(
'id' => 'editing_member',
'title' => __( 'Editing Memberships', 'rcp' ),
'content' => rcp_render_members_tab_content( 'editing_member' )
)
);
break;
case $rcp_customers_page :
$screen->add_help_tab(
array(
'id' => 'general',
'title' => __( 'General', 'rcp' ),
'content' => rcp_render_customers_tab_content( 'general' )
)
);
$screen->add_help_tab(
array(
'id' => 'customer_details',
'title' => __( 'Customer Details', 'rcp' ),
'content' => rcp_render_customers_tab_content( 'customer_details' )
)
);
$screen->add_help_tab(
array(
'id' => 'editing_customers',
'title' => __( 'Editing Customers', 'rcp' ),
'content' => rcp_render_customers_tab_content( 'editing_customers' )
)
);
break;
case $rcp_subscriptions_page :
$screen->add_help_tab(
array(
'id' => 'general',
'title' => __( 'General', 'rcp' ),
'content' => rcp_render_subscriptions_tab_content( 'general' )
)
);
$screen->add_help_tab(
array(
'id' => 'adding_subscriptions',
'title' => __( 'Adding Levels', 'rcp' ),
'content' => rcp_render_subscriptions_tab_content( 'adding_subscriptions' )
)
);
$screen->add_help_tab(
array(
'id' => 'editing_subscriptions',
'title' => __( 'Editing Levels', 'rcp' ),
'content' => rcp_render_subscriptions_tab_content( 'editing_subscriptions' )
)
);
$screen->add_help_tab(
array(
'id' => 'deleting_subscriptions',
'title' => __( 'Deleting Levels', 'rcp' ),
'content' => rcp_render_subscriptions_tab_content( 'deleting_subscriptions' )
)
);
break;
case $rcp_discounts_page :
$screen->add_help_tab(
array(
'id' => 'general',
'title' => __( 'General', 'rcp' ),
'content' => rcp_render_discounts_tab_content( 'general' )
)
);
$screen->add_help_tab(
array(
'id' => 'adding_discounts',
'title' => __( 'Adding Discounts', 'rcp' ),
'content' => rcp_render_discounts_tab_content( 'adding_discounts' )
)
);
$screen->add_help_tab(
array(
'id' => 'editing_discounts',
'title' => __( 'Editing Discounts', 'rcp' ),
'content' => rcp_render_discounts_tab_content( 'editing_discounts' )
)
);
$screen->add_help_tab(
array(
'id' => 'using_discounts',
'title' => __( 'Using Discounts', 'rcp' ),
'content' => rcp_render_discounts_tab_content( 'using_discounts' )
)
);
break;
case $rcp_payments_page :
$screen->add_help_tab(
array(
'id' => 'general',
'title' => __( 'General', 'rcp' ),
'content' => rcp_render_payments_tab_content( 'general' )
)
);
break;
case $rcp_settings_page :
$screen->add_help_tab(
array(
'id' => 'general',
'title' => __( 'General', 'rcp' ),
'content' => rcp_render_settings_tab_content( 'general' )
)
);
$screen->add_help_tab(
array(
'id' => 'pages',
'title' => __( 'Pages', 'rcp' ),
'content' => rcp_render_settings_tab_content( 'pages' )
)
);
$screen->add_help_tab(
array(
'id' => 'messages',
'title' => __( 'Messages', 'rcp' ),
'content' => rcp_render_settings_tab_content( 'messages' )
)
);
$screen->add_help_tab(
array(
'id' => 'payments',
'title' => __( 'Payments', 'rcp' ),
'content' => rcp_render_settings_tab_content( 'payments' )
)
);
$screen->add_help_tab(
array(
'id' => 'emails',
'title' => __( 'Emails', 'rcp' ),
'content' => rcp_render_settings_tab_content( 'emails' )
)
);
$screen->add_help_tab(
array(
'id' => 'invoices',
'title' => __( 'Invoices', 'rcp' ),
'content' => rcp_render_settings_tab_content( 'invoices' )
)
);
$screen->add_help_tab(
array(
'id' => 'misc',
'title' => __( 'Misc', 'rcp' ),
'content' => rcp_render_settings_tab_content( 'misc' )
)
);
$screen->add_help_tab(
array(
'id' => 'logging',
'title' => __( 'Logging', 'rcp' ),
'content' => rcp_render_settings_tab_content( 'logging' )
)
);
break;
default:
break;
endswitch;
}
add_action('admin_menu', 'rcp_help_tabs', 100);

View File

@@ -0,0 +1,380 @@
<?php
/**
* Help Menus
*
* @package Restrict Content Pro
* @subpackage Admin/Help Menus
* @copyright Copyright (c) 2017, Restrict Content Pro
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
*/
if ( get_bloginfo('version') < 3.3 ) {
// use old help tab format for WP version less than 3.3
include('help-menus-setup-old.php');
} else {
// use the new, better format
include('help-menus-setup.php');
}
/**
* Render members tab content
*
* @param string $id
*
* @return string
*/
function rcp_render_members_tab_content( $id ) {
switch( $id ) :
case 'general' :
ob_start(); ?>
<p><?php _e( 'This page displays an overview of the memberships on your site, sorted by last updated.', 'rcp' ); ?></p>
<p><?php _e( 'By default, all memberships are shown in the list, but you can choose to filter by status by simply clicking on the status name, just above the memberships table.', 'rcp' ); ?></p>
<p><?php _e( 'On this page, you can perform a variety of tasks, including:', 'rcp' ); ?></p>
<ul>
<li><?php _e( 'View membership details of any customer', 'rcp' ); ?></li>
<li><?php _e( 'Edit the membership details of any customer', 'rcp' ); ?></li>
<li><?php _e( 'Activate / Cancel / Expire / Delete the membership of any customer', 'rcp' ); ?></li>
<li><?php _e( 'Add new memberships to pre-existing or new customers', 'rcp' ); ?></li>
</ul>
<p><?php _e( 'The search feature has two options: you can search by user account information such as name, email, or login; or you can search by gateway subscription ID.', 'rcp' ); ?></p>
<?php
break;
case 'adding_subs' :
ob_start(); ?>
<p><?php _e( 'Adding a membership to a new or existing user is easy. Simply click "Add New" at the top of the page. You will be asked to enter a customer email address - this can be the email of a customer that already exists, or the email for a brand new user. A new user and customer record will be created if they don\'t already exist. Then choose the other information, such as membership level, status, expiration date, etc.', 'rcp' ); ?></p>
<p><?php _e( '<strong>Note</strong>: when you add a membership to a user manually, you <em>cannot</em> charge that user for the membership. This simply allows you to grant access to premium content for special cases, such as when you have given a membership away as a competition prize, or a user has paid with some alternate method.', 'rcp' ); ?></p>
<p><?php _e( 'Also note, you can also add / modify a user\'s membership from the regular WordPress Users page. At the right side of each user entry will be links to Add / Edit Membership.', 'rcp' ); ?></p>
<?php
break;
case 'member_details' :
ob_start(); ?>
<p><?php _e( 'The details page for a member shows information about that customer\'s membership, including:', 'rcp' ); ?></p>
<ul>
<li><?php _e( 'The Status of the membership, either Active, Pending, Expired, or Cancelled', 'rcp' ); ?></li>
<li><?php _e( 'The membership level the customer is signed up with', 'rcp' ); ?></li>
<li><?php _e( 'The membership\'s billing cycle and times it has been billed for so far', 'rcp' ); ?></li>
<li><?php _e( 'The expiration date for the customer\'s membership', 'rcp' ); ?></li>
<li><?php _e( 'Payment gateway identifiers, such as the customer ID and/or subscription ID', 'rcp' ); ?></li>
<li><?php _e( 'A list of all payments that have been made for this membership', 'rcp' ); ?></li>
<li><?php _e( 'Notes and logs associated with the membership', 'rcp' ); ?></li>
</ul>
<?php
break;
case 'editing_member' :
ob_start(); ?>
<p><?php _e( 'The Edit Membership page allows administrators to modify details of a customer\'s membership. The details that can be changed are:', 'rcp' ); ?></p>
<ul>
<li><?php _e( 'Status - sets the state of the customer\'s membership. Only <em>Active</em> and <em>Cancelled</em> members can view restricted content', 'rcp' ); ?></li>
<li><?php _e( 'Date Created - this is the date the membership was first created', 'rcp' ); ?></li>
<li><?php _e( 'Expiration Date - this is the date the customer\'s membership will expire or automatically renew. When a member\'s expiration date is reach, their membership status will be automatically changed to Expired', 'rcp' ); ?></li>
<li><?php _e( 'Auto Renew - if checked, this designates that the customer has a recurring membership. Note that checking this on or off doesn\'t impact the subscription/billing in the payment gateway.', 'rcp' ); ?></li>
<li><?php _e( 'Gateway Customer ID - the customer\'s ID in the payment gateway. Not all payment gateways utilize this. In Stripe this value begins with <em>cus_</em>', 'rcp' ); ?></li>
<li><?php _e( 'Gateway Subscription ID - the customer\'s subscription ID in the payment gateway, if they have a recurring membership. In Stripe this value begins with <em>sub_</em>', 'rcp' ); ?></li>
</ul>
<?php
break;
default;
break;
endswitch;
return ob_get_clean();
}
/**
* Render Customer tab content
*
* @param string $id
*
* @since 3.0
* @return string
*/
function rcp_render_customers_tab_content( $id ) {
switch ( $id ) {
case 'general' :
ob_start(); ?>
<p><?php _e( 'This page displays an overview of the customers on your site, sorted by ID.', 'rcp' ); ?></p>
<p><?php _e( 'By default, all customers are shown in the list, but you can choose to filter by verification status by simply clicking on the status name, just above the customers table.', 'rcp' ); ?></p>
<p><?php _e( 'On this page, you can perform a variety of tasks, including:', 'rcp' ); ?></p>
<ul>
<li><?php _e( 'View details of any customer', 'rcp' ); ?></li>
<li><?php _e( 'Edit the details of any customer', 'rcp' ); ?></li>
<li><?php _e( 'Delete customers', 'rcp' ); ?></li>
</ul>
<p><?php _e( 'The search box will search user logins, display names, and email addresses.', 'rcp' ); ?></p>
<?php
break;
case 'customer_details' :
ob_start(); ?>
<p><?php _e( 'The details page for a customer shows the following information:', 'rcp' ); ?></p>
<ul>
<li><?php _e( 'Account username (with a link to edit the user account)', 'rcp' ); ?></li>
<li><?php _e( 'The customer ID number', 'rcp' ); ?></li>
<li><?php _e( 'The customer\'s first and last name', 'rcp' ); ?></li>
<li><?php _e( 'The customer\'s email address', 'rcp' ); ?></li>
<li><?php _e( 'The date the customer registered', 'rcp' ); ?></li>
<li><?php _e( 'The date the customer last logged in to their account', 'rcp' ); ?></li>
<li><?php _e( 'The customer\'s email verification status', 'rcp' ); ?></li>
<li><?php _e( 'The customer\'s known IP addresses', 'rcp' ); ?></li>
<li><?php _e( 'The customer\'s memberships', 'rcp' ); ?></li>
<li><?php _e( 'The customer\'s payments', 'rcp' ); ?></li>
<li><?php _e( 'Notes about the customer', 'rcp' ); ?></li>
</ul>
<?php
break;
case 'editing_customers' :
ob_start(); ?>
<p><?php _e( 'You can edit the following information about each customer:', 'rcp' ); ?></p>
<ul>
<li><?php _e( 'First and last name - changing these fields also updates the values associated with the user account.', 'rcp' ); ?></li>
<li><?php _e( 'Email address - updating this also updates the email address associated with the user account.', 'rcp' ); ?></li>
<li><?php _e( 'Notes' ); ?></li>
</ul>
<p><?php _e( 'If you delete a customer, their memberships will automatically be cancelled. The associated user account will <strong>not</strong> be deleted.', 'rcp' ); ?></p>
<?php break;
}
return ob_get_clean();
}
/**
* Render Membership Level tab content
*
* @param string $id
*
* @return string
*/
function rcp_render_subscriptions_tab_content( $id ) {
switch( $id ) :
case 'general' :
ob_start(); ?>
<p><?php _e( 'Membership levels allow you to setup different membership packages. For example, you could have one package that grants members access to your premium content for one month, and another that grants users access for an entire year. There is no limit to the number of packages you can create. You can also create "Trial" packages; these grant users premium access for a limited period of time, and can be completely free.', 'rcp' ); ?></p>
<p><?php _e( 'This page will show you an overview of all the membership packages you have created on your site. It will also show a variety of details for each package, including the total number of Active subscribers for each level.', 'rcp' ); ?></p>
<?php
break;
case 'adding_subscriptions' :
ob_start(); ?>
<p><?php _e( 'Adding new membership levels is very simple. First, enter the name you want to give the membership package. This name is displayed on the registration form. Second, give your membership package a description. This is also shown on the registration form.', 'rcp' ); ?></p>
<p><?php _e( 'Next you need to choose the duration for your membership package. There are several of options for this:', 'rcp' ); ?></p>
<ol>
<li><?php _e( 'If you are creating a free, unlimited registration, enter "0" here. This will cause users who register with this package to have no expiration date.', 'rcp' ); ?></li>
<li><?php _e( 'If you are creating a trial membership, which will grant users access to premium content for a limited amount of time for free, then choose the length of time you wish the trial to last.', 'rcp' ); ?></li>
<li><?php _e( 'If you are creating a regular, paid membership, then simply enter the duration for the membership.', 'rcp' ); ?></li>
</ol>
<p><?php _e( 'Once you have entered a number for the duration, ensure you also choose the correct time unit for the package. This is either <em>Day(s)</em>, <em>Month(s)</em>, or <em>Year(s)</em>.', 'rcp' ); ?></p>
<p><?php _e( 'Next, enter the price for this membership. The price will be the amount paid for the duration chosen above. So, for example, if you entered 3 Months above, then this would be the price for 3 months of access to the premium content.', 'rcp' ); ?></p>
<p><?php _e( 'If you want a free or trial membership, simply enter "0", or choose "Free" from the drop down.', 'rcp' ); ?></p>
<?php
break;
case 'editing_subscriptions' :
ob_start(); ?>
<p><?php _e( 'After you have created a membership level, you may edit it at anytime. Making changes to a membership level will have no effect on current subscribers to that membership, even if you change the price of the package.', 'rcp' ); ?></p>
<p><?php _e( 'To edit a membership level, click "Edit" on the right side of the screen for the membership you wish to modify. You will be presented with an edit form to change any and all details of the package. Simply make the changes you need and click "Update Membership Level".', 'rcp' ); ?></p>
<?php
break;
case 'deleting_subscriptions' :
ob_start(); ?>
<p><?php _e( 'If at anytime you wish to remove a membership level, you may do so by clicked "Delete" on the right side of the screen, from the Membership Levels page. A popup notification will appear, alerting you that you are about to remove the level permanently. If you confirm, the data for the membership level will be deleted, with no way to get it back.', 'rcp' ); ?></p>
<p><?php _e( '<strong>Note</strong>: when you delete a membership level, all subscribers of that membership will have their status changed to <strong>Cancelled</strong>, meaning that all of them will have their access to premium content revoked.', 'rcp' ); ?></p>
<p><?php _e( 'If you are going to delete a membership with active subscribers, it is advised that you first change the membership level of each of the subscribers before deleting the membership package.', 'rcp' ); ?></p>
<?php
break;
default;
break;
endswitch;
return ob_get_clean();
}
/**
* Render discounts tab content
*
* @param string $id
*
* @return string
*/
function rcp_render_discounts_tab_content( $id ) {
switch( $id ) :
case 'general' :
ob_start(); ?>
<p><?php _e( 'Discount codes allow you to give special offers to new registrations, giving extra incentive for users to sign up for your website\'s premium content section. Restrict Content Pro\'s discount codes work just like any other. There are two kinds:', 'rcp' ); ?></p>
<ul>
<li><?php _e( 'Flat - a flat dollar amount discount. This will take the specified number of dollars (or whatever your currency is) off of the base membership price.', 'rcp' ); ?></li>
<li><?php printf( __( 'Percentage - a discount based on a percentage amount. So if your membership is %1$s, and your discount is 10%%, the registration price will be %2$s.', 'rcp' ), rcp_currency_filter( 10 ), rcp_currency_filter( 9 ) ); ?></li>
</ul>
<?php
break;
case 'adding_discounts' :
ob_start(); ?>
<p><?php _e( 'You may create an unlimited number of discount codes, and adding them is simple. From the Discount Codes menu page, simply fill out the form for Add New Discount.', 'rcp' ); ?></p>
<ul>
<li><?php _e( 'Name - This is just used for your own administrative / organizational purposes.', 'rcp' ); ?></li>
<li><?php _e( 'Description - This is used to describe the discount code, and only used for administrative / organizational purposes.', 'rcp' ); ?></li>
<li><?php _e( 'Code - This is the actual code that users will enter in the registration form when signing up. The code can be anything you want, though a string of all uppercase letters, that preferably spell out a word or phrase, is recommended. It is best to avoid using spaces.', 'rcp' ); ?></li>
<li><?php _e( 'Type - This is the type of discount you want this code to give, either flat or percentage. Read "General" for an explanation of code types.', 'rcp' ); ?></li>
<li><?php _e( 'Amount - This is the amount of discount to give with this code. The discount amount is subtracted from the membership base price.', 'rcp' ); ?></li>
<li><?php _e( 'Membership Level - You can choose to limit the discount code to a specific membership level only, or allow it to be activated on any level.', 'rcp' ); ?></li>
<li><?php _e( 'Expiration Date - Optionally, you can select a date for the discount code to expire. Leave blank for no expiration.', 'rcp' ); ?></li>
<li><?php _e( 'Max Uses - You can specify a maximum number of times a discount code may be used. Leave blank for unlimited.', 'rcp' ); ?></li>
</ul>
<?php
break;
case 'editing_discounts' :
ob_start(); ?>
<p><?php _e( 'Discount codes can be edited at anytime to change the name, description, code, type, and/or amount. You can also deactivate codes to make them unavailable, but keep them available for future use.', 'rcp' ); ?></p>
<p><?php _e( 'To edit a discount, click "Edit" on the right side of the screen, next to the discount code you wish to modify. This will bring up a form with all of the discount code\'s information. Simply change what you wish and click "Update Discount" when finished. You may cancel your editing by clicking "Cancel" at the top of the page.', 'rcp' ); ?></p>
<?php
break;
case 'using_discounts' :
ob_start(); ?>
<p><?php _e( 'Discount codes are used when a user registers a new membership on your site. As long as you have at least one discount code created, there will be an option for the user to enter a code when filling out the registration form.', 'rcp' ); ?></p>
<p><?php _e( 'If a user enters a discount code, then that code is checked for validity when the form is submitted. If the code is invalid, an error will be shown, and if the code is valid, then the discount will be applied to the membership price when the user is redirected to the payment gateway.', 'rcp' ); ?></p>
<p><?php _e( '<strong>Note</strong>: users may only use a discount code one time. When a code is used, it is recorded in the database for that user and may never be used by them again.', 'rcp' ); ?></p>
<p><?php _e( 'Each time a discount code is used, a count will be increased in the database so that you can see the total number of times a code has been used.', 'rcp' ); ?></p>
<p><?php _e( 'If you wish to see all the discount codes a particular user has used, click "Details" on the user from the Members page.', 'rcp' ); ?></p>
<?php
break;
default;
break;
endswitch;
return ob_get_clean();
}
/**
* Render payments tab content
*
* @param string $id
*
* @return string
*/
function rcp_render_payments_tab_content( $id ) {
switch( $id ) :
case 'general' :
ob_start(); ?>
<p><?php _e( 'This page is a log of all payments that have ever been recorded with Restrict Content Pro. Each time a payment is made, whether it is a one-time sign up payment, or a recurring membership payment, it is logged here.', 'rcp' ); ?></p>
<p><?php _e( 'You can see the membership package the payment was made for, the date is was made, the total amount paid, and the user that made the payment.', 'rcp' ); ?></p>
<p><?php _e( 'At the bottom of the payments list, you can also see the total amount that has been earned from membership payments.', 'rcp' ); ?></p>
<p><?php _e( 'Payment data is permanent and cannot be manipulated or changed.', 'rcp' ); ?></p>
<p><?php _e( '<strong>Note</strong>: this page only lists completed payments. It will not display any payments that are pending, voided, or cancelled.', 'rcp' ); ?></p>
<?php
break;
default;
break;
endswitch;
return ob_get_clean();
}
/**
* Render settings tab content
*
* @param string $id
*
* @return string
*/
function rcp_render_settings_tab_content( $id ) {
switch( $id ) :
case 'general' :
ob_start(); ?>
<p><?php _e( 'This Settings page lets you configure all of the options available for Restrict Content Pro. You should configure the settings as desired before using the plugin.', 'rcp' ); ?></p>
<p><?php printf( __( 'If you have any trouble with these settings, or anything else with the plugin, you are welcome to request assistance through our <a href="%s">support forms</a>.', 'rcp' ), 'http://restrictcontentpro.com/support' ); ?></p>
<?php
break;
case 'pages' :
ob_start(); ?>
<p><?php _e( 'Restrict Content Pro automatically creates several pages for use inside the plugin. Each page should contain a specific shortcode to display the correct contents.', 'rcp' ); ?></p>
<p><?php _e( '<strong>Registration Page</strong> - This is the page that contains the [register_form] short code. This option is necessary in order to generate the link (to the registration page) used by short codes such as [subscription_details], which shows the details of a user\'s current membership, or a link to the registration page if not logged in.', 'rcp' ); ?></p>
<p><?php _e( '<strong>Success Page</strong> - This is the page that users are sent to after they have a successful registration. If the user is signing up for a free account, they will be sent to this page and immediately logged in. If the user is signing up for a premium membership, they will be sent to this page after submitting payment.', 'rcp' ); ?></p>
<p><?php _e( '<strong>Account Page</strong> - This page displays the currently logged in user\'s membership information. It contains the [subscription_details] shortcode.', 'rcp' ); ?></p>
<p><?php _e( '<strong>Edit Profile Page</strong> - This is the page that contains the [rcp_profile_editor] shortcode and allows the member to update their profile information, including first name, last name, email address, and password.', 'rcp' ); ?></p>
<p><?php printf( __( '<strong>Update Billing Card Page</strong> - This page contains the [rcp_update_card] shortcode and allows the member to update the credit card used for payments. This is only available with some payment gateways. Read <a href="%s">our help article</a> for more information.', 'rcp' ), 'http://docs.restrictcontentpro.com/article/1608-rcpupdatecard' ); ?></p>
<?php
break;
case 'messages' :
ob_start(); ?>
<p><?php _e( 'These are the messages displayed to a user when they attempt to view content that they do not have access to.', 'rcp' ); ?></p>
<p><?php _e( '<strong>Free Content Message</strong> - this message will be displayed to non-logged in users when they attempt to access a post or page that is restricted to registered users only. In this case, registered users refers to members that have an account on the site, not necessarily users that have a paid membership. So this message will only be displayed to non-logged in users.', 'rcp' ); ?></p>
<p><?php _e( '<strong>Premium Content Message</strong> - this message is displayed to users, logged in or not, when they attempt to access premium-members-only content. This message will be displayed even to logged in users, if they do not have an active membership on the site.', 'rcp' ); ?></p>
<p><?php _e( 'You may use HTML tags in these messages', 'rcp' ); ?></p>
<?php
break;
case 'payments' :
ob_start(); ?>
<p><?php _e( 'These settings control payment settings, enabled gateways, and API keys.', 'rcp' ); ?></p>
<p><?php _e( '<strong>Currency</strong> - Choose the currency for your site\'s membership packages.', 'rcp' ); ?></p>
<p><?php _e( '<strong>Currency Position</strong> - Choose the location of your currency sign, either before or after the amount.', 'rcp' ); ?></p>
<p><?php _e( '<strong>Enabled Gateways</strong> - Choose which gateway(s) you wish to enable on your registration form. You may choose one or several. After selecting a gateway, you also need to scroll down to enter your API key(s) and other details.', 'rcp' ); ?></p>
<p><?php printf( __( '<strong>Sandbox Mode</strong> - This option allows you to test the plugin with your chosen gateway\'s sandbox tools . You can submit payments using test accounts and/or card data . Leave this option as <strong> unchecked</strong> in order for your site to function live. Contact <a href="%s">support</a> if you have any questions about processing test payments.', 'rcp' ), 'http://restrictcontentpro.com/support' ); ?></p>
<?php
break;
case 'emails' :
ob_start(); ?>
<p><?php _e( 'These settings allow you to customize the emails that are sent to users when their membership statuses change. Emails are sent to users when their accounts are activated (after successful payment), when accounts are cancelled, when a membership reaches its expiration date, and when a user signs up for a free trial account. Emails are <strong>not</strong> sent when a user\'s status or membership is manually changed by site admins.', 'rcp' ); ?></p>
<p><?php _e( 'Each message that is sent out to users can be customized to your liking. There are a variety of template tags available for use in the emails, and those are listed below (and to the right of the input fields):', 'rcp' ); ?></p>
<?php echo rcp_get_emails_tags_list(); ?>
<p><?php _e( 'Each of these template tags will be automatically replaced with their values when the email is sent.', 'rcp' ); ?></p>
<p><?php _e( 'You may use HTML in the emails.', 'rcp' ); ?></p>
<?php
break;
case 'invoices' :
ob_start(); ?>
<p><?php _e( 'These settings allow you to customize the appearance of the payment invoices made available to your customers. All fields are optional.', 'rcp' ); ?></p>
<p><?php _e( '<strong>Invoice Logo</strong> - Upload a business logo to display on the invoices.', 'rcp' ); ?></p>
<p><?php _e( '<strong>Company Name</strong> - The name of your company.', 'rcp' ); ?></p>
<p><?php _e( '<strong>Name</strong> - A personal name that will be shown on the invoice.', 'rcp' ); ?></p>
<p><?php _e( '<strong>Address</strong> - There are several address fields you can fill out, including address line 1, address line 1, and a field for city/state/zip.', 'rcp' ); ?></p>
<p><?php _e( '<strong>Email</strong> - An email address to appear on the invoice.', 'rcp' ); ?></p>
<p><?php _e( '<strong>Header Text</strong> - This text will appear in the header of each invoice.', 'rcp' ); ?></p>
<p><?php _e( '<strong>Notes</strong> - Enter any additional notes you\'d like to display on the invoice here. This is inserted below the invoice totals.', 'rcp' ); ?></p>
<p><?php _e( '<strong>Footer Text</strong> - Text entered in this box will appear on the footer of each invoice.', 'rcp' ); ?></p>
<?php
break;
case 'misc' :
ob_start(); ?>
<p><?php _e( '<strong>Hide Restricted Posts</strong> - this option will cause all premium posts to be completely hidden from users who do not have access to them. This is useful if you wish to have content that is 100% invisible to non-authorized users. What this means is that premium posts won\'t be listed on blog pages, archives, recent post widgets, search results, RSS feeds, or anywhere else. If, when this setting is enabled, a user tries to access a premium post from a direct URL, they will be automatically redirected to the page you choose below.', 'rcp' ); ?></p>
<p><?php _e( '<strong>Redirect Page</strong> - this is the page non-authorized users are sent to when they try to access a premium post by direct URL.', 'rcp' ); ?></p>
<p><?php _e( '<strong>Redirect Default Login URL</strong> - this option will force the wp-login.php URL to redirect to the page you choose below.', 'rcp' ); ?></p>
<p><?php _e( '<strong>Login Page</strong> - this is the page the default login URL redirects to. This page should contain the [login_form] short code.', 'rcp' ); ?></p>
<p><?php _e( '<strong>Content Excerpts</strong> - choose whether or not to show excerpts to members without access to the content. You can choose a global setting like "always" or "never", or you can choose to decide for each post individually.', 'rcp' ); ?></p>
<p><?php _e( '<strong>Prevent Account Sharing</strong> - check this on if you\'d like to prevent multiple users from logging into the same account simultaneously.', 'rcp' ); ?></p>
<p><?php _e( '<strong>Disable WordPress Toolbar</strong> - this option will disable the WordPress toolbar for your subscribers. It will not disable the toolbar for administrators.', 'rcp' ); ?></p>
<p><?php _e( '<strong>Disable Form CSS</strong> - the plugin adds a small amount of CSS code to the registration form. Check this option to prevent that CSS from being loaded. This is useful if you only want to use your own styling.', 'rcp' ); ?></p>
<p><?php printf( __( '<strong>reCaptcha</strong> - Check this to enable a reCaptcha validation form on the registration form. This is an anti-spam protection and will require that the user enter letters / numbers in a field that match a provided image. This requires that you have a reCaptcha account, which is <a href="%s">free to signup for</a>.', 'rcp' ), 'https://www.google.com/recaptcha' ); ?></p>
<p><?php printf( __( '<strong>Opt into beta versions</strong> - this option allows you to test the Restrict Content Pro beta versions. If enabled, you\'ll receive an update notification in WordPress when a new beta version is available. You can read more about beta testing in <a href="%s">our help article</a>.', 'rcp' ), 'http://docs.restrictcontentpro.com/article/1784-test-beta-versions' ); ?></p>
<?php
break;
case 'logging' :
ob_start(); ?>
<p><?php _e( '<strong>Enable IPN Reports</strong> - by checking this option, you will enable an automatic email that is sent to the WordPress admin email anytime a PayPal IPN attempt is made. IPN attempts are made when a user signs up for a paid membership, and when recurring payments are made or cancelled.', 'rcp' ); ?></p>
<p><?php _e( 'When an IPN attempt is made, it is either Valid, or Invalid. A valid IPN is one that resulted in a successful payment and notification of the payment. An invalid IPN attempt happens when, for whatever reason, PayPal is unable to correctly notify your site of a payment or membership change.', 'rcp' ); ?></p>
<p><?php _e( 'With this option enabled, the email address set in the General WordPress Settings will get an email every time an IPN request is made. This is useful for debugging, in the case something is not working correctly.', 'rcp' ); ?></p>
<?php
break;
default;
break;
endswitch;
return ob_get_clean();
}

View File

@@ -0,0 +1 @@
<?php // Silence is golden.

View File

@@ -0,0 +1,396 @@
<?php
/**
* Import Actions
*
* @package restrict-content-pro
* @copyright Copyright (c) 2019, Restrict Content Pro team
* @license GPL2+
* @since 3.1
*/
use RCP\Utils\Batch;
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Upload the CSV import file and create the batch processing job.
*
* @since 3.1
* @return void
*/
function rcp_upload_csv_import_file_ajax() {
if ( ! current_user_can( 'rcp_manage_settings' ) ) {
wp_send_json_error( array(
'message' => __( 'Error: You do not have permission to perform this action.', 'rcp' )
) );
}
if ( ! function_exists( 'wp_handle_upload' ) ) {
require_once( ABSPATH . 'wp-admin/includes/file.php' );
}
if ( ! wp_verify_nonce( $_REQUEST['rcp_ajax_import_nonce'], 'rcp_ajax_import' ) ) {
wp_send_json_error( array(
'message' => __( 'Error: Nonce verification failed', 'rcp' )
) );
}
if ( empty( $_POST['importer'] ) ) {
wp_send_json_error( array(
'message' => __( 'Error: Missing importer key.', 'rcp' ),
'request' => $_REQUEST
) );
}
$importer_details = rcp_get_csv_importer( $_POST['importer'] );
if ( empty( $importer_details ) ) {
wp_send_json_error( array(
'message' => __( 'Error: No such registered importer.', 'rcp' ),
'request' => $_REQUEST
) );
}
if ( empty( $_FILES['import_file'] ) ) {
wp_send_json_error( array(
'message' => __( 'Error: Missing import file. Please provide an import file.', 'rcp' ),
'request' => $_REQUEST
) );
}
$accepted_mime_types = array(
'text/csv',
'text/comma-separated-values',
'text/plain',
'text/anytext',
'text/*',
'text/plain',
'text/anytext',
'text/*',
'application/csv',
'application/excel',
'application/vnd.ms-excel',
'application/vnd.msexcel',
);
$file_type_data = wp_check_filetype_and_ext( $_FILES['import_file']['tmp_name'], $_FILES['import_file']['name'] );
$file_type = ! empty( $file_type_data['type'] ) ? strtolower( $file_type_data['type'] ) : strtolower( $_FILES['import_file']['type'] );
if ( empty( $file_type ) || ! in_array( $file_type, $accepted_mime_types ) ) {
wp_send_json_error( array(
'message' => sprintf( __( 'Error: The file you uploaded does not appear to be a CSV file. File type: %s', 'rcp' ), esc_html( $file_type ) ),
'request' => $_REQUEST
) );
}
if ( ! file_exists( $_FILES['import_file']['tmp_name'] ) ) {
wp_send_json_error( array(
'message' => __( 'Error: Something went wrong during the upload process, please try again.', 'rcp' ),
'request' => $_REQUEST
) );
}
// Let WordPress import the file. We will remove it after import is complete
$import_file = wp_handle_upload( $_FILES['import_file'], array( 'test_form' => false ) );
// Sanitize import settings.
if ( ! empty( $_POST['import_settings'] ) && is_array( $_POST['import_settings'] ) ) {
$settings = array_map( 'sanitize_text_field', $_POST['import_settings'] );
} else {
$settings = array();
}
if ( $import_file && empty( $import_file['error'] ) ) {
/**
* Use this hook to include the job callback class file.
*
* @param string $importer_details ['callback'] Name of the class file.
*/
do_action( 'rcp_batch_processing_class_include', $importer_details['callback'] );
switch ( $importer_details['key'] ) {
case 'memberships' :
$job_name = __( 'CSV Memberships Import', 'rcp' );
$description = __( 'Import memberships from file: %s', 'rcp' );
break;
case 'payments' :
$job_name = __( 'CSV Payments Import', 'rcp' );
$description = __( 'Import payments from file: %s', 'rcp' );
break;
default :
$job_name = sprintf( __( 'CSV %s Import', 'rcp' ), $importer_details['name'] );
$description = __( 'Import data from file: %s', 'rcp' );
break;
}
// Ensure we get a unique job name.
$job_check = Batch\get_jobs( array( 'name' => $job_name, 'queue' => 'rcp_csv_import' ) );
if ( $job_check ) {
$suffix = 2;
do {
$alt_name = sprintf( '%s #%d', $job_name, $suffix );
$job_check = Batch\get_jobs( array( 'name' => $alt_name, 'queue' => 'rcp_csv_import' ) );
$suffix++;
} while ( $job_check );
$job_name = $alt_name;
}
$job_id = Batch\add_batch_job( array(
'name' => $job_name,
'description' => sprintf( $description, basename( $import_file['file'] ) ),
'callback' => sanitize_text_field( $importer_details['callback'] ),
'queue' => 'rcp_csv_import',
'data' => array(
'file_path' => sanitize_text_field( _wp_relative_upload_path( $import_file['file'] ) ),
'settings' => $settings
)
) );
if ( is_wp_error( $job_id ) ) {
wp_send_json_error( array(
'message' => sprintf( __( 'Error: %s', 'rcp' ), $job_id->get_error_message() )
) );
} elseif ( empty( $job_id ) ) {
wp_send_json_error( array(
'message' => __( 'Error: Batch job creation failed.', 'rcp' )
) );
}
$job = Batch\get_job( $job_id );
if ( empty( $job ) || ! class_exists( $job->get_callback() ) ) {
wp_send_json_error( array(
'message' => __( 'Error: Unable to get batch job callback.', 'rcp' )
) );
}
/**
* @var RCP_Batch_Callback_CSV_Import_Base $importer
*/
$importer = $job->get_callback_object();
wp_send_json_success( array(
'job_id' => $job_id,
'first_row' => $importer->get_first_row(),
'columns' => $importer->get_columns(),
'nonce' => wp_create_nonce( 'rcp_ajax_import' )
) );
} else {
/**
* Error generated by _wp_handle_upload()
* @see _wp_handle_upload() in wp-admin/includes/file.php
*/
wp_send_json_error( array( 'message' => $import_file['error'] ) );
}
exit;
}
add_action( 'rcp_action_upload_import_file', 'rcp_upload_csv_import_file_ajax' );
/**
* Process CSV import
*
* This handles saving the field mapping.
*
* @since 3.1
* @return void
*/
function rcp_process_csv_import() {
if ( ! current_user_can( 'rcp_manage_settings' ) ) {
wp_send_json_error( array(
'message' => __( 'Error: You do not have permission to perform this action.', 'rcp' ),
'request' => $_REQUEST
) );
}
if ( ! wp_verify_nonce( $_REQUEST['nonce'], 'rcp_ajax_import' ) ) {
wp_send_json_error( array(
'message' => __( 'Error: Nonce verification failed', 'rcp' ),
'request' => $_REQUEST
) );
}
if ( empty( $_REQUEST['job_id'] ) ) {
wp_send_json_error( array(
'message' => __( 'Error: Missing job ID.', 'rcp' ),
'request' => $_REQUEST
) );
}
$job = Batch\get_job( absint( $_REQUEST['job_id'] ) );
if ( empty( $job ) ) {
wp_send_json_error( array(
'message' => __( 'Error: Unable to get batch job.', 'rcp' )
) );
}
$importer = rcp_get_csv_importer_by_callback( $job->get_callback() );
if ( empty( $importer ) ) {
wp_send_json_error( array(
'message' => __( 'Error: Unable to get importer information.', 'rcp' )
) );
}
/**
* Use this hook to include the job callback class file.
*
* @param string $job_callback Name of the class file.
*/
do_action( 'rcp_batch_processing_class_include', $job->get_callback() );
if ( ! class_exists( $job->get_callback() ) ) {
wp_send_json_error( array(
'message' => __( 'Error: Missing job callback.', 'rcp' )
) );
}
// Map the fields to the database columns.
parse_str( $_REQUEST['mapping'], $map );
$job->add_data( array(
'field_map' => array_map( 'sanitize_text_field', $map['rcp_import_field'] )
) );
$redirect_url = add_query_arg( array(
'rcp-job-id' => absint( $job->get_id() ),
'rcp-job-autostart' => 1
), admin_url( 'admin.php?page=rcp-tools&tab=batch' ) );
wp_send_json_success( esc_url_raw( $redirect_url ) );
exit;
}
add_action( 'wp_ajax_rcp_process_csv_import', 'rcp_process_csv_import' );
/**
* Include batch CSV import class files.
*
* @param string $callback Import class name.
*
* @since 3.1
* @return void
*/
function rcp_include_batch_import_files( $callback ) {
$importer = rcp_get_csv_importer_by_callback( $callback );
if ( empty( $importer ) ) {
return;
}
// Include the main file.
require_once RCP_PLUGIN_DIR . 'core/includes/batch/csv-imports/class-batch-csv-import-base.php';
// Include the file specifically for this importer.
if ( file_exists( $importer['callback_file'] ) ) {
require_once $importer['callback_file'];
}
}
add_action( 'rcp_batch_processing_class_include', 'rcp_include_batch_import_files' );
/**
* Memberships Importer: add additional settings to the import UI.
*
* @param array $importer Importer details.
*
* @since 3.1
* @return void
*/
function rcp_csv_importer_memberships_settings( $importer ) {
?>
<tr>
<th>
<label for="rcp-membership-level"><?php _e( 'Membership Level', 'rcp' ); ?></label>
</th>
<td>
<select id="rcp-membership-level" name="import_settings[object_id]">
<?php
$membership_levels = rcp_get_membership_levels( array( 'number' => 999 ) );
echo '<option value="" selected>' . __( '- Use CSV Column -', 'rcp' ) . '</option>';
foreach ( $membership_levels as $level ) {
echo '<option value="' . esc_attr( absint( $level->get_id() ) ) . '">' . esc_html( $level->get_name() ) . '</option>';
}
?>
</select>
<p class="description"><?php _e( 'Select the membership level to add users to. Membership levels can also be specified in the CSV file.', 'rcp' ); ?></p>
</td>
</tr>
<tr>
<th>
<label for="rcp-status"><?php _e( 'Status', 'rcp' ); ?></label>
</th>
<td>
<select id="rcp-status" name="import_settings[status]">
<option value="" selected><?php _e( '- Use CSV Column -', 'rcp' ); ?></option>
<option value="active"><?php _e( 'Active', 'rcp' ); ?></option>
<option value="pending"><?php _e( 'Pending', 'rcp' ); ?></option>
<option value="cancelled"><?php _e( 'Cancelled', 'rcp' ); ?></option>
<option value="expired"><?php _e( 'Expired', 'rcp' ); ?></option>
</select>
<p class="description"><?php _e( 'Select the status to set for all imported memberships. Statuses can also be set in the CSV file.', 'rcp_csvui' ); ?></p>
</td>
</tr>
<tr>
<th>
<label for="rcp-expiration"><?php _e( 'Expiration', 'rcp' ); ?></label>
</th>
<td>
<input type="text" id="rcp-expiration" name="import_settings[expiration_date]" value="" class="rcp-datepicker"/>
<p class="description"><?php _e( 'Select the expiration date for all memberships. Leave blank if specified in the CSV file. If an expiration date is not provided in either place, it will be automatically calculated based on the selected membership level.', 'rcp' ); ?></p>
</td>
</tr>
<?php if ( rcp_multiple_memberships_enabled() ) : ?>
<tr>
<th>
<label for="rcp-existing-customers"><?php _e( 'Existing Customers', 'rcp' ); ?></label>
</th>
<td>
<select id="rcp-existing-customers" name="import_settings[existing_customers]">
<option value="new" selected><?php _e( 'Add Additional Memberships', 'rcp' ); ?></option>
<option value="update"><?php _e( 'Update Existing Memberships', 'rcp' ); ?></option>
</select>
<p class="description"><?php _e( 'If importing a membership for a customer that already exists, you can either insert an additional membership record, or update/change the existing membership record.', 'rcp' ); ?></p>
</td>
</tr>
<?php endif; ?>
<tr>
<th>
<label for="rcp-membership-import-disable-notification-emails"><?php _e( 'Disable Notification Emails', 'rcp' ); ?></label>
</th>
<td>
<input type="checkbox" id="rcp-membership-import-disable-notification-emails" name="import_settings[disable_notification_emails]" value="1"/>
<span class="description"><?php _e( 'Check on to disable customer and admin notification emails during the import process.', 'rcp' ); ?></span>
</td>
</tr>
<tr>
<th>
<label for="rcp-send-set-password-emails"><?php _e( 'Send "Set Password" Emails', 'rcp' ); ?></label>
</th>
<td>
<input type="checkbox" id="rcp-send-set-password-emails" name="import_settings[send_set_password_emails]" value="1"/>
<span class="description"><?php _e( 'If checked, new accounts will be sent an email inviting them to set a password. Existing accounts will not receive one.', 'rcp' ); ?></span>
</td>
</tr>
<?php
}
add_action( 'rcp_csv_importer_settings_memberships', 'rcp_csv_importer_memberships_settings' );

View File

@@ -0,0 +1,146 @@
<?php
/**
* Import Functions
*
* @package restrict-content-pro
* @copyright Copyright (c) 2019, Restrict Content Pro team
* @license GPL2+
* @since 3.1
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Get an array of the available CSV importers and their settings.
*
* @since 3.1
* @return array
*/
function rcp_get_csv_importers() {
$importers = array(
/**
* Memberships
*/
'memberships' => array(
// Name used in titles and labels.
'name' => __( 'Memberships', 'rcp' ),
// Unique identifier. Same as the array key above.
'key' => 'memberships',
// Description printed on the import page.
'description' => sprintf( __( 'Use this tool to import user memberships into Restrict Content Pro. See <a href="%s">this article</a> for further instructions and a sample CSV file.', 'rcp' ), 'https://docs.restrictcontentpro.com/article/1579-import-members-from-a-csv-file' ),
// Batch processor callback class name.
'callback' => 'RCP_Batch_Callback_Import_Memberships',
// Path to the above class file.
'callback_file' => RCP_PLUGIN_DIR . 'core/includes/batch/csv-imports/class-import-memberships.php',
/*
* Array of supported columns. The key is what you're looking for in the batch
* processor callback. The value is the expected name of the column header. The
* value is just used to auto-select a column; it doesn't actually affect functionality.
*/
'columns' => array(
'user_email' => __( 'User Email', 'rcp' ),
'first_name' => __( 'First Name', 'rcp' ),
'last_name' => __( 'Last Name', 'rcp' ),
'user_login' => __( 'User Login', 'rcp' ),
'user_password' => __( 'User Password', 'rcp' ),
'membership_level_name' => __( 'Membership Level Name', 'rcp' ),
'status' => __( 'Status', 'rcp' ),
'created_date' => __( 'Created Date', 'rcp' ),
'expiration_date' => __( 'Expiration Date', 'rcp' ),
'auto_renew' => __( 'Auto Renew', 'rcp' ),
'times_billed' => __( 'Times Billed', 'rcp' ),
'gateway' => __( 'Gateway', 'rcp' ),
'gateway_customer_id' => __( 'Gateway Customer ID', 'rcp' ),
'gateway_subscription_id' => __( 'Gateway Subscription ID', 'rcp' ),
'subscription_key' => __( 'Subscription Key', 'rcp' )
)
),
/**
* Payments
*/
'payments' => array(
'name' => __( 'Payments', 'rcp' ),
'key' => 'payments',
'description' => sprintf( __( 'Use this tool to import user payments into Restrict Content Pro. See <a href="%s">this article</a> for further instructions and a sample CSV file.', 'rcp' ), 'https://docs.restrictcontentpro.com/article/2265-importing-payments' ),
'callback' => 'RCP_Batch_Callback_Import_Payments',
'callback_file' => RCP_PLUGIN_DIR . 'core/includes/batch/csv-imports/class-import-payments.php',
'columns' => array(
'status' => __( 'Status', 'rcp' ),
'subscription' => __( 'Membership Level Name', 'rcp' ),
'object_id' => __( 'Membership Level ID', 'rcp' ),
'amount' => __( 'Total Amount', 'rcp' ),
'subtotal' => __( 'Subtotal', 'rcp' ),
'credits' => __( 'Credits', 'rcp' ),
'fees' => __( 'Fees', 'rcp' ),
'discount_amount' => __( 'Discount Amount', 'rcp' ),
'discount_code' => __( 'Discount Code', 'rcp' ),
'user_login' => __( 'User Login', 'rcp' ),
'user_email' => __( 'User Email', 'rcp' ),
'membership_id' => __( 'Membership ID', 'rcp' ),
'gateway' => __( 'Gateway', 'rcp' ),
'transaction_id' => __( 'Transaction ID', 'rcp' ),
'transaction_type' => __( 'Transaction Type', 'rcp' ),
'date' => __( 'Date', 'rcp' ),
)
)
);
/**
* Filters the available CSV importers. Use this filter to add support
* for a custom importer.
*
* @param array $importers
*
* @since 3.1
*/
return apply_filters( 'rcp_csv_importers', $importers );
}
/**
* Get details about a specific importer by key.
*
* @param string $key
*
* @since 3.1
* @return array|false Array of importer details on success, false on failure.
*/
function rcp_get_csv_importer( $key ) {
$importers = rcp_get_csv_importers();
if ( ! array_key_exists( $key, $importers ) ) {
return false;
}
return $importers[$key];
}
/**
* Get details about a specific importer by callback class name.
*
* @param string $callback Batch processor callback class name.
*
* @return array|false Array of importer details on success, false on failure.
*/
function rcp_get_csv_importer_by_callback( $callback ) {
$importers = rcp_get_csv_importers();
if ( empty( $importers ) ) {
return false;
}
foreach ( $importers as $importer ) {
if ( $callback === $importer['callback'] ) {
return $importer;
}
}
return false;
}

View File

@@ -0,0 +1 @@
<?php // Silence is golden.

View File

@@ -0,0 +1 @@
<?php // Silence is golden.

View File

@@ -0,0 +1,267 @@
<?php
/**
* Edit Member Page
*
* @package Restrict Content Pro
* @subpackage Admin/Edit Member
* @copyright Copyright (c) 2017, Restrict Content Pro
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
*/
if( isset( $_GET['edit_member'] ) ) {
$member_id = absint( $_GET['edit_member'] );
} elseif( isset( $_GET['view_member'] ) ) {
$member_id = absint( $_GET['view_member'] );
}
$member = new RCP_Member( $member_id );
$current_status = $member->get_status();
$subscription_level_id = $member->get_subscription_id();
$expiration_date = $member->get_expiration_date( false );
// If member is pending, get pending details.
if ( 'pending' == $current_status ) {
$pending_subscription_id = $member->get_pending_subscription_id();
if ( ! empty( $pending_subscription_id ) ) {
$subscription_level_id = $pending_subscription_id;
}
if ( empty( $expiration_date ) ) {
$expiration_date = $member->calculate_expiration( true );
}
}
?>
<h1>
<?php _e( 'Edit Member:', 'rcp' ); echo ' ' . $member->display_name; ?>
</h1>
<?php if( ! $member->exists() ) : ?>
<div class="error settings-error">
<p><?php _e( 'Error: Invalid member ID.', 'rcp' ); ?></p>
</div>
<?php return; ?>
<?php endif; ?>
<?php if( $switch_to_url = rcp_get_switch_to_url( $member->ID ) ) { ?>
<a href="<?php echo esc_url( $switch_to_url ); ?>" class="rcp_switch"><?php _e('Switch to User', 'rcp'); ?></a>
<?php } ?>
<form id="rcp-edit-member" action="" method="post">
<table class="form-table">
<tbody>
<?php do_action( 'rcp_edit_member_before', $member->ID ); ?>
<tr valign="top">
<th scope="row" valign="top">
<label for="rcp-userlogin"><?php _e( 'User Login', 'rcp' ); ?></label>
</th>
<td>
<input id="rcp-userlogin" type="text" value="<?php echo esc_attr( $member->user_login ); ?>" disabled="disabled"/>
<p class="description"><?php _e( 'The member\'s login name. This cannot be changed.', 'rcp' ); ?></p>
</td>
</tr>
<tr valign="top">
<th scope="row" valign="top">
<label for="rcp-email"><?php _e( 'User Email', 'rcp' ); ?></label>
</th>
<td>
<input id="rcp-email" name="email" type="text" value="<?php echo esc_attr( $member->user_email ); ?>"/>
<p class="description"><?php _e( 'The member\'s email address.', 'rcp' ); ?> <a href="<?php echo esc_url( add_query_arg( 'user_id', $member->ID, admin_url( 'user-edit.php' ) ) ); ?>" title="<?php _e( 'View User\'s Profile', 'rcp' ); ?>"><?php _e( 'Edit User Account', 'rcp' ); ?></a></p>
</td>
</tr>
<tr valign="top">
<th scope="row" valign="top">
<label for="rcp-status"><?php _e( 'Status', 'rcp' ); ?></label>
</th>
<td>
<select name="status" id="rcp-status">
<?php
$statuses = array( 'active', 'expired', 'cancelled', 'pending', 'free' );
foreach( $statuses as $status ) :
echo '<option value="' . esc_attr( $status ) . '"' . selected( $status, rcp_get_status( $member->ID ), false ) . '>' . ucwords( $status ) . '</option>';
endforeach;
?>
</select>
<span alt="f223" class="rcp-help-tip dashicons dashicons-editor-help" title="<?php _e( 'An Active status is required to access paid content. Members with a status of Cancelled may continue to access paid content until the expiration date on their account is reached.', 'rcp' ); ?>"></span>
<?php if ( $member->is_pending_verification() ) : ?>
<p class="description"><?php printf( __( '(Pending email verification. <a href="%s">Click to manually verify email.</a>)', 'rcp' ), esc_url( wp_nonce_url( add_query_arg( array( 'rcp-action' => 'verify_email', 'member_id' => $member->ID ), add_query_arg( 'edit_member', $member->ID, admin_url( 'admin.php?page=rcp-members' ) ) ), 'rcp-manually-verify-email-nonce' ) ) ); ?></p>
<?php endif; ?>
<p class="description"><?php _e( 'The status of this user\'s subscription', 'rcp' ); ?></p>
<p id="rcp-revoke-access-wrap">
<input type="checkbox" id="rcp-revoke-access" name="rcp-revoke-access" value="1">
<label for="rcp-revoke-access"><?php _e( 'Revoke access now', 'rcp' ); ?></label>
<span alt="f223" class="rcp-help-tip dashicons dashicons-editor-help" title="<?php esc_attr_e( 'If not enabled, the member will retain access until the end of their current term. If checked, the member\'s status will be changed to "expired" and access will be revoked immediately.', 'rcp' ); ?>"></span>
</p>
</td>
</tr>
<tr valign="top">
<th scope="row" valign="top">
<label for="rcp-level"><?php _e( 'Subscription Level', 'rcp' ); ?></label>
</th>
<td>
<select name="level" id="rcp-level">
<?php
foreach( rcp_get_subscription_levels( 'all' ) as $key => $level ) :
echo '<option value="' . esc_attr( absint( $level->id ) ) . '"' . selected( $level->id, $subscription_level_id, false ) . '>' . esc_html( $level->name ) . '</option>';
endforeach;
?>
</select>
<p class="description"><?php _e( 'Choose the subscription level for this user', 'rcp' ); ?></p>
</td>
</tr>
<tr valign="top">
<th scope="row" valign="top">
<label for="rcp-key"><?php _e( 'Subscription Key', 'rcp' ); ?></label>
</th>
<td>
<input id="rcp-key" type="text" value="<?php echo esc_attr( $member->get_subscription_key() ); ?>" disabled="disabled"/>
<span alt="f223" class="rcp-help-tip dashicons dashicons-editor-help" title="<?php _e( 'This key is used for reference purposes and may be shown on payment and subscription records in your merchant accounts.', 'rcp' ); ?>"></span>
<p class="description"><?php _e( 'The member\'s subscription key. This cannot be changed.', 'rcp' ); ?></p>
</td>
</tr>
<tr valign="top">
<th scope="row" valign="top">
<label for="rcp-expiration"><?php _e( 'Expiration date', 'rcp' ); ?></label>
</th>
<td>
<?php
if( ! empty( $expiration_date ) && 'none' != $expiration_date ) {
$expiration_date = date( 'Y-m-d', strtotime( $expiration_date, current_time( 'timestamp' ) ) );
}
?>
<input name="expiration" id="rcp-expiration" type="text" class="rcp-datepicker" value="<?php echo esc_attr( $expiration_date ); ?>"/>
<label for="rcp-unlimited">
<input name="unlimited" id="rcp-unlimited" type="checkbox"<?php checked( $expiration_date, 'none' ); ?>/>
<span class="description"><?php _e( 'Never expires?', 'rcp' ); ?></span>
</label>
<span alt="f223" class="rcp-help-tip dashicons dashicons-editor-help" title="<?php _e( 'This is the date the member will lose access to content if their membership is not renewed.', 'rcp' ); ?>"></span>
<p class="description"><?php _e( 'Enter the expiration date for this user in the format of yyyy-mm-dd', 'rcp' ); ?></p>
</td>
</tr>
<tr valign="top">
<th scope="row" valign="top">
<label for="rcp-payment-profile-id"><?php _e( 'Payment Profile ID', 'rcp' ); ?></label>
</th>
<td>
<input name="payment-profile-id" id="rcp-payment-profile-id" type="text" value="<?php echo esc_attr( $member->get_payment_profile_id() ); ?>"/>
<p class="description"><?php _e( 'This is the customer\'s payment profile ID in the payment processor', 'rcp' ); ?></p>
</td>
</tr>
<tr valign="top">
<th scope="row" valign="top">
<?php _e( 'Recurring', 'rcp' ); ?>
</th>
<td>
<label for="rcp-recurring">
<input name="recurring" id="rcp-recurring" type="checkbox" value="1" <?php checked( 1, rcp_is_recurring( $member->ID ) ); ?>/>
<?php _e( 'Is this user\'s subscription recurring?', 'rcp' ); ?>
</label>
<span alt="f223" class="rcp-help-tip dashicons dashicons-editor-help" title="<?php _e( 'If checked, this member has a recurring subscription. Only customers with recurring memberships will be given the option to cancel their membership on their subscription details page.', 'rcp' ); ?>"></span>
</td>
</tr>
<tr valign="top">
<th scope="row" valign="top">
<?php _e( 'Trialing', 'rcp' ); ?>
</th>
<td>
<label for="rcp-trialing">
<input name="trialing" id="rcp-trialing" type="checkbox" value="1" <?php checked( 1, rcp_is_trialing( $member->ID ) ); ?>/>
<?php _e( 'Does this user have a trial membership?', 'rcp' ); ?>
</label>
<span alt="f223" class="rcp-help-tip dashicons dashicons-editor-help" title="<?php _e( 'Members are limited to a single trial membership. Once a trial has been used, the member may not sign up for another trial membership.', 'rcp' ); ?>"></span>
</td>
</tr>
<tr valign="top">
<th scope="row" valign="top">
<?php _e( 'Sign Up Method', 'rcp' ); ?>
</th>
<td>
<?php $method = get_user_meta( $member->ID, 'rcp_signup_method', true ) ? get_user_meta( $member->ID, 'rcp_signup_method', true ) : 'live';?>
<select name="signup_method" id="rcp-signup-method">
<option value="live" <?php selected( $method, 'live' ); ?>><?php _e( 'User Signup', 'rcp' ); ?>
<option value="manual" <?php selected( $method, 'manual' ); ?>><?php _e( 'Added by admin manually', 'rcp' ); ?>
<option value="imported" <?php selected( $method, 'imported' ); ?>><?php _e( 'Imported', 'rcp' ); ?>
</select>
<p class="description"><?php _e( 'Was this a real signup or a membership given to the user', 'rcp' ); ?></p>
</td>
</tr>
<tr valign="top">
<th scope="row" valign="top">
<label for="rcp-notes"><?php _e( 'User Notes', 'rcp' ); ?></label>
</th>
<td>
<textarea name="notes" id="rcp-notes" class="large-text" rows="10" cols="50"><?php echo esc_textarea( get_user_meta( $member->ID, 'rcp_notes', true ) ); ?></textarea>
<p class="description"><?php _e( 'Use this area to record notes about this user if needed', 'rcp' ); ?></p>
</td>
</tr>
<?php if ( ! empty( $rcp_options['enable_terms'] ) ) : ?>
<tr valign="top">
<th scope="row" valign="top">
<label for="rcp-terms-agreed"><?php _e( 'Agreed to Terms', 'rcp' ); ?></label>
</th>
<td>
<?php
$terms_agreed = get_user_meta( $member->ID, 'rcp_terms_agreed', true );
if ( ! empty( $terms_agreed ) && is_array( $terms_agreed ) ) {
foreach ( $terms_agreed as $terms_agreed_date ) {
echo date_i18n( get_option( 'date_format' ) . ' H:i:s', $terms_agreed_date ) . '<br />';
}
} else {
_e( 'None', 'rcp' );
}
?>
</td>
</tr>
<?php endif; ?>
<?php if ( ! empty( $rcp_options['enable_privacy_policy'] ) ) : ?>
<tr valign="top">
<th scope="row" valign="top">
<label for="rcp-privacy-policy-agreed"><?php _e( 'Agreed to Privacy Policy', 'rcp' ); ?></label>
</th>
<td>
<?php
$privacy_policy_agreed = get_user_meta( $member->ID, 'rcp_privacy_policy_agreed', true );
if ( ! empty( $privacy_policy_agreed ) && is_array( $privacy_policy_agreed ) ) {
foreach ( $privacy_policy_agreed as $privacy_policy_agreed_date ) {
echo date_i18n( get_option( 'date_format' ) . ' H:i:s', $privacy_policy_agreed_date ) . '<br />';
}
} else {
_e( 'None', 'rcp' );
}
?>
</td>
</tr>
<?php endif; ?>
<tr class="form-field">
<th scope="row" valign="top">
<?php _e( 'Discount codes used', 'rcp' ); ?>
</th>
<td>
<?php
$discounts = get_user_meta( $member->ID, 'rcp_user_discounts', true );
if( $discounts ) {
foreach( $discounts as $discount ) {
if( is_string( $discount ) ) {
echo $discount . '<br/>';
}
}
} else {
_e( 'None', 'rcp' );
}
?>
</td>
</tr>
<?php do_action( 'rcp_edit_member_after', $member->ID ); ?>
</tbody>
</table>
<h4><?php _e( 'Payments', 'rcp' ); ?></h4>
<?php echo rcp_print_user_payments_formatted( $member->ID ); ?>
<p class="submit">
<input type="hidden" name="rcp-action" value="edit-member"/>
<input type="hidden" name="user" value="<?php echo absint( urldecode( $_GET['edit_member'] ) ); ?>"/>
<input type="submit" value="<?php _e( 'Update User Subscription', 'rcp' ); ?>" class="button-primary"/>
</p>
<?php wp_nonce_field( 'rcp_edit_member_nonce', 'rcp_edit_member_nonce' ); ?>
</form>

View File

@@ -0,0 +1 @@
<?php // Silence is golden.

View File

@@ -0,0 +1,472 @@
<?php
/**
* Member Actions
*
* @package restrict-content-pro
* @subpackage Admin/Member Actions
* @copyright Copyright (c) 2017, Restrict Content Pro
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
* @since 2.9
*/
// Exit if accessed directly
if ( ! defined( 'ABSPATH' ) ) exit;
/**
* Edit a member
*
* @deprecated 3.0 In favour of `rcp_process_edit_customer()`.
* @see rcp_process_edit_customer()
*
* @since 2.9
* @return void
*/
function rcp_process_edit_member() {
if ( ! wp_verify_nonce( $_POST['rcp_edit_member_nonce'], 'rcp_edit_member_nonce' ) ) {
wp_die( __( 'Nonce verification failed.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 403 ) );
}
if ( ! current_user_can( 'rcp_manage_members' ) ) {
wp_die( __( 'You do not have permission to perform this action.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 403 ) );
}
$levels = new RCP_Levels();
$user_id = absint( $_POST['user'] );
$member = new RCP_Member( $user_id );
$email = sanitize_text_field( $_POST['email'] );
$status = sanitize_text_field( $_POST['status'] );
$level_id = absint( $_POST['level'] );
$expiration = isset( $_POST['expiration'] ) ? sanitize_text_field( $_POST['expiration'] ) : 'none';
$expiration = 'none' !== $expiration ? date( 'Y-m-d 23:59:59', strtotime( $_POST['expiration'], current_time( 'timestamp' ) ) ) : $expiration;
$revoke_access = isset( $_POST['rcp-revoke-access'] );
$current_user = wp_get_current_user();
rcp_log( sprintf( '%s has started editing member #%d.', $current_user->user_login, $user_id ) );
$previous_expiration = $member->get_expiration_date( false );
if ( $previous_expiration != $expiration ) {
rcp_log( sprintf( 'Updated member #%d expiration date from %s to %s.', $user_id, $previous_expiration, $expiration ) );
}
if ( isset( $_POST['notes'] ) ) {
update_user_meta( $user_id, 'rcp_notes', wp_kses( $_POST['notes'], array() ) );
}
if ( isset( $_POST['cancel_subscription'] ) && $member->can_cancel() ) {
rcp_log( sprintf( 'Cancelling payment profile for member #%d.', $user_id ) );
$cancelled = $member->cancel_payment_profile( false );
}
if( ! empty( $_POST['expiration'] ) && ( 'cancelled' != $status || ! $revoke_access ) ) {
$member->set_expiration_date( $expiration );
} elseif( $revoke_access && ! $member->is_expired() ) {
$member->set_expiration_date( date( 'Y-m-d H:i:s', strtotime( '-1 day', current_time( 'timestamp' ) ) ) );
// Set status to 'expired' later.
$status = 'expired';
}
if ( isset( $_POST['level'] ) ) {
$current_id = rcp_get_subscription_id( $user_id );
$new_level = $levels->get_level( $level_id );
$old_level = $levels->get_level( $current_id );
if ( $current_id != $level_id ) {
rcp_log( sprintf( 'Changed member #%d membership level from %d to %d.', $user_id, $current_id, $level_id ) );
$member->set_subscription_id( $level_id );
// Remove the old user role
$role = ! empty( $old_level->role ) ? $old_level->role : 'subscriber';
$member->remove_role( $role );
// Add the new user role
$role = ! empty( $new_level->role ) ? $new_level->role : 'subscriber';
$member->add_role( $role );
// Set joined date for the new subscription
$member->set_joined_date( '', $level_id );
}
}
if ( isset( $_POST['recurring'] ) ) {
$member->set_recurring( true );
} else {
$member->set_recurring( false );
}
if ( isset( $_POST['trialing'] ) ) {
update_user_meta( $user_id, 'rcp_is_trialing', 'yes' );
} else {
delete_user_meta( $user_id, 'rcp_is_trialing' );
}
if ( isset( $_POST['signup_method'] ) ) {
update_user_meta( $user_id, 'rcp_signup_method', $_POST['signup_method'] );
}
if ( $status !== $member->get_status() ) {
$member->set_status( $status );
}
if ( isset( $_POST['payment-profile-id'] ) ) {
$member->set_payment_profile_id( $_POST['payment-profile-id'] );
}
if ( $email != $member->user_email ) {
rcp_log( sprintf( 'Changing email for member #%d.', $user_id ) );
wp_update_user( array( 'ID' => $user_id, 'user_email' => $email ) );
}
do_action( 'rcp_edit_member', $user_id );
rcp_log( sprintf( '%s finished editing member #%d.', $current_user->user_login, $user_id ) );
$redirect = admin_url( 'admin.php?page=rcp-members&edit_member=' . $user_id );
if ( isset( $cancelled ) && is_wp_error( $cancelled ) ) {
$redirect = add_query_arg( 'rcp_message', 'member_cancelled_error', $redirect );
} else {
$redirect = add_query_arg( 'rcp_message', 'user_updated', $redirect );
}
wp_safe_redirect( $redirect );
exit;
}
add_action( 'rcp_action_edit-member', 'rcp_process_edit_member' );
/**
* Add a subscription to an existing member
*
* @deprecated 3.0 In favour of `rcp_process_add_membership()`.
* @see rcp_process_add_membership()
*
* @since 2.9
* @return void
*/
function rcp_process_add_member_subscription() {
if ( ! wp_verify_nonce( $_POST['rcp_add_member_nonce'], 'rcp_add_member_nonce' ) ) {
wp_die( __( 'Nonce verification failed.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 403 ) );
}
if ( ! current_user_can( 'rcp_manage_members' ) ) {
wp_die( __( 'You do not have permission to perform this action.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 403 ) );
}
if ( empty( $_POST['level'] ) || empty( $_POST['user'] ) ) {
wp_die( __( 'Please fill out all fields.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 400 ) );
}
// Don't add if chosen expiration date is in the past.
if ( isset( $_POST['expiration'] ) && strtotime( 'NOW', current_time( 'timestamp' ) ) > strtotime( $_POST['expiration'], current_time( 'timestamp' ) ) && 'none' !== $_POST['expiration'] ) {
rcp_log( sprintf( 'Failed adding subscription to an existing user: chosen expiration date ( %s ) is in the past.', $_POST['expiration'] ), true );
wp_safe_redirect( admin_url( 'admin.php?page=rcp-members&rcp_message=user_not_added' ) );
exit;
}
$levels = new RCP_Levels();
$user = get_user_by( 'login', $_POST['user'] );
if ( ! $user ) {
wp_die( __( 'You entered a username that does not exist.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 400 ) );
}
$member = new RCP_Member( $user->ID );
$expiration = isset( $_POST['expiration'] ) ? sanitize_text_field( $_POST['expiration'] ) : 'none';
$level_id = absint( $_POST['level'] );
$subscription = $levels->get_level( $level_id );
if ( ! $subscription ) {
wp_die( __( 'Please supply a valid membership level.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 400 ) );
}
$member->set_expiration_date( $expiration );
$new_subscription = get_user_meta( $user->ID, '_rcp_new_subscription', true );
if ( empty( $new_subscription ) ) {
update_user_meta( $user->ID, '_rcp_new_subscription', '1' );
}
update_user_meta( $user->ID, 'rcp_signup_method', 'manual' );
$member->set_subscription_id( $level_id );
$status = $subscription->price == 0 ? 'free' : 'active';
$member->set_status( $status );
// Add the new user role
$role = ! empty( $subscription->role ) ? $subscription->role : 'subscriber';
$user->add_role( $role );
// Set joined date for the new subscription
$member->set_joined_date( '', $level_id );
if ( isset( $_POST['recurring'] ) ) {
update_user_meta( $user->ID, 'rcp_recurring', 'yes' );
} else {
delete_user_meta( $user->ID, 'rcp_recurring' );
}
rcp_log( sprintf( 'Successfully added new subscription for user #%d. Level ID: %d; Status: %s; Expiration Date: %s; Role: %s', $member->ID, $level_id, $status, $expiration, $role ) );
wp_safe_redirect( admin_url( 'admin.php?page=rcp-members&rcp_message=user_added' ) );
exit;
}
add_action( 'rcp_action_add-subscription', 'rcp_process_add_member_subscription' );
/**
* Process bulk edit members
*
* @deprecated 3.0
*
* @since 2.9
* @return void
*/
function rcp_process_bulk_edit_members() {
if ( ! wp_verify_nonce( $_POST['rcp_bulk_edit_nonce'], 'rcp_bulk_edit_nonce' ) ) {
wp_die( __( 'Nonce verification failed.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 403 ) );
}
if ( ! current_user_can( 'rcp_manage_members' ) ) {
wp_die( __( 'You do not have permission to perform this action.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 403 ) );
}
if ( empty( $_POST['member-ids'] ) ) {
wp_die( __( 'Please select at least one member to edit.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 400 ) );
}
$member_ids = array_map( 'absint', $_POST['member-ids'] );
$action = ! empty( $_POST['rcp-bulk-action'] ) ? sanitize_text_field( $_POST['rcp-bulk-action'] ) : false;
foreach ( $member_ids as $member_id ) {
$member = new RCP_Member( $member_id );
if ( ! empty( $_POST['expiration'] ) && 'delete' !== $action ) {
$member->set_expiration_date( date( 'Y-m-d 23:59:59', strtotime( $_POST['expiration'], current_time( 'timestamp' ) ) ) );
}
if ( $action ) {
switch ( $action ) {
case 'mark-active' :
$member->set_status( 'active' );
break;
case 'mark-expired' :
$member->set_status( 'expired' );
break;
case 'mark-cancelled' :
$member->cancel();
if( ! empty( $_POST['rcp-revoke-access'] ) && ! $member->is_expired() ) {
$member->set_expiration_date( date( 'Y-m-d H:i:s', strtotime( '-1 day', current_time( 'timestamp' ) ) ) );
}
break;
}
}
}
wp_safe_redirect( admin_url( 'admin.php?page=rcp-members&rcp_message=members_updated' ) );
exit;
}
add_action( 'rcp_action_bulk_edit_members', 'rcp_process_bulk_edit_members' );
/**
* Cancel a member from the Members table
*
* @deprecated 3.0 In favour of `rcp_process_cancel_membership()`.
* @see rcp_process_cancel_membership()
*
* @since 2.9
* @return void
*/
function rcp_process_cancel_member() {
if ( ! wp_verify_nonce( $_GET['_wpnonce'], 'rcp-cancel-nonce' ) ) {
wp_die( __( 'Nonce verification failed.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 403 ) );
}
if ( ! current_user_can( 'rcp_manage_members' ) ) {
wp_die( __( 'You do not have permission to perform this action.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 403 ) );
}
if ( ! isset( $_GET['member_id'] ) ) {
wp_die( __( 'Please select a member.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 400 ) );
}
rcp_cancel_member_payment_profile( urldecode( absint( $_GET['member_id'] ) ) );
wp_safe_redirect( admin_url( add_query_arg( 'rcp_message', 'member_cancelled', 'admin.php?page=rcp-members' ) ) );
exit;
}
add_action( 'rcp_action_cancel_member', 'rcp_process_cancel_member' );
/**
* Re-send a member's verification email
*
* @since 2.9
* @return void
*/
function rcp_process_resend_verification() {
if ( ! wp_verify_nonce( $_GET['_wpnonce'], 'rcp-verification-nonce' ) ) {
wp_die( __( 'Nonce verification failed.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 403 ) );
}
if ( ! current_user_can( 'rcp_manage_members' ) ) {
wp_die( __( 'You do not have permission to perform this action.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 403 ) );
}
if ( ! isset( $_GET['member_id'] ) && ! isset( $_GET['customer_id'] ) ) {
wp_die( __( 'Please select a customer.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 400 ) );
}
$customer_id = ! empty( $_GET['customer_id'] ) ? absint( $_GET['customer_id'] ) : false;
if ( empty( $customer_id ) ) {
$customer = rcp_get_customer_by_user_id( absint( $_GET['member_id'] ) );
if ( ! empty( $customer ) ) {
$customer_id = $customer->get_id();
}
}
$current_user = wp_get_current_user();
rcp_log( sprintf( '%s re-sending email verification to customer #%d.', $current_user->user_login, $customer_id ) );
rcp_send_email_verification( urldecode( absint( $_GET['member_id'] ) ) );
$page_args = array(
'rcp_message' => 'verification_sent'
);
if ( ! empty( $customer_id ) ) {
$page_args['customer_id'] = $customer_id;
$page_args['view'] = 'edit';
}
wp_safe_redirect( rcp_get_customers_admin_page( $page_args ) );
exit;
}
add_action( 'rcp_action_send_verification', 'rcp_process_resend_verification' );
/**
* Manually verify a member's email
*
* @since 2.9.5
* @return void
*/
function rcp_process_manually_verify_email() {
if ( ! wp_verify_nonce( $_GET['_wpnonce'], 'rcp-manually-verify-email-nonce' ) ) {
wp_die( __( 'Nonce verification failed.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 403 ) );
}
if ( ! current_user_can( 'rcp_manage_members' ) ) {
wp_die( __( 'You do not have permission to perform this action.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 403 ) );
}
if ( ! isset( $_GET['member_id'] ) && ! isset( $_GET['customer_id'] ) ) {
wp_die( __( 'Please select a customer.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 400 ) );
}
$current_user = wp_get_current_user();
if ( ! empty( $_GET['customer_id'] ) ) {
/*
* New: Verify by customer ID.
*/
$customer = rcp_get_customer( absint( $_GET['customer_id'] ) );
if ( empty( $customer ) ) {
wp_die( __( 'Invalid customer ID.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 400 ) );
}
rcp_log( sprintf( '%s manually verifying email of customer #%d.', $current_user->user_login, $customer->get_id() ) );
$customer->verify_email();
$customer->add_note( sprintf( __( 'Email manually verified by %s.', 'rcp' ), $current_user->user_login ) );
} else {
/*
* Backwards Compatibility
* Verify by user ID.
*/
$member = new RCP_Member( absint( $_GET['member_id'] ) );
rcp_log( sprintf( '%s manually verifying email of member #%d.', $current_user->user_login, $member->ID ) );
$member->verify_email();
$member->add_note( sprintf( __( 'Email manually verified by %s.', 'rcp' ), $current_user->user_login ) );
}
$redirect_url = wp_get_referer();
if ( empty( $redirect_url ) ) {
$redirect_url = rcp_get_customers_admin_page();
} else {
$redirect_url = remove_query_arg( 'rcp_message', $redirect_url );
}
wp_safe_redirect( add_query_arg( 'rcp_message', 'email_verified', $redirect_url ) );
exit;
}
add_action( 'rcp_action_verify_email', 'rcp_process_manually_verify_email' );
/**
* If someone visits ?page=rcp-members&edit_member=123 we need to redirect them to the new customer edit page for
* this corresponding user account.
*
* @since 3.0
* @return void
*/
function rcp_redirect_edit_member_url() {
if ( empty( $_GET['page'] ) || 'rcp-members' != $_GET['page'] ) {
return;
}
if ( empty( $_GET['edit_member'] ) ) {
return;
}
$user_id = absint( $_GET['edit_member'] );
$customer = rcp_get_customer_by( 'user_id', $user_id );
if ( empty( $customer ) ) {
return;
}
wp_safe_redirect( rcp_get_customers_admin_page( array(
'customer_id' => $customer->get_id(),
'view' => 'edit'
) ) );
exit;
}
add_action( 'admin_init', 'rcp_redirect_edit_member_url' );

View File

@@ -0,0 +1,69 @@
<?php
/**
* Members Page
*
* @package Restrict Content Pro
* @subpackage Admin/Members Page
* @copyright Copyright (c) 2017, Restrict Content Pro
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
*/
/**
* Render members table
*
* @return void
*/
function rcp_members_page() {
do_action( 'stellarwp/telemetry/restrict-content-pro/optin' );
do_action( 'stellarwp/telemetry/restrict-content/optin' );
if ( ! empty( $_GET['view'] ) && 'edit' == $_GET['view'] && ! empty( $_GET['membership_id'] ) ) {
require_once RCP_PLUGIN_DIR . 'core/includes/admin/memberships/edit-membership.php';
} elseif ( ! empty( $_GET['view'] ) && 'add' == $_GET['view'] ) {
require_once RCP_PLUGIN_DIR . 'core/includes/admin/memberships/add-membership.php';
} elseif ( ! empty( $_GET['view'] ) && 'cancel-confirmation' == $_GET['view'] ) {
require_once RCP_PLUGIN_DIR . 'core/includes/admin/memberships/cancel-membership.php';
} else {
// List all memberships.
rcp_memberships_list();
}
return;
}
/**
* Display the list of memberships.
*
* @since 3.0
* @return void
*/
function rcp_memberships_list() {
include_once RCP_PLUGIN_DIR . 'core/includes/admin/memberships/class-memberships-table.php';
$table_class = new \RCP\Admin\Memberships_Table();
$table_class->prepare_items();
?>
<div class="wrap">
<h1>
<?php _e( 'Memberships', 'rcp' ); ?>
<a href="<?php echo esc_url( rcp_get_memberships_admin_page( array( 'view' => 'add' ) ) ); ?>" class="page-title-action"><?php _e( 'Add New', 'rcp' ); ?></a>
</h1>
<?php do_action( 'rcp_members_above_table' ); ?>
<form id="rcp-memberships-filter" method="GET" action="<?php echo esc_url( add_query_arg( 'page', 'rcp-members', admin_url( 'admin.php' ) ) ); ?>">
<input type="hidden" name="page" value="rcp-members"/>
<?php
$table_class->views();
$table_class->search_box( __( 'Search memberships', 'rcp' ), 'rcp-memberships' );
$table_class->display();
?>
</form>
<?php do_action( 'rcp_members_below_table' ); ?>
</div>
<?php
}

View File

@@ -0,0 +1,196 @@
<?php
/**
* Add Membership
*
* @package restrict-content-pro
* @copyright Copyright (c) 2018, Restrict Content Pro team
* @license GPL2+
* @since 3.0
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
if ( ! isset( $_GET['view'] ) || 'add' != $_GET['view'] ) {
wp_die( __( 'Something went wrong.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 400 ) );
}
?>
<div class="wrap">
<h1><?php _e( 'Add Membership', 'rcp' ); ?></h1>
<div id="rcp-item-card-wrapper">
<div class="rcp-info-wrapper rcp-item-section rcp-membership-card-wrapper">
<form id="rcp-add-membership-info" method="POST">
<div class="rcp-item-info">
<table class="widefat striped">
<tbody>
<tr>
<th scope="row" class="row-title">
<label for="rcp-customer-email"><?php _e( 'Customer:', 'rcp' ); ?></label>
</th>
<td>
<?php if ( ! empty( $_GET['customer_id'] ) ) :
$customer = rcp_get_customer( absint( $_GET['customer_id'] ) );
if ( ! empty( $customer ) ) {
$user = get_userdata( $customer->get_user_id() );
?>
<a href="<?php echo esc_url( rcp_get_customers_admin_page( array( 'customer_id' => $customer->get_id(), 'view' => 'edit' ) ) ); ?>"><?php echo esc_html( $user->display_name ); ?></a>
<input type="hidden" name="customer_id" value="<?php echo esc_attr( $customer->get_id() ); ?>"/>
<?php
}
?>
<?php else : ?>
<input type="text" id="rcp-customer-email" class="rcp-user-search" data-return-field="user_email" name="user_email" placeholder="<?php esc_attr_e( 'Email', 'rcp' ); ?>" value="<?php echo ! empty( $_GET['email'] ) ? esc_attr( rawurldecode( $_GET['email'] ) ) : ''; ?>"/>
<span alt="f223" class="rcp-help-tip dashicons dashicons-editor-help" title="<?php esc_attr_e( 'Enter the email of an existing customer. If a customer doesn\'t exist with this email, a new one will be created.', 'rcp' ); ?>"></span>
<div id="rcp_user_search_results"></div>
<?php endif; ?>
</td>
</tr>
<tr>
<th scope="row" class="row-title">
<label for="rcp-membership-level"><?php _e( 'Membership Level:', 'rcp' ); ?></label>
</th>
<td>
<?php
$levels = rcp_get_membership_levels( array( 'number' => 999 ) );
if ( $levels ) {
echo '<select id="rcp-membership-level" name="object_id">';
foreach ( $levels as $level ) {
echo '<option value="' . esc_attr( $level->get_id() ) . '">' . esc_html( $level->get_name() ) . '</option>';
}
echo '</select>';
} else {
_e( 'No levels found', 'rcp' );
}
?>
</td>
</tr>
<tr>
<th scope="row">
<label for="rcp-status"><?php _e( 'Membership Status:', 'rcp' ); ?></label>
</th>
<td>
<select name="status" id="rcp-status">
<?php
$statuses = array( 'active', 'expired', 'cancelled', 'pending' );
foreach ( $statuses as $status ) :
echo '<option value="' . esc_attr( $status ) . '">' . rcp_get_status_label( $status ) . '</option>';
endforeach;
?>
</select>
</td>
</tr>
<tr>
<th scope="row" class="row-title">
<label><?php _e( 'Billing Cycle:', 'rcp' ); ?></label>
</th>
<td>
<label for="rcp-initial-amount" class="screen-reader-text"><?php _e( 'Initial Amount', 'rcp' ); ?></label>
<?php echo rcp_get_currency_symbol(); ?>
<input type="text" id="rcp-initial-amount" name="initial_amount" placeholder="0.00" style="width: 80px;" value="" readonly/> <!-- @todo make this editable -->
<span id="rcp-billing-cycle-recurring">
&nbsp;<?php _e( 'initially, then', 'rcp' ); ?>&nbsp;
<label for="rcp-recurring-amount" class="screen-reader-text"><?php _e( 'Recurring Amount', 'rcp' ); ?></label>
<?php echo rcp_get_currency_symbol(); ?>
<input type="text" id="rcp-recurring-amount" name="recurring_amount" placeholder="0.00" style="width: 80px;" value="" readonly/> <!-- @todo make this editable -->
&nbsp;<?php _e( 'for renewals', 'rcp' ); ?>
</span>
</td>
</tr>
<tr>
<th scope="row" class="row-title">
<label for="rcp-times-billed"><?php _e( 'Times Billed:', 'rcp' ); ?></label>
</th>
<td>
<input type="number" id="rcp-times-billed" name="times_billed" min="0" step="1" value="0"/>
<span alt="f223" class="rcp-help-tip dashicons dashicons-editor-help" title="<?php esc_attr_e( 'Number of times this membership has been billed for so far.', 'rcp' ); ?>"></span>
</td>
</tr>
<tr>
<th scope="row" class="row-title">
<label for="rcp-membership-created"><?php _e( 'Date Created:', 'rcp' ); ?></label>
</th>
<td>
<input type="text" id="rcp-membership-created" name="created_date" class="rcp-datepicker rcp-membership-created" value="<?php echo esc_attr( date( 'Y-m-d', current_time( 'timestamp' ) ) ); ?>"/>
</td>
</tr>
<tr>
<th scope="row" class="row-title">
<label for="rcp-membership-expiration">
<?php _e( 'Expiration Date:', 'rcp' ); ?>
</label>
</th>
<td>
<input type="text" id="rcp-membership-expiration" name="expiration_date" class="rcp-datepicker rcp-membership-expiration" value=""/>
<input type="checkbox" id="rcp-membership-expiration-none" name="expiration_date_none" value="1"/>
<label for="rcp-membership-expiration-none"><?php _e( 'Never expires', 'rcp' ); ?></label>
</td>
</tr>
<tr>
<th scope="row" class="row-title">
<label for="rcp-recurring"><?php _e( 'Auto Renew:', 'rcp' ); ?></label>
</th>
<td>
<input type="checkbox" name="auto_renew" id="rcp-recurring" value="1"/>
<span alt="f223" class="rcp-help-tip dashicons dashicons-editor-help" title="<?php esc_attr_e( 'Note: Checking this does not automatically create a recurring subscription. The customer should already have one created in the payment gateway.', 'rcp' ); ?>"></span>
</td>
</tr>
<tr>
<th scope="row" class="row-title">
<label for="rcp-payment-method"><?php _e( 'Payment Method:', 'rcp' ); ?></label>
</th>
<td>
<select id="rcp-payment-method" name="gateway">
<?php
$gateways = rcp_get_payment_gateways();
foreach ( $gateways as $gateway_key => $gateway ) {
?>
<option value="<?php echo esc_attr( $gateway_key ); ?>" <?php selected( $gateway_key, 'manual' ); ?>><?php echo esc_html( $gateway['admin_label'] ); ?></option>
<?php
}
?>
</select>
</td>
</tr>
<tr>
<th scope="row" class="row-title">
<label for="rcp-membership-gateway-customer-id"><?php _e( 'Gateway Customer ID:', 'rcp' ); ?></label>
</th>
<td>
<input type="text" id="rcp-membership-gateway-customer-id" name="gateway_customer_id" value=""/>
</td>
</tr>
<tr>
<th scope="row" class="row-title">
<label for="rcp-membership-gateway-subscription-id"><?php _e( 'Gateway Subscription ID:', 'rcp' ); ?></label>
</th>
<td>
<input type="text" id="rcp-membership-gateway-subscription-id" name="gateway_subscription_id" value=""/>
</td>
</tr>
<?php
/**
* Add additional fields to the Add Membership form.
*
* @since 3.0.5
*/
do_action( 'rcp_add_membership_after' );
?>
</tbody>
</table>
</div>
<div id="rcp-item-edit-actions" class="edit-item">
<input type="hidden" name="rcp-action" value="add_membership"/>
<?php wp_nonce_field( 'rcp_add_membership', 'rcp_add_membership_nonce' ); ?>
<input type="submit" class="button button-primary" value="<?php _e( 'Add Membership', 'rcp' ); ?>"/>
</div>
</form>
</div>
</div>
</div>

View File

@@ -0,0 +1,57 @@
<?php
/**
* Cancel Membership
*
* @package restrict-content-pro
* @copyright Copyright (c) 2018, Restrict Content Pro team
* @license GPL2+
* @since 3.0
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
if ( ! isset( $_GET['membership_id'] ) || ! is_numeric( $_GET['membership_id'] ) ) {
wp_die( __( 'Something went wrong.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 400 ) );
}
$membership_id = absint( $_GET['membership_id'] );
$membership = rcp_get_membership( $membership_id );
if ( empty( $membership ) ) {
wp_die( __( 'Something went wrong.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 400 ) );
}
// Prevent editing disabled memberships.
if ( $membership->is_disabled() ) {
wp_die( __( 'Invalid membership.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 403 ) );
}
// Prevent cancelling memberships that cannot be cancelled.
if ( ! $membership->can_cancel() ) {
wp_die( __( 'This membership cannot be cancelled.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 403 ) );
}
$cancel_url = wp_nonce_url( rcp_get_memberships_admin_page( array(
'membership_id' => $membership->get_id(),
'rcp-action' => 'cancel_membership'
) ), 'cancel_membership' );
$edit_url = rcp_get_memberships_admin_page( array(
'membership_id' => $membership->get_id(),
'view' => 'edit'
) );
?>
<div class="wrap">
<h1><?php _e( 'Confirm Membership Cancellation', 'rcp' ) ?></h1>
<p><?php printf( __( 'Are you sure you wish to cancel <a href="%s">membership #%d</a>? This will stop automatic billing. The customer will retain access to restricted content until the membership expiration date, %s.', 'rcp' ), esc_url( $edit_url ), $membership->get_id(), $membership->get_expiration_date() ); ?></p>
<?php if ( $membership->has_payment_plan() && ! $membership->at_maximum_renewals() ) : ?>
<div class="notice notice-error inline">
<p><?php printf( __( 'Note: This membership is a payment plan still in progress; it has only completed %d / %d payments. If you cancel this membership, future installment payments will not be processed automatically.', 'rcp' ), $membership->get_times_billed(), $membership->get_maximum_renewals() + 1 ); ?></p>
</div>
<?php endif; ?>
<p>
<a href="<?php echo esc_url( $cancel_url ); ?>" class="button button-primary"><?php _e( 'Cancel Membership', 'rcp' ); ?></a>
</p>
</div>

View File

@@ -0,0 +1,616 @@
<?php
/**
* Memberships List Table
*
* @package restrict-content-pro
* @copyright Copyright (c) 2018, Restrict Content Pro
* @license GPL2+
* @since 3.0
*/
namespace RCP\Admin;
/**
* Class Memberships_Table
*
* @since 3.0
* @package RCP\Admin
*/
class Memberships_Table extends List_Table {
/**
* Constructor.
*
* @since 3.0
* @see WP_List_Table::__construct()
*/
public function __construct() {
parent::__construct( [
'singular' => 'Membership',
'plural' => 'Memberships',
'ajax' => false,
] );
$this->process_bulk_action();
$this->get_counts();
}
/**
* Get the base URL for the memberships list table.
*
* @since 3.0
* @return string Base URL.
*/
public function get_base_url() {
return rcp_get_memberships_admin_page();
}
/**
* Retrieve the table columns.
*
* @since 3.0
* @return array
*/
public function get_columns() {
$columns = array(
'cb' => '<input type="checkbox" />',
'customer' => __( 'Customer', 'rcp' ),
'object_id' => __( 'Membership', 'rcp' ),
'status' => __( 'Status', 'rcp' ),
'auto_renew' => __( 'Recurring', 'rcp' ),
'created_date' => __( 'Created', 'rcp' ),
'expiration_date' => __( 'Expiration', 'rcp' ),
);
/*
* Backwards compatibility: add an "extra" column if someone is hooking into the old action to add
* their own column. Everything gets bundled into one column because this is the only way we can realistically
* do it.
*/
if ( has_action( 'rcp_members_page_table_header' ) ) {
$columns['custom'] = __( 'Extra', 'rcp' );
}
$columns = apply_filters( 'rcp_memberships_list_table_columns', $columns );
return $columns;
}
/**
* Retrieve the sortable columns.
*
* @since 3.0
* @return array
*/
public function get_sortable_columns() {
return array(
'object_id' => array( 'object_id', false ),
'status' => array( 'status', false ),
'auto_renew' => array( 'auto_renew', false ),
'created_date' => array( 'created_date', false ),
'expiration_date' => array( 'expiration_date', false )
);
}
/**
* Gets the name of the primary column.
*
* @since 3.0
* @return string
*/
protected function get_primary_column_name() {
return 'customer';
}
/**
* This function renders any other columns in the list table.
*
* @param \RCP_Membership $membership Membership object.
* @param string $column_name The name of the column
*
* @since 3.0
* @return string Column Name
*/
public function column_default( $membership, $column_name ) {
$value = '';
/*
* Backwards compatibility: show content of custom columns from old action hook.
*/
if ( 'custom' == $column_name && has_action( 'rcp_members_page_table_column' ) ) {
$customer = $membership->get_customer();
$user_id = $customer instanceof \RCP_Customer ? $customer->get_user_id() : 0;
ob_start();
do_action( 'rcp_members_page_table_column', $user_id );
$column_content = ob_get_clean();
$value = wp_strip_all_tags( $column_content );
}
/**
* Filters the column value.
*
* @param string $value Column value.
* @param \RCP_Membership $membership Membership object.
*
* @since 3.0
*/
$value = apply_filters( 'rcp_memberships_list_table_column_' . $column_name, $value, $membership );
return $value;
}
/**
* Render the checkbox column.
*
* @param \RCP_Membership $membership
*
* @since 3.0
* @return string
*/
public function column_cb( $membership ) {
return sprintf(
'<input type="checkbox" name="%1$s[]" value="%2$s" />',
'membership_id',
$membership->get_id()
);
}
/**
* Render the "Customer" column.
*
* @param \RCP_Membership $membership
*
* @since 3.0
* @return string
*/
public function column_customer( $membership ) {
$membership_id = $membership->get_id();
$customer = $membership->get_customer();
$user_id = $customer instanceof \RCP_Customer ? $customer->get_user_id() : 0;
$user = ! empty( $user_id ) ? get_userdata( $user_id ) : false;
if ( $user instanceof \WP_User ) {
$display_name = ! empty( $user->display_name ) ? $user->display_name : $user->user_login;
} else {
$display_name = __( '(Unknown)', 'rcp' );
}
$edit_membership_url = rcp_get_memberships_admin_page( array(
'membership_id' => absint( $membership_id ),
'view' => 'edit'
) );
$edit_customer_url = $customer instanceof \RCP_Customer ? rcp_get_customers_admin_page( array(
'customer_id' => $customer->get_id(),
'view' => 'edit'
) ) : '';
$cancel_url = wp_nonce_url( add_query_arg( array(
'rcp-action' => 'cancel_membership',
'membership_id' => urlencode( $membership_id )
), $this->get_base_url() ), 'cancel_membership' );
$actions = array(
'edit_membership' => '<a href="' . esc_url( $edit_membership_url ) . '">' . __( 'Edit Membership', 'rcp' ) . '</a>',
);
// Only add Edit Customer link if we have a customer.
if ( ! empty( $edit_customer_url ) ) {
$actions['edit_customer'] = '<a href="' . esc_url( $edit_customer_url ) . '">' . __( 'Edit Customer', 'rcp' ) . '</a>';
}
if ( $membership->can_cancel() ) {
$actions['cancel'] = '<a href="' . esc_url( $cancel_url ) . '" class="rcp_cancel">' . __( 'Cancel', 'rcp' ) . '</a>';
}
// Membership ID goes last.
$actions['membership_id'] = '<span class="rcp-id-col">' . sprintf( __( 'ID: %d', 'rcp' ), $membership_id ) . '</span>';
ob_start();
/**
* @deprecated 3.0 Use `rcp_memberships_list_table_row_actions` instead.
*/
do_action( 'rcp_member_row_actions', $user_id );
$custom_row_actions = ob_get_clean();
if ( $custom_row_actions ) {
$actions['custom_row_actions'] = $custom_row_actions;
}
/**
* Filters the row actions.
*
* @param array $actions Default actions.
* @param \RCP_Membership $membership Membership object.
*
* @since 3.0
*/
$actions = apply_filters( 'rcp_memberships_list_table_row_actions', $actions, $membership );
return '<strong><a class="row-title" href="' . esc_url( $edit_membership_url ) . '">' . esc_html( $display_name ) . '</a></strong>' . $this->row_actions( $actions );
}
/**
* Render the "Membership" column.
*
* @param \RCP_Membership $membership
*
* @since 3.0
* @return string
*/
public function column_object_id( $membership ) {
return $membership->get_membership_level_name();
}
/**
* Render the "Status" column.
*
* @param \RCP_Membership $membership
*
* @since 3.0
* @return string
*/
public function column_status( $membership ) {
return rcp_print_membership_status( $membership->get_id(), false );
}
/**
* Render the "Recurring" column.
*
* @param \RCP_Membership $membership
*
* @since 3.0
* @return string
*/
public function column_auto_renew( $membership ) {
return $membership->is_recurring() ? __( 'Yes', 'rcp' ) : __( 'No', 'rcp' );
}
/**
* Render the "Created" column.
*
* @param \RCP_Membership $membership
*
* @since 3.0
* @return string
*/
public function column_created_date( $membership ) {
return $membership->get_created_date();
}
/**
* Render the "Expiration" column.
*
* @param \RCP_Membership $membership
*
* @since 3.0
* @return string
*/
public function column_expiration_date( $membership ) {
return $membership->get_expiration_date();
}
/**
* Message to be displayed when there are no memberships.
*
* @since 3.0
* @return void
*/
public function no_items() {
esc_html_e( 'No memberships found.', 'rcp' );
}
/**
* Retrieve the bulk actions.
*
* @since 3.0
* @return array
*/
public function get_bulk_actions() {
return array(
'activate' => __( 'Activate', 'rcp' ),
'expire' => __( 'Expire', 'rcp' ),
'cancel' => __( 'Cancel', 'rcp' ),
'delete' => __( 'Permanently Delete', 'rcp' )
);
}
/**
* Process bulk actions.
*
* @since 3.0
* @return void
*/
public function process_bulk_action() {
// Bail if a nonce was not supplied.
if ( ! isset( $_REQUEST['_wpnonce'] ) ) {
return;
}
if ( ! wp_verify_nonce( $_REQUEST['_wpnonce'], 'bulk-memberships' ) ) {
return;
}
$ids = wp_parse_id_list( (array) $this->get_request_var( 'membership_id', false ) );
// Bail if no IDs
if ( empty( $ids ) ) {
return;
}
$current_user = wp_get_current_user();
foreach ( $ids as $id ) {
$membership = rcp_get_membership( absint( $id ) );
if ( empty( $membership ) ) {
continue;
}
switch ( $this->current_action() ) {
case 'activate':
$membership->activate();
break;
case 'expire':
$membership->add_note( sprintf( __( 'Membership expired via bulk action by user %s (#%d).', 'rcp' ), $current_user->user_login, $current_user->ID ) );
$membership->expire();
break;
case 'cancel':
$membership->add_note( sprintf( __( 'Membership cancelled via bulk action by user %s (#%d).', 'rcp' ), $current_user->user_login, $current_user->ID ) );
if ( $membership->can_cancel() ) {
$membership->cancel_payment_profile();
} else {
$membership->cancel();
}
break;
case 'delete':
$membership->disable(); // we don't truly delete
break;
}
}
$this->show_admin_notice( $this->current_action() );
}
/**
* Show admin notice for bulk actions.
*
* @param string $action The action to show the notice for.
*
* @access private
* @since 3.0.8
* @return void
*/
private function show_admin_notice( $action ) {
$message = '';
switch ( $action ) {
case 'activate' :
$message = __( 'Membership(s) activated.', 'rcp' );
break;
case 'expire' :
$message = __( 'Membership(s) expired.', 'rcp' );
break;
case 'cancel' :
$message = __( 'Membership(s) cancelled.', 'rcp' );
break;
case 'delete' :
$message = __( 'Membership(s) deleted.', 'rcp' );
break;
}
if ( empty( $message ) ) {
return;
}
echo '<div class="updated"><p>' . $message . '</p></div>';
}
/**
* Retrieve the membership counts.
*
* @since 3.0
* @return void
*/
public function get_counts() {
$this->counts = rcp_get_membership_counts();
}
/**
* Retrieve memberships data.
*
* @param bool $count Whether or not to get membership objects (false) or just count the total number (true).
*
* @since 3.0
* @return array|int
*/
public function memberships_data( $count = false ) {
$search_type = $this->get_request_var( 'search_type', '' );
$args = array(
'number' => $this->per_page,
'offset' => $this->get_offset(),
'orderby' => sanitize_text_field( $this->get_request_var( 'orderby', 'date_modified' ) ),
'order' => sanitize_text_field( $this->get_request_var( 'order', 'DESC' ) ),
'object_id' => sanitize_text_field( $this->get_request_var( 'object_id', '' ) ),
'status' => $this->get_status(),
);
/*
* Filter by customer ID
*/
$customer_id = $this->get_request_var( 'customer_id' );
if ( ! empty( $customer_id ) ) {
$args['customer_id'] = absint( $customer_id );
}
$search = $this->get_search();
if ( ! empty( $search ) ) {
if ( 'user' == $search_type ) {
/*
* Search by user account
* This process sucks because our query class doesn't do joins.
*/
// First we have to search for user accounts.
$user_ids = get_users( array(
'number' => -1,
'search' => '*' . $search . '*',
'fields' => 'ids'
) );
// No user results - bail.
if ( empty( $user_ids ) ) {
return $count ? 0 : array();
}
// Now get all customers based on these accounts.
$customer_ids = rcp_get_customers( array(
'number' => 999,
'user_id__in' => $user_ids,
'fields' => 'ID'
) );
// No customer results - bail.
if ( empty( $customer_ids ) ) {
return $count ? 0 : array();
}
// Finally, include these customer IDs in the memberships query.
$args['customer_id__in'] = $customer_ids;
} else {
/*
* Search by any membership field.
*/
$args['search'] = $search;
}
}
if ( $count ) {
return rcp_count_memberships( $args );
}
return rcp_get_memberships( $args );
}
/**
* Setup the final data for the table.
*
* @since 3.0
* @return void
*/
public function prepare_items() {
$columns = $this->get_columns();
$hidden = array();
$sortable = $this->get_sortable_columns();
$this->_column_headers = array( $columns, $hidden, $sortable );
$this->items = $this->memberships_data();
$total = $this->memberships_data( true );
// Setup pagination
$this->set_pagination_args( array(
'total_items' => $total,
'per_page' => $this->per_page,
'total_pages' => ceil( $total / $this->per_page )
) );
}
/**
* Display extra table nav. This includes the membership level filter.
*
* @param string $which
*
* @since 3.0
*/
protected function extra_tablenav( $which ) {
if ( 'top' !== $which ) {
return;
}
$level_id = $this->get_request_var( 'object_id', '' );
$levels = rcp_get_membership_levels( array( 'number' => 999 ) );
if ( empty( $levels ) ) {
return;
}
?>
<div class="alignleft actions">
<label for="rcp-memberships-level-filter" class="screen-reader-text"><?php _e( 'Filter by membership level', 'rcp' ); ?></label>
<select id="rcp-memberships-level-filter" name="object_id">
<option value="" <?php selected( $level_id, '' ); ?>><?php _e( 'All Membership Levels', 'rcp' ); ?></option>
<?php foreach ( $levels as $level ) : ?>
<option value="<?php echo esc_attr( $level->get_id() ); ?>" <?php selected( $level_id, $level->get_id() ); ?>><?php echo esc_html( $level->get_name() ); ?></option>
<?php endforeach; ?>
</select>
<?php if ( $this->get_status() ) : ?>
<input type="hidden" name="status" value="<?php echo esc_attr( $this->get_status() ); ?>" />
<?php endif; ?>
<?php submit_button( __( 'Filter' ), '', 'filter_action', false ); ?>
</div>
<?php
}
/**
* Show the search field.
*
* @param string $text Label for the search box
* @param string $input_id ID of the search box
*
* @since 3.0
*/
public function search_box( $text, $input_id ) {
// Bail if no items and no search
if ( ! $this->get_search() && ! $this->has_items() ) {
return;
}
$orderby = $this->get_request_var( 'orderby' );
$order = $this->get_request_var( 'order' );
$search_type = $this->get_request_var( 'search_type', 'user' );
$input_id = $input_id . '-search-input';
if ( ! empty( $orderby ) ) {
echo '<input type="hidden" name="orderby" value="' . esc_attr( $orderby ) . '" />';
}
if ( ! empty( $order ) ) {
echo '<input type="hidden" name="order" value="' . esc_attr( $order ) . '" />';
}
?>
<p class="search-box">
<label class="screen-reader-text" for="rcp-memberships-search-type"><?php esc_html_e( 'Choose a field to search', 'rcp' ); ?></label>
<select id="rcp-memberships-search-type" name="search_type" style="float:left;">
<option value="user" <?php selected( $search_type, 'user' ); ?>><?php _e( 'User Account (name, email, login)', 'rcp' ); ?></option>
<option value="gateway_id" <?php selected( $search_type, 'gateway_id' ); ?>><?php _e( 'Gateway Subscription ID', 'rcp' ); ?></option>
</select>
<label class="screen-reader-text" for="<?php echo esc_attr( $input_id ); ?>"><?php echo esc_html( $text ); ?>:</label>
<input type="search" id="<?php echo esc_attr( $input_id ); ?>" name="s" value="<?php _admin_search_query(); ?>"/>
<?php submit_button( esc_html( $text ), 'button', false, false, array( 'ID' => 'search-submit' ) ); ?>
</p>
<?php
}
}

View File

@@ -0,0 +1,488 @@
<?php
/**
* Edit Membership
*
* @package restrict-content-pro
* @copyright Copyright (c) 2018, Restrict Content Pro team
* @license GPL2+
* @since 3.0
*/
use RCP\Membership_Level;
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
if ( ! isset( $_GET['membership_id'] ) || ! is_numeric( $_GET['membership_id'] ) ) {
wp_die( __( 'Something went wrong.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 400 ) );
}
$membership_id = $_GET['membership_id'];
$membership = rcp_get_membership( $membership_id );
if ( empty( $membership ) ) {
wp_die( __( 'Something went wrong.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 400 ) );
}
// Prevent editing disabled memberships.
if ( $membership->is_disabled() ) {
wp_die( __( 'Invalid membership.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 403 ) );
}
$customer = $membership->get_customer();
$user = $customer instanceof RCP_Customer ? get_userdata( $customer->get_user_id() ) : false;
$membership_level = rcp_get_membership_level( $membership->get_object_id() );
$created_date = date( 'Y-m-d H:i:s', strtotime( $membership->get_created_date( false ), current_time( 'timestamp' ) ) );
$expiration_date = date( 'Y-m-d', strtotime( $membership->get_expiration_date( false ), current_time( 'timestamp' ) ) );
// Action URLs.
$cancel_url = wp_nonce_url( rcp_get_memberships_admin_page( array(
'membership_id' => $membership->get_id(),
'rcp-action' => 'cancel_membership'
) ), 'cancel_membership' );
$expire_url = wp_nonce_url( rcp_get_memberships_admin_page( array(
'membership_id' => $membership->get_id(),
'rcp-action' => 'expire_membership'
) ), 'expire_membership' );
// If this is a payment plan then override the cancellation URL to take them to a second confirmation screen.
if ( $membership->has_payment_plan() ) {
$cancel_url = rcp_get_memberships_admin_page( array(
'membership_id' => $membership->get_id(),
'view' => 'cancel-confirmation',
) );
}
// Payments
$payments = $membership->get_payments( array( 'number' => 5 ) );
?>
<div class="wrap">
<h1><?php _e( 'Membership Details', 'rcp' ); ?></h1>
<div id="rcp-item-card-wrapper">
<div class="rcp-info-wrapper rcp-item-section rcp-membership-card-wrapper">
<form id="rcp-edit-membership-info" method="POST">
<div class="rcp-item-info">
<table class="widefat striped">
<tbody>
<tr>
<th scope="row" class="row-title">
<label for="tablecell"><?php _e( 'ID:', 'rcp' ); ?></label>
</th>
<td>
<?php echo $membership->get_id(); ?>
</td>
</tr>
<tr>
<th scope="row" class="row-title">
<label for="tablecell"><?php _e( 'Customer:', 'rcp' ); ?></label>
</th>
<td>
<?php if ( $customer instanceof RCP_Customer && $user instanceof WP_User ) : ?>
<a href="<?php echo esc_url( rcp_get_customers_admin_page( array( 'customer_id' => $customer->get_id(), 'view' => 'edit' ) ) ); ?>"><?php echo ! empty( $user->display_name ) ? esc_html( $user->display_name ) : esc_html( $user->user_login ); ?></a>
<?php else : ?>
<?php _e( '(Unknown)', 'rcp' ); ?>
<?php endif; ?>
</td>
</tr>
<tr>
<th scope="row" class="row-title">
<label for="rcp-membership-level"><?php _e( 'Membership Level:', 'rcp' ); ?></label>
</th>
<td>
<span class="rcp-current-membership-level"><?php echo $membership->get_membership_level_name(); ?></span>
<select name="object_id" id="rcp-membership-level" class="hidden">
<?php foreach ( rcp_get_membership_levels( array( 'number' => 999 ) ) as $level ) : ?>
<option value="<?php echo esc_attr( $level->get_id() ); ?>" <?php selected( $level->get_id(), $membership->get_object_id() ); ?>><?php echo esc_html( $level->get_name() ); ?></option>
<?php endforeach; ?>
</select>
<input type="submit" name="rcp_change_membership_level" class="button hidden" id="rcp-change-membership-level-button" title="<?php echo $membership->is_recurring() ? esc_attr__( 'Warning: The subscription will be cancelled at the payment gateway.', 'rcp' ) : ''; ?>" value="<?php esc_attr_e( 'Change Level', 'rcp' ); ?>">
<span>&nbsp;&ndash;&nbsp;</span>
<a href="#" id="rcp-edit-membership-level"><?php _e( 'Edit', 'rcp' ); ?></a>
</td>
</tr>
<tr>
<th scope="row">
<label for="rcp-status"><?php _e( 'Membership Status:', 'rcp' ); ?></label>
</th>
<td>
<select name="status" id="rcp-status">
<?php
$statuses = array( 'active', 'expired', 'cancelled', 'pending' );
foreach ( $statuses as $status ) :
echo '<option value="' . esc_attr( $status ) . '"' . selected( $status, $membership->get_status(), false ) . '>' . rcp_get_status_label( $status ) . '</option>';
endforeach;
?>
</select>
<span alt="f223" class="rcp-help-tip dashicons dashicons-editor-help" title="<?php esc_attr_e( 'Active memberships have access to restricted content. Members with a status of Cancelled may continue to access restricted content until the expiration date on their account is reached. When a user reaches his or her expiration date, their status is updated to Expired.', 'rcp' ); ?>"></span>
<span id="rcp-membership-status-action-buttons">
<?php if ( 'cancelled' != $membership->get_status() ) :
$title_text = $membership->can_cancel() ? __( 'Cancel membership and recurring billing. The customer will retain access until they reach the expiration date.', 'rcp' ) : __( 'Membership cannot be cancelled as it does not have a recurring subscription.', 'rcp' );
?>
<a class="button rcp_cancel" id="rcp-cancel-membership-button" href="<?php echo esc_url( $cancel_url ) ?>" title="<?php echo esc_attr( $title_text ); ?>" <?php echo ! $membership->can_cancel() ? ' disabled="disabled"' : ''; ?>><?php _e( 'Cancel', 'rcp' ); ?></a>
<?php endif; ?>
<?php if ( $membership->is_active() ) : ?>
<a class="button" id="rcp-expire-membership-button" href="<?php echo esc_url( $expire_url ); ?>" title="<?php esc_attr_e( 'Revoke the customer\'s access immediately', 'rcp' ); ?>"><?php _e( 'Expire', 'rcp' ); ?></a>
<?php endif; ?>
</span>
</td>
</tr>
<tr>
<th scope="row" class="row-title">
<label><?php _e( 'Billing Cycle:', 'rcp' ); ?></label>
</th>
<td>
<?php if ( $membership->can_change_gateway_price() ) : ?>
<label for="rcp-initial-amount" class="screen-reader-text"><?php _e( 'Initial Amount', 'rcp' ); ?></label>
<?php echo rcp_get_currency_symbol(); ?>
<input type="text" id="rcp-initial-amount" name="initial_amount" placeholder="0.00" style="width: 80px;" value="<?php echo esc_attr( $membership->get_initial_amount() ); ?>" readonly/>
<span id="rcp-billing-cycle-recurring">
&nbsp;<?php _e( 'initially, then', 'rcp' ); ?>&nbsp;
<label for="rcp-recurring-amount" class="screen-reader-text"><?php _e( 'Recurring Amount', 'rcp' ); ?></label>
<?php echo rcp_get_currency_symbol(); ?>
<input type="text" id="rcp-recurring-amount" name="recurring_amount" placeholder="0.00" style="width: 80px;" value="<?php echo esc_attr( $membership->get_recurring_amount() ); ?>"/>
<?php
$duration_unit = lcfirst( rcp_filter_duration_unit( $membership_level->duration_unit, $membership_level->duration ) );
printf( _n( 'every %2$s', '%d %s', $membership_level->duration, 'rcp' ), $membership_level->duration, $duration_unit );
?>
</span>
<?php else :
echo $membership->get_formatted_billing_cycle();
endif; ?>
</td>
</tr>
<tr>
<th scope="row" class="row-title">
<label><?php _e( 'Times Billed:', 'rcp' ); ?></label>
</th>
<td>
<?php
if ( $membership_level instanceof Membership_Level ) {
if ( 0 == $membership->get_maximum_renewals() && ! $membership_level->is_lifetime() && ! $membership_level->is_free() ) {
printf( __( '%d / Until Cancelled', 'rcp' ), $membership->get_times_billed() );
} else {
$renewals = $membership_level->is_free() ? 1 : $membership->get_maximum_renewals() + 1;
printf( __( '%d / %d', 'rcp' ), $membership->get_times_billed(), $renewals );
}
} else {
_e( 'Unknown (membership level not found)', 'rcp' );
}
?>
</td>
</tr>
<tr>
<th scope="row" class="row-title">
<label for="rcp-membership-created"><?php _e( 'Date Created:', 'rcp' ); ?></label>
</th>
<td>
<span class="rcp-membership-created"><?php echo $membership->get_created_date(); ?></span>
<input type="text" id="rcp-membership-created" name="created_date" class="rcp-datepicker rcp-membership-created hidden" value="<?php echo esc_attr( $created_date ); ?>"/>
<span>&nbsp;&ndash;&nbsp;</span>
<a href="#" id="rcp-edit-membership-created"><?php _e( 'Edit', 'rcp' ); ?></a>
</td>
</tr>
<tr>
<th scope="row" class="row-title">
<label for="rcp-membership-expiration">
<?php echo $membership->is_trialing() ? __( 'Trialling Until:', 'rcp' ) : __( 'Expiration Date:', 'rcp' ); ?>
</label>
</th>
<td>
<span class="rcp-membership-expiration"><?php echo ( 'none' == $membership->get_expiration_date() ) ? __( 'Never Expires', 'rcp' ) : $membership->get_expiration_date(); ?></span>
<input type="text" id="rcp-membership-expiration" name="expiration_date" class="rcp-datepicker rcp-membership-expiration hidden" value="<?php echo esc_attr( $expiration_date ); ?>"/>
<span class="rcp-membership-expiration-none-wrap hidden">
<input type="checkbox" id="rcp-membership-expiration-none" name="expiration_date_none" value="1" <?php checked( 'none' == $membership->get_expiration_date() ); ?> />
<label for="rcp-membership-expiration-none"><?php _e( 'Never expires', 'rcp' ); ?></label>
</span>
<span>&nbsp;&ndash;&nbsp;</span>
<a href="#" id="rcp-edit-membership-expiration"><?php _e( 'Edit', 'rcp' ); ?></a>
</td>
</tr>
<?php if ( 'cancelled' == $membership->get_status() ) : ?>
<tr>
<th scope="row" class="row-title">
<label for="rcp-membership-cancellation-date"><?php _e( 'Cancellation Date:', 'rcp' ); ?></label>
</th>
<td>
<?php
$cancellation_date = $membership->get_cancellation_date();
if ( empty( $cancellation_date ) ) {
_e( 'Unknown', 'rcp' );
} else {
echo $cancellation_date;
}
?>
</td>
</tr>
<?php endif; ?>
<tr>
<th scope="row" class="row-title">
<label for="rcp-recurring"><?php _e( 'Auto Renew:', 'rcp' ); ?></label>
</th>
<td>
<input type="checkbox" name="auto_renew" id="rcp-recurring" value="1" <?php checked( $membership->is_recurring() ); ?>/>
<span alt="f223" class="rcp-help-tip dashicons dashicons-editor-help" title="<?php _e( 'If checked, this member has a recurring subscription. Only customers with recurring memberships will be given the option to cancel their membership on their subscription details page.', 'rcp' ); ?>"></span>
</td>
</tr>
<?php if ( 'free' != $membership->get_gateway() ) : ?>
<tr>
<th scope="row" class="row-title">
<label for="rcp-payment-method"><?php _e( 'Payment Method:', 'rcp' ); ?></label>
</th>
<td>
<?php
$gateways = rcp_get_payment_gateways();
$gateway_used = $membership->get_gateway();
?>
<select id="rcp-payment-method" name="gateway">
<?php
foreach ( $gateways as $gateway_key => $gateway ) {
?>
<option value="<?php echo esc_attr( $gateway_key ); ?>" <?php selected( $gateway_key, $gateway_used ); ?>><?php echo esc_html( $gateway['admin_label'] ); ?></option>
<?php
}
?>
</select>
</td>
</tr>
<tr>
<th scope="row" class="row-title">
<label for="rcp-membership-gateway-customer-id"><?php _e( 'Gateway Customer ID:', 'rcp' ); ?></label>
</th>
<td>
<span class="rcp-membership-gateway-customer-id">
<?php
$gateway_customer_id = $membership->get_gateway_customer_id();
if ( ! empty( $gateway_customer_id ) ) : ?>
<a href="<?php echo esc_url( rcp_get_gateway_customer_id_url( $membership->get_gateway(), $gateway_customer_id ) ); ?>" target="_blank">
<?php echo esc_html( $gateway_customer_id ) ?>
</a>
<?php endif; ?>
</span>
<input type="text" id="rcp-membership-gateway-customer-id" name="gateway_customer_id" class="hidden" value="<?php echo esc_attr( $membership->get_gateway_customer_id() ); ?>"/>
<span>&nbsp;&ndash;&nbsp;</span>
<a href="#" id="rcp-edit-membership-gateway-customer-id"><?php _e( 'Edit', 'rcp' ); ?></a>
</td>
</tr>
<tr>
<th scope="row" class="row-title">
<label for="rcp-membership-gateway-subscription-id"><?php _e( 'Gateway Subscription ID:', 'rcp' ); ?></label>
</th>
<td>
<span class="rcp-membership-gateway-subscription-id">
<?php
$gateway_subscription_id = $membership->get_gateway_subscription_id();
if ( ! empty( $gateway_subscription_id ) ) : ?>
<a href="<?php echo esc_url( rcp_get_gateway_subscription_id_url( $membership->get_gateway(), $gateway_subscription_id ) ); ?>" target="_blank">
<?php echo esc_html( $gateway_subscription_id ) ?>
</a>
<?php endif; ?>
</span>
<input type="text" id="rcp-membership-gateway-subscription-id" name="gateway_subscription_id" class="hidden" value="<?php echo esc_attr( $membership->get_gateway_subscription_id() ); ?>"/>
<span>&nbsp;&ndash;&nbsp;</span>
<a href="#" id="rcp-edit-membership-gateway-subscription-id"><?php _e( 'Edit', 'rcp' ); ?></a>
</td>
</tr>
<?php endif; ?>
<tr>
<th scope="row" class="row-title">
<?php _e( 'Subscription Key:', 'rcp' ); ?>
</th>
<td>
<?php echo esc_html( $membership->get_subscription_key() ); ?>
</td>
</tr>
<?php if ( $membership->was_upgrade() ) : ?>
<tr>
<th scope="row" class="row-title">
<label><?php _e( 'Changed From:', 'rcp' ); ?></label>
</th>
<td>
<?php
$previous_membership = rcp_get_membership( $membership->get_upgraded_from() );
if ( ! empty( $previous_membership ) ) {
echo $previous_membership->get_membership_level_name();
}
?>
</td>
</tr>
<?php endif; ?>
<?php
/**
* Used for adding additional content to the end of the membership table.
*
* @param RCP_Membership $membership
*
* @since 3.0
*/
do_action( 'rcp_edit_membership_after', $membership );
?>
</tbody>
</table>
</div>
<div id="rcp-membership-notices">
<?php if ( ! $membership->can_change_next_bill_date() ) : ?>
<div class="notice notice-info inline hidden" id="rcp-membership-expiration-update-notice">
<p><?php _e( 'Changing the expiration date will not affect when renewal payments are processed.', 'rcp' ); ?></p>
</div>
<?php else : ?>
<div class="notice notice-success inline hidden" id="rcp-membership-expiration-update-notice">
<p><?php _e( 'The renewal date in the payment gateway will be updated to match the new expiration date.', 'rcp' ); ?></p>
</div>
<?php endif; ?>
<?php if ( $membership->can_change_gateway_price() ) : ?>
<div class="notice notice-success inline hidden" id="rcp-membership-recurring-price-update-notice">
<p><?php _e( 'The renewal price in the payment gateway will be updated.', 'rcp' ); ?></p>
</div>
<?php endif; ?>
<div class="notice notice-info inline hidden" id="rcp-membership-recurring-update-notice">
<?php if ( $membership->can_toggle_auto_renew() ) : ?>
<p id="rcp-membership-recurring-enable-auto-renew">
<strong><?php _e( 'Enabling Auto Renew:', 'rcp' ); ?></strong> <?php _e( 'A new subscription will be created at the payment gateway.', 'rcp' ); ?>
<?php
if ( $membership->get_expiration_time() >= current_time( 'timestamp' ) ) {
printf( __( 'The customer will be automatically billed %s on: %s.', 'rcp' ), $membership->get_recurring_amount( true ), $membership->get_expiration_date( true ) );
} else {
printf( __( 'The customer will be charged %s immediately.', 'rcp' ), $membership->get_recurring_amount( true ) );
}
?>
</p>
<p id="rcp-membership-recurring-disable-auto-renew">
<strong><?php _e( 'Disabling Auto Renew:', 'rcp' ); ?></strong> <?php _e( 'The subscription at the payment gateway will be cancelled, but the membership status will not change.', 'rcp' ); ?>
</p>
<?php else : ?>
<p><?php _e( 'Changing the recurring indicator will not set up or remove a subscription with the gateway. This checkbox is for updating RCP records only.', 'rcp' ); ?></p>
<?php endif; ?>
</div>
<div class="notice notice-warning inline hidden" id="rcp-membership-gateway-subscription-id-update-notice">
<p><?php _e( 'Changing the gateway subscription ID can result in renewals not being processed. Do this with caution.', 'rcp' ); ?></p>
</div>
</div>
<div id="rcp-item-edit-actions" class="edit-item">
<input type="hidden" name="rcp-action" value="edit_membership"/>
<input type="hidden" name="membership_id" value="<?php echo esc_attr( $membership->get_id() ); ?>"/>
<?php wp_nonce_field( 'rcp_edit_membership', 'rcp_edit_membership_nonce' ); ?>
<input type="submit" name="rcp_update_membership" id="rcp_update_membership" class="button button-primary" value="<?php _e( 'Update Membership', 'rcp' ); ?>"/>
&nbsp;<input type="submit" name="rcp_delete_membership" class="rcp-delete-membership button" value="<?php _e( 'Delete Membership', 'rcp' ); ?>"/>
</div>
</form>
</div>
<?php do_action( 'rcp_membership_details_before_payments', $membership ); ?>
<div id="rcp-membership-payments-wrapper" class="rcp-item-section">
<h3><?php _e( 'Payments:', 'rcp' ); ?></h3>
<table class="wp-list-table widefat striped payments">
<thead>
<tr>
<th class="column-primary"><?php _e( 'ID', 'rcp' ); ?></th>
<th><?php _e( 'Date', 'rcp' ); ?></th>
<th><?php _e( 'Amount', 'rcp' ); ?></th>
<th><?php _e( 'Status', 'rcp' ); ?></th>
<th><?php _e( 'Transaction ID', 'rcp' ); ?></th>
<th><?php _e( 'Invoice', 'rcp' ); ?></th>
</tr>
</thead>
<tbody>
<?php if ( ! empty( $payments ) ) : ?>
<?php foreach ( $payments as $payment ) : ?>
<tr>
<td class="column-primary" data-colname="<?php esc_attr_e( 'ID', 'rcp' ); ?>">
<a href="<?php echo esc_url( add_query_arg( 'payment_id', urlencode( $payment->id ), admin_url( 'admin.php?page=rcp-payments&view=edit-payment' ) ) ); ?>"><?php echo $payment->id; ?></a>
<button type="button" class="toggle-row">
<span class="screen-reader-text"><?php _e( 'Show more details', 'rcp' ); ?></span>
</button>
</td>
<td data-colname="<?php esc_attr_e( 'Date', 'rcp' ); ?>"><?php echo $payment->date; ?></td>
<td data-colname="<?php esc_attr_e( 'Amount', 'rcp' ); ?>"><?php echo rcp_currency_filter( $payment->amount ); ?></td>
<td data-colname="<?php esc_attr_e( 'Status', 'rcp' ); ?>"><?php echo rcp_get_status_label( $payment->status ); ?></td>
<td data-colname="<?php esc_attr_e( 'Transaction ID', 'rcp' ); ?>"><?php echo rcp_get_merchant_transaction_id_link( $payment ); ?></td>
<td data-colname="<?php esc_attr_e( 'Invoice', 'rcp' ); ?>">
<a href="<?php echo esc_url( rcp_get_invoice_url( $payment->id ) ); ?>"><?php _e( 'View Invoice', 'rcp' ); ?></a>
</td>
</tr>
<?php endforeach; ?>
<?php if ( 5 === count( $payments ) ) : ?>
<tr>
<td colspan="6">
<a href="<?php echo esc_url( add_query_arg( 'membership_id', urlencode( $membership->get_id() ), admin_url( 'admin.php?page=rcp-payments' ) ) ); ?>"><?php _e( 'View all payments', 'rcp' ); ?></a>
</td>
</tr>
<?php endif; ?>
<?php else : ?>
<tr>
<td colspan="6"><?php _e( 'No payments found.', 'rcp' ); ?></td>
</tr>
<?php endif; ?>
</tbody>
<?php if ( current_user_can( 'rcp_manage_payments' ) ) : ?>
<tfoot>
<tr class="alternate">
<td colspan="6">
<form id="rcp-membership-add-renewal" method="POST">
<p>
<?php _e( 'Use this form to manually record a renewal payment.', 'rcp' ); ?>
<span alt="f223" class="rcp-help-tip dashicons dashicons-editor-help" title="<?php esc_attr_e( 'Note: this does not initiate a charge in your merchant processor. This should only be used for recording a missed payment or one that was manually collected.', 'rcp' ); ?>"></span>
</p>
<p>
<label for="rcp-payment-amount" class="rcp-payment-field-label"><?php _e( 'Amount:', 'rcp' ); ?></label>
<input type="text" id="rcp-payment-amount" class="regular-text" style="width: 100px; padding: 3px;" name="amount" value="<?php echo esc_attr( $membership->get_recurring_amount() ); ?>" placeholder="0.00">
</p>
<p>
<label for="rcp-payment-transaction-id" class="rcp-payment-field-label"><?php _e( 'Transaction ID:', 'rcp' ); ?></label>
<input type="text" id="rcp-payment-transaction-id" class="regular-text" style="width: 100px; padding: 3px;" name="transaction_id" value="" placeholder="">
</p>
<p>
<label for="rcp-payment-status" class="rcp-payment-field-label"><?php _e( 'Status', 'rcp' ); ?></label>
<select id="rcp-payment-status" name="status">
<option value="pending"><?php _e( 'Pending', 'rcp' ); ?></option>
<option value="complete" selected="selected"><?php _e( 'Complete', 'rcp' ); ?></option>
<option value="failed"><?php _e( 'Failed', 'rcp' ); ?></option>
<option value="refunded"><?php _e( 'Refunded', 'rcp' ); ?></option>
<option value="abandoned"><?php _e( 'Abandoned', 'rcp' ); ?></option>
</select>
</p>
<input type="hidden" name="rcp-action" value="add_membership_payment"/>
<input type="hidden" name="membership_id" value="<?php echo esc_attr( $membership->get_id() ); ?>"/>
<?php wp_nonce_field( 'rcp_add_membership_payment', 'rcp_add_membership_payment_nonce' ); ?>
<?php if ( $membership->can_renew() ) : ?>
<input type="submit" name="renew_and_add_payment" class="button alignright" style="margin-left: 8px;" value="<?php esc_attr_e( 'Record Payment and Renew Membership', 'rcp' ); ?>"/>
<?php endif; ?>
<input type="submit" name="add_payment_only" class="button alignright" value="<?php esc_attr_e( 'Record Payment Only', 'rcp' ); ?>"/>
</form>
</td>
</tr>
</tfoot>
<?php endif; ?>
</table>
</div>
<?php do_action( 'rcp_membership_details_after_payments', $membership ); ?>
<div id="rcp-membership-notes-wrapper" class="rcp-item-section">
<h3><?php _e( 'Notes:', 'rcp' ); ?></h3>
<div id="rcp-membership-notes" class="rcp-item-notes">
<?php echo wpautop( $membership->get_notes() ); ?>
</div>
<form id="rcp-edit-membership-notes" method="POST">
<label for="rcp-add-membership-note" class="screen-reader-text"><?php _e( 'Add Note', 'rcp' ); ?></label>
<textarea id="rcp-add-membership-note" class="rcp-add-item-note" name="new_note" placeholder="<?php esc_attr_e( 'Add a note...', 'rcp' ); ?>"></textarea>
<div class="edit-item">
<input type="hidden" name="rcp-action" value="add_membership_note"/>
<input type="hidden" name="membership_id" value="<?php echo esc_attr( $membership->get_id() ); ?>"/>
<?php wp_nonce_field( 'rcp_add_membership_note', 'rcp_add_membership_note_nonce' ); ?>
<input type="submit" class="button" value="<?php esc_attr_e( 'Add Note', 'rcp' ); ?>"/>
</div>
</form>
</div>
</div>
</div>

View File

@@ -0,0 +1 @@
<?php // Silence is golden.

View File

@@ -0,0 +1,661 @@
<?php
/**
* Membership Actions
*
* @package restrict-content-pro
* @copyright Copyright (c) 2018, Restrict Content Pro
* @license GPL2+
* @since 3.0
*/
use RCP\Membership_Level;
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Edit a membership
*
* @since 3.0
* @return void
*/
function rcp_process_add_membership() {
if ( ! wp_verify_nonce( $_POST['rcp_add_membership_nonce'], 'rcp_add_membership' ) ) {
wp_die( __( 'Nonce verification failed.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 403 ) );
}
if ( ! current_user_can( 'rcp_manage_members' ) ) {
wp_die( __( 'You do not have permission to perform this action.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 403 ) );
}
$current_user = wp_get_current_user();
rcp_log( sprintf( '%s has started adding a new membership.', $current_user->display_name ) );
$membership_level = rcp_get_membership_level( absint( $_POST['object_id'] ) );
if ( ! $membership_level instanceof Membership_Level ) {
wp_die( __( 'Invalid membership level.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 400 ) );
}
if ( ! empty( $_POST['customer_id'] ) ) {
$customer = rcp_get_customer( absint( $_POST['customer_id'] ) );
} else {
$customer_email = ! empty( $_POST['user_email'] ) ? $_POST['user_email'] : false;
if ( empty( $customer_email ) ) {
wp_die( __( 'Please enter a valid customer email.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 400 ) );
}
$user = get_user_by( 'email', $customer_email );
// If no user exists with this email, create one.
if ( empty( $user ) ) {
rcp_log( 'Creating new user account.' );
$user_id = wp_insert_user( array(
'user_login' => sanitize_text_field( $customer_email ),
'user_email' => sanitize_text_field( $customer_email ),
'user_pass' => wp_generate_password()
) );
if ( empty( $user_id ) ) {
wp_die( __( 'Error creating customer account.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 500 ) );
}
$user = get_userdata( $user_id );
} else {
rcp_log( sprintf( 'Adding membership for existing user #%d.', $user->ID ) );
}
// Check for a customer record.
$customer = rcp_get_customer_by_user_id( $user->ID );
// Create a new customer.
if ( empty( $customer ) ) {
rcp_log( sprintf( 'Creating new customer record for user #%d.', $user->ID ) );
$customer_id = rcp_add_customer( array(
'user_id' => absint( $user->ID )
) );
if ( empty( $customer_id ) ) {
wp_die( __( 'Error creating customer record.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 500 ) );
}
$customer = rcp_get_customer( $customer_id );
} else {
rcp_log( sprintf( 'Adding membership to existing customer #%d.', $customer->get_id() ) );
}
}
if ( ! is_object( $customer ) ) {
wp_die( __( 'Error locating customer record.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 500 ) );
}
$data = array(
'object_id' => absint( $_POST['object_id'] ),
'object_type' => 'membership',
'initial_amount' => sanitize_text_field( $_POST['initial_amount'] ),
'recurring_amount' => sanitize_text_field( $_POST['recurring_amount'] ),
'created_date' => date( 'Y-m-d H:i:s', strtotime( $_POST['created_date'], current_time( 'timestamp' ) ) ),
'expiration_date' => ! empty( $_POST['expiration_date_none'] ) ? 'none' : date( 'Y-m-d 23:59:59', strtotime( $_POST['expiration_date'], current_time( 'timestamp' ) ) ),
'auto_renew' => ! empty( $_POST['auto_renew'] ) ? 1 : 0,
'times_billed' => absint( $_POST['times_billed'] ),
'maximum_renewals' => $membership_level->get_maximum_renewals(),
'status' => sanitize_text_field( wp_unslash( $_POST['status'] ) ),
'gateway_customer_id' => sanitize_text_field( wp_unslash( $_POST['gateway_customer_id'] ) ),
'gateway_subscription_id' => sanitize_text_field( wp_unslash( $_POST['gateway_subscription_id'] ) ),
'gateway' => sanitize_text_field( wp_unslash( $_POST['gateway'] ) ),
'signup_method' => 'manual'
);
/**
* Add new membership.
*/
$membership_id = $customer->add_membership( $data );
if ( empty( $membership_id ) ) {
wp_die( __( 'Error adding membership record.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 500 ) );
}
$membership = rcp_get_membership( $membership_id );
if ( $membership instanceof RCP_Membership ) {
$membership->add_note( sprintf( __( 'Membership manually created by %s.', 'rcp' ), $current_user->user_login ) );
}
$redirect = add_query_arg( 'rcp_message', 'membership_updated', rcp_get_memberships_admin_page( array(
'membership_id' => urlencode( $membership_id ),
'view' => 'edit'
) ) );
wp_safe_redirect( $redirect );
exit;
}
add_action( 'rcp_action_add_membership', 'rcp_process_add_membership' );
/**
* Edit a membership
*
* @since 3.0
* @return void
*/
function rcp_process_edit_membership() {
if ( ! wp_verify_nonce( $_POST['rcp_edit_membership_nonce'], 'rcp_edit_membership' ) ) {
wp_die( __( 'Nonce verification failed.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 403 ) );
}
if ( ! current_user_can( 'rcp_manage_members' ) ) {
wp_die( __( 'You do not have permission to perform this action.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 403 ) );
}
if ( empty( $_POST['membership_id'] ) ) {
wp_die( __( 'Invalid membership ID.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 400 ) );
}
$membership_id = absint( $_POST['membership_id'] );
$membership = rcp_get_membership( $membership_id );
if ( empty( $membership ) ) {
wp_die( __( 'Invalid membership.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 400 ) );
}
$current_user = wp_get_current_user();
/**
* Delete membership.
*/
if ( ! empty( $_POST['rcp_delete_membership'] ) ) {
rcp_log( sprintf( '%s deleting membership #%d.', $current_user->user_login, $membership_id ) );
$membership->disable();
$redirect = add_query_arg( 'rcp_message', 'membership_deleted', rcp_get_memberships_admin_page() );
wp_safe_redirect( $redirect );
exit;
}
/**
* Change membership level.
*/
if ( ! empty( $_POST['rcp_change_membership_level'] ) ) {
$new_level_id = ! empty( $_POST['object_id'] ) ? absint( $_POST['object_id'] ) : 0;
$old_level_id = $membership->get_object_id();
if ( ! empty( $new_level_id ) && $new_level_id != $old_level_id ) {
rcp_log( sprintf( '%s changing membership level for membership #%d. Old level ID: %d; New level ID: %d.', $current_user->user_login, $membership_id, $old_level_id, $new_level_id ) );
$new_status = $membership->get_status();
$recurring = $membership->is_recurring();
// Disable the old membership.
$membership->disable();
$new_membership_id = $membership->get_customer()->add_membership( array(
'status' => $new_status, // keep the same status
'object_id' => $new_level_id,
'gateway' => $membership->get_gateway(),
'upgraded_from' => $membership->get_id()
) );
if ( empty ( $new_membership_id ) ) {
wp_die( __( 'Error changing membership level.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 500 ) );
}
/**
* Triggers when the membership level is manually changed.
*
* @param int $new_membership_id ID number of the new membership record.
* @param RCP_Membership $membership Membership object for the old record, which is now disabled.
* @param bool $recurring Whether or not the old membership was recurring.
*/
do_action( 'rcp_membership_level_manually_changed', $new_membership_id, $membership, $recurring );
$redirect = add_query_arg( 'rcp_message', 'membership_level_changed', rcp_get_memberships_admin_page( array(
'membership_id' => urlencode( $new_membership_id ),
'view' => 'edit'
) ) );
wp_safe_redirect( $redirect );
exit;
}
}
$redirect_query_args = array( 'rcp_message' => 'membership_updated' );
rcp_log( sprintf( '%s has started editing membership #%d.', $current_user->user_login, $membership_id ) );
// Data to update.
$args = array();
// Membership level ID. The role is automatically updated in rcp_update_user_role_on_membership_object_id_transition()
// This is commented out because I'm not sure I want to encourage even doing this...
/*$object_id = ! empty( $_POST['object_id'] ) ? $_POST['object_id'] : false;
if ( ! empty( $object_id ) && $object_id != $membership->get_object_id() ) {
$args['object_id'] = absint( $object_id );
// Change recurring amount. @todo move to action
$new_membership_level = rcp_get_subscription_details( absint( $object_id ) );
$args['recurring_amount'] = $new_membership_level->price;
$args['maximum_renewals'] = ! empty( $new_membership_level->maximum_renewals ) ? absint( $new_membership_level->maximum_renewals ) : 0;
}*/
// Status
$status = ! empty( $_POST['status'] ) ? $_POST['status'] : false;
if ( ! empty( $status ) && $status != $membership->get_status() ) {
switch ( $status ) {
case 'cancelled' :
if ( $membership->can_cancel() ) {
$cancelled = $membership->cancel_payment_profile();
if ( is_wp_error( $cancelled ) ) {
// Bail if cancellation failed.
$redirect = add_query_arg( array(
'rcp_message' => 'membership_cancellation_failed',
'rcp_cancel_failure_message' => urlencode( $cancelled->get_error_message() )
), rcp_get_memberships_admin_page( array(
'membership_id' => urlencode( $membership_id ),
'view' => 'edit'
) ) );
wp_safe_redirect( $redirect );
exit;
}
} else {
$membership->cancel();
}
break;
default :
$args['status'] = sanitize_text_field( $status );
break;
}
}
// Recurring amount.
$recurring_amount = ! empty( $_POST['recurring_amount'] ) ? sanitize_text_field( $_POST['recurring_amount'] ) : 0;
if ( ! empty( $recurring_amount ) && $recurring_amount != $membership->get_recurring_amount() && $membership->can_change_gateway_price() ) {
$amount_changed = $membership->change_gateway_price( $recurring_amount );
if ( ! is_wp_error( $amount_changed ) ) {
$args['recurring_amount'] = $recurring_amount;
}
}
// Date Created
$date_created = ! empty( $_POST['created_date'] ) ? date( 'Y-m-d H:i:s', strtotime( $_POST['created_date'], current_time( 'timestamp' ) ) ) : false;
if ( $date_created != $membership->get_created_date( false ) ) {
$args['created_date'] = sanitize_text_field( $date_created );
}
// Expiration Date
$expiration_date = ! empty( $_POST['expiration_date_none'] ) ? 'none' : date( 'Y-m-d 23:59:59', strtotime( $_POST['expiration_date'], current_time( 'timestamp' ) ) );
if ( $expiration_date != $membership->get_expiration_date( false ) ) {
$args['expiration_date'] = sanitize_text_field( $expiration_date );
if ( $membership->is_trialing() ) {
$args['trial_end_date'] = sanitize_text_field( $expiration_date );
}
if ( $membership->can_change_next_bill_date() ) {
$membership->change_next_bill_date( $expiration_date );
}
}
// Gateway
$gateway = ! empty( $_POST['gateway'] ) ? wp_unslash( $_POST['gateway'] ) : '';
if ( ! empty( $gateway ) && $gateway != $membership->get_gateway() ) {
$args['gateway'] = sanitize_text_field( $gateway );
}
// Gateway Customer ID
$gateway_customer_id = ! empty( $_POST['gateway_customer_id'] ) ? wp_unslash( $_POST['gateway_customer_id'] ) : '';
if ( $gateway_customer_id != $membership->get_gateway_customer_id() ) {
$args['gateway_customer_id'] = sanitize_text_field( $gateway_customer_id );
}
// Gateway Subscription ID
$gateway_subscription_id = ! empty( $_POST['gateway_subscription_id'] ) ? wp_unslash( $_POST['gateway_subscription_id'] ) : '';
if ( $gateway_subscription_id != $membership->get_gateway_subscription_id() ) {
$args['gateway_subscription_id'] = sanitize_text_field( $gateway_subscription_id );
}
// Auto renew
$auto_renew = ! empty( $_POST['auto_renew'] ) ? true : false;
if ( $auto_renew != $membership->is_recurring() ) {
if ( $membership->can_toggle_auto_renew() ) {
if ( $auto_renew ) {
/**
* Toggle auto renew on.
*/
$auto_renew_toggle_result = $membership->toggle_auto_renew_on();
if ( true === $auto_renew_toggle_result ) {
$membership->add_note( sprintf( __( 'Auto renew enabled by %s.', 'rcp' ), $current_user->user_login ) );
// Prevent the admin from overwriting this.
if ( isset( $args['gateway_subscription_id'] ) ) {
unset( $args['gateway_subscription_id'] );
}
}
} else {
$auto_renew_toggle_result = $membership->toggle_auto_renew_off();
if ( true === $auto_renew_toggle_result ) {
$membership->add_note( sprintf( __( 'Auto renew disabled by %s.', 'rcp' ), $current_user->user_login ) );
// This should be wiped.
if ( isset( $args['gateway_subscription_id'] ) ) {
$args['gateway_subscription_id'] = '';
}
}
}
if ( is_wp_error( $auto_renew_toggle_result ) ) {
$redirect_query_args['rcp_auto_renew_toggle_error'] = rawurlencode( $auto_renew_toggle_result->get_error_message() );
}
} else {
$args['auto_renew'] = (int) $auto_renew;
}
}
if ( ! empty( $args ) ) {
$membership->update( $args );
$membership->add_note( sprintf( __( 'Membership edited by %s.', 'rcp' ), $current_user->user_login ) );
}
// New action that users can use to save custom fields.
do_action( 'rcp_after_membership_admin_update', $membership, $args );
$redirect = add_query_arg( $redirect_query_args, rcp_get_memberships_admin_page( array(
'membership_id' => urlencode( $membership_id ),
'view' => 'edit'
) ) );
wp_safe_redirect( $redirect );
exit;
}
add_action( 'rcp_action_edit_membership', 'rcp_process_edit_membership' );
/**
* When a membership level is manually changed, create a new recurring subscription for the new membership
* if the old one was recurring.
*
* @param int $new_membership_id ID of the new membership record.
* @param RCP_Membership $old_membership Membership object for the old record, which is now disabled.
* @param bool $recurring Whether or not the old membership was recurring.
*
* @since 3.5
* @return void
*/
function rcp_create_gateway_subscription_on_level_change( $new_membership_id, $old_membership, $recurring ) {
// We only create subscriptions for recurring memberships.
if ( ! $recurring ) {
return;
}
$membership = rcp_get_membership( $new_membership_id );
if ( empty( $membership ) ) {
return;
}
if ( ! $membership->can_create_gateway_subscription() ) {
return;
}
$membership->create_gateway_subscription( false );
}
add_action( 'rcp_membership_level_manually_changed', 'rcp_create_gateway_subscription_on_level_change', 10, 3 );
/**
* Process adding a new note to the membership.
*
* @todo ajaxify
*
* @since 3.0
* @return void
*/
function rcp_process_add_membership_note() {
if ( ! wp_verify_nonce( $_POST['rcp_add_membership_note_nonce'], 'rcp_add_membership_note' ) ) {
wp_die( __( 'Nonce verification failed.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 403 ) );
}
if ( ! current_user_can( 'rcp_manage_members' ) ) {
wp_die( __( 'You do not have permission to perform this action.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 403 ) );
}
if ( empty( $_POST['membership_id'] ) ) {
wp_die( __( 'Invalid membership ID.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 400 ) );
}
$membership_id = absint( $_POST['membership_id'] );
$membership = rcp_get_membership( $membership_id );
if ( empty( $membership ) ) {
wp_die( __( 'Invalid membership.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 400 ) );
}
$new_note = wp_unslash( $_POST['new_note'] );
if ( empty( $new_note ) ) {
wp_die( __( 'Please enter a note.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 400 ) );
}
$current_user = wp_get_current_user();
rcp_log( sprintf( '%s is adding a new note to membership #%d.', $current_user->user_login, $membership_id ) );
$membership->add_note( sanitize_text_field( $new_note ) );
$redirect = add_query_arg( 'rcp_message', 'membership_note_added', rcp_get_memberships_admin_page( array( 'membership_id' => urlencode( $membership_id ), 'view' => 'edit' ) ) );
wp_safe_redirect( $redirect );
exit;
}
add_action( 'rcp_action_add_membership_note', 'rcp_process_add_membership_note' );
/**
* Process expiring a membership. This expires the membership and cancels the payment profile.
*
* @since 3.0
* @return void
*/
function rcp_process_expire_membership() {
if ( ! wp_verify_nonce( $_GET['_wpnonce'], 'expire_membership' ) ) {
wp_die( __( 'Nonce verification failed.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 403 ) );
}
if ( ! current_user_can( 'rcp_manage_members' ) ) {
wp_die( __( 'You do not have permission to perform this action.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 403 ) );
}
if ( empty( $_GET['membership_id'] ) ) {
wp_die( __( 'Invalid membership ID.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 400 ) );
}
$membership_id = absint( $_GET['membership_id'] );
$membership = rcp_get_membership( $membership_id );
if ( empty( $membership ) ) {
wp_die( __( 'Invalid membership.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 400 ) );
}
$current_user = wp_get_current_user();
rcp_log( sprintf( '%s is expiring membership #%d.', $current_user->user_login, $membership_id ) );
// Cancel gateway subscription.
if ( $membership->can_cancel() ) {
$membership->cancel_payment_profile( false );
$membership->set_recurring( false );
}
$membership->expire();
$redirect = add_query_arg( 'rcp_message', 'membership_expired', rcp_get_memberships_admin_page( array( 'membership_id' => urlencode( $membership_id ), 'view' => 'edit' ) ) );
wp_safe_redirect( $redirect );
exit;
}
add_action( 'rcp_action_expire_membership', 'rcp_process_expire_membership' );
/**
* Process revoking membership access. This expires the membership and cancels the payment profile.
*
* @since 3.0
* @return void
*/
function rcp_process_cancel_membership() {
if ( ! wp_verify_nonce( $_GET['_wpnonce'], 'cancel_membership' ) ) {
wp_die( __( 'Nonce verification failed.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 403 ) );
}
if ( ! current_user_can( 'rcp_manage_members' ) ) {
wp_die( __( 'You do not have permission to perform this action.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 403 ) );
}
if ( empty( $_GET['membership_id'] ) ) {
wp_die( __( 'Invalid membership ID.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 400 ) );
}
$membership_id = absint( $_GET['membership_id'] );
$membership = rcp_get_membership( $membership_id );
if ( empty( $membership ) ) {
wp_die( __( 'Invalid membership.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 400 ) );
}
$current_user = wp_get_current_user();
rcp_log( sprintf( '%s is cancelling membership #%d.', $current_user->user_login, $membership_id ) );
$membership->add_note( sprintf( __( 'Membership cancelled via admin link by user %s (#%d).', 'rcp' ), $current_user->user_login, $current_user->ID ) );
// Cancel gateway subscription.
if ( $membership->can_cancel() ) {
$cancelled = $membership->cancel_payment_profile();
if ( is_wp_error( $cancelled ) ) {
// Bail and show error if cancellation failed.
$redirect = add_query_arg( array(
'rcp_message' => 'membership_cancellation_failed',
'rcp_cancel_failure_message' => urlencode( $cancelled->get_error_message() )
), rcp_get_memberships_admin_page( array(
'membership_id' => urlencode( $membership_id ),
'view' => 'edit'
) ) );
wp_safe_redirect( $redirect );
exit;
}
} else {
$membership->cancel();
}
$redirect = add_query_arg( 'rcp_message', 'membership_cancelled', rcp_get_memberships_admin_page( array( 'membership_id' => urlencode( $membership_id ), 'view' => 'edit' ) ) );
wp_safe_redirect( $redirect );
exit;
}
add_action( 'rcp_action_cancel_membership', 'rcp_process_cancel_membership' );
/**
* Insert a new payment for a membership.
*
* @since 3.0
* @return void
*/
function rcp_process_add_membership_payment() {
if ( ! wp_verify_nonce( $_POST['rcp_add_membership_payment_nonce'], 'rcp_add_membership_payment' ) ) {
wp_die( __( 'Nonce verification failed.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 403 ) );
}
if ( ! current_user_can( 'rcp_manage_payments' ) ) {
wp_die( __( 'You do not have permission to perform this action.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 403 ) );
}
if ( empty( $_POST['membership_id'] ) ) {
wp_die( __( 'Invalid membership ID.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 400 ) );
}
$current_user = wp_get_current_user();
$membership = rcp_get_membership( absint( $_GET['membership_id'] ) );
rcp_log( sprintf( '%s manually inserting new payment record for membership #%d.', $current_user->user_login, $membership->get_id() ) );
// Renew first, if specified.
if ( ! empty( $_POST['renew_and_add_payment'] ) ) {
$membership->renew( $membership->is_recurring() );
}
$auth_key = defined( 'AUTH_KEY' ) ? AUTH_KEY : '';
$default_transaction_id = strtolower( md5( $membership->get_subscription_key() . date( 'Y-m-d H:i:s' ) . $auth_key . uniqid( 'rcp', true ) ) );
$transaction_id = ! empty( $_POST['transaction_id'] ) ? wp_unslash( $_POST['transaction_id'] ) : $default_transaction_id;
/**
* @var RCP_Payments $rcp_payments_db
*/
global $rcp_payments_db;
$membership_level = rcp_get_membership_level( $membership->get_object_id() );
$data = array(
'amount' => ! empty( $_POST['amount'] ) ? sanitize_text_field( $_POST['amount'] ) : 0.00,
'subtotal' => $membership_level instanceof Membership_Level ? sanitize_text_field( $membership_level->get_price() ) : 0.00,
'user_id' => $membership->get_user_id(),
'customer_id' => $membership->get_customer()->get_id(),
'membership_id' => $membership->get_id(),
'date' => date( 'Y-m-d H:i:s', current_time( 'timestamp' ) ),
'payment_type' => 'manual',
'transaction_type' => 'renewal',
'subscription' => $membership->get_membership_level_name(),
'subscription_key' => $membership->get_subscription_key(),
'transaction_id' => sanitize_text_field( $transaction_id ),
'status' => ! empty( $_POST['status'] ) ? sanitize_text_field( wp_unslash( $_POST['status'] ) ) : 'complete',
'object_id' => $membership->get_object_id(),
'object_type' => 'subscription'
);
$add = $rcp_payments_db->insert( $data );
if ( ! empty( $add ) ) {
$cache_args = array( 'earnings' => 1, 'subscription' => 0, 'user_id' => 0, 'date' => '' );
$cache_key = md5( implode( ',', $cache_args ) );
delete_transient( $cache_key );
$message = 'payment_added';
} else {
rcp_log( sprintf( 'Failed adding new manual payment by %s.', $current_user->user_login ), true );
$message = 'payment_not_added';
}
$url = rcp_get_memberships_admin_page( array(
'membership_id' => $membership->get_id(),
'view' => 'edit',
'rcp_message' => $message
) );
wp_safe_redirect( $url );
exit;
}
add_action( 'rcp_action_add_membership_payment', 'rcp_process_add_membership_payment' );

View File

@@ -0,0 +1,134 @@
<?php
/**
* Meta Box View
*
* HTML display of the meta box.
*
* @package Restrict Content Pro
* @subpackage Admin/Meta Box View
* @copyright Copyright (c) 2017, Restrict Content Pro
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
*/
global $rcp_options;
$pt_restrictions = rcp_get_post_type_restrictions( get_post_type( get_the_ID() ) );
$disabled = ! empty( $pt_restrictions ) ? ' disabled="disabled"' : '';
// If entire post type is restricted, use those settings. Otherwise use individual post settings.
$is_paid = ( ! empty( $pt_restrictions ) && array_key_exists( 'is_paid', $pt_restrictions ) ) ? $pt_restrictions['is_paid'] : get_post_meta( get_the_ID(), '_is_paid', true );
$sub_levels = ( ! empty( $pt_restrictions ) && array_key_exists( 'subscription_level', $pt_restrictions ) ) ? $pt_restrictions['subscription_level'] : get_post_meta( get_the_ID(), 'rcp_subscription_level', true );
$set_level = is_array( $sub_levels ) ? '' : $sub_levels;
$access_level = ( ! empty( $pt_restrictions ) && array_key_exists( 'access_level', $pt_restrictions ) ) ? $pt_restrictions['access_level'] : get_post_meta( get_the_ID(), 'rcp_access_level', true );
$access_level = is_numeric( $access_level ) ? absint( $access_level ) : '';
$content_excerpts = isset( $rcp_options['content_excerpts'] ) ? $rcp_options['content_excerpts'] : 'individual';
$show_excerpt = 'always' === $content_excerpts || ( 'individual' === $content_excerpts && get_post_meta( get_the_ID(), 'rcp_show_excerpt', true ) );
$user_role = ( ! empty( $pt_restrictions ) && array_key_exists( 'user_level', $pt_restrictions ) ) ? $pt_restrictions['user_level'] : get_post_meta( get_the_ID(), 'rcp_user_level', true );
$access_display = is_numeric( $access_level ) ? '' : ' style="display:none;"';
$level_set_display = ! empty( $sub_levels ) || ! empty( $is_paid ) ? '' : ' style="display:none;"';
$levels_display = is_array( $sub_levels ) ? '' : ' style="display:none;"';
$role_set_display = '' != $user_role ? '' : ' style="display:none;"';
/* If nothing is set for "Members of membership level(s)", default the choice
* to "Members of any membership level(s)".
*/
if ( empty( $sub_levels ) && empty( $set_level ) ) {
$set_level = 'any';
}
?>
<div id="rcp-metabox-field-restrict-by" class="rcp-metabox-field">
<?php if ( ! empty( $pt_restrictions ) ) : ?>
<p><?php printf( __( 'This entire post type is restricted. Visit the <a href="%s">post type\'s restriction page</a> to change the settings.', 'rcp' ), esc_url( rcp_get_restrict_post_type_page_url( get_post_type() ) ) ); ?></p>
<?php endif; ?>
<p><strong><?php _e( 'Member access options', 'rcp' ); ?></strong></p>
<p>
<?php _e( 'Select who should have access to this content.', 'rcp' ); ?>
<span alt="f223" class="rcp-help-tip dashicons dashicons-editor-help" title="<?php _e( '<strong>Membership level</strong>: a membership level refers to a membership option. For example, you might have a Gold, Silver, and Bronze membership level. <br/><br/><strong>Access Level</strong>: refers to a tiered system where a member\'s ability to view content is determined by the access level assigned to their account. A member with an access level of 5 can view content assigned to access levels of 5 and lower.', 'rcp' ); ?>"></span>
</p>
<p>
<select id="rcp-restrict-by" name="rcp_restrict_by" <?php echo $disabled; ?>>
<option value="unrestricted" <?php selected( true, ( empty( $sub_levels ) && empty( $access_level ) && empty( $is_paid ) ) ); ?>><?php _e( 'Everyone', 'rcp' ); ?></option>
<option value="subscription-level"<?php selected( true, ! empty( $sub_levels ) || ! empty( $is_paid ) ); ?>><?php _e( 'Members of membership level(s)', 'rcp' ); ?></option>
<option value="access-level"<?php selected( true, is_numeric( $access_level ) ); ?>><?php _e( 'Members with an access level', 'rcp' ); ?></option>
<option value="registered-users"<?php selected( true, empty( $sub_levels ) && ! is_numeric( $access_level ) && ! empty( $user_role ) && 'All' !== $user_role ); ?>><?php _e( 'Members with a certain role', 'rcp' ); ?></option>
</select>
</p>
</div>
<div id="rcp-metabox-field-levels" class="rcp-metabox-field"<?php echo $level_set_display; ?>>
<label for="rcp_subscription_level_any">
<input type="radio" name="rcp_subscription_level_any_set" id="rcp_subscription_level_any" value="any"<?php checked( 'any', $set_level ); echo $disabled; ?>/>
&nbsp;<?php _e( 'Members of any membership level(s)', 'rcp' ); ?><br/>
</label>
<label for="rcp_subscription_level_any_paid">
<input type="radio" name="rcp_subscription_level_any_set" id="rcp_subscription_level_any_paid" value="any-paid"<?php checked( true, $set_level == 'any-paid' || ( ! empty( $is_paid ) && 'any' !== $sub_levels ) ); echo $disabled; ?>/>
&nbsp;<?php _e( 'Members of any paid membership level(s)', 'rcp' ); ?><br/>
</label>
<label for="rcp_subscription_level_specific">
<input type="radio" name="rcp_subscription_level_any_set" id="rcp_subscription_level_specific" value="specific"<?php checked( true, is_array( $sub_levels ) ); echo $disabled; ?>/>
&nbsp;<?php _e( 'Members of specific membership levels', 'rcp' ); ?><br/>
</label>
<p class="rcp-subscription-levels"<?php echo $levels_display; ?>>
<?php foreach( rcp_get_membership_levels( array( 'number' => 999 ) ) as $level ) : ?>
<label for="rcp_subscription_level_<?php echo esc_attr( $level->get_id() ); ?>">
<input type="checkbox" name="rcp_subscription_level[]"<?php checked( true, in_array( $level->get_id(), (array) $sub_levels ) ); ?> class="rcp_subscription_level" id="rcp_subscription_level_<?php echo esc_attr( $level->get_id() ); ?>" value="<?php echo esc_attr( $level->get_id() ); ?>" data-price="<?php echo esc_attr( $level->get_price() ); ?>"<?php echo $disabled; ?>/>
&nbsp;<?php echo esc_html( $level->get_name() ); ?><br/>
</label>
<?php endforeach; ?>
</p>
</div>
<div id="rcp-metabox-field-access-levels" class="rcp-metabox-field"<?php echo $access_display; ?>>
<p>
<select name="rcp_access_level" id="rcp-access-level-field" <?php echo $disabled; ?>>
<?php foreach( rcp_get_access_levels() as $key => $access_level_label ) : ?>
<option id="rcp_access_level<?php echo $key; ?>" value="<?php echo esc_attr( $key ); ?>"<?php selected( $key, $access_level ); ?>><?php printf( __( '%s and higher', 'rcp' ), $key ); ?></option>
<?php endforeach; ?>
</select>
</p>
</div>
<div id="rcp-metabox-field-role" class="rcp-metabox-field"<?php echo $role_set_display; ?>>
<p>
<span><?php _e( 'Require member to have capabilities from this user role.', 'rcp' ); ?></span>
</p>
<p>
<?php
$roles = get_editable_roles();
$roles = array_merge( array( 'all' => array( 'name' => 'Any' ) ), $roles );
$selected_roles = is_array( $user_role ) ? $user_role : array( strtolower( $user_role ) );
foreach( $roles as $key => $role ) : ?>
<label for="rcp_user_level_<?php echo esc_attr( $key ); ?>">
<input type="checkbox" name="rcp_user_level[]" id="rcp_user_level_<?php echo esc_attr( $key ); ?>" class="rcp-user-role" value="<?php echo esc_attr( $key ); ?>"<?php checked( true, in_array( $key, $selected_roles ) ); echo $disabled; ?>>
&nbsp;<?php echo translate_user_role( $role['name'] ); ?><br/>
</label>
<?php endforeach; ?>
</p>
</div>
<?php do_action( 'rcp_metabox_additional_options_before' ); ?>
<?php if( apply_filters( 'rcp_metabox_show_additional_options', true ) ) : ?>
<div id="rcp-metabox-field-options" class="rcp-metabox-field">
<p><strong><?php _e( 'Additional options', 'rcp' ); ?></strong></p>
<p>
<?php
$disabled = ( 'always' === $content_excerpts || 'never' === $content_excerpts ) ? ' disabled="disabled"' : '';
$message = __( 'You can automatically enable or disable excerpts for all posts by adjusting your Content Excerpts setting in Restrict > Settings > Misc.', 'rcp' );
if ( 'always' === $content_excerpts ) {
$message = __( 'This option is disabled because excerpts are enabled for all posts. This can be changed in Restrict > Settings > Misc.', 'rcp' );
} elseif ( 'never' === $content_excerpts ) {
$message = __( 'This option is disabled because excerpts are disabled for all posts. This can be changed in Restrict > Settings > Misc.', 'rcp' );
}
?>
<label for="rcp-show-excerpt">
<input type="checkbox" name="rcp_show_excerpt" id="rcp-show-excerpt" value="1"<?php echo $disabled; checked( true, $show_excerpt ); ?>/>
<?php _e( 'Show excerpt to members without access to this content.', 'rcp' ); ?>
</label>
<span alt="f223" class="rcp-help-tip dashicons dashicons-editor-help" title="<?php echo esc_attr( $message ); ?>"></span>
</p>
<p>
<?php printf(
__( 'Optionally use [restrict paid="true"] ... [/restrict] shortcode to restrict partial content. %sView documentation for additional options%s.', 'rcp' ),
'<a href="' . esc_url( 'http://docs.restrictcontentpro.com/article/1593-restricting-post-and-page-content' ) . '" target="_blank">',
'</a>'
); ?>
</p>
</div>
<?php endif; ?>

View File

@@ -0,0 +1,229 @@
<?php
/**
* Meta Box
*
* @package Restrict Content Pro
* @subpackage Admin/Meta Box
* @copyright Copyright (c) 2017, Restrict Content Pro
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
*/
/**
* Get metabox fields
*
* @return array
*/
function rcp_get_metabox_fields() {
//custom meta boxes
$rcp_prefix = 'rcp_';
$rcp_meta_box = array(
'id' => 'rcp_meta_box',
'title' => __( 'Restrict this content', 'rcp' ),
'context' => 'normal',
'priority' => apply_filters( 'rcp_metabox_priority', 'high' ),
'fields' => array() // No longer used
);
return apply_filters( 'rcp_metabox_fields', $rcp_meta_box );
}
/**
* Add meta box to supported post types
*
* @uses rcp_get_metabox_fields()
* @uses rcp_get_metabox_post_types()
*
* @return void
*/
function rcp_add_meta_boxes() {
$rcp_meta_box = rcp_get_metabox_fields();
foreach ( rcp_get_metabox_post_types() as $post_type ) {
add_meta_box( $rcp_meta_box['id'], $rcp_meta_box['title'], 'rcp_render_meta_box', $post_type, $rcp_meta_box['context'], $rcp_meta_box['priority'] );
}
}
add_action( 'add_meta_boxes', 'rcp_add_meta_boxes' );
/**
* Returns all post types the meta box should be added to.
*
* @since 2.9
* @return array
*/
function rcp_get_metabox_post_types() {
$post_types = get_post_types( array( 'public' => true, 'show_ui' => true ) );
$post_types = (array) apply_filters( 'rcp_metabox_post_types', $post_types );
$exclude = apply_filters( 'rcp_metabox_excluded_post_types', array( 'forum', 'topic', 'reply', 'product', 'attachment' ) );
return array_diff( $post_types, $exclude );
}
/**
* Callback function to show fields in meta box
*
* @return void
*/
function rcp_render_meta_box() {
global $post;
$rcp_meta_box = rcp_get_metabox_fields();
// Use nonce for verification
echo '<input type="hidden" name="rcp_meta_box" value="'. wp_create_nonce( basename( __FILE__ ) ) . '" />';
do_action( 'rcp_metabox_fields_before' );
include RCP_PLUGIN_DIR . 'core/includes/admin/metabox-view.php';
do_action( 'rcp_metabox_fields_after' );
}
/**
* Save data from meta box
*
* @param int $post_id ID of the post being saved.
*
* @return void
*/
function rcp_save_meta_data( $post_id ) {
// verify nonce
if ( ! isset( $_POST['rcp_meta_box'] ) || ! wp_verify_nonce( $_POST['rcp_meta_box'], basename( __FILE__ ) ) ) {
return;
}
// check autosave
if ( defined( 'DOING_AUTOSAVE' ) && DOING_AUTOSAVE ) {
return;
}
// check permissions
if ( 'page' == $_POST['post_type'] ) {
if ( ! current_user_can( 'edit_page', $post_id ) ) {
return;
}
} elseif ( ! current_user_can( 'edit_post', $post_id ) ) {
return;
}
$is_paid = false;
$restrict_by = ! empty( $_POST['rcp_restrict_by'] ) ? sanitize_text_field( $_POST['rcp_restrict_by'] ) : 'unrestricted';
switch( $restrict_by ) {
case 'unrestricted' :
delete_post_meta( $post_id, 'rcp_access_level' );
delete_post_meta( $post_id, 'rcp_subscription_level' );
delete_post_meta( $post_id, 'rcp_user_level' );
break;
case 'subscription-level' :
$level_set = sanitize_text_field( $_POST['rcp_subscription_level_any_set'] );
switch( $level_set ) {
case 'any' :
update_post_meta( $post_id, 'rcp_subscription_level', 'any' );
break;
case 'any-paid' :
$is_paid = true;
update_post_meta( $post_id, 'rcp_subscription_level', 'any-paid' );
break;
case 'specific' :
$is_paid = true;
$levels = array_map( 'absint', $_POST[ 'rcp_subscription_level' ] );
foreach( $levels as $level ) {
$price = rcp_get_subscription_price( $level );
if( empty( $price ) ) {
$is_paid = false;
break;
}
}
update_post_meta( $post_id, 'rcp_subscription_level', $levels );
break;
}
// Remove unneeded fields
delete_post_meta( $post_id, 'rcp_access_level' );
break;
case 'access-level' :
update_post_meta( $post_id, 'rcp_access_level', absint( $_POST[ 'rcp_access_level' ] ) );
// Remove unneeded fields
delete_post_meta( $post_id, 'rcp_subscription_level' );
break;
case 'registered-users' :
// Remove unneeded fields
delete_post_meta( $post_id, 'rcp_access_level' );
// Remove unneeded fields
delete_post_meta( $post_id, 'rcp_subscription_level' );
break;
}
global $rcp_options;
$content_excerpts = isset( $rcp_options['content_excerpts'] ) ? $rcp_options['content_excerpts'] : 'individual';
$show_excerpt = isset( $_POST['rcp_show_excerpt'] );
$user_role = ! empty( $_POST['rcp_user_level'] ) ? $_POST[ 'rcp_user_level' ] : 'all';
if ( ! is_array( $user_role ) ) {
$user_role = array( $user_role );
}
$user_role = array_map( 'sanitize_text_field', $user_role );
if ( 'individual' === $content_excerpts && $show_excerpt ) {
update_post_meta( $post_id, 'rcp_show_excerpt', $show_excerpt );
} else {
delete_post_meta( $post_id, 'rcp_show_excerpt' );
}
if ( ! empty( $_POST['rcp_restrict_by'] ) && 'unrestricted' !== $_POST['rcp_restrict_by'] ) {
update_post_meta( $post_id, 'rcp_user_level', $user_role );
}
if ( $is_paid ) {
update_post_meta( $post_id, '_is_paid', $is_paid );
} else {
delete_post_meta( $post_id, '_is_paid' );
}
do_action( 'rcp_save_post_meta', $post_id );
}
add_action( 'save_post', 'rcp_save_meta_data' );

View File

@@ -0,0 +1,664 @@
<?php
/**
* Payments List Table
*
* @package restrict-content-pro
* @copyright Copyright (c) 2019, Restrict Content Pro
* @license GPL2+
* @since 3.1
*/
namespace RCP\Admin;
/**
* Class Payments_Table
*
* @since 3.1
* @package RCP\Admin
*/
class Payments_Table extends List_Table {
/**
* Constructor.
*
* @since 3.1
* @see WP_List_Table::__construct()
*/
public function __construct() {
parent::__construct( [
'singular' => 'Payment',
'plural' => 'Payments',
'ajax' => false,
] );
$this->process_bulk_action();
$this->get_counts();
}
/**
* Get the base URL for the payments list table.
*
* @since 3.1
* @return string Base URL.
*/
public function get_base_url() {
$args = array(
'page' => 'rcp-payments'
);
$payments_page = add_query_arg( $args, admin_url( 'admin.php' ) );
return $payments_page;
}
/**
* Retrieve the table columns.
*
* @since 3.1
* @return array
*/
public function get_columns() {
$columns = array(
'cb' => '<input type="checkbox" />',
'id' => __( 'ID', 'rcp' ),
'customer' => __( 'Customer', 'rcp' ),
'membership' => __( 'Membership', 'rcp' ),
'date' => __( 'Date', 'rcp' ),
'amount' => __( 'Amount', 'rcp' ),
'type' => __( 'Type', 'rcp' ),
'gateway' => __( 'Gateway', 'rcp' ),
'transaction_id' => __( 'Transaction ID', 'rcp' ),
'status' => __( 'Status', 'rcp' )
);
/*
* Backwards compatibility: add an "extra" column if someone is hooking into the old action to add
* their own column. Everything gets bundled into one column because this is the only way we can realistically
* do it.
*/
if ( has_action( 'rcp_payments_page_table_header' ) ) {
$columns['custom'] = __( 'Extra', 'rcp' );
}
/**
* Filters the table columns.
*
* @param array $columns
*
* @since 3.1
*/
$columns = apply_filters( 'rcp_payments_list_table_columns', $columns );
return $columns;
}
/**
* Retrieve the sortable columns.
*
* // @todo At some point we'll add amount, type, and gateway
*
* @since 3.1
* @return array
*/
public function get_sortable_columns() {
return array(
'id' => array( 'id', false ),
'membership' => array( 'membership', false ),
'date' => array( 'date', false ),
'transaction_id' => array( 'transaction_id', false ),
'status' => array( 'status', false ),
);
}
/**
* Gets the name of the primary column.
*
* @since 3.1
* @return string
*/
protected function get_primary_column_name() {
return 'id';
}
/**
* This function renders any other columns in the list table.
*
* @param object $payment Payment object.
* @param string $column_name The name of the column
*
* @since 3.1
* @return string Column Name
*/
public function column_default( $payment, $column_name ) {
$value = '';
$gateway = ! empty( $payment->gateway ) ? $payment->gateway : '';
switch ( $column_name ) {
case 'customer' :
$user = get_userdata( $payment->user_id );
if ( ! empty( $user ) ) {
$value = ! empty( $user->display_name ) ? esc_html( $user->display_name ) : esc_html( $user->user_login );
} else {
$value = sprintf( __( 'User #%d (deleted)', 'rcp' ), $payment->user_id );
}
break;
case 'membership' :
$value = esc_html( $payment->subscription );
break;
case 'date' :
$value = esc_html( $payment->date );
break;
case 'amount' :
$value = rcp_currency_filter( $payment->amount );
break;
case 'type' :
if ( ! empty( $payment->transaction_type ) ) {
$value = esc_html( rcp_get_status_label( $payment->transaction_type ) );
} elseif ( 'manual' != $gateway ) {
// Prevent "manual" from duplicating twice (here and gateway column).
$value = esc_html( $payment->payment_type );
}
break;
case 'gateway' :
if ( ! empty( $gateway ) ) {
if ( 'free' == $gateway ) {
$value = __( 'None', 'rcp' );
} else {
$value = rcp_get_payment_gateway_details( $gateway, 'admin_label' );
}
} else {
$value = __( 'Unknown', 'rcp' );
}
break;
case 'transaction_id' :
$value = rcp_get_merchant_transaction_id_link( $payment );
break;
case 'status' :
$value = rcp_get_payment_status_label( $payment );
break;
}
/*
* Backwards compatibility: show content of custom columns from old action hook.
*/
if ( 'custom' == $column_name && has_action( 'rcp_payments_page_table_column' ) ) {
ob_start();
do_action( 'rcp_payments_page_table_column', $payment->id );
$column_content = ob_get_clean();
$value = wp_strip_all_tags( $column_content );
}
/**
* Filters the column value.
*
* @param string $value Column value.
* @param object $payment Payment object.
*
* @since 3.1
*/
$value = apply_filters( 'rcp_payments_list_table_column_' . $column_name, $value, $payment );
return $value;
}
/**
* Render the checkbox column.
*
* @param object $payment
*
* @since 3.1
* @return string
*/
public function column_cb( $payment ) {
return sprintf(
'<input type="checkbox" name="%1$s[]" value="%2$s" />',
'payment_id',
$payment->id
);
}
/**
* Render the main ID column.
*
* @param object $payment
*
* @since 3.1
* @return string
*/
public function column_id( $payment ) {
$edit_url = add_query_arg( array(
'payment_id' => absint( $payment->id ),
'view' => 'edit-payment'
), $this->get_base_url() );
$invoice_url = rcp_get_invoice_url( $payment->id );
$customer_url = rcp_get_customers_admin_page( array(
'customer_id' => ! empty( $payment->customer_id ) ? urlencode( $payment->customer_id ) : 0,
'view' => 'edit'
) );
$customer_payments_url = add_query_arg( 'user_id', urlencode( $payment->user_id ), $this->get_base_url() );
$delete_url = wp_nonce_url( add_query_arg( array(
'payment_id' => urlencode( $payment->id ),
'rcp-action' => 'delete_payment'
), $this->get_base_url() ), 'rcp_delete_payment_nonce' );
// Link to edit payment.
$actions = array(
'edit' => '<a href="' . esc_url( $edit_url ) . '" title="' . esc_attr__( 'Edit payment', 'rcp' ) . '">' . __( 'Edit', 'rcp' ) . '</a>'
);
// Link to view invoice.
$actions['invoice'] = '<a href="' . esc_url( $invoice_url ) . '" title="' . esc_attr__( 'View invoice', 'rcp' ) . '">' . __( 'Invoice', 'rcp' ) . '</a>';
// Link to view customer profile.
if ( ! empty( $payment->customer_id ) ) {
$actions['customer'] = '<a href="' . esc_url( $customer_url ) . '" title="' . esc_attr__( 'View customer details' ) . '">' . __( 'Customer Details', 'rcp' ) . '</a>';
}
/*
* Link to view all payments by this customer.
* Only display if we're not already viewing all payments for this customer.
*/
if ( $this->get_request_var( 'user_id' ) != $payment->user_id ) {
$actions['customer_payments'] = '<a href="' . esc_url( $customer_payments_url ) . '" title="' . esc_attr__( 'View all payments by this customer', 'rcp' ) . '">' . __( 'Customer Payments', 'rcp' ) . '</a>';
}
// Link to delete this payment.
$actions['delete'] = '<span class="trash"><a href="' . esc_url( $delete_url ) . '" title="' . esc_attr__( 'Delete payment', 'rcp' ) . '" class="rcp-delete-payment">' . __( 'Delete', 'rcp' ) . '</a></span>';
// Display the payment ID number.
$actions['payment_id'] = '<span class="id rcp-id-col">' . sprintf( __( 'ID: %d', 'rcp' ), $payment->id ) . '</span>';
ob_start();
/**
* @deprecated 3.1 Use `rcp_payments_list_table_row_actions` instead.
*/
do_action( 'rcp_payments_page_table_row_actions', $payment );
$custom_row_actions = ob_get_clean();
if ( $custom_row_actions ) {
$actions['custom_row_actions'] = $custom_row_actions;
}
/**
* Filters the row actions.
*
* @param array $actions Default actions.
* @param object $payment Payment object.
*
* @since 3.1
*/
$actions = apply_filters( 'rcp_payments_list_table_row_actions', $actions, $payment );
$final = '<strong><a href="' . esc_url( $edit_url ) . '" title="' . esc_attr__( 'Edit payment', 'rcp' ) . '">' . esc_html( $payment->id ) . '</a></strong>';
if ( current_user_can( 'rcp_manage_payments' ) ) {
$final .= $this->row_actions( $actions );
}
return $final;
}
/**
* Message to be displayed when there are no payments.
*
* @since 3.1
* @return void
*/
public function no_items() {
esc_html_e( 'No payments found.', 'rcp' );
}
/**
* Retrieve the bulk actions.
*
* @since 3.1
* @return array
*/
public function get_bulk_actions() {
return array(
'delete' => __( 'Permanently Delete', 'rcp' )
);
}
/**
* Process bulk actions.
*
* @since 3.1
* @return void
*/
public function process_bulk_action() {
// Bail if a nonce was not supplied.
if ( ! isset( $_REQUEST['_wpnonce'] ) ) {
return;
}
if ( ! wp_verify_nonce( $_REQUEST['_wpnonce'], 'bulk-payments' ) ) {
return;
}
$ids = wp_parse_id_list( (array) $this->get_request_var( 'payment_id', false ) );
// Bail if no IDs
if ( empty( $ids ) ) {
return;
}
$payments = new \RCP_Payments();
foreach ( $ids as $payment_id ) {
switch ( $this->current_action() ) {
case 'delete':
$payments->delete( $payment_id );
break;
}
}
$this->show_admin_notice( $this->current_action(), count( $ids ) );
}
/**
* Show admin notice for bulk actions.
*
* @param string $action The action to show the notice for.
* @param int $number Number of items that were processed.
*
* @access private
* @since 3.1
* @return void
*/
private function show_admin_notice( $action, $number = 1 ) {
$message = '';
switch ( $action ) {
case 'delete' :
$message = _n( '1 payment deleted.', sprintf( '%d payments deleted.', $number ), $number, 'rcp' );
break;
}
if ( empty( $message ) ) {
return;
}
echo '<div class="updated"><p>' . $message . '</p></div>';
}
/**
* Retrieve the payment counts.
*
* @since 3.1
* @return void
*/
public function get_counts() {
$payments = new \RCP_Payments();
$this->counts = array(
'total' => $payments->count(),
'complete' => $payments->count( array( 'status' => 'complete' ) ),
'pending' => $payments->count( array( 'status' => 'pending' ) ),
'refunded' => $payments->count( array( 'status' => 'refunded' ) ),
'failed' => $payments->count( array( 'status' => 'failed' ) ),
'abandoned' => $payments->count( array( 'status' => 'abandoned' ) ),
);
}
/**
* Retrieve payments data.
*
* @param bool $count Whether or not to get payment objects (false) or just count the total number (true).
*
* @since 3.1
* @return array|int
*/
public function payments_data( $count = false ) {
$payments = new \RCP_Payments();
$args = array(
'number' => $this->per_page,
'offset' => $this->get_offset(),
'orderby' => sanitize_text_field( $this->get_request_var( 'orderby', 'id' ) ),
'order' => sanitize_text_field( $this->get_request_var( 'order', 'DESC' ) ),
'status' => $this->get_status(),
);
// Search
$search_type = $this->get_request_var( 'search_type', 'transaction_id' );
$search = $this->get_search();
if ( ! empty( $search ) ) {
if ( 'user' == $search_type ) {
// First we have to search for user accounts.
$user_ids = get_users( array(
'number' => 1,
'search' => '*' . $search . '*',
'fields' => 'ids'
) );
// No user results - bail.
if ( empty( $user_ids ) ) {
return $count ? 0 : array();
}
// Set the first result as the user_id arg.
$args['user_id'] = $user_ids[0];
} else {
$args['s'] = $this->get_search();
}
}
// User ID
$user_id = $this->get_request_var( 'user_id' );
if ( ! empty( $user_id ) ) {
$args['user_id'] = absint( $user_id );
}
// Transaction type
$trans_type = $this->get_request_var( 'transaction_type' );
if ( ! empty( $trans_type ) ) {
$args['transaction_type'] = sanitize_text_field( $trans_type );
}
// Membership level ID
$object_id = $this->get_request_var( 'object_id' );
if ( ! empty( $object_id ) ) {
$args['object_id'] = absint( $object_id );
}
// Gateway
$gateway = $this->get_request_var( 'gateway' );
if ( ! empty( $gateway ) ) {
$args['gateway'] = sanitize_text_field( $gateway );
}
// Start Date
$start_date = $this->get_request_var( 'start-date' );
if ( ! empty( $start_date ) ) {
$args['date']['start'] = sanitize_text_field( $start_date );
}
// End Date
$end_date = $this->get_request_var( 'end-date' );
if ( ! empty( $end_date ) ) {
$args['date']['end'] = sanitize_text_field( $end_date );
}
if ( $count ) {
return $payments->count( $args );
}
return $payments->get_payments( $args );
}
/**
* Setup the final data for the table.
*
* @since 3.1
* @return void
*/
public function prepare_items() {
$columns = $this->get_columns();
$hidden = array();
$sortable = $this->get_sortable_columns();
$this->_column_headers = array( $columns, $hidden, $sortable );
$this->items = $this->payments_data();
$total = $this->payments_data( true );
// Setup pagination
$this->set_pagination_args( array(
'total_items' => $total,
'per_page' => $this->per_page,
'total_pages' => ceil( $total / $this->per_page )
) );
}
/**
* Get a list of CSS classes for the WP_List_Table table tag.
*
* We override this so we can add the "rcp-payments" class for backwards compatibility.
*
* @since 3.1
* @return array List of CSS classes for the table tag.
*/
public function get_table_classes() {
return array( 'widefat', 'fixed', 'striped', $this->_args['plural'], 'rcp-payments' );
}
/**
* Display extra table nav. This includes the transaction type filter.
*
* @param string $which
*
* @since 3.1
*/
protected function extra_tablenav( $which ) {
if ( 'top' !== $which ) {
return;
}
$start_date = isset( $_GET['start-date'] ) ? sanitize_text_field( $_GET['start-date'] ) : null;
$end_date = isset( $_GET['end-date'] ) ? sanitize_text_field( $_GET['end-date'] ) : null;
$gateway = $this->get_request_var( 'gateway', '' );
$gateways = rcp_get_payment_gateways();
$transaction_type = $this->get_request_var( 'transaction_type', '' );
$types = array(
'new',
'renewal',
'upgrade',
'downgrade'
);
$level_id = $this->get_request_var( 'object_id', '' );
$levels = rcp_get_membership_levels( array( 'number' => 999 ) );
?>
<div class="alignleft actions">
<label for="rcp-payments-start-date"><?php _e( 'Start Date', 'rcp' ); ?></label>
<input type="text" id="rcp-payments-start-date" name="start-date" class="rcp-datepicker" value="<?php echo esc_attr( $start_date ); ?>" placeholder="YYYY-mm-dd"/>
<label for="rcp-payments-end-date"><?php _e( 'End Date', 'rcp' ); ?></label>
<input type="text" id="rcp-payments-end-date" name="end-date" class="rcp-datepicker" value="<?php echo esc_attr( $end_date ); ?>" placeholder="YYYY-mm-dd"/>
<?php if ( ! empty( $gateways ) ) : ?>
<label for="rcp-payment-gateways-filter" class="screen-reader-text"><?php _e( 'Filter by gateway', 'rcp' ); ?></label>
<select id="rcp-payment-gateways-filter" name="gateway">
<option value="" <?php selected( $gateway, '' ); ?>><?php _e( 'All Gateways', 'rcp' ); ?></option>
<?php foreach ( $gateways as $gateway_slug => $gateway_info ) : ?>
<option value="<?php echo esc_attr( $gateway_slug ); ?>" <?php selected( $gateway, $gateway_slug ); ?>><?php echo $gateway_info['admin_label']; ?></option>
<?php endforeach; ?>
</select>
<?php endif; ?>
<label for="rcp-payment-transaction-types-filter" class="screen-reader-text"><?php _e( 'Filter by transaction type', 'rcp' ); ?></label>
<select id="rcp-payment-transaction-types-filter" name="transaction_type">
<option value="" <?php selected( $transaction_type, '' ); ?>><?php _e( 'All Types', 'rcp' ); ?></option>
<?php foreach ( $types as $type ) : ?>
<option value="<?php echo esc_attr( $type ); ?>" <?php selected( $transaction_type, $type ); ?>><?php echo rcp_get_status_label( $type ); ?></option>
<?php endforeach; ?>
</select>
<?php if ( ! empty( $levels ) ) : ?>
<label for="rcp-memberships-level-filter" class="screen-reader-text"><?php _e( 'Filter by membership level', 'rcp' ); ?></label>
<select id="rcp-memberships-level-filter" name="object_id">
<option value="" <?php selected( $level_id, '' ); ?>><?php _e( 'All Membership Levels', 'rcp' ); ?></option>
<?php foreach ( $levels as $level ) : ?>
<option value="<?php echo esc_attr( $level->get_id() ); ?>" <?php selected( $level_id, $level->get_id() ); ?>><?php echo esc_html( $level->get_name() ); ?></option>
<?php endforeach; ?>
</select>
<?php endif; ?>
<?php submit_button( __( 'Filter' ), '', 'filter_action', false ); ?>
</div>
<?php
}
/**
* Show the search field.
*
* @param string $text Label for the search box
* @param string $input_id ID of the search box
*
* @since 3.1
*/
public function search_box( $text, $input_id ) {
// Bail if no items and no search
if ( ! $this->get_search() && ! $this->has_items() ) {
return;
}
$orderby = $this->get_request_var( 'orderby' );
$order = $this->get_request_var( 'order' );
$search_type = $this->get_request_var( 'search_type', 'transaction_id' );
$input_id = $input_id . '-search-input';
if ( ! empty( $orderby ) ) {
echo '<input type="hidden" name="orderby" value="' . esc_attr( $orderby ) . '" />';
}
if ( ! empty( $order ) ) {
echo '<input type="hidden" name="order" value="' . esc_attr( $order ) . '" />';
}
?>
<p class="search-box">
<label class="screen-reader-text" for="rcp-payments-search-type"><?php esc_html_e( 'Choose a field to search', 'rcp' ); ?></label>
<select id="rcp-payments-search-type" name="search_type" style="float:left;">
<option value="transaction_id" <?php selected( $search_type, 'transaction_id' ); ?>><?php _e( 'Transaction ID', 'rcp' ); ?></option>
<option value="user" <?php selected( $search_type, 'user' ); ?>><?php _e( 'User Account (name, email, login)', 'rcp' ); ?></option>
</select>
<label class="screen-reader-text" for="<?php echo esc_attr( $input_id ); ?>"><?php echo esc_html( $text ); ?>:</label>
<input type="search" id="<?php echo esc_attr( $input_id ); ?>" name="s" value="<?php _admin_search_query(); ?>"/>
<?php submit_button( esc_html( $text ), 'button', false, false, array( 'ID' => 'search-submit' ) ); ?>
</p>
<?php
}
}

View File

@@ -0,0 +1,138 @@
<?php
/**
* Edit Payment Page
*
* @package Restrict Content Pro
* @subpackage Admin/Edit Payment
* @copyright Copyright (c) 2017, Restrict Content Pro
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
*/
use RCP\Membership_Level;
/**
* @var RCP_Payments $rcp_payments_db
*/
global $rcp_payments_db;
$payment_id = ! empty( $_GET['payment_id'] ) ? absint( $_GET['payment_id'] ) : 0;
$payment = $rcp_payments_db->get_payment( $payment_id );
$user = get_userdata( $payment->user_id );
$membership_level = rcp_get_membership_level( $payment->object_id );
?>
<h1>
<?php _e( 'Edit Payment', 'rcp' ); ?> -
<a href="<?php echo admin_url( '/admin.php?page=rcp-payments' ); ?>" class="button-secondary">
<?php _e( 'Cancel', 'rcp' ); ?>
</a>
</h1>
<form id="rcp-edit-payment" action="" method="post">
<table class="form-table">
<tbody>
<?php do_action( 'rcp_edit_payment_before', $payment, $membership_level, $user ); ?>
<tr valign="top">
<th scope="row" valign="top">
<label for="rcp-user-id"><?php _e( 'User', 'rcp' ); ?></label>
</th>
<td>
<input type="text" name="user" autocomplete="off" id="rcp-user" class="regular-text rcp-user-search" value="<?php echo is_object( $user ) ? esc_attr( $user->user_login ) : ''; ?>"/>
<img class="rcp-ajax waiting" src="<?php echo admin_url( 'images/wpspin_light.gif' ); ?>" style="display: none;"/>
<?php if ( is_object( $user ) ) : ?>
<a href="<?php echo esc_url( add_query_arg( 'edit_member', $user->ID, admin_url( 'admin.php?page=rcp-members' ) ) ); ?>"><?php _e( 'Edit Member', 'rcp' ); ?></a>
<?php endif; ?>
<div id="rcp_user_search_results"></div>
<p class="description"><?php _e( 'The user name this payment belongs to.', 'rcp' ); ?></p>
</td>
</tr>
<tr valign="top">
<th scope="row" valign="top">
<label for="rcp-amount"><?php _e( 'Amount', 'rcp' ); ?></label>
</th>
<td>
<input type="text" name="amount" id="rcp-amount" pattern="^[+\-]?[0-9]{1,3}(?:,?[0-9]{3})*(\.[0-9]{2})?$" title="<?php _e( 'Please enter a payment amount in the format of 1.99', 'rcp' ); ?>" min="0.00" value="<?php echo esc_attr( $payment->amount ); ?>"/>
<p class="description"><?php _e( 'The amount of this payment', 'rcp' ); ?></p>
</td>
</tr>
<tr valign="top">
<th scope="row" valign="top">
<label for="rcp-subscription-level"><?php _e( 'Membership Level', 'rcp' ); ?></label>
</th>
<td>
<?php
if ( $membership_level instanceof Membership_Level ) {
echo '<a href="' . esc_url( admin_url( 'admin.php?page=rcp-member-levels&edit_subscription=' . $membership_level->get_id() ) ) . '">' . esc_html( $membership_level->get_name() ) . '</a>';
}
?>
<p class="description"><?php _e( 'Membership level this payment was for', 'rcp' ); ?></p>
</td>
</tr>
<tr valign="top">
<th scope="row" valign="top">
<label for="rcp-discount-code"><?php _e( 'Discount Code', 'rcp' ); ?></label>
</th>
<td>
<?php echo ! empty( $payment->discount_code ) ? esc_html( $payment->discount_code ) : __( 'No discount used', 'rcp' ); ?>
<p class="description"><?php _e( 'Discount code used when making this payment', 'rcp' ); ?></p>
</td>
</tr>
<tr valign="top">
<th scope="row" valign="top">
<label for="rcp-date"><?php _e( 'Payment Date', 'rcp' ); ?></label>
</th>
<td>
<input name="date" id="rcp-date" type="text" class="rcp-datepicker" value="<?php echo esc_attr( date( 'Y-m-d H:i:s', strtotime( $payment->date, current_time( 'timestamp' ) ) ) ); ?>"/>
<p class="description"><?php _e( 'The date for this payment in the format of yyyy-mm-dd', 'rcp' ); ?></p>
</td>
</tr>
<tr valign="top">
<th scope="row" valign="top">
<label for="rcp-gateway"><?php _e( 'Gateway', 'rcp' ); ?></label>
</th>
<td>
<?php echo ! empty( $payment->gateway ) ? ucwords( $payment->gateway ) : __( 'Unknown gateway used', 'rcp' ); ?>
<p class="description"><?php _e( 'Gateway used to make the payment', 'rcp' ); ?></p>
</td>
</tr>
<tr valign="top">
<th scope="row" valign="top">
<label for="rcp-date"><?php _e( 'Transaction ID', 'rcp' ); ?></label>
</th>
<td>
<input name="transaction-id" id="rcp-transaction-id" type="text" class="regular-text" value="<?php echo esc_attr( $payment->transaction_id ); ?>"/>
<p class="description"><?php _e( 'The transaction ID for this payment, if any. Click to view in merchant account:', 'rcp' );
echo '&nbsp;' . rcp_get_merchant_transaction_id_link( $payment ); ?></p>
</td>
</tr>
<tr valign="top">
<th scope="row" valign="top">
<label for="rcp-status"><?php _e( 'Status', 'rcp' ); ?></label>
</th>
<td>
<select name="status" id="rcp-status">
<option value="pending"<?php selected( $payment->status, 'pending' ); ?>><?php _e( 'Pending', 'rcp' ); ?></option>
<option value="complete"<?php selected( $payment->status, 'complete' ); ?>><?php _e( 'Complete', 'rcp' ); ?></option>
<option value="failed"<?php selected( $payment->status, 'failed' ); ?>><?php _e( 'Failed', 'rcp' ); ?></option>
<option value="refunded"<?php selected( $payment->status, 'refunded' ); ?>><?php _e( 'Refunded', 'rcp' ); ?></option>
<option value="abandoned"<?php selected( $payment->status, 'abandoned' ); ?>><?php _e( 'Abandoned', 'rcp' ); ?></option>
</select>
<p class="description"><?php _e( 'The status of this payment.', 'rcp' ); ?></p>
</td>
</tr>
<tr valign="top">
<th scope="row" valign="top">
<label for="rcp-status"><?php _e( 'Invoice', 'rcp' ); ?></label>
</th>
<td>
<a href="<?php echo esc_url( rcp_get_invoice_url( $payment_id ) ); ?>" class="button-secondary" target="_blank"><?php _e( 'View Invoice', 'rcp' ); ?></a>
</td>
</tr>
<?php do_action( 'rcp_edit_payment_after', $payment, $membership_level, $user ); ?>
</tbody>
</table>
<p class="submit">
<input type="hidden" name="rcp-action" value="edit-payment"/>
<input type="hidden" name="payment-id" value="<?php echo esc_attr( $payment_id ); ?>"/>
<input type="submit" value="<?php _e( 'Update Payment', 'rcp' ); ?>" class="button-primary"/>
</p>
<?php wp_nonce_field( 'rcp_edit_payment_nonce', 'rcp_edit_payment_nonce' ); ?>
</form>

View File

@@ -0,0 +1 @@
<?php // Silence is golden.

View File

@@ -0,0 +1,96 @@
<?php
/**
* New Payment Page
*
* @package Restrict Content Pro
* @subpackage Admin/New Payment
* @copyright Copyright (c) 2017, Restrict Content Pro
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
*/
?>
<h1>
<?php _e( 'Create Payment', 'rcp' ); ?> -
<a href="<?php echo admin_url( '/admin.php?page=rcp-payments' ); ?>" class="button-secondary">
<?php _e( 'Cancel', 'rcp' ); ?>
</a>
</h1>
<form id="rcp-add-payment" action="" method="post">
<table class="form-table">
<tbody>
<?php do_action( 'rcp_add_payment_before' ); ?>
<tr valign="top">
<th scope="row" valign="top">
<label for="rcp-user-id"><?php _e( 'User', 'rcp' ); ?></label>
</th>
<td>
<input type="text" name="user" autocomplete="off" id="rcp-user" class="regular-text rcp-user-search"/>
<img class="rcp-ajax waiting" src="<?php echo admin_url('images/wpspin_light.gif'); ?>" style="display: none;"/>
<div id="rcp_user_search_results"></div>
<p class="description"><?php _e('Begin typing the user name to add a payment record for.', 'rcp'); ?></p>
</td>
</tr>
<tr valign="top">
<th scope="row" valign="top">
<label for="rcp-membership-level"><?php _e( 'Membership Level', 'rcp' ); ?></label>
</th>
<td>
<select id="rcp-membership-level" name="membership_level_id">
<?php foreach ( rcp_get_membership_levels( array( 'number' => 999 ) ) as $membership_level ) : ?>
<option value="<?php echo esc_attr( $membership_level->get_id() ); ?>"><?php echo esc_html( $membership_level->get_name() ); ?></option>
<?php endforeach; ?>
</select>
<p class="description"><?php _e( 'The membership level this payment is for.', 'rcp' ); ?></p>
</td>
</tr>
<tr valign="top">
<th scope="row" valign="top">
<label for="rcp-amount"><?php _e( 'Amount', 'rcp' ); ?></label>
</th>
<td>
<input type="text" name="amount" id="rcp-amount" pattern="^[+\-]?[0-9]{1,3}(?:,?[0-9]{3})*(\.[0-9]{2})?$" title="<?php _e( 'Please enter a payment amount in the format of 1.99', 'rcp' ); ?>" min="0.00" value=""/>
<p class="description"><?php _e( 'The amount of this payment', 'rcp' ); ?></p>
</td>
</tr>
<tr valign="top">
<th scope="row" valign="top">
<label for="rcp-date"><?php _e( 'Payment Date', 'rcp' ); ?></label>
</th>
<td>
<input name="date" id="rcp-date" type="text" class="rcp-datepicker" value=""/>
<p class="description"><?php _e( 'Enter the date for this payment in the format of yyyy-mm-dd', 'rcp' ); ?></p>
</td>
</tr>
<tr valign="top">
<th scope="row" valign="top">
<label for="rcp-date"><?php _e( 'Transaction ID', 'rcp' ); ?></label>
</th>
<td>
<input name="transaction-id" id="rcp-transaction-id" type="text" class="regular-text" value=""/>
<p class="description"><?php _e( 'Enter the transaction ID for this payment, if any', 'rcp' ); ?></p>
</td>
</tr>
<tr valign="top">
<th scope="row" valign="top">
<label for="rcp-status"><?php _e( 'Status', 'rcp' ); ?></label>
</th>
<td>
<select name="status" id="rcp-status">
<option value="pending"><?php _e( 'Pending', 'rcp' ); ?></option>
<option value="complete"><?php _e( 'Complete', 'rcp' ); ?></option>
<option value="failed"><?php _e( 'Failed', 'rcp' ); ?></option>
<option value="refunded"><?php _e( 'Refunded', 'rcp' ); ?></option>
<option value="abandoned"><?php _e( 'Abandoned', 'rcp' ); ?></option>
</select>
<p class="description"><?php _e( 'The status of this payment.', 'rcp' ); ?></p>
</td>
</tr>
<?php do_action( 'rcp_add_payment_after' ); ?>
</tbody>
</table>
<p class="submit">
<input type="hidden" name="rcp-action" value="add-payment"/>
<input type="submit" value="<?php _e( 'Create Payment', 'rcp' ); ?>" class="button-primary"/>
</p>
<?php wp_nonce_field( 'rcp_add_payment_nonce', 'rcp_add_payment_nonce' ); ?>
</form>

View File

@@ -0,0 +1,179 @@
<?php
/**
* Payment Actions
*
* @package restrict-content-pro
* @subpackage Admin/Payment Actions
* @copyright Copyright (c) 2017, Restrict Content Pro
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
* @since 2.9
*/
// Exit if accessed directly
use RCP\Membership_Level;
if ( ! defined( 'ABSPATH' ) ) exit;
/**
* Add a new manual payment
*
* @since 2.9
* @return void
*/
function rcp_process_add_payment() {
if ( ! wp_verify_nonce( $_POST['rcp_add_payment_nonce'], 'rcp_add_payment_nonce' ) ) {
wp_die( __( 'Nonce verification failed.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 403 ) );
}
if ( ! current_user_can( 'rcp_manage_payments' ) ) {
wp_die( __( 'You do not have permission to perform this action.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 403 ) );
}
$current_user = wp_get_current_user();
rcp_log( sprintf( '%s manually inserting new payment record.', $current_user->user_login ) );
$payments = new RCP_Payments();
$user = get_user_by( 'login', $_POST['user'] );
if ( $user ) {
$membership_level = rcp_get_membership_level( absint( $_POST['membership_level_id'] ) );
$customer = rcp_get_customer_by( 'user_id', $user->ID );
$data = array(
'amount' => empty( $_POST['amount'] ) ? 0.00 : sanitize_text_field( $_POST['amount'] ),
'user_id' => $user->ID,
'date' => empty( $_POST['date'] ) ? date( 'Y-m-d H:i:s', current_time( 'timestamp' ) ) : date( 'Y-m-d', strtotime( $_POST['date'], current_time( 'timestamp' ) ) ) . ' ' . date( 'H:i:s', current_time( 'timestamp' ) ),
'payment_type' => 'manual',
'subscription' => $membership_level instanceof Membership_Level ? sanitize_text_field( $membership_level->get_name() ) : '',
'object_id' => $membership_level instanceof Membership_Level ? $membership_level->get_id() : 0,
'object_type' => 'subscription',
'transaction_id' => sanitize_text_field( wp_unslash( $_POST['transaction-id'] ) ),
'status' => sanitize_text_field( wp_unslash( $_POST['status'] ) ),
);
// We're setting the subtotal here so we can use $data['amount'] as a fallback.
$data['subtotal'] = $membership_level instanceof Membership_Level ? sanitize_text_field( $membership_level->get_price() ) : $data['amount'];
if ( $customer instanceof RCP_Customer && $membership_level instanceof Membership_Level ) {
$data['customer_id'] = $customer->get_id();
$memberships = $customer->get_memberships( array(
'object_id' => $membership_level->get_id(),
'object_type' => 'membership',
'number' => 1
) );
if ( isset( $memberships[0] ) && $memberships[0] instanceof RCP_Membership ) {
$data['subscription_key'] = $memberships[0]->get_subscription_key();
$data['membership_id'] = $memberships[0]->get_id();
}
}
if ( empty( $data['subscription_key'] ) ) {
$data['subscription_key'] = rcp_get_subscription_key( $user->ID );
}
$add = $payments->insert( $data );
}
if ( ! empty( $add ) ) {
$cache_args = array( 'earnings' => 1, 'subscription' => 0, 'user_id' => 0, 'date' => '' );
$cache_key = md5( implode( ',', $cache_args ) );
delete_transient( $cache_key );
$url = admin_url( 'admin.php?page=rcp-payments&rcp_message=payment_added' );
} else {
rcp_log( sprintf( 'Failed adding new manual payment by %s: supplied user login doesn\'t exist.', $current_user->user_login ), true );
$url = admin_url( 'admin.php?page=rcp-payments&rcp_message=payment_not_added' );
}
wp_safe_redirect( $url );
exit;
}
add_action( 'rcp_action_add-payment', 'rcp_process_add_payment' );
/**
* Edit an existing payment
*
* @since 2.9
* @return void
*/
function rcp_process_edit_payment() {
if ( ! wp_verify_nonce( $_POST['rcp_edit_payment_nonce'], 'rcp_edit_payment_nonce' ) ) {
wp_die( __( 'Nonce verification failed.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 403 ) );
}
if ( ! current_user_can( 'rcp_manage_payments' ) ) {
wp_die( __( 'You do not have permission to perform this action.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 403 ) );
}
$payments = new RCP_Payments();
$payment_id = absint( $_POST['payment-id'] );
$user = get_user_by( 'login', $_POST['user'] );
$current_user = wp_get_current_user();
rcp_log( sprintf( '%s manually updating payment #%d.', $current_user->user_login, $payment_id ) );
if ( $user && $payment_id ) {
$data = array(
'amount' => empty( $_POST['amount'] ) ? 0.00 : sanitize_text_field( $_POST['amount'] ),
'user_id' => $user->ID,
'date' => empty( $_POST['date'] ) ? date( 'Y-m-d H:i:s', current_time( 'timestamp' ) ) : date( 'Y-m-d H:i:s', strtotime( $_POST['date'], current_time( 'timestamp' ) ) ),
'transaction_id' => sanitize_text_field( wp_unslash( $_POST['transaction-id'] ) ),
'status' => sanitize_text_field( wp_unslash( $_POST['status'] ) ),
);
$update = $payments->update( $payment_id, $data );
}
if ( ! empty( $update ) ) {
$cache_args = array( 'earnings' => 1, 'subscription' => 0, 'user_id' => 0, 'date' => '' );
$cache_key = md5( implode( ',', $cache_args ) );
delete_transient( $cache_key );
$url = admin_url( 'admin.php?page=rcp-payments&rcp_message=payment_updated' );
} else {
$url = admin_url( 'admin.php?page=rcp-payments&rcp_message=payment_not_updated' );
}
wp_safe_redirect( $url );
exit;
}
add_action( 'rcp_action_edit-payment', 'rcp_process_edit_payment' );
/**
* Delete a payment
*
* @since 2.9
* @return void
*/
function rcp_process_delete_payment() {
if ( ! wp_verify_nonce( $_GET['_wpnonce'], 'rcp_delete_payment_nonce' ) ) {
wp_die( __( 'Nonce verification failed.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 403 ) );
}
if ( ! current_user_can( 'rcp_manage_payments' ) ) {
wp_die( __( 'You do not have permission to perform this action.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 403 ) );
}
$current_user = wp_get_current_user();
rcp_log( sprintf( '%s deleting payment #%d.', $current_user->user_login, absint( $_GET['payment_id'] ) ) );
$payments = new RCP_Payments();
$payments->delete( absint( $_GET['payment_id'] ) );
wp_safe_redirect( admin_url( add_query_arg( 'rcp_message', 'payment_deleted', 'admin.php?page=rcp-payments' ) ) );
exit;
}
add_action( 'rcp_action_delete_payment', 'rcp_process_delete_payment' );

View File

@@ -0,0 +1,68 @@
<?php
/**
* Payments Page
*
* @package Restrict Content Pro
* @subpackage Admin/Payments Page
* @copyright Copyright (c) 2017, Restrict Content Pro
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
*/
/**
* Renders the Restrict > Payments page
*
* @since 1.0
* @return void
*/
function rcp_payments_page() {
include_once RCP_PLUGIN_DIR . 'core/includes/admin/payments/class-payments-table.php';
$table_class = new \RCP\Admin\Payments_Table();
$table_class->prepare_items();
$rcp_payments = new RCP_Payments();
$status = $table_class->get_request_var( 'status' );
do_action( 'stellarwp/telemetry/restrict-content-pro/optin' );
do_action( 'stellarwp/telemetry/restrict-content/optin' );
?>
<div class="wrap">
<?php
if( isset( $_GET['view'] ) && 'new-payment' == $_GET['view'] ) :
include( 'new-payment.php' );
elseif( isset( $_GET['view'] ) && 'edit-payment' == $_GET['view'] ) :
include( 'edit-payment.php' );
else : ?>
<h1>
<?php _e( 'Payments', 'rcp' ); ?>
<a href="<?php echo admin_url( '/admin.php?page=rcp-payments&view=new-payment' ); ?>" class="add-new-h2">
<?php _e( 'Create Payment', 'rcp' ); ?>
</a>
</h1>
<?php if ( 'pending' === $status ) : ?>
<div class="notice notice-large notice-warning">
<?php printf( __( 'Pending payments are converted to Complete when finalized. Read more about pending payments <a href="%s">here</a>.', 'rcp' ), 'http://docs.restrictcontentpro.com/article/1903-pending-payments' ); ?>
</div>
<?php endif; ?>
<p class="total"><strong><?php _e( 'Total Earnings', 'rcp' ); ?>: <?php echo rcp_currency_filter( $rcp_payments->get_earnings() ); ?></strong></p>
<?php do_action('rcp_payments_page_top'); ?>
<form id="rcp-payments-filter" method="GET" action="<?php echo esc_url( add_query_arg( 'page', 'rcp-payments', admin_url( 'admin.php' ) ) ); ?>">
<input type="hidden" name="page" value="rcp-payments"/>
<?php
$table_class->views();
$table_class->search_box( __( 'Search payments', 'rcp' ), 'rcp-payments' );
$table_class->display();
?>
</form>
<?php do_action( 'rcp_payments_page_bottom' ); ?>
<?php endif; ?>
</div><!--end wrap-->
<?php
}

View File

@@ -0,0 +1 @@
<?php // Silence is golden.

View File

@@ -0,0 +1,114 @@
<?php
/**
* Restrict Post Type View
*
* HTML display of the restrict post type page.
*
* @package restrict-content-pro
* @subpackage Admin/Restrict Post Type View
* @copyright Copyright (c) 2017, Restrict Content Pro
* @license GPL2+
* @since 2.9
*/
$screen = get_current_screen();
$post_type = ! empty( $screen->post_type ) ? $screen->post_type : 'post';
$restrictions = rcp_get_post_type_restrictions( $post_type );
$is_paid = array_key_exists( 'is_paid', $restrictions ) ? true : false;
$sub_levels = array_key_exists( 'subscription_level', $restrictions ) ? $restrictions['subscription_level'] : false;
$set_level = is_array( $sub_levels ) ? '' : $sub_levels;
$access_level = array_key_exists( 'access_level', $restrictions ) ? $restrictions['access_level'] : false;
$access_level = is_numeric( $access_level ) ? absint( $access_level ) : '';
$user_role = array_key_exists( 'user_level', $restrictions ) ? $restrictions['user_level'] : false;
$access_display = is_numeric( $access_level ) ? '' : ' style="display:none;"';
$level_set_display = ! empty( $sub_levels ) || ! empty( $is_paid ) ? '' : ' style="display:none;"';
$levels_display = is_array( $sub_levels ) ? '' : ' style="display:none;"';
$role_set_display = '' != $user_role ? '' : ' style="display:none;"';
?>
<form method="POST" action="">
<p><?php _e( 'Use this form to restrict an entire post type. If set to "Everyone", you will be able to configure restrictions on a post-by-post basis.', 'rcp' ); ?></p>
<div id="rcp-metabox-field-restrict-by" class="rcp-metabox-field">
<p><strong><?php _e( 'Member access options', 'rcp' ); ?></strong></p>
<p>
<?php _e( 'Select who should have access to this content.', 'rcp' ); ?>
<span alt="f223" class="rcp-help-tip dashicons dashicons-editor-help" title="<?php _e( '<strong>Membership level</strong>: a membership level refers to a membership option. For example, you might have a Gold, Silver, and Bronze membership level. <br/><br/><strong>Access Level</strong>: refers to a tiered system where a member\'s ability to view content is determined by the access level assigned to their account. A member with an access level of 5 can view content assigned to access levels of 5 and lower.', 'rcp' ); ?>"></span>
</p>
<p>
<label for="rcp-restrict-by" class="screen-reader-text"><?php _e( 'Select who should have access to this content', 'rcp' ); ?></label>
<select id="rcp-restrict-by" name="rcp_restrict_by">
<option value="unrestricted" <?php selected( true, ( empty( $sub_levels ) && empty( $access_level ) && empty( $is_paid ) ) ); ?>><?php _e( 'Everyone (or configure posts individually)', 'rcp' ); ?></option>
<option value="subscription-level"<?php selected( true, ! empty( $sub_levels ) || ! empty( $is_paid ) ); ?>><?php _e( 'Members of membership level(s)', 'rcp' ); ?></option>
<option value="access-level"<?php selected( true, is_numeric( $access_level ) ); ?>><?php _e( 'Members with an access level', 'rcp' ); ?></option>
<option value="registered-users"<?php selected( true, empty( $sub_levels ) && ! is_numeric( $access_level ) && ! empty( $user_role ) && 'All' !== $user_role ); ?>><?php _e( 'Members with a certain role', 'rcp' ); ?></option>
</select>
</p>
</div>
<div id="rcp-metabox-field-levels" class="rcp-metabox-field"<?php echo $level_set_display; ?>>
<label for="rcp_subscription_level_any">
<input type="radio" name="rcp_subscription_level_any_set" id="rcp_subscription_level_any" value="any"<?php checked( 'any', $set_level ); ?>/>
&nbsp;<?php _e( 'Members of any membership level(s)', 'rcp' ); ?><br/>
</label>
<label for="rcp_subscription_level_any_paid">
<input type="radio" name="rcp_subscription_level_any_set" id="rcp_subscription_level_any_paid" value="any-paid"<?php checked( true, $set_level == 'any-paid' || ( ! empty( $is_paid ) && 'any' !== $sub_levels ) ); ?>/>
&nbsp;<?php _e( 'Members of any paid membership level(s)', 'rcp' ); ?><br/>
</label>
<label for="rcp_subscription_level_specific">
<input type="radio" name="rcp_subscription_level_any_set" id="rcp_subscription_level_specific" value="specific"<?php checked( true, is_array( $sub_levels ) ); ?>/>
&nbsp;<?php _e( 'Members of specific membership levels', 'rcp' ); ?><br/>
</label>
<p class="rcp-subscription-levels"<?php echo $levels_display; ?>>
<?php foreach ( rcp_get_membership_levels( array( 'number' => 999 ) ) as $level ) : ?>
<label for="rcp_subscription_level_<?php echo esc_attr( $level->get_id() ); ?>">
<input type="checkbox" name="rcp_subscription_level[]"<?php checked( true, in_array( $level->get_id(), (array) $sub_levels ) ); ?> class="rcp_subscription_level" id="rcp_subscription_level_<?php echo esc_attr( $level->get_id() ); ?>" value="<?php echo esc_attr( $level->get_id() ); ?>" data-price="<?php echo esc_attr( $level->get_price() ); ?>"/>
&nbsp;<?php echo esc_html( $level->get_name() ); ?><br/>
</label>
<?php endforeach; ?>
</p>
</div>
<div id="rcp-metabox-field-access-levels" class="rcp-metabox-field"<?php echo $access_display; ?>>
<p>
<label for="rcp-access-level-field" class="screen-reader-text"><?php _e( 'Require members to have this access level or higher.', 'rcp' ); ?></label>
<select name="rcp_access_level" id="rcp-access-level-field">
<?php foreach ( rcp_get_access_levels() as $key => $access_level_label ) : ?>
<option id="rcp_access_level<?php echo $key; ?>" value="<?php echo esc_attr( $key ); ?>"<?php selected( $key, $access_level ); ?>><?php printf( __( '%s and higher', 'rcp' ), $key ); ?></option>
<?php endforeach; ?>
</select>
</p>
</div>
<div id="rcp-metabox-field-role" class="rcp-metabox-field"<?php echo $role_set_display; ?>>
<p>
<label for="rcp-user-level-field"><?php _e( 'Require member to have capabilities from this user role.', 'rcp' ); ?></label>
</p>
<p>
<?php
$roles = get_editable_roles();
$roles = array_merge( array( 'all' => array( 'name' => 'Any' ) ), $roles );
$selected_roles = is_array( $user_role ) ? $user_role : array( strtolower( $user_role ) );
foreach( $roles as $key => $role ) : ?>
<label for="rcp_user_level_<?php echo esc_attr( $key ); ?>">
<input type="checkbox" name="rcp_user_level[]" id="rcp_user_level_<?php echo esc_attr( $key ); ?>" class="rcp-user-role" value="<?php echo esc_attr( $key ); ?>"<?php checked( true, in_array( $key, $selected_roles ) ); ?>>
&nbsp;<?php echo translate_user_role( $role['name'] ); ?><br/>
</label>
<?php endforeach; ?>
</p>
</div>
<?php
/**
* Used to insert additional post type restriction settings or notes.
*
* @param string $post_type Current post type.
* @param array $restrictions Array of restrictions for this post type.
*
* @since 2.9
*/
do_action( 'rcp_post_type_restrictions', $post_type, $restrictions );
?>
<p>
<?php wp_nonce_field( 'rcp_save_post_type_restrictions', 'rcp_save_post_type_restrictions_nonce' ); ?>
<input type="hidden" name="rcp_post_type" value="<?php echo esc_attr( $post_type ); ?>">
<input type="hidden" name="rcp-action" value="save_post_type_restrictions"/>
<input type="submit" class="button button-primary" value="<?php esc_attr_e( 'Save', 'rcp' ); ?>">
</p>
</form>

View File

@@ -0,0 +1,242 @@
<?php
/**
* Page for Restricting a Post Type
*
* @package restrict-content-pro
* @subpackage Admin/Restrict Post Type
* @copyright Copyright (c) 2017, Restrict Content Pro
* @license GPL2+
* @since 2.9
*/
use RCP\Membership_Level;
/**
* Render page for restricting an entire post type.
*
* @since 2.9
* @return void
*/
function rcp_restrict_post_type_page() {
$screen = get_current_screen();
$post_type = ! empty( $screen->post_type ) ? $screen->post_type : 'post';
$post_type_details = get_post_type_object( $post_type );
?>
<div class="wrap">
<h1><?php printf( __( 'Restrict All %s', 'rcp' ), $post_type_details->labels->name ); ?></h1>
<div class="metabox-holder">
<div class="postbox">
<div class="inside">
<?php
do_action( 'rcp_restrict_post_type_fields_before' );
include RCP_PLUGIN_DIR . 'core/includes/admin/post-types/restrict-post-type-view.php';
do_action( 'rcp_restrict_post_type_fields_after' );
?>
</div>
</div>
</div>
</div>
<?php
}
/**
* Save post type restrictions
*
* @since 2.9
* @return void
*/
function rcp_save_post_type_restrictions() {
if ( ! isset( $_POST['rcp_save_post_type_restrictions_nonce'] ) || ! wp_verify_nonce( $_POST['rcp_save_post_type_restrictions_nonce'], 'rcp_save_post_type_restrictions' ) ) {
wp_die( __( 'Nonce verification failed.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 403 ) );
}
$post_type = isset( $_POST['rcp_post_type'] ) ? $_POST['rcp_post_type'] : 'post';
// Check permissions
$post_type_details = get_post_type_object( $post_type );
$capability = isset( $post_type_details->cap->edit_posts ) ? $post_type_details->cap->edit_posts : 'edit_posts';
if ( ! current_user_can( $capability ) ) {
wp_die( __( 'You do not have permission to perform this action.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 403 ) );
}
$is_paid = false;
$restrict_by = sanitize_text_field( $_POST['rcp_restrict_by'] );
$restricted_post_types = rcp_get_restricted_post_types();
$this_post_type_restrictions = rcp_get_post_type_restrictions( $post_type );
if ( ! is_array( $this_post_type_restrictions ) ) {
$this_post_type_restrictions = array();
}
$levels = rcp_get_membership_levels( array( 'number' => 999 ) );
switch ( $restrict_by ) {
case 'unrestricted' :
unset( $this_post_type_restrictions['access_level'] );
unset( $this_post_type_restrictions['subscription_level'] );
unset( $this_post_type_restrictions['user_level'] );
break;
case 'subscription-level' :
$level_set = sanitize_text_field( $_POST['rcp_subscription_level_any_set'] );
switch ( $level_set ) {
case 'any' :
$this_post_type_restrictions['subscription_level'] = 'any';
break;
case 'any-paid' :
$is_paid = true;
$this_post_type_restrictions['subscription_level'] = 'any-paid';
break;
case 'specific' :
$levels = array_map( 'absint', $_POST['rcp_subscription_level'] );
foreach ( $levels as $level_id ) {
$level = rcp_get_membership_level( $level_id );
if ( $level instanceof Membership_Level && ! $level->is_free() ) {
$is_paid = true;
break;
}
}
$this_post_type_restrictions['subscription_level'] = $levels;
break;
}
// Remove unneeded fields
unset( $this_post_type_restrictions['access_level'] );
break;
case 'access-level' :
$this_post_type_restrictions['access_level'] = absint( $_POST['rcp_access_level'] );
foreach ( $levels as $level ) {
if ( ! $level->is_free() ) {
$is_paid = true;
break;
}
}
// Remove unneeded fields
unset( $this_post_type_restrictions['subscription_level'] );
break;
case 'registered-users' :
// Remove unneeded fields
unset( $this_post_type_restrictions['access_level'] );
// Remove unneeded fields
unset( $this_post_type_restrictions['subscription_level'] );
foreach ( $levels as $level ) {
if ( ! $level->is_free() ) {
$is_paid = true;
break;
}
}
break;
}
$user_role = ! empty( $_POST['rcp_user_level'] ) ? $_POST[ 'rcp_user_level' ] : 'all';
if ( ! is_array( $user_role ) ) {
$user_role = array( $user_role );
}
$user_role = array_map( 'sanitize_text_field', $user_role );
if ( 'unrestricted' !== $_POST['rcp_restrict_by'] ) {
$this_post_type_restrictions['user_level'] = $user_role;
}
if ( $is_paid ) {
$this_post_type_restrictions['is_paid'] = $is_paid;
} else {
unset( $this_post_type_restrictions['is_paid'] );
}
// Save the restrictions.
if ( ! empty( $this_post_type_restrictions ) ) {
$restricted_post_types[ $post_type ] = $this_post_type_restrictions;
} else {
unset( $restricted_post_types[ $post_type ] );
}
if ( empty( $restricted_post_types ) ) {
delete_option( 'rcp_restricted_post_types' );
} else {
update_option( 'rcp_restricted_post_types', $restricted_post_types );
}
do_action( 'rcp_save_post_type_restrictions', $post_type );
$url = add_query_arg( array(
'rcp_message' => 'post-type-updated'
), rcp_get_restrict_post_type_page_url( $post_type ) );
wp_safe_redirect( $url );
exit;
}
add_action( 'rcp_action_save_post_type_restrictions', 'rcp_save_post_type_restrictions' );
/**
* Returns the URL to the post type restriction page
*
* @param string $post_type
*
* @since 2.9
* @return string
*/
function rcp_get_restrict_post_type_page_url( $post_type = '' ) {
if ( empty( $post_type ) ) {
$post_type = get_post_type();
}
if ( 'post' == $post_type ) {
$restrict_url = add_query_arg( array( 'page' => 'rcp-restrict-post-type' ), admin_url( 'edit.php' ) );
} else {
$restrict_url = add_query_arg( array(
'post_type' => urlencode( $post_type ),
'page' => urlencode( 'rcp-restrict-post-type-' . $post_type )
), admin_url( 'edit.php' ) );
}
return $restrict_url;
}

View File

@@ -0,0 +1 @@
<?php // Silence is golden.

View File

@@ -0,0 +1,141 @@
<?php
/**
* Add/Edit Membership Reminder
*
* @package Restrict Content Pro
* @subpackage Admin/Reminders/Subscription Reminders View
* @copyright Copyright (c) 2017, Restrict Content Pro
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
* @since 2.9
*/
$reminder_type = isset( $_GET['rcp_reminder_type'] ) ? $_GET['rcp_reminder_type'] : 'renewal';
$notices = new RCP_Reminders();
$notice_id = isset( $_GET['notice'] ) ? absint( $_GET['notice'] ) : 0;
$new_notice = ! isset( $_GET['notice'] );
$default = array(
'type' => $reminder_type,
'subject' => '',
'send_period' => 'today',
'message' => '',
'enabled' => false,
'levels' => array()
);
$notice = ! $new_notice ? $notices->get_notice( $notice_id ) : $default;
?>
<div class="wrap">
<h1>
<?php echo $notice_id ? __( 'Edit Reminder Notice', 'rcp' ) : __( 'Add Reminder Notice', 'rcp' ); ?> -
<a href="<?php echo esc_url( admin_url( 'admin.php?page=rcp-settings#emails' ) ); ?>" class="add-new-h2"><?php _e( 'Go Back', 'rcp' ); ?></a>
</h1>
<?php if ( empty( $notice ) ) : ?>
<div class="error settings-error">
<p><?php _e( 'Error: Invalid notice ID.', 'rcp' ); ?></p>
</div>
<?php
echo '</div>'; // close .wrap
return;
endif; ?>
<form id="rcp-edit-reminder-notice" method="POST">
<table class="form-table">
<tbody>
<tr>
<th scope="row" valign="top">
<label for="rcp-notice-type"><?php _e( 'Notice Type', 'rcp' ); ?></label>
</th>
<td>
<select id="rcp-notice-type" name="rcp_reminder_type">
<?php foreach ( $notices->get_notice_types() as $type => $label ) : ?>
<option value="<?php echo esc_attr( $type ); ?>" <?php selected( $type, $notice['type'] ); ?>><?php echo esc_html( $label ); ?></option>
<?php endforeach; ?>
</select>
<p class="description"><?php _e( 'Is this a renewal notice or an expiration notice?', 'rcp' ); ?></p>
<p class="description">
<?php _e( '<strong>Expiration notices</strong> are sent to "active" and "cancelled" memberships that <strong>do not</strong> have auto renew enabled. They can be used to inform customers that their memberships will not be automatically renewed and they will need to do a manual renewal to retain access to their content.', 'rcp' ); ?> <br>
<?php _e( '<strong>Reminder notices</strong> are sent to "active" memberships that <strong>do</strong> have auto renew enabled. They can be used to inform customers that their memberships will be automatically renewed and give them a chance to cancel if they do not wish to continue.', 'rcp' ); ?>
</p>
</td>
</tr>
<tr>
<th scope="row" valign="top">
<label for="rcp-notice-subject"><?php _e( 'Email Subject', 'rcp' ); ?></label>
</th>
<td>
<input type="text" name="rcp_reminder_subject" id="rcp-notice-subject" class="regular-text" value="<?php echo esc_attr( stripslashes( $notice['subject'] ) ); ?>"/>
<p class="description"><?php _e( 'The subject line of the reminder notice email', 'rcp' ); ?></p>
</td>
</tr>
<tr>
<th scope="row" valign="top">
<label for="rcp-notice-period"><?php _e( 'Email Period', 'rcp' ); ?></label>
</th>
<td>
<select name="rcp_reminder_period" id="rcp-notice-period">
<?php foreach ( $notices->get_notice_periods() as $period => $label ) : ?>
<option value="<?php echo esc_attr( $period ); ?>"<?php selected( $period, $notice['send_period'] ); ?>><?php echo esc_html( $label ); ?></option>
<?php endforeach; ?>
</select>
<p class="description"><?php _e( 'When should this email be sent?', 'rcp' ); ?></p>
</td>
</tr>
<tr>
<th scope="row" valign="top">
<label for="rcp-notice-levels"><?php _e( 'Membership Levels', 'rcp' ); ?></label>
</th>
<td>
<?php
$levels = rcp_get_membership_levels( array( 'number' => 999 ) );
if ( $levels ) : ?>
<?php
$current = ! empty( $notice['levels'] ) && is_array( $notice['levels'] ) ? $notice['levels'] : array();
foreach ( $levels as $level ) :
// Don't bother showing levels that never expire.
if ( $level->is_lifetime() ) {
continue;
}
?>
<input type="checkbox" id="rcp-notice-levels-<?php echo esc_attr( $level->get_id() ); ?>" name="rcp_reminder_levels[]" value="<?php echo esc_attr( $level->get_id() ); ?>" <?php checked( true, in_array( $level->get_id(), $current ) ); ?>>
<label for="rcp-notice-levels-<?php echo esc_attr( $level->get_id() ); ?>"><?php echo esc_html( $level->get_name() ); ?></label>
<br>
<?php
endforeach;
endif; ?>
<p class="description"><?php _e( 'The membership levels this reminder will be sent for. Leave blank for all levels.', 'rcp' ); ?></p>
</td>
</tr>
<tr>
<th scope="row" valign="top">
<label for="rcp-notice-enabled"><?php _e( 'Enable Notice', 'rcp' ); ?></label>
</th>
<td>
<input type="checkbox" id="rcp-notice-enabled" name="rcp_reminder_enabled" value="1" <?php checked( ! empty( $notice['enabled'] ), true ); ?>>
<span><?php _e( 'Check to enable sending the email. If unchecked, the email won\'t be sent to members.', 'rcp' ); ?></span>
</td>
</tr>
<tr>
<th scope="row" valign="top">
<label for="rcp-notice-message"><?php _e( 'Email Message', 'rcp' ); ?></label>
</th>
<td>
<?php wp_editor( wpautop( wp_kses_post( wptexturize( $notice['message'] ) ) ), 'rcp-notice-message', array( 'textarea_name' => 'rcp_reminder_message' ) ); ?>
<p class="description"><?php _e( 'The email message to be sent with the reminder notice. The following template tags can be used in the message:', 'rcp' ); ?></p>
<?php echo rcp_get_emails_tags_list(); ?>
</td>
</tr>
</tbody>
</table>
<p class="submit">
<input type="hidden" name="rcp-action" value="add_edit_reminder_notice"/>
<input type="hidden" name="notice-id" value="<?php echo ! $new_notice ? esc_attr( $notice_id ) : ''; ?>"/>
<?php wp_nonce_field( 'rcp_add_edit_reminder', 'rcp_add_edit_reminder_nonce' ); ?>
<input type="submit" value="<?php echo ! $new_notice ? esc_attr__( 'Edit Reminder Notice', 'rcp' ) : esc_attr__( 'Add Reminder Notice', 'rcp' ); ?>" class="button-primary"/>
</p>
</form>
</div>

View File

@@ -0,0 +1,218 @@
<?php
/**
* Subscription Reminders Page
*
* @package Restrict Content Pro
* @subpackage Admin/Reminders/Subscription Reminders
* @copyright Copyright (c) 2017, Restrict Content Pro
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
* @since 2.9
*/
use RCP\Membership_Level;
/**
* Removes the Subscription Reminder menu link
*
* @since 2.9
* @return void
*/
function rcp_hide_reminder_page() {
remove_submenu_page( 'rcp-members', 'rcp-reminder' );
}
/**
* Renders the add/edit subscription reminder notice screen
*
* @since 2.9
* @return void
*/
function rcp_subscription_reminder_page() {
include RCP_PLUGIN_DIR . 'core/includes/admin/reminders/subscription-reminder-view.php';
}
/**
* Display subscription reminder table
*
* @param string $type Type to display (expiration or renewal).
*
* @since 2.9
* @return void
*/
function rcp_subscription_reminder_table( $type = 'expiration' ) {
$reminders = new RCP_Reminders();
$notices = $reminders->get_notices( $type );
$type_label = ( 'expiration' == $type ) ? __( 'Expiration', 'rcp' ) : __( 'Renewal', 'rcp' );
?>
<table id="rcp-<?php echo esc_attr( $type ); ?>-reminders" class="wp-list-table widefat fixed posts rcp-email-reminders">
<thead>
<tr>
<th scope="col" class="rcp-reminder-subject-col"><?php _e( 'Subject', 'rcp' ); ?></th>
<th scope="col" class="rcp-reminder-period-col"><?php _e( 'Send Period', 'rcp' ); ?></th>
<th scope="col" class="rcp-reminder-status"><?php _e( 'Status', 'rcp' ); ?></th>
<th scope="col" class="rcp-reminder-levels"><?php _e( 'Level(s)', 'rcp' ); ?></th>
<th scope="col" class="rcp-reminder-action-col"><?php _e( 'Actions', 'rcp' ); ?></th>
</tr>
</thead>
<?php if ( ! empty( $notices ) ) : $i = 1; ?>
<?php foreach ( $notices as $key => $notice ) : $notice = $reminders->get_notice( $key ); ?>
<tr<?php echo ( 0 == $i % 2 ) ? ' class="alternate"' : ''; ?>>
<td><?php echo esc_html( stripslashes( $notice['subject'] ) ); ?></td>
<td><?php echo esc_html( $reminders->get_notice_period_label( $key ) ); ?></td>
<td><?php echo ! empty( $notice['enabled'] ) ? __( 'Enabled', 'rcp' ) : __( 'Disabled', 'rcp' ); ?></td>
<td>
<?php
$levels = ! empty( $notice['levels'] ) && is_array( $notice['levels'] ) ? $notice['levels'] : array();
if ( ! empty( $levels ) && count( $levels ) > 1 ) {
esc_html_e( 'Multiple Levels', 'rcp' );
} elseif ( is_array( $levels ) && count( $levels ) == 1 ) {
$this_level = rcp_get_membership_level( $levels );
echo $this_level instanceof Membership_Level ? esc_html( $this_level->get_name() ) : '';
} else {
esc_html_e( 'All Levels', 'rcp' );
}
?>
</td>
<td>
<a href="<?php echo esc_url( admin_url( 'admin.php?page=rcp-reminder&rcp-action=edit_subscription_reminder&notice=' . $key ) ); ?>" class="rcp-edit-reminder-notice" data-key="<?php echo esc_attr( $key ); ?>"><?php _e( 'Edit', 'rcp' ); ?></a>&nbsp;|
<a href="<?php echo esc_url( add_query_arg( array( 'rcp_preview_email' => urlencode( $key ) ), home_url() ) ); ?>" class="rcp-preview-reminder-notice" target="_blank"><?php _e( 'Preview', 'rcp' ); ?></a> |
<a href="<?php echo esc_url( wp_nonce_url( admin_url( 'admin.php?page=rcp-reminder&rcp-action=send_test_reminder&notice-id=' . $key ), 'rcp_send_test_reminder' ) ); ?>" class="rcp-send-test-reminder-notice"><?php _e( 'Send Test Email', 'rcp' ); ?></a>&nbsp;|
<a href="<?php echo esc_url( wp_nonce_url( admin_url( 'admin.php?page=rcp-reminder&rcp-action=delete_subscription_reminder&notice-id=' . $key ), 'rcp_delete_reminder_notice' ) ); ?>" class="rcp-delete rcp-delete-reminder"><?php _e( 'Delete', 'rcp' ); ?></a>
</td>
</tr>
<?php $i ++; endforeach; ?>
<?php else : ?>
<tr>
<td colspan="3"><?php _e( 'No reminders set.', 'rcp' ); ?></td>
</tr>
<?php endif; ?>
</table>
<p>
<a href="<?php echo esc_url( admin_url( 'admin.php?page=rcp-reminder&rcp-action=add_subscription_reminder&rcp_reminder_type=' . urlencode( $type ) ) ); ?>" class="button-secondary" id="rcp-add-renewal-notice"><?php printf( __( 'Add %s Reminder', 'rcp' ), $type_label ); ?></a>
</p>
<?php
}
/**
* Add or edit reminder notice
*
* @since 2.9
* @return void
*/
function rcp_process_add_edit_reminder_notice() {
if ( ! current_user_can( 'rcp_manage_settings' ) ) {
wp_die( __( 'You do not have permission to add reminder notices', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 403 ) );
}
if ( ! wp_verify_nonce( $_POST['rcp_add_edit_reminder_nonce'], 'rcp_add_edit_reminder' ) ) {
wp_die( __( 'Nonce verification failed', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 403 ) );
}
$notice_id = $_POST['notice-id']; // We're adding a new notice if this is an empty string.
$subject = isset( $_POST['rcp_reminder_subject'] ) ? sanitize_text_field( $_POST['rcp_reminder_subject'] ) : __( 'Your Subscription is About to Renew', 'rcp' );
$period = isset( $_POST['rcp_reminder_period'] ) ? sanitize_text_field( $_POST['rcp_reminder_period'] ) : '+1month';
$message = isset( $_POST['rcp_reminder_message'] ) ? wp_kses( stripslashes( $_POST['rcp_reminder_message'] ), wp_kses_allowed_html( 'post' ) ) : false;
$type = isset( $_POST['rcp_reminder_type'] ) ? sanitize_text_field( $_POST['rcp_reminder_type'] ) : 'renewal';
$enabled = isset( $_POST['rcp_reminder_enabled'] );
$levels = isset( $_POST['rcp_reminder_levels'] ) && is_array( $_POST['rcp_reminder_levels'] ) ? array_map( 'absint', $_POST['rcp_reminder_levels'] ) : '';
// Disable message if subject and/or message are empty.
if ( $enabled && ( empty( $message ) || empty( $subject ) ) ) {
$enabled = false;
}
$reminders = new RCP_Reminders();
$notices = $reminders->get_notices();
$settings = array(
'subject' => $subject,
'message' => $message,
'send_period' => $period,
'type' => $type,
'enabled' => $enabled,
'levels' => $levels
);
if ( '' != $notice_id ) {
$notices[ absint( $notice_id ) ] = $settings;
$redirect_url = admin_url( 'admin.php?page=rcp-settings&rcp_message=reminder_updated#emails' );
} else {
$notices[] = $settings;
$redirect_url = admin_url( 'admin.php?page=rcp-settings&rcp_message=reminder_added#emails' );
}
update_option( 'rcp_reminder_notices', $notices );
wp_safe_redirect( $redirect_url );
exit;
}
add_action( 'rcp_action_add_edit_reminder_notice', 'rcp_process_add_edit_reminder_notice' );
/**
* Delete a reminder notice
*
* @since 2.9
* @return void
*/
function rcp_process_delete_reminder_notice() {
if ( ! current_user_can( 'rcp_manage_settings' ) ) {
wp_die( __( 'You do not have permission to delete reminder notices', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 403 ) );
}
if ( ! wp_verify_nonce( $_GET['_wpnonce'], 'rcp_delete_reminder_notice' ) ) {
wp_die( __( 'Nonce verification failed', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 401 ) );
}
if ( empty( $_GET['notice-id'] ) && 0 !== (int) $_GET['notice-id'] ) {
wp_die( __( 'No reminder notice ID was provided', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 400 ) );
}
$reminders = new RCP_Reminders();
$notices = $reminders->get_notices();
unset( $notices[ absint( $_GET['notice-id'] ) ] );
update_option( 'rcp_reminder_notices', $notices );
wp_safe_redirect( admin_url( 'admin.php?page=rcp-settings&rcp_message=reminder_deleted#emails' ) );
exit;
}
add_action( 'rcp_action_delete_subscription_reminder', 'rcp_process_delete_reminder_notice' );
/**
* Send a test reminder notice
*
* @since 2.9
* @return void
*/
function rcp_process_send_test_reminder_notice() {
if ( ! current_user_can( 'rcp_manage_settings' ) ) {
wp_die( __( 'You do not have permission to send test reminder notices', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 403 ) );
}
if ( ! wp_verify_nonce( $_GET['_wpnonce'], 'rcp_send_test_reminder' ) ) {
wp_die( __( 'Nonce verification failed', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 401 ) );
}
if ( empty( $_GET['notice-id'] ) && 0 !== (int) $_GET['notice-id'] ) {
wp_die( __( 'No reminder notice ID was provided', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 400 ) );
}
$reminders = new RCP_Reminders();
$reminders->send_test_notice( absint( $_GET['notice-id'] ) );
wp_safe_redirect( admin_url( 'admin.php?page=rcp-settings&rcp_message=test_reminder_sent#emails' ) );
exit;
}
add_action( 'rcp_action_send_test_reminder', 'rcp_process_send_test_reminder_notice' );

View File

@@ -0,0 +1,94 @@
<?php
/**
* Screen Options
*
* @package Restrict Content Pro
* @subpackage Admin/Screen Options
* @copyright Copyright (c) 2017, Restrict Content Pro
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
*/
/**
* Setup screen options
*
* @return void
*/
function rcp_screen_options() {
global $rcp_members_page;
global $rcp_customers_page;
global $rcp_subscriptions_page;
global $rcp_payments_page;
$screen = get_current_screen();
if(!is_object($screen))
return;
switch($screen->id) :
case $rcp_members_page :
$args = array(
'label' => __('Memberships per page', 'rcp'),
'default' => 10,
'option' => 'rcp_members_per_page'
);
add_screen_option( 'per_page', $args );
break;
case $rcp_customers_page :
$args = array(
'label' => __( 'Customers per page', 'rcp' ),
'default' => 10,
'option' => 'rcp_customers_per_page'
);
add_screen_option( 'per_page', $args );
break;
case $rcp_payments_page :
$args = array(
'label' => __('Payments per page', 'rcp'),
'default' => 10,
'option' => 'rcp_payments_per_page'
);
add_screen_option( 'per_page', $args );
break;
case $rcp_subscriptions_page :
$args = array(
'label' => __( 'Membership Levels per page', 'rcp' ),
'default' => 10,
'option' => 'rcp_membership_levels_per_page'
);
add_screen_option( 'per_page', $args );
break;
endswitch;
}
/**
* Filters option for number of rows when listing members/payments
*
* @param bool|int $status Screen option value. Default false to skip.
* @param string $option The option name.
* @param int $value The number of rows to use.
*
* @return int|bool
*/
function rcp_set_screen_option($status, $option, $value) {
if ( 'rcp_members_per_page' == $option ) {
return $value;
}
if ( 'rcp_customers_per_page' == $option ) {
return $value;
}
if ( 'rcp_payments_per_page' == $option ) {
return $value;
}
if ( 'rcp_membership_levels_per_page' == $option ) {
return $value;
}
return $status;
}
add_filter('set-screen-option', 'rcp_set_screen_option', 10, 3);

View File

@@ -0,0 +1 @@
<?php // Silence is golden.

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,480 @@
<?php
/**
* Membership Levels List Table
*
* @package restrict-content-pro
* @copyright Copyright (c) 2020, Sandhills Development, LLC
* @license GPL2+
* @since 3.1
*/
namespace RCP\Admin;
use RCP\Membership_Level;
/**
* Class Membership_Levels_Table
*
* @since 3.1
* @package RCP\Admin
*/
class Membership_Levels_Table extends List_Table {
/**
* Constructor.
*
* @since 3.1
* @see WP_List_Table::__construct()
*/
public function __construct() {
parent::__construct( [
'singular' => 'Membership Level',
'plural' => 'Membership Levels',
'ajax' => false,
] );
$this->process_bulk_action();
$this->get_counts();
}
/**
* Get the base URL for the membership levels list table.
*
* @return string Base URL.
* @since 3.1
*/
public function get_base_url() {
$args = array(
'page' => 'rcp-member-levels'
);
$levels_page = add_query_arg( $args, admin_url( 'admin.php' ) );
return $levels_page;
}
/**
* Retrieve the table columns.
*
* @return array
* @since 3.1
*/
public function get_columns() {
$columns = array(
'cb' => '<input type="checkbox" />',
'name' => __( 'Name', 'rcp' ),
'description' => __( 'Description', 'rcp' ),
'status' => __( 'Status', 'rcp' ),
'access_level' => __( 'Access Level', 'rcp' ),
'duration' => __( 'Duration', 'rcp' ),
'price' => __( 'Price', 'rcp' ),
'memberships' => __( 'Memberships', 'rcp' )
);
/*
* Backwards compatibility: add an "extra" column if someone is hooking into the old action to add
* their own column. Everything gets bundled into one column because this is the only way we can realistically
* do it.
*/
if ( has_action( 'rcp_levels_page_table_header' ) ) {
$columns['custom'] = __( 'Extra', 'rcp' );
}
// Now add "order" in, because we want that to be last.
$columns['order'] = __( 'Order', 'rcp' );
/**
* Filters the table columns.
*
* @param array $columns
*
* @since 3.1
*/
$columns = apply_filters( 'rcp_membership_levels_list_table_columns', $columns );
return $columns;
}
/**
* Retrieve the sortable columns.
*
* @return array
* @since 3.1
*/
public function get_sortable_columns() {
return array(
'name' => array( 'name', false ),
'status' => array( 'status', false ),
'access_level' => array( 'level', false ),
'order' => array( 'list_order', false )
);
}
/**
* Gets the name of the primary column.
*
* @return string
* @since 3.1
*/
protected function get_primary_column_name() {
return 'name';
}
/**
* This function renders any other columns in the list table.
*
* @param Membership_Level $membership_level Membership level object.
* @param string $column_name The name of the column
*
* @return string Column Name
* @since 3.1
*/
public function column_default( $membership_level, $column_name ) {
$value = '';
switch ( $column_name ) {
case 'description' :
$value = $membership_level->get_description();
break;
case 'status' :
$value = ucwords( $membership_level->get_status() );
break;
case 'access_level' :
$value = $membership_level->get_access_level() ? $membership_level->get_access_level() : __( 'none', 'rcp' );
break;
case 'duration' :
if ( $membership_level->is_lifetime() ) {
$value = __( 'unlimited', 'rcp' );
} else {
$value = $membership_level->get_duration() . ' ' . rcp_filter_duration_unit( $membership_level->get_duration_unit(), $membership_level->get_duration() );
}
break;
case 'price' :
if ( $membership_level->is_free() ) {
$value = __( 'Free', 'rcp' );
} else {
$value = rcp_currency_filter( $membership_level->get_price() );
}
break;
case 'memberships' :
$memberships_page = rcp_get_memberships_admin_page( array( 'object_id' => urlencode( $membership_level->get_id() ) ) );
$membership_count = rcp_count_memberships( array(
'status__in' => array( 'active', 'cancelled' ),
'object_id' => $membership_level->get_id()
) );
$value = '<a href="' . esc_url( $memberships_page ) . '">' . $membership_count . '</a>';
break;
case 'order' :
$value = '<a href="#" class="rcp-drag-handle"></a>';
break;
}
/*
* Backwards compatibility: show content of custom columns from old action hook.
*/
if ( 'custom' == $column_name && has_action( 'rcp_levels_page_table_column' ) ) {
ob_start();
do_action( 'rcp_levels_page_table_column', $membership_level->get_id() );
$column_content = ob_get_clean();
$value = wp_strip_all_tags( $column_content );
}
/**
* Filters the column value.
*
* @param string $value Column value.
* @param object $membership_level Membership level object.
*
* @since 3.1
*/
$value = apply_filters( 'rcp_membership_levels_list_table_column_' . $column_name, $value, $membership_level );
return $value;
}
/**
* Render the checkbox column.
*
* @param Membership_Level $membership_level
*
* @return string
* @since 3.1
*/
public function column_cb( $membership_level ) {
return sprintf(
'<input type="checkbox" name="%1$s[]" value="%2$s" />',
'membership_level_id',
$membership_level->get_id()
);
}
/**
* Render the "Name" column.
*
* @param Membership_Level $membership_level
*
* @return string
* @since 3.1
*/
public function column_name( $membership_level ) {
$edit_level_url = add_query_arg( 'edit_subscription', urlencode( $membership_level->get_id() ), $this->get_base_url() );
$actions = array(
'edit' => '<a href="' . esc_url( $edit_level_url ) . '">' . __( 'Edit', 'rcp' ) . '</a>',
);
if ( 'active' == $membership_level->get_status() ) {
$deactivate_url = wp_nonce_url( add_query_arg( array(
'rcp-action' => 'deactivate_subscription',
'level_id' => $membership_level->get_id() ),
$this->get_base_url()
), 'rcp-deactivate-subscription-level' );
$actions['deactivate'] = '<a href="' . esc_url( $deactivate_url ) . '">' . __( 'Deactivate', 'rcp' ) . '</a>';
} else {
$activate_url = wp_nonce_url( add_query_arg( array(
'rcp-action' => 'activate_subscription',
'level_id' => $membership_level->get_id() ),
$this->get_base_url()
), 'rcp-activate-subscription-level' );
$actions['activate'] = '<a href="' . esc_url( $activate_url ) . '">' . __( 'Activate', 'rcp' ) . '</a>';
}
$delete_url = wp_nonce_url( add_query_arg( array(
'rcp-action' => 'delete_subscription',
'level_id' => $membership_level->get_id()
), $this->get_base_url() ), 'rcp-delete-subscription-level' );
$actions['delete'] = '<span class="trash"><a href="' . esc_url( $delete_url ) . '" class="rcp_delete_subscription">' . __( 'Delete', 'rcp' ) . '</a></span>';
$actions['level_id'] = '<span class="rcp-sub-id-col rcp-id-col">' . sprintf( __( 'ID: %d', 'rcp' ), $membership_level->get_id() ) . '</span>';
ob_start();
/**
* @deprecated 3.1 Use `rcp_membership_levels_list_table_row_actions` instead.
*/
do_action( 'rcp_membership_level_row_actions', $membership_level );
$custom_row_actions = ob_get_clean();
if ( $custom_row_actions ) {
$actions['custom_row_actions'] = $custom_row_actions;
}
/**
* Filters the row actions.
*
* @param array $actions Default actions.
* @param Membership_Level $membership_level Membership level object.
*
* @since 3.1
*/
$actions = apply_filters( 'rcp_membership_levels_list_table_row_actions', $actions, $membership_level );
$final = '<strong><a class="row-title" href="' . esc_url( $edit_level_url ) . '">' . esc_html( $membership_level->get_name() ) . '</a></strong>';
if ( current_user_can( 'rcp_manage_levels' ) ) {
$final .= $this->row_actions( $actions );
}
return $final;
}
/**
* Message to be displayed when there are no membership levels.
*
* @return void
* @since 3.1
*/
public function no_items() {
esc_html_e( 'No membership levels found.', 'rcp' );
}
/**
* Retrieve the bulk actions.
*
* @return array
* @since 3.1
*/
public function get_bulk_actions() {
return array(
'activate' => __( 'Activate', 'rcp' ),
'deactivate' => __( 'Deactivate', 'rcp' ),
'delete' => __( 'Permanently Delete', 'rcp' )
);
}
/**
* Process bulk actions.
*
* @return void
* @since 3.1
*/
public function process_bulk_action() {
// Bail if a nonce was not supplied.
if ( ! isset( $_REQUEST['_wpnonce'] ) ) {
return;
}
if ( ! wp_verify_nonce( $_REQUEST['_wpnonce'], 'bulk-membershiplevels' ) ) {
return;
}
$ids = wp_parse_id_list( (array) $this->get_request_var( 'membership_level_id', false ) );
// Bail if no IDs
if ( empty( $ids ) ) {
return;
}
foreach ( $ids as $level_id ) {
switch ( $this->current_action() ) {
case 'activate':
rcp_update_membership_level( $level_id, array( 'status' => 'active' ) );
break;
case 'deactivate':
rcp_update_membership_level( $level_id, array( 'status' => 'inactive' ) );
break;
case 'delete':
rcp_delete_membership_level( $level_id );
break;
}
}
$this->show_admin_notice( $this->current_action() );
}
/**
* Show admin notice for bulk actions.
*
* @param string $action The action to show the notice for.
*
* @access private
* @return void
* @since 3.1
*/
private function show_admin_notice( $action ) {
$message = '';
switch ( $action ) {
case 'activate' :
$message = __( 'Membership level(s) activated.', 'rcp' );
break;
case 'deactivate' :
$message = __( 'Membership level(s) deactivated.', 'rcp' );
break;
case 'delete' :
$message = __( 'Membership level(s) deleted.', 'rcp' );
break;
}
if ( empty( $message ) ) {
return;
}
echo '<div class="updated"><p>' . $message . '</p></div>';
}
/**
* Retrieve the membership level counts.
*
* @return void
* @since 3.1
*/
public function get_counts() {
$this->counts = array(
'total' => rcp_count_membership_levels(),
'active' => rcp_count_membership_levels( array( 'status' => 'active' ) ),
'inactive' => rcp_count_membership_levels( array( 'status' => 'inactive' ) )
);
}
/**
* Retrieve membership levels data.
*
* @param bool $count Whether or not to get membership level objects (false) or just count the total number (true).
*
* @since 3.1
* @return Membership_Level[]|int
*/
public function levels_data( $count = false ) {
$args = array(
'number' => $this->per_page,
'offset' => $this->get_offset(),
'orderby' => sanitize_text_field( $this->get_request_var( 'orderby', 'list_order' ) ),
'order' => sanitize_text_field( $this->get_request_var( 'order', 'ASC' ) ),
'status' => $this->get_status(),
);
if ( $this->get_search() ) {
$args['search'] = sanitize_text_field( $this->get_search() );
}
if ( $count ) {
return rcp_count_membership_levels( $args );
}
return rcp_get_membership_levels( $args );
}
/**
* Setup the final data for the table.
*
* @return void
* @since 3.1
*/
public function prepare_items() {
$columns = $this->get_columns();
$hidden = array();
$sortable = $this->get_sortable_columns();
$this->_column_headers = array( $columns, $hidden, $sortable );
$this->items = $this->levels_data();
$total = $this->levels_data( true );
// Setup pagination
$this->set_pagination_args( array(
'total_items' => $total,
'per_page' => $this->per_page,
'total_pages' => ceil( $total / $this->per_page )
) );
}
/**
* Get a list of CSS classes for the WP_List_Table table tag.
*
* We override this so we can add the "rcp-subscriptions" class for backwards compatibility.
*
* @since 3.1
*
* @return array List of CSS classes for the table tag.
*/
public function get_table_classes() {
return array( 'widefat', 'fixed', 'striped', $this->_args['plural'], 'rcp-subscriptions' );
}
}

View File

@@ -0,0 +1,173 @@
<?php
/**
* Edit Membership Level Page
*
* @package Restrict Content Pro
* @subpackage Admin/Edit Membership Level
* @copyright Copyright (c) 2017, Restrict Content Pro
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
*/
use RCP\Membership_Level;
$level = rcp_get_membership_level( absint( urldecode( $_GET['edit_subscription'] ) ) );
if ( ! $level instanceof Membership_Level ) {
wp_die( __( 'Invalid membership level.', 'rcp' ) );
}
?>
<h1>
<?php printf( __( 'Edit Membership Level: %s', 'rcp' ), esc_html( $level->get_name() ) ); ?>
<a href="<?php echo admin_url( '/admin.php?page=rcp-member-levels' ); ?>" class="add-new-h2">
<?php _e( 'Cancel', 'rcp' ); ?>
</a>
</h1>
<form id="rcp-edit-subscription" action="" method="post">
<table class="form-table">
<tbody>
<tr class="form-field">
<th scope="row" valign="top">
<label for="rcp-name"><?php _e( 'Name', 'rcp' ); ?></label>
</th>
<td>
<input name="name" id="rcp-name" type="text" value="<?php echo esc_attr( $level->get_name() ); ?>"/>
<p class="description"><?php _e( 'The name of this membership level. This is shown on the registration page.', 'rcp' ); ?></p>
</td>
</tr>
<tr class="form-field">
<th scope="row" valign="top">
<label for="rcp-description"><?php _e( 'Description', 'rcp' ); ?></label>
</th>
<td>
<textarea name="description" id="rcp-description"><?php echo esc_textarea( $level->get_description() ); ?></textarea>
<p class="description"><?php _e( 'The description of this membership level. This is shown on the registration page.', 'rcp' ); ?></p>
</td>
</tr>
<tr class="form-field">
<th scope="row" valign="top">
<label for="rcp-level"><?php _e( 'Access Level', 'rcp' ); ?></label>
</th>
<td>
<select id="rcp-level" name="level">
<?php
foreach( rcp_get_access_levels() as $access ) {
echo '<option value="' . absint( $access ) . '" ' . selected( $access, $level->get_access_level(), false ) . '">' . esc_html( $access ) . '</option>';
}
?>
</select>
<p class="description"><?php _e( 'Level of access this membership gives.', 'rcp' ); ?></p>
</td>
</tr>
<tr class="form-field">
<th scope="row" valign="top">
<label for="rcp-duration"><?php _e( 'Duration', 'rcp' ); ?></label>
</th>
<td>
<input type="text" id="rcp-duration" name="duration" value="<?php echo absint( $level->get_duration() ); ?>"/>
<select name="duration_unit" id="rcp-duration-unit">
<option value="day" <?php selected( $level->get_duration_unit(), 'day' ); ?>><?php _e( 'Day(s)', 'rcp' ); ?></option>
<option value="month" <?php selected( $level->get_duration_unit(), 'month' ); ?>><?php _e( 'Month(s)', 'rcp' ); ?></option>
<option value="year" <?php selected( $level->get_duration_unit(), 'year' ); ?>><?php _e( 'Year(s)', 'rcp' ); ?></option>
</select>
<p class="description"><?php _e( 'Length of time for this membership level. Enter 0 for unlimited.', 'rcp' ); ?></p>
</td>
</tr>
<?php
/**
* Action to add the free trial input fields
* @param Membership_Level $level
*/
do_action( 'rcp_edit_subscription_after_set_trial_duration', $level );
?>
<tr class="form-field">
<th scope="row" valign="top">
<label for="rcp-maximum-renewals-setting"><?php _e( 'Maximum Renewals', 'rcp' ); ?></label>
</th>
<td>
<select name="maximum_renewals_setting" id="rcp-maximum-renewals-setting">
<option value="forever" <?php selected( ! $level->get_maximum_renewals() ); ?>><?php _e( 'Until Cancelled', 'rcp' ); ?></option>
<option value="specific" <?php selected( $level->get_maximum_renewals() > 0 ); ?>><?php _e( 'Specific Number', 'rcp' ); ?></option>
</select>
<label for="rcp-maximum-renewals" class="screen-reader-text"><?php _e( 'Enter the maximum number of renewals', 'rcp' ); ?></label>
<input type="number" id="rcp-maximum-renewals" name="maximum_renewals" value="<?php echo esc_attr( $level->get_maximum_renewals() ); ?>"<?php echo empty( $level->get_maximum_renewals() ) ? ' style="display: none;"' : ''; ?>/>
<p class="description">
<?php _e( 'Number of renewals to process after the first payment.', 'rcp' ); ?>
<span alt="f223" class="rcp-help-tip dashicons dashicons-editor-help" title="<?php esc_attr_e( '<strong>Until Cancelled</strong>: will continue billing the member indefinitely, or until they cancel their membership. <br/><br/><strong>Specific Number</strong> will allow you to enter the number of additional times you wish to bill the customer after their first payment. If you enter "3", the member will be billed once immediately when they sign up, then 3 more times after that. Then billing will stop automatically.', 'rcp' ); ?>"></span>
</p>
</td>
</tr>
<tr class="form-field"<?php echo empty( $level->get_maximum_renewals() ) ? ' style="display: none;"' : ''; ?>>
<th scope="row" valign="top">
<label for="rcp-after-final-payment"><?php _e( 'After Final Payment', 'rcp' ); ?></label>
</th>
<td>
<select name="after_final_payment" id="rcp-after-final-payment">
<option value="lifetime" <?php selected( $level->get_after_final_payment(), 'lifetime' ); ?>><?php _e( 'Grant Lifetime Access', 'rcp' ); ?></option>
<option value="expire_immediately" <?php selected( $level->get_after_final_payment(), 'expire_immediately' ); ?>><?php _e( 'End Membership Immediately', 'rcp' ); ?></option>
<option value="expire_term_end" <?php selected( $level->get_after_final_payment(), 'expire_term_end' ); ?>><?php _e( 'End Membership at End of Billing Period', 'rcp' ); ?></option>
</select>
<p class="description">
<?php _e( 'Action to take after the final payment has been received.', 'rcp'); ?>
<span alt="f223" class="rcp-help-tip dashicons dashicons-editor-help" title="<?php esc_attr_e( '<strong>Grant Lifetime Access</strong>: will update the member\'s expiration date to "none" to give them lifetime access to restricted content. <br/><br/><strong>End Membership Immediately</strong>: will make the user\'s membership expire immediately after the final payment is received and they will lose access to restricted content. <br/><br/><strong>End Membership at End of Billing Period</strong>: will allow the user to complete one more period after the final payment, after which their membership will expire. For example, if the membership duration is set to 1 month, the user will make their final payment then have access for 1 more month after that before expiring.', 'rcp' ); ?>"></span>
</p>
</td>
</tr>
<tr class="form-field">
<th scope="row" valign="top">
<label for="rcp-price"><?php _e( 'Price', 'rcp' ); ?></label>
</th>
<td>
<input type="text" id="rcp-price" name="price" value="<?php echo esc_attr( $level->get_price() ); ?>" pattern="^(\d+\.\d{1,2})|(\d+)$"/>
<p class="description"><?php _e( 'The price of this membership level. Enter 0 for free.', 'rcp' ); ?></p>
</td>
</tr>
<tr class="form-field">
<th scope="row" valign="top">
<label for="rcp-fee"><?php _e( 'Signup Fee', 'rcp' ); ?></label>
</th>
<td>
<input type="text" id="rcp-fee" name="fee" value="<?php echo esc_attr( $level->get_fee() ); ?>"/>
<p class="description"><?php _e( 'Optional signup fee to charge subscribers for the first billing cycle. Enter a negative number to give a discount on the first payment.', 'rcp' ); ?></p>
</td>
</tr>
<tr class="form-field">
<th scope="row" valign="top">
<label for="rcp-status"><?php _e( 'Status', 'rcp' ); ?></label>
</th>
<td>
<select name="status" id="rcp-status">
<option value="active" <?php selected( $level->get_status(), 'active' ); ?>><?php _e( 'Active', 'rcp' ); ?></option>
<option value="inactive" <?php selected( $level->get_status(), 'inactive' ); ?>><?php _e( 'Inactive', 'rcp' ); ?></option>
</select>
<p class="description">
<?php
printf(
__('Inactive membership levels do not appear on the %s shortcode page. Learn more about membership level statuses in <a href="%s" target="_blank">our documentation article</a>.', 'rcp'),
'[register_form]',
esc_url( 'https://docs.restrictcontentpro.com/article/2257-active-vs-inactive-membership-levels' )
);
?>
</p>
</td>
</tr>
<tr class="form-field">
<th scope="row" valign="top">
<label for="rcp-role"><?php _e( 'User Role', 'rcp' ); ?></label>
</th>
<td>
<select name="role" id="rcp-role">
<?php wp_dropdown_roles( $level->get_role() ); ?>
</select>
<p class="description"><?php _e( 'The user role given to the member after signing up.', 'rcp' ); ?></p>
</td>
</tr>
<?php do_action( 'rcp_edit_subscription_form', $level ); ?>
</tbody>
</table>
<p class="submit">
<input type="hidden" name="rcp-action" value="edit-subscription"/>
<input type="hidden" name="subscription_id" value="<?php echo absint( urldecode( $_GET['edit_subscription'] ) ); ?>"/>
<input type="submit" value="<?php _e( 'Update Membership Level', 'rcp' ); ?>" class="button-primary"/>
</p>
<?php wp_nonce_field( 'rcp_edit_level_nonce', 'rcp_edit_level_nonce' ); ?>
</form>

View File

@@ -0,0 +1 @@
<?php // Silence is golden.

View File

@@ -0,0 +1,210 @@
<?php
/**
* Membership Level Actions
*
* @package restrict-content-pro
* @subpackage Admin/Membership Actions
* @copyright Copyright (c) 2017, Restrict Content Pro
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
* @since 2.9
*/
// Exit if accessed directly
if ( ! defined( 'ABSPATH' ) ) exit;
/**
* Add a new membership level
*
* @since 2.9
* @return void
*/
function rcp_process_add_subscription_level() {
if ( ! wp_verify_nonce( $_POST['rcp_add_level_nonce'], 'rcp_add_level_nonce' ) ) {
wp_die( __( 'Nonce verification failed.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 403 ) );
}
if ( ! current_user_can( 'rcp_manage_levels' ) ) {
wp_die( __( 'You do not have permission to perform this action.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 403 ) );
}
if ( empty( $_POST['name'] ) ) {
rcp_log( 'Failed creating new membership level: empty membership name.', true );
$url = admin_url( 'admin.php?page=rcp-member-levels&rcp_message=level_missing_fields' );
wp_safe_redirect( esc_url_raw( $url ) );
exit;
}
$data = wp_unslash( $_POST );
// Disable payment plan if maximum renewals set to "Until Cancelled".
if ( ! empty( $data['maximum_renewals_setting'] ) && 'forever' == $data['maximum_renewals_setting'] ) {
$data['maximum_renewals'] = 0;
}
$level_id = rcp_add_membership_level( $data );
if ( $level_id && ! is_wp_error( $level_id ) ) {
$url = admin_url( 'admin.php?page=rcp-member-levels&rcp_message=level_added' );
} else {
if ( is_wp_error( $level_id ) ) {
$url = add_query_arg( 'rcp_message', urlencode( $level_id->get_error_code() ), 'admin.php?page=rcp-member-levels' );
} else {
$url = admin_url( 'admin.php?page=rcp-member-levels&rcp_message=level_not_added' );
}
}
wp_safe_redirect( $url );
exit;
}
add_action( 'rcp_action_add-level', 'rcp_process_add_subscription_level' );
/**
* Edit an existing membership level
*
* @since 2.9
* @return void
*/
function rcp_process_edit_subscription_level() {
if ( ! wp_verify_nonce( $_POST['rcp_edit_level_nonce'], 'rcp_edit_level_nonce' ) ) {
wp_die( __( 'Nonce verification failed.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 403 ) );
}
if ( ! current_user_can( 'rcp_manage_levels' ) ) {
wp_die( __( 'You do not have permission to perform this action.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 403 ) );
}
$data = wp_unslash( $_POST );
// Disable payment plan if maximum renewals set to "Until Cancelled".
if ( ! empty( $data['maximum_renewals_setting'] ) && 'forever' == $data['maximum_renewals_setting'] ) {
$data['maximum_renewals'] = 0;
}
$update = rcp_update_membership_level( absint( $data['subscription_id'] ), $data );
if ( $update && ! is_wp_error( $update ) ) {
$url = admin_url( 'admin.php?page=rcp-member-levels&rcp_message=level_updated' );
} else {
if ( is_wp_error( $update ) ) {
$url = add_query_arg( 'rcp_message', urlencode( $update->get_error_code() ), 'admin.php?page=rcp-member-levels' );
} else {
$url = admin_url( 'admin.php?page=rcp-member-levels&rcp_message=level_not_updated' );
}
}
wp_safe_redirect( $url );
exit;
}
add_action( 'rcp_action_edit-subscription', 'rcp_process_edit_subscription_level' );
/**
* Delete a membership level
*
* @since 2.9
* @return void
*/
function rcp_process_delete_subscription_level() {
if ( ! wp_verify_nonce( $_GET['_wpnonce'], 'rcp-delete-subscription-level' ) ) {
wp_die( __( 'Nonce verification failed.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 403 ) );
}
if ( ! current_user_can( 'rcp_manage_levels' ) ) {
wp_die( __( 'You do not have permission to perform this action.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 403 ) );
}
if ( ! isset( $_GET['level_id'] ) ) {
wp_die( __( 'Please choose a membership level.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 400 ) );
}
$level_id = absint( $_GET['level_id'] );
$memberships = rcp_get_memberships( array(
'status' => 'active',
'object_id' => $level_id
) );
// Cancel all active members of this membership level.
if ( ! empty( $memberships ) ) {
foreach ( $memberships as $membership ) {
/**
* @var RCP_Membership $membership
*/
$membership->cancel();
}
}
rcp_delete_membership_level( $level_id );
wp_safe_redirect( add_query_arg( 'rcp_message', 'level_deleted', 'admin.php?page=rcp-member-levels' ) );
exit;
}
add_action( 'rcp_action_delete_subscription', 'rcp_process_delete_subscription_level' );
/**
* Activate a membership level
*
* @since 2.9
* @return void
*/
function rcp_process_activate_subscription() {
if ( ! wp_verify_nonce( $_GET['_wpnonce'], 'rcp-activate-subscription-level' ) ) {
wp_die( __( 'Nonce verification failed.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 403 ) );
}
if ( ! current_user_can( 'rcp_manage_levels' ) ) {
wp_die( __( 'You do not have permission to perform this action.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 403 ) );
}
if ( ! isset( $_GET['level_id'] ) ) {
wp_die( __( 'Please choose a membership level.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 400 ) );
}
$level_id = absint( $_GET['level_id'] );
rcp_update_membership_level( $level_id, array( 'status' => 'active' ) );
rcp_log( sprintf( 'Successfully activated membership level #%d.', $level_id ) );
wp_safe_redirect( add_query_arg( 'rcp_message', 'level_activated', 'admin.php?page=rcp-member-levels' ) );
exit;
}
add_action( 'rcp_action_activate_subscription', 'rcp_process_activate_subscription' );
/**
* Deactivate a membership level
*
* @since 2.9
* @return void
*/
function rcp_process_deactivate_subscription() {
if ( ! wp_verify_nonce( $_GET['_wpnonce'], 'rcp-deactivate-subscription-level' ) ) {
wp_die( __( 'Nonce verification failed.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 403 ) );
}
if ( ! current_user_can( 'rcp_manage_levels' ) ) {
wp_die( __( 'You do not have permission to perform this action.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 403 ) );
}
if ( ! isset( $_GET['level_id'] ) ) {
wp_die( __( 'Please choose a membership level.', 'rcp' ), __( 'Error', 'rcp' ), array( 'response' => 400 ) );
}
$level_id = absint( $_GET['level_id'] );
rcp_update_membership_level( $level_id, array( 'status' => 'inactive' ) );
rcp_log( sprintf( 'Successfully deactivated membership level #%d.', $level_id ) );
wp_safe_redirect( add_query_arg( 'rcp_message', 'level_deactivated', 'admin.php?page=rcp-member-levels' ) );
exit;
}
add_action( 'rcp_action_deactivate_subscription', 'rcp_process_deactivate_subscription' );

View File

@@ -0,0 +1,209 @@
<?php
/**
* Membership Levels Page
*
* @package Restrict Content Pro
* @subpackage Admin/Membership Levels
* @copyright Copyright (c) 2020, Sandhills Development, LLC
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
*/
use RCP\Admin\Membership_Levels_Table;
/**
* Render membership levels page
*
* @return void
*/
function rcp_member_levels_page() {
include_once RCP_PLUGIN_DIR . 'core/includes/admin/subscriptions/class-membership-levels-table.php';
$table_class = new Membership_Levels_Table();
$table_class->prepare_items();
do_action( 'stellarwp/telemetry/restrict-content-pro/optin' );
do_action( 'stellarwp/telemetry/restrict-content/optin' );
?>
<div class="wrap">
<?php if(isset($_GET['edit_subscription'])) :
include('edit-subscription.php');
else : ?>
<h1><?php _e('Membership Levels', 'rcp'); ?></h1>
<form id="rcp-memberships-filter" method="GET" action="<?php echo esc_url( add_query_arg( 'page', 'rcp-member-levels', admin_url( 'admin.php' ) ) ); ?>">
<input type="hidden" name="page" value="rcp-member-levels"/>
<?php
$table_class->views();
$table_class->search_box( __( 'Search membership levels', 'rcp' ), 'rcp-membership-levels' );
$table_class->display();
?>
</form>
<?php do_action('rcp_levels_below_table'); ?>
<?php if( current_user_can( 'rcp_manage_levels' ) ) : ?>
<h2><?php _e('Add New Level', 'rcp'); ?></h2>
<form id="rcp-member-levels" action="" method="post">
<table class="form-table">
<tbody>
<tr class="form-field">
<th scope="row" valign="top">
<label for="rcp-name"><?php _e('Name', 'rcp'); ?></label>
</th>
<td>
<input type="text" id="rcp-name" name="name" value=""/>
<p class="description"><?php _e('The name of the membership level.', 'rcp'); ?></p>
</td>
</tr>
<tr class="form-field">
<th scope="row" valign="top">
<label for="rcp-description"><?php _e('Description', 'rcp'); ?></label>
</th>
<td>
<textarea id="rcp-description" name="description"></textarea>
<p class="description"><?php _e('Membership level description. This is shown on the registration form.', 'rcp'); ?></p>
</td>
</tr>
<tr class="form-field">
<th scope="row" valign="top">
<label for="rcp-level"><?php _e('Access Level', 'rcp'); ?></label>
</th>
<td>
<select id="rcp-level" name="level">
<?php
$access_levels = rcp_get_access_levels();
foreach( $access_levels as $access ) {
echo '<option value="' . $access . '">' . $access . '</option>';
}
?>
</select>
<p class="description">
<?php _e('Level of access this membership gives. Leave None for default or you are unsure what this is.', 'rcp'); ?>
<span alt="f223" class="rcp-help-tip dashicons dashicons-editor-help" title="<?php _e( '<strong>Access Level</strong>: refers to a tiered system where a member\'s ability to view content is determined by the access level assigned to their account. A member with an access level of 5 can view content assigned to access levels of 5 and lower, whereas a member with an access level of 4 can only view content assigned to levels of 4 and lower.', 'rcp' ); ?>"></span>
</p>
</td>
</tr>
<tr class="form-field">
<th scope="row" valign="top">
<label for="rcp-duration"><?php _e('Duration', 'rcp'); ?></label>
</th>
<td>
<input type="text" id="rcp-duration" name="duration" value="0"/>
<select name="duration_unit" id="rcp-duration-unit">
<option value="day"><?php _e('Day(s)', 'rcp'); ?></option>
<option value="month"><?php _e('Month(s)', 'rcp'); ?></option>
<option value="year"><?php _e('Year(s)', 'rcp'); ?></option>
</select>
<p class="description">
<?php _e('Length of time for this membership level. Enter 0 for unlimited.', 'rcp'); ?>
<span alt="f223" class="rcp-help-tip dashicons dashicons-editor-help" title="<?php _e( '<strong>Example</strong>: setting this to 1 month would make memberships last 1 month, after which they will renew automatically or be marked as expired.', 'rcp' ); ?>"></span>
</p>
</td>
</tr>
<tr class="form-field">
<th scope="row" valign="top">
<label for="rcp-maximum-renewals-setting"><?php _e( 'Maximum Renewals', 'rcp' ); ?></label>
</th>
<td>
<select name="maximum_renewals_setting" id="rcp-maximum-renewals-setting">
<option value="forever"><?php _e( 'Until Cancelled', 'rcp' ); ?></option>
<option value="specific"><?php _e( 'Specific Number', 'rcp' ); ?></option>
</select>
<label for="rcp-maximum-renewals" class="screen-reader-text"><?php _e( 'Enter the maximum number of renewals', 'rcp' ); ?></label>
<input type="number" id="rcp-maximum-renewals" name="maximum_renewals" value="0" style="display:none;"/>
<p class="description">
<?php _e( 'Number of renewals to process after the first payment.', 'rcp' ); ?>
<span alt="f223" class="rcp-help-tip dashicons dashicons-editor-help" title="<?php esc_attr_e( '<strong>Until Cancelled</strong>: will continue billing the member indefinitely, or until they cancel their membership. <br/><br/><strong>Specific Number</strong> will allow you to enter the number of additional times you wish to bill the customer after their first payment. If you enter "3", the member will be billed once immediately when they sign up, then 3 more times after that. Then billing will stop automatically.', 'rcp' ); ?>"></span>
</p>
</td>
</tr>
<tr class="form-field" style="display: none;">
<th scope="row" valign="top">
<label for="rcp-after-final-payment"><?php _e( 'After Final Payment', 'rcp' ); ?></label>
</th>
<td>
<select name="after_final_payment" id="rcp-after-final-payment">
<option value="lifetime"><?php _e( 'Grant Lifetime Access', 'rcp' ); ?></option>
<option value="expire_immediately"><?php _e( 'End Membership Immediately', 'rcp' ); ?></option>
<option value="expire_term_end"><?php _e( 'End Membership at End of Billing Period', 'rcp' ); ?></option>
</select>
<p class="description">
<?php _e( 'Action to take after the final payment has been received.', 'rcp'); ?>
<span alt="f223" class="rcp-help-tip dashicons dashicons-editor-help" title="<?php esc_attr_e( '<strong>Grant Lifetime Access</strong>: will update the member\'s expiration date to "none" to give them lifetime access to restricted content. <br/><br/><strong>End Membership Immediately</strong>: will make the user\'s membership expire immediately after the final payment is received and they will lose access to restricted content. <br/><br/><strong>End Membership at End of Billing Period</strong>: will allow the user to complete one more period after the final payment, after which their membership will expire. For example, if the membership duration is set to 1 month, the user will make their final payment then have access for 1 more month after that before expiring.', 'rcp' ); ?>"></span>
</p>
</td>
</tr>
<?php
/**
* Action to add the free trial input fields
*/
do_action( 'rcp_new_subscription_after_set_trial_duration' );
?>
<tr class="form-field">
<th scope="row" valign="top">
<label for="rcp-price"><?php _e('Price', 'rcp'); ?></label>
</th>
<td>
<input type="text" id="rcp-price" name="price" value="0" pattern="^(\d+\.\d{1,2})|(\d+)$"/>
<p class="description">
<?php _e('The price of this membership level. Enter 0 for free.', 'rcp'); ?>
<span alt="f223" class="rcp-help-tip dashicons dashicons-editor-help" title="<?php _e( 'This price refers to the amount paid per duration period. For example, if duration period is set to 1 month, this would be the amount charged each month.', 'rcp' ); ?>"></span>
</p>
</td>
</tr>
<tr class="form-field">
<th scope="row" valign="top">
<label for="rcp-fee"><?php _e('Signup Fee', 'rcp'); ?></label>
</th>
<td>
<input type="text" id="rcp-fee" name="fee" value="0"/>
<p class="description"><?php _e('Optional signup fee to charge subscribers for the first billing cycle. Enter a negative number to give a discount on the first payment.', 'rcp'); ?></p>
</td>
</tr>
<tr class="form-field">
<th scope="row" valign="top">
<label for="rcp-status"><?php _e('Status', 'rcp'); ?></label>
</th>
<td>
<select name="status" id="rcp-status">
<option value="active"><?php _e('Active', 'rcp'); ?></option>
<option value="inactive"><?php _e('Inactive', 'rcp'); ?></option>
</select>
<p class="description">
<?php
printf(
__('Inactive membership levels do not appear on the %s shortcode page. Learn more about membership level statuses in <a href="%s" target="_blank">our documentation article</a>.', 'rcp'),
'[register_form]',
esc_url( 'https://docs.restrictcontentpro.com/article/2257-active-vs-inactive-membership-levels' )
);
?>
</p>
</td>
</tr>
<tr class="form-field">
<th scope="row" valign="top">
<label for="rcp-role"><?php _e( 'User Role', 'rcp' ); ?></label>
</th>
<td>
<select name="role" id="rcp-role">
<?php wp_dropdown_roles( 'subscriber' ); ?>
</select>
<p class="description"><?php _e( 'The user role given to the member after signing up.', 'rcp' ); ?></p>
</td>
</tr>
<?php do_action( 'rcp_add_subscription_form' ); ?>
</tbody>
</table>
<p class="submit">
<input type="hidden" name="rcp-action" value="add-level"/>
<input type="submit" value="<?php _e('Add Membership Level', 'rcp'); ?>" class="button-primary"/>
</p>
<?php wp_nonce_field( 'rcp_add_level_nonce', 'rcp_add_level_nonce' ); ?>
</form>
<?php endif; ?>
<?php endif; ?>
</div><!--end wrap-->
<?php
}

View File

@@ -0,0 +1,181 @@
<?php
/**
* Adds custom fields to category edit screens
*
* These options are for restricting content within categories
*
* @package Restrict Content Pro
* @subpackage Admin/Categories
* @copyright Copyright (c) 2017, Pippin Williamson
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
* @since 2.0
*/
// Exit if accessed directly
if ( ! defined( 'ABSPATH' ) ) exit;
/**
* Setup actions for taxonomy restricted fields
*
* @since 2.5
* @return void
*/
function rcp_setup_taxonomy_edit_fields() {
$taxonomies = rcp_get_restricted_taxonomies();
foreach( $taxonomies as $taxonomy ) {
add_action( "{$taxonomy}_edit_form_fields", 'rcp_term_edit_meta_fields' );
add_action( "{$taxonomy}_add_form_fields", 'rcp_term_add_meta_fields' );
}
}
add_action( 'admin_init', 'rcp_setup_taxonomy_edit_fields' );
/**
* Add restriction options to the edit term page
*
* @access public
* @since 2.0
* @return void
*/
function rcp_term_edit_meta_fields( $term ) {
// retrieve the existing value(s) for this meta field. This returns an array
$term_meta = rcp_get_term_restrictions( $term->term_id );
$access_level = isset( $term_meta['access_level'] ) ? absint( $term_meta['access_level'] ) : 0;
$subscription_levels = isset( $term_meta['subscriptions'] ) ? array_map( 'absint', $term_meta['subscriptions'] ) : array();
?>
<tr>
<th scope="row"><?php _e( 'Paid Only?', 'rcp' ); ?></th>
<td>
<label for="rcp_category_meta[paid_only]">
<input type="checkbox" name="rcp_category_meta[paid_only]" id="rcp_category_meta[paid_only]" value="1"<?php checked( true, isset( $term_meta['paid_only'] ) ); ?>>
<span class="description"><?php _e( 'Restrict items in this category to paid subscribers only?', 'rcp' ); ?></span>
</label>
</td>
</tr>
<tr>
<th scope="row"><?php _e( 'Access Level', 'rcp' ); ?></th>
<td>
<label for="rcp_category_meta[access_level]">
<select name="rcp_category_meta[access_level]" id="rcp_category_meta[access_level]">
<?php foreach( rcp_get_access_levels() as $level ) : ?>
<option value="<?php echo esc_attr( $level ); ?>"<?php selected( $level, $access_level ); ?>><?php echo $level; ?></option>
<?php endforeach; ?>
</select>
<span class="description"><?php _e( 'Access level required to view content in this category.', 'rcp' ); ?></span>
</label>
</td>
</tr>
<tr>
<th scope="row"><?php _e( 'Membership Levels', 'rcp' ); ?></th>
<td>
<?php foreach( rcp_get_membership_levels( array( 'number' => 999 ) ) as $level ) : ?>
<label for="rcp_category_meta[subscriptions][<?php echo esc_attr( $level->get_id() ); ?>]">
<input type="checkbox" name="rcp_category_meta[subscriptions][<?php echo esc_attr( $level->get_id() ); ?>]" id="rcp_category_meta[subscriptions][<?php echo esc_attr( $level->get_id() ); ?>]" value="1"<?php checked( true, in_array( $level->get_id(), $subscription_levels ) ); ?>>
<?php echo esc_html( $level->get_name() ); ?>
</label><br/>
<?php endforeach; ?>
<span class="description"><?php _e( 'Membership levels allowed to view content in this category. Leave unchecked for all.', 'rcp' ); ?></span>
<?php wp_nonce_field( 'rcp_edit_term', 'rcp_edit_term' ); ?>
</td>
</tr>
<?php
}
/**
* Add restriction options to the add term page
*
* @param string $taxonomy
*
* @access public
* @since 2.7
* @return void
*/
function rcp_term_add_meta_fields( $taxonomy ) {
?>
<div class="form-field">
<h2><?php _e( 'Restriction Options', 'rcp' ); ?></h2>
<label for="rcp_category_meta[paid_only]">
<p><?php _e( 'Paid Only?', 'rcp' ); ?></p>
<input type="checkbox" name="rcp_category_meta[paid_only]" id="rcp_category_meta[paid_only]" value="1">
<span class="description"><?php _e( 'Restrict items in this category to paid subscribers only?', 'rcp' ); ?></span>
</label>
</div>
<div class="form-field">
<label for="rcp_category_meta[access_level]">
<p><?php _e( 'Access Level', 'rcp' ); ?></p>
<select name="rcp_category_meta[access_level]" id="rcp_category_meta[access_level]">
<?php foreach( rcp_get_access_levels() as $level ) : ?>
<option value="<?php echo esc_attr( $level ); ?>"><?php echo $level; ?></option>
<?php endforeach; ?>
</select>
<span class="description"><?php _e( 'Access level required to view content in this category.', 'rcp' ); ?></span>
</label>
</div>
<div class="form-field">
<p><?php _e( 'Membership Levels', 'rcp' ); ?></p>
<?php foreach( rcp_get_membership_levels( array( 'number' => 999 ) ) as $level ) : ?>
<label for="rcp_category_meta[subscriptions][<?php echo esc_attr( $level->get_id() ); ?>]">
<input type="checkbox" name="rcp_category_meta[subscriptions][<?php echo esc_attr( $level->get_id() ); ?>]" id="rcp_category_meta[subscriptions][<?php echo esc_attr( $level->get_id() ); ?>]" value="1"/>
<?php echo esc_html( $level->get_name() ); ?>
</label>
<?php endforeach; ?>
<span class="description"><?php _e( 'Membership levels allowed to view content in this category. Leave unchecked for all.', 'rcp' ); ?></span>
<?php wp_nonce_field( 'rcp_edit_term', 'rcp_edit_term' ); ?>
</div>
<?php
}
/**
* Save our custom term meta
*
* @param int $term_id Term ID.
* @param int $tt_id Term taxonomy ID.
* @param string $taxonomy Taxonomy slug.
*
* @access public
* @since 2.0
* @return void
*/
function rcp_save_term_meta( $term_id, $tt_id, $taxonomy ) {
if ( empty( $_POST['rcp_edit_term'] ) || ! wp_verify_nonce( $_POST['rcp_edit_term'], 'rcp_edit_term' ) ) {
return;
}
$restricted_taxonomies = rcp_get_restricted_taxonomies();
if ( ! in_array( $taxonomy, $restricted_taxonomies ) ) {
return;
}
$fields = ! empty( $_POST['rcp_category_meta'] ) ? $_POST['rcp_category_meta'] : array();
if( ! empty( $_POST['rcp_category_meta']['subscriptions'] ) ) {
$fields['subscriptions'] = array_map( 'absint', array_keys( $_POST['rcp_category_meta']['subscriptions'] ) );
}
if( ! empty( $fields['access_level'] ) ) {
if( 'None' == $fields['access_level'] ) {
unset( $fields['access_level'] );
}
}
if ( function_exists( 'update_term_meta' ) ) {
if ( ! empty( $fields ) ) {
update_term_meta( $term_id, 'rcp_restricted_meta', $fields );
} else {
delete_term_meta( $term_id, 'rcp_restricted_meta' );
}
// remove deprecated data
delete_option( "rcp_category_meta_$term_id" );
} else {
// fallback to older method of handling term meta
update_option( "rcp_category_meta_$term_id", $fields );
}
}
add_action( 'edited_term', 'rcp_save_term_meta', 10, 3 );
add_action( 'created_term', 'rcp_save_term_meta', 10, 3 );

View File

@@ -0,0 +1 @@
<?php // Silence is golden.

View File

@@ -0,0 +1,421 @@
<?php
/**
* System Info
*
* @package Restrict Content Pro
* @subpackage Admin/System Info
* @copyright Copyright (c) 2017, Restrict Content Pro
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
*/
use RCP\Membership_Level;
/**
* Displays the system info report
*
* @since 2.5
* @return string $return The compiled system info report.
*/
function rcp_tools_system_info_report() {
global $rcp_options, $wpdb;
$restrict_content_obj = restrict_content_pro();
// Get theme info
$theme_data = wp_get_theme();
$theme = $theme_data->Name . ' ' . $theme_data->Version;
$return = '### Begin System Info ###' . "\n\n";
// Start with the basics...
$return .= '-- Site Info' . "\n\n";
$return .= 'Site URL: ' . site_url() . "\n";
$return .= 'Home URL: ' . home_url() . "\n";
$return .= 'Multisite: ' . ( is_multisite() ? 'Yes' : 'No' ) . "\n";
$return = apply_filters( 'rcp_system_info_after_site_info', $return );
// WordPress configuration
$return .= "\n" . '-- WordPress Configuration' . "\n\n";
$return .= 'Version: ' . get_bloginfo( 'version' ) . "\n";
$return .= 'Language: ' . get_locale() . "\n";
$return .= 'Permalink Structure: ' . ( get_option( 'permalink_structure' ) ? get_option( 'permalink_structure' ) : 'Default' ) . "\n";
$return .= 'Active Theme: ' . $theme . "\n";
$return .= 'Show On Front: ' . get_option( 'show_on_front' ) . "\n";
// Only show page specs if frontpage is set to 'page'
if( get_option( 'show_on_front' ) === 'page' ) {
$front_page_id = get_option( 'page_on_front' );
$blog_page_id = get_option( 'page_for_posts' );
$return .= 'Page On Front: ' . ( $front_page_id != 0 ? get_the_title( $front_page_id ) . ' (#' . $front_page_id . ')' : 'Unset' ) . "\n";
$return .= 'Page For Posts: ' . ( $blog_page_id != 0 ? get_the_title( $blog_page_id ) . ' (#' . $blog_page_id . ')' : 'Unset' ) . "\n";
}
$return .= 'ABSPATH: ' . ABSPATH . "\n";
$return .= 'Table Prefix: ' . 'Length: ' . strlen( $wpdb->prefix ) . ' Status: ' . ( strlen( $wpdb->prefix ) > 16 ? 'ERROR: Too long' : 'Acceptable' ) . "\n";
$return .= 'WP_DEBUG: ' . ( defined( 'WP_DEBUG' ) ? WP_DEBUG ? 'Enabled' : 'Disabled' : 'Not set' ) . "\n";
$return .= 'Memory Limit: ' . WP_MEMORY_LIMIT . "\n";
$return .= 'Registered Post Stati: ' . implode( ', ', get_post_stati() ) . "\n";
$return .= 'Date Format: ' . sprintf( '%s (%s)', get_option( 'date_format' ), date( get_option( 'date_format' ), current_time( 'timestamp' ) ) ) . "\n";
$return .= 'Time Format: ' . sprintf( '%s (%s)', get_option( 'time_format' ), date( get_option( 'time_format' ), current_time( 'timestamp' ) ) ) . "\n";
$return .= 'Timezone: ' . get_option( 'timezone_string' ) . "\n";
$return .= 'Membership: ' . ( get_option( 'users_can_register' ) ? 'Enabled' : 'Disabled' ) . "\n";
$return .= 'Default Role: ' . get_option( 'default_role' ) . "\n";
$return = apply_filters( 'rcp_system_info_after_wordpress_config', $return );
// RCP Config
$auto_renew_options = array( 1 => 'Always auto renew', 2 => 'Never auto renew', 3 => 'Let customer choose whether to auto renew' );
$restrict_content_version = ! $restrict_content_obj->is_pro() ? RCF_VERSION : RCP_PLUGIN_VERSION;
$return .= "\n" . '-- RCP Configuration' . "\n\n";
$return .= 'Version: ' . $restrict_content_version . "\n";
$return .= 'Upgraded on: ' . sprintf( '%s from %s', get_option( 'rcp_version_upgraded_on', '(unknown date)' ), get_option( 'rcp_version_upgraded_from', 0 ) ) . "\n";
$return .= 'License Key: ' . ( ! empty( $rcp_options['license_key'] ) ? $rcp_options['license_key'] . "\n" : "Not set\n" );
$return .= 'Multiple Memberships: ' . ( rcp_multiple_memberships_enabled() ? "Enabled\n" : "Disabled\n" );
$return .= 'Auto Renew: ' . ( ! empty( $rcp_options['auto_renew'] ) && array_key_exists( $rcp_options['auto_renew'], $auto_renew_options ) ? $auto_renew_options[$rcp_options['auto_renew']] . "\n" : "Invalid Configuration\n" );
$return .= 'Currency: ' . ( ! empty( $rcp_options['currency'] ) ? $rcp_options['currency'] . "\n" : "Invalid Configuration\n" );
$return .= 'Currency Position: ' . ( ! empty( $rcp_options['currency_position'] ) ? $rcp_options['currency_position'] . "\n" : "Invalid Configuration\n" );
$return .= 'Sandbox Mode: ' . ( rcp_is_sandbox() ? "True" . "\n" : "False\n" );
$return = apply_filters( 'rcp_system_info_after_rcp_config', $return );
// RCP pages
$return .= "\n" . '-- RCP Page Configuration' . "\n\n";
$return .= 'Registration Page: ' . ( ! empty( $rcp_options['registration_page'] ) ? get_permalink( $rcp_options['registration_page'] ) . "\n" : "Unset\n" );
$return .= 'Success Page: ' . ( ! empty( $rcp_options['redirect'] ) ? get_permalink( $rcp_options['redirect'] ) . "\n" : "Unset\n" );
$return .= 'Account Page: ' . ( ! empty( $rcp_options['account_page'] ) ? get_permalink( $rcp_options['account_page'] ) . "\n" : "Unset\n" );
$return .= 'Edit Profile Page: ' . ( ! empty( $rcp_options['edit_profile'] ) ? get_permalink( $rcp_options['edit_profile'] ) . "\n" : "Unset\n" );
$return .= 'Update Billing Card Page: ' . ( ! empty( $rcp_options['update_card'] ) ? get_permalink( $rcp_options['update_card'] ) . "\n" : "Unset\n" );
$return = apply_filters( 'rcp_system_info_after_rcp_pages', $return );
// RCP gateways
$return .= "\n" . '-- RCP Enabled Gateways' . "\n\n";
$gateways = new RCP_Payment_Gateways;
if( $gateways->enabled_gateways ) {
foreach( $gateways->enabled_gateways as $key => $gateway ) {
if ( ! is_array( $gateway ) ) {
$return .= $key . "\n";
continue;
}
$test_api = 'Not Set';
$live_api = 'Not Set';
$additional_gateway_info = '';
switch ( $key ) {
case 'manual' :
$test_api = $live_api = 'n/a';
break;
case 'paypal' :
case 'paypal_express' :
case 'paypal_pro' :
if ( ! empty( $rcp_options['test_paypal_api_username'] ) && ! empty( $rcp_options['test_paypal_api_password'] ) && ! empty( $rcp_options['test_paypal_api_signature'] ) ) {
$test_api = 'Set';
}
if ( ! empty( $rcp_options['live_paypal_api_username'] ) && ! empty( $rcp_options['live_paypal_api_password'] ) && ! empty( $rcp_options['live_paypal_api_signature'] ) ) {
$live_api = 'Set';
}
break;
case 'stripe' :
case 'stripe_checkout' :
if ( ! empty( $rcp_options['stripe_test_secret'] ) && ! empty( $rcp_options['stripe_test_publishable'] ) ) {
$test_api = 'Set';
}
if ( ! empty( $rcp_options['stripe_live_secret'] ) && ! empty( $rcp_options['stripe_live_publishable'] ) ) {
$live_api = 'Set';
}
$additional_gateway_info .= ' Statement Descriptor: ' . ( ! empty( $rcp_options['statement_descriptor'] ) ? $rcp_options['statement_descriptor'] . "\n" : "\n" );
$additional_gateway_info .= ' Statement Suffix: ' . ( ! empty( $rcp_options['statement_descriptor_suffix'] ) ? $rcp_options['statement_descriptor_suffix'] . "\n" : "\n" );
break;
case 'twocheckout' :
if ( ! empty( $rcp_options['twocheckout_test_private'] ) && ! empty( $rcp_options['twocheckout_test_publishable'] ) && ! empty( $rcp_options['twocheckout_test_seller_id'] ) ) {
$test_api = 'Set';
}
if ( ! empty( $rcp_options['twocheckout_live_private'] ) && ! empty( $rcp_options['twocheckout_live_publishable'] ) && ! empty( $rcp_options['twocheckout_live_seller_id'] ) ) {
$live_api = 'Set';
}
break;
case 'authorizenet' :
if ( ! empty( $rcp_options['authorize_test_api_login'] ) && ! empty( $rcp_options['authorize_test_txn_key'] ) ) {
$test_api = 'Set';
}
if ( ! empty( $rcp_options['authorize_api_login'] ) && ! empty( $rcp_options['authorize_txn_key'] ) ) {
$live_api = 'Set';
}
break;
case 'braintree' :
if ( ! empty( $rcp_options['braintree_sandbox_merchantId'] ) && ! empty( $rcp_options['braintree_sandbox_publicKey'] ) && ! empty( $rcp_options['braintree_sandbox_privateKey'] ) && ! empty( $rcp_options['braintree_sandbox_encryptionKey'] ) ) {
$test_api = 'Set';
}
if ( ! empty( $rcp_options['braintree_live_merchantId'] ) && ! empty( $rcp_options['braintree_live_publicKey'] ) && ! empty( $rcp_options['braintree_live_privateKey'] ) && ! empty( $rcp_options['braintree_live_encryptionKey'] ) ) {
$live_api = 'Set';
}
break;
}
$return .= str_pad( $gateway['admin_label'] . ' (' . $key . '): ', 35 ) . sprintf( 'Test API Keys: %s; Live API Keys: %s', $test_api, $live_api ) . "\n";
$return .= $additional_gateway_info;
}
} else {
$return .= 'None' . "\n";
}
$return = apply_filters( 'rcp_system_info_after_rcp_gateways', $return );
// RCP membership levels
$return .= "\n" . '-- RCP Membership Levels' . "\n\n";
$levels = rcp_get_membership_levels( array( 'number' => 999 ) );
if ( ! empty( $levels ) ) {
foreach ( $levels as $level ) {
$return .= str_pad( $level->get_name() . ':', 40 ) . sprintf(
'%s; ID: %d; Price: %s; Fee: %s; Duration: %s %s; Trial: %s %s; Access Level: %s; Role: %s; Maximum Renewals: %d (%s)',
$level->get_status(),
$level->get_id(),
$level->get_price(),
$level->get_fee(),
$level->get_duration(),
$level->get_duration_unit(),
$level->get_trial_duration(),
$level->get_trial_duration_unit(),
$level->get_access_level(),
$level->get_role(),
$level->get_maximum_renewals(),
$level->get_after_final_payment()
) . "\n";
}
}
$return = apply_filters( 'rcp_system_info_after_rcp_subscription_levels', $return );
// RCP Misc Settings
$auto_add_level = ! empty( $rcp_options['auto_add_users'] ) ? rcp_get_membership_level( $rcp_options['auto_add_users'] ) : false;
$return .= "\n" . '-- RCP Misc Settings' . "\n\n";
$return .= 'Hide Restricted Posts: ' . ( ! empty( $rcp_options['hide_premium'] ) ? "True\n" : "False\n" );
$return .= 'Redirect Page: ' . ( ! empty( $rcp_options['redirect_from_premium'] ) ? get_permalink( $rcp_options['redirect_from_premium'] ) . "\n" : "Unset\n" );
$return .= 'Redirect Default Login URL ' . ( ! empty( $rcp_options['hijack_login_url'] ) ? "True\n" : "False\n" );
$return .= 'Login Page: ' . ( ! empty( $rcp_options['login_redirect'] ) ? get_permalink( $rcp_options['login_redirect'] ) . "\n" : "Unset\n" );
$return .= 'Auto Add Users To Membership: ' . ( $auto_add_level instanceof Membership_Level ? $auto_add_level->get_name() . ' (ID #' . $auto_add_level->get_id() . ")\n" : "None\n" );
$return .= 'Content Excerpts: ' . ( ! empty( $rcp_options['content_excerpts'] ) ? ucwords( $rcp_options['content_excerpts'] ) : 'Individual' ) . "\n";
$return .= 'Discount Signup Fees ' . ( ! empty( $rcp_options['discount_fees'] ) ? "Yes\n" : "No\n" );
$return .= 'Prevent Account Sharing: ' . ( ! empty( $rcp_options['no_login_sharing'] ) ? "True\n" : "False\n" );
$return .= 'Disable WordPress Toolbar ' . ( ! empty( $rcp_options['disable_toolbar'] ) ? "True\n" : "False\n" );
$return .= 'Disable Form CSS: ' . ( ! empty( $rcp_options['disable_css'] ) ? "True\n" : "False\n" );
$return .= 'Enable reCaptcha: ' . ( ! empty( $rcp_options['enable_recaptcha'] ) ? "True\n" : "False\n" );
$return .= 'reCaptcha Site Key: ' . ( ! empty( $rcp_options['recaptcha_public_key'] ) ? "Set\n" : "Unset\n" );
$return .= 'reCaptcha Secret Key: ' . ( ! empty( $rcp_options['recaptcha_private_key'] ) ? "Set\n" : "Unset\n" );
$return .= 'Enable Debug Mode: ' . ( ! empty( $rcp_options['debug_mode'] ) ? "True\n" : "False\n" );
$return .= 'Remove Data on Uninstall: ' . ( ! empty( $rcp_options['remove_data_on_uninstall'] ) ? "True\n" : "False\n" );
$return .= 'Switch Free Subscriptions: ' . ( ! empty( $rcp_options['disable_trial_free_subs'] ) ? "True\n" : "False\n" );
$return .= 'Opt Into Beta: ' . ( ! empty( $rcp_options['show_beta_updates'] ) ? "True\n" : "False\n" );
$return .= 'Proration: ' . ( ! apply_filters( 'rcp_disable_prorate_credit', false, get_current_user_id() ) ? "Enabled\n" : "Disabled\n" );
$return = apply_filters( 'rcp_system_info_after_rcp_misc_settings', $return );
// RCP Email Settings
$email_verification = isset( $rcp_options['email_verification'] ) ? ucwords( $rcp_options['email_verification'] ) : 'Off';
$return .= "\n" . '-- RCP Email Settings' . "\n\n";
$return .= 'RCP_DISABLE_EMAILS Constant: ' . sprintf( 'Status: %s', ( defined( 'RCP_DISABLE_EMAILS' ) ) ? ( RCP_DISABLE_EMAILS ? 'True' : 'False' ) : 'Not Set' ) . "\n";
$return .= 'Email Verification: ' . sprintf( 'Status: %s; Subject: %s; Body: %s', $email_verification, ( ! empty( $rcp_options['verification_subject'] ) ? 'Set' : 'Not Set' ), ( ! empty( $rcp_options['verification_email'] ) ? 'Set' : 'Not Set' ) ) . "\n";
$return .= 'Active Subscription (member): ' . sprintf( 'Status: %s; Subject: %s; Body: %s', ( ! empty( $rcp_options['disable_active_email'] ) ? 'Disabled' : 'Enabled' ), ( ! empty( $rcp_options['active_subject'] ) ? 'Set' : 'Not Set' ), ( ! empty( $rcp_options['active_email'] ) ? 'Set' : 'Not Set' ) ) . "\n";
$return .= 'Active Subscription (admin): ' . sprintf( 'Status: %s; Subject: %s; Body: %s', ( ! empty( $rcp_options['disable_active_email_admin'] ) ? 'Disabled' : 'Enabled' ), ( ! empty( $rcp_options['active_subject_admin'] ) ? 'Set' : 'Not Set' ), ( ! empty( $rcp_options['active_email_admin'] ) ? 'Set' : 'Not Set' ) ) . "\n";
$return .= 'Cancelled Subscription (member): ' . sprintf( 'Status: %s; Subject: %s; Body: %s', ( ! empty( $rcp_options['disable_cancelled_email'] ) ? 'Disabled' : 'Enabled' ), ( ! empty( $rcp_options['cancelled_subject'] ) ? 'Set' : 'Not Set' ), ( ! empty( $rcp_options['cancelled_email'] ) ? 'Set' : 'Not Set' ) ) . "\n";
$return .= 'Cancelled Subscription (admin): ' . sprintf( 'Status: %s; Subject: %s; Body: %s', ( ! empty( $rcp_options['disable_cancelled_email_admin'] ) ? 'Disabled' : 'Enabled' ), ( ! empty( $rcp_options['cancelled_subject_admin'] ) ? 'Set' : 'Not Set' ), ( ! empty( $rcp_options['cancelled_email_admin'] ) ? 'Set' : 'Not Set' ) ) . "\n";
$return .= 'Expired Subscription (member): ' . sprintf( 'Status: %s; Subject: %s; Body: %s', ( ! empty( $rcp_options['disable_expired_email'] ) ? 'Disabled' : 'Enabled' ), ( ! empty( $rcp_options['expired_subject'] ) ? 'Set' : 'Not Set' ), ( ! empty( $rcp_options['expired_email'] ) ? 'Set' : 'Not Set' ) ) . "\n";
$return .= 'Expired Subscription (admin): ' . sprintf( 'Status: %s; Subject: %s; Body: %s', ( ! empty( $rcp_options['disable_expired_email_admin'] ) ? 'Disabled' : 'Enabled' ), ( ! empty( $rcp_options['expired_subject_admin'] ) ? 'Set' : 'Not Set' ), ( ! empty( $rcp_options['expired_email_admin'] ) ? 'Set' : 'Not Set' ) ) . "\n";
$return .= 'Free Subscription (member): ' . sprintf( 'Status: %s; Subject: %s; Body: %s', ( ! empty( $rcp_options['disable_free_email'] ) ? 'Disabled' : 'Enabled' ), ( ! empty( $rcp_options['free_subject'] ) ? 'Set' : 'Not Set' ), ( ! empty( $rcp_options['free_email'] ) ? 'Set' : 'Not Set' ) ) . "\n";
$return .= 'Free Subscription (admin): ' . sprintf( 'Status: %s; Subject: %s; Body: %s', ( ! empty( $rcp_options['disable_free_email_admin'] ) ? 'Disabled' : 'Enabled' ), ( ! empty( $rcp_options['free_subject_admin'] ) ? 'Set' : 'Not Set' ), ( ! empty( $rcp_options['free_email_admin'] ) ? 'Set' : 'Not Set' ) ) . "\n";
$return .= 'Trial Subscription (member): ' . sprintf( 'Status: %s; Subject: %s; Body: %s', ( ! empty( $rcp_options['disable_trial_email'] ) ? 'Disabled' : 'Enabled' ), ( ! empty( $rcp_options['trial_subject'] ) ? 'Set' : 'Not Set' ), ( ! empty( $rcp_options['trial_email'] ) ? 'Set' : 'Not Set' ) ) . "\n";
$return .= 'Trial Subscription (admin): ' . sprintf( 'Status: %s; Subject: %s; Body: %s', ( ! empty( $rcp_options['disable_trial_email_admin'] ) ? 'Disabled' : 'Enabled' ), ( ! empty( $rcp_options['trial_subject_admin'] ) ? 'Set' : 'Not Set' ), ( ! empty( $rcp_options['trial_email_admin'] ) ? 'Set' : 'Not Set' ) ) . "\n";
$return .= 'Payment Received (member): ' . sprintf( 'Status: %s; Subject: %s; Body: %s', ( ! empty( $rcp_options['disable_payment_received_email'] ) ? 'Disabled' : 'Enabled' ), ( ! empty( $rcp_options['payment_received_subject'] ) ? 'Set' : 'Not Set' ), ( ! empty( $rcp_options['payment_received_email'] ) ? 'Set' : 'Not Set' ) ) . "\n";
$return .= 'Renewal Payment Failed (member): ' . sprintf( 'Status: %s; Subject: %s; Body: %s', ( ! empty( $rcp_options['disable_renewal_payment_failed_email'] ) ? 'Disabled' : 'Enabled' ), ( ! empty( $rcp_options['renewal_payment_failed_subject'] ) ? 'Set' : 'Not Set' ), ( ! empty( $rcp_options['renewal_payment_failed_email'] ) ? 'Set' : 'Not Set' ) ) . "\n";
$return .= 'New User Notifications: ' . ( ! empty( $rcp_options['disable_new_user_notices'] ) ? 'Disabled' : 'Enabled' ) . "\n";
$return = apply_filters( 'rcp_system_info_after_rcp_email_settings', $return );
// RCP Email Reminder Settings
$return .= "\n" . '-- RCP Email Reminders' . "\n\n";
$reminders = new RCP_Reminders();
$notices = $reminders->get_notices();
if ( ! empty( $notices ) ) {
foreach ( $notices as $notice ) {
$return .= str_pad( ucwords( $notice['type'] ) . ' ' . $notice['send_period'], 26 ) . sprintf( 'Status: %s; Subject: %s; Body: %s', ( ! empty( $notice['enabled'] ) ? 'Enabled' : 'Disabled' ), ( ! empty( $notice['subject'] ) ? 'Set' : 'Not Set' ), ( ! empty( $notice['message'] ) ? 'Set' : 'Not Set' ) ) . "\n";
}
} else {
$return .= "None\n";
}
$return = apply_filters( 'rcp_system_info_after_rcp_reminder_settings', $return );
// Database
$return .= "\n" . '-- Database' . "\n\n";
foreach ( restrict_content_pro()->components as $component_key => $component ) {
$table = $component->get_interface( 'table' );
if ( $table instanceof RCP\Database\Table ) {
$needs_upgrade = $table->needs_upgrade() ? ' - NEEDS UPGRADE' : '';
$return .= str_pad( sprintf( '%s version:', $component_key ), 40 ) . $table->get_version() . $needs_upgrade . "\n";
}
$integrity = 'unknown';
$schema = $component->get_interface( 'schema' );
if ( $schema instanceof RCP\Database\Schema && $table instanceof RCP\Database\Table ) {
$integrity = 'VALID';
$missing = array();
foreach ( $schema->columns as $column ) {
if ( ! $column instanceof RCP\Database\Column ) {
continue;
}
if ( ! $table->column_exists( $column->name ) ) {
$missing[] = $column->name;
}
}
if ( ! empty( $missing ) ) {
$integrity = 'MISSING COLUMNS: ' . implode( ', ', $missing );
}
}
$return .= str_pad( sprintf( '%s schema:', $component_key ), 40 ) . $integrity . "\n";
}
// RCP Templates
$files = array();
$directories = array( get_stylesheet_directory() . '/rcp/' );
if ( is_child_theme() ) {
$directories[] = get_template_directory() . '/rcp/';
}
foreach ( $directories as $dir ) {
if ( is_dir( $dir ) && ( count( glob( "$dir/*" ) ) !== 0 ) ) {
foreach ( glob( $dir . '/*' ) as $file ) {
if ( ! array_key_exists( basename( $file ), $files ) ) {
$files[ basename( $file ) ] = 'Filename: ' . basename( $file );
}
}
}
}
if ( ! empty( $files ) ) {
$return .= "\n" . '-- RCP Template Overrides' . "\n\n";
$return .= implode( "\n", $files ) . "\n";
$return = apply_filters( 'rcp_system_info_after_rcp_templates', $return );
}
// Get plugins that have an update
$updates = get_plugin_updates();
// Must-use plugins
// NOTE: MU plugins can't show updates!
$muplugins = get_mu_plugins();
if( count( $muplugins ) > 0 ) {
$return .= "\n" . '-- Must-Use Plugins' . "\n\n";
foreach( $muplugins as $plugin => $plugin_data ) {
$return .= $plugin_data['Name'] . ': ' . $plugin_data['Version'] . "\n";
}
$return = apply_filters( 'rcp_system_info_after_wordpress_mu_plugins', $return );
}
// WordPress active plugins
$return .= "\n" . '-- WordPress Active Plugins' . "\n\n";
$plugins = get_plugins();
$active_plugins = get_option( 'active_plugins', array() );
foreach( $plugins as $plugin_path => $plugin ) {
if( !in_array( $plugin_path, $active_plugins ) )
continue;
$update = ( array_key_exists( $plugin_path, $updates ) ) ? ' (needs update - ' . $updates[$plugin_path]->update->new_version . ')' : '';
$return .= $plugin['Name'] . ': ' . $plugin['Version'] . $update . "\n";
}
$return = apply_filters( 'rcp_system_info_after_wordpress_active_plugins', $return );
// WordPress inactive plugins
$return .= "\n" . '-- WordPress Inactive Plugins' . "\n\n";
foreach( $plugins as $plugin_path => $plugin ) {
if( in_array( $plugin_path, $active_plugins ) )
continue;
$update = ( array_key_exists( $plugin_path, $updates ) ) ? ' (needs update - ' . $updates[$plugin_path]->update->new_version . ')' : '';
$return .= $plugin['Name'] . ': ' . $plugin['Version'] . $update . "\n";
}
$return = apply_filters( 'rcp_system_info_after_wordpress_inactive_plugins', $return );
if( is_multisite() ) {
// WordPress Multisite active plugins
$return .= "\n" . '-- Network Active Plugins' . "\n\n";
$plugins = wp_get_active_network_plugins();
$active_plugins = get_site_option( 'active_sitewide_plugins', array() );
foreach( $plugins as $plugin_path ) {
$plugin_base = plugin_basename( $plugin_path );
if( !array_key_exists( $plugin_base, $active_plugins ) )
continue;
$update = ( array_key_exists( $plugin_path, $updates ) ) ? ' (needs update - ' . $updates[$plugin_path]->update->new_version . ')' : '';
$plugin = get_plugin_data( $plugin_path );
$return .= $plugin['Name'] . ': ' . $plugin['Version'] . $update . "\n";
}
$return = apply_filters( 'rcp_system_info_after_wordpress_network_active_plugins', $return );
}
// Server configuration (really just versioning)
$return .= "\n" . '-- Webserver Configuration' . "\n\n";
$return .= 'PHP Version: ' . PHP_VERSION . "\n";
$return .= 'MySQL Version: ' . $wpdb->db_version() . "\n";
$return .= 'Webserver Info: ' . $_SERVER['SERVER_SOFTWARE'] . "\n";
$return = apply_filters( 'rcp_system_info_after_server_config', $return );
// PHP configuration
$return .= "\n" . '-- PHP Configuration' . "\n\n";
$return .= 'Safe Mode: ' . ( ini_get( 'safe_mode' ) ? 'Enabled' : 'Disabled' . "\n" );
$return .= 'Memory Limit: ' . ini_get( 'memory_limit' ) . "\n";
$return .= 'Upload Max Size: ' . ini_get( 'upload_max_filesize' ) . "\n";
$return .= 'Post Max Size: ' . ini_get( 'post_max_size' ) . "\n";
$return .= 'Upload Max Filesize: ' . ini_get( 'upload_max_filesize' ) . "\n";
$return .= 'Time Limit: ' . ini_get( 'max_execution_time' ) . "\n";
$return .= 'Max Input Vars: ' . ini_get( 'max_input_vars' ) . "\n";
$return .= 'Display Errors: ' . ( ini_get( 'display_errors' ) ? 'On (' . ini_get( 'display_errors' ) . ')' : 'N/A' ) . "\n";
$return = apply_filters( 'rcp_system_info_after_php_config', $return );
// PHP extensions and such
$return .= "\n" . '-- PHP Extensions' . "\n\n";
$return .= 'cURL: ' . ( function_exists( 'curl_init' ) ? 'Supported' : 'Not Supported' ) . "\n";
$return .= 'fsockopen: ' . ( function_exists( 'fsockopen' ) ? 'Supported' : 'Not Supported' ) . "\n";
$return .= 'SOAP Client: ' . ( class_exists( 'SoapClient' ) ? 'Installed' : 'Not Installed' ) . "\n";
$return .= 'Suhosin: ' . ( extension_loaded( 'suhosin' ) ? 'Installed' : 'Not Installed' ) . "\n";
$return = apply_filters( 'rcp_system_info_after_php_extensions', $return );
$return .= "\n" . '-- Miscellaneous' . "\n\n";
$return .= 'System Info Generated: ' . current_time( 'mysql', true ) . ' (GMT)';
$return .= "\n\n" . '### End System Info ###';
return $return;
}

View File

@@ -0,0 +1,571 @@
<?php
/**
* Tools Page
*
* @package Restrict Content Pro
* @subpackage Admin/Tools
* @copyright Copyright (c) 2017, Restrict Content Pro
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
*/
/**
* Displays the Tools page
*
* @since 2.5
* @return void
*/
function rcp_tools_page() {
if( ! current_user_can( 'rcp_manage_settings' ) ) {
return;
}
do_action( 'stellarwp/telemetry/restrict-content-pro/optin' );
do_action( 'stellarwp/telemetry/restrict-content/optin' );
$active_tab = isset( $_GET['tab'] ) ? $_GET['tab'] : 'system_info';
?>
<div class="wrap">
<h1><?php
if( defined('IS_PRO') && IS_PRO ) {
_e( 'Restrict Content Pro Tools', 'rcp' );
}
else {
_e( 'Restrict Content Tools', 'rcp' );
}
?></h1>
<h2 class="nav-tab-wrapper">
<?php
foreach( rcp_get_tools_tabs() as $tab_id => $tab_name ) {
$tab_url = add_query_arg( array(
'tab' => $tab_id
) );
$tab_url = remove_query_arg( array(
'rcp_message'
), $tab_url );
$active = $active_tab == $tab_id ? ' nav-tab-active' : '';
echo '<a href="' . esc_url( $tab_url ) . '" class="nav-tab' . $active . '">' . esc_html( $tab_name ) . '</a>';
}
?>
</h2>
<?php do_action( 'rcp_tools_tab_subnav_' . $active_tab ); ?>
<div class="metabox-holder">
<?php do_action( 'rcp_tools_tab_' . $active_tab ); ?>
</div>
</div>
<?php
}
/**
* Retrieve tools tabs
*
* @since 2.9
* @return array
*/
function rcp_get_tools_tabs() {
$tabs = array(
'system_info' => __( 'System Info', 'rcp' ),
'debug' => __( 'Debugging', 'rcp' )
);
if ( current_user_can( 'rcp_manage_settings' ) ) {
$tabs['import'] = __( 'Import', 'rcp' );
}
if ( rcp_current_user_can_export() ) {
$tabs['export'] = __( 'Export', 'rcp' );
}
if ( ! empty( $_GET['tab'] ) && 'batch' === $_GET['tab'] ) {
$tabs['batch'] = __( 'Batch Processing', 'rcp' );
}
return apply_filters( 'rcp_tools_tabs', $tabs );
}
/**
* Display system information tab
*
* @since 2.9
* @return void
*/
function rcp_tools_display_system_info() {
include RCP_PLUGIN_DIR . 'core/includes/admin/tools/system-info.php';
?>
<form action="<?php echo esc_url( admin_url( 'admin.php?page=rcp-tools' ) ); ?>" method="post" dir="ltr">
<textarea readonly="readonly" onclick="this.focus(); this.select()" id="rcp-system-info-textarea" name="rcp-sysinfo" title="To copy the system info, click below then press Ctrl + C (PC) or Cmd + C (Mac)."><?php echo rcp_tools_system_info_report(); ?></textarea>
<p class="submit">
<input type="hidden" name="rcp-action" value="download_sysinfo" />
<?php submit_button( 'Download System Info File', 'primary', 'rcp-download-sysinfo', false ); ?>
</p>
</form>
<?php
}
add_action( 'rcp_tools_tab_system_info', 'rcp_tools_display_system_info' );
/**
* Listens for system info download requests and delivers the file
*
* @since 2.5
* @return void
*/
function rcp_tools_sysinfo_download() {
if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
return;
}
if ( ! current_user_can( 'rcp_manage_settings' ) ) {
return;
}
if ( ! isset( $_POST['rcp-download-sysinfo'] ) ) {
return;
}
nocache_headers();
header( 'Content-Type: text/plain' );
header( 'Content-Disposition: attachment; filename="rcp-system-info.txt"' );
echo wp_strip_all_tags( $_POST['rcp-sysinfo'] );
exit;
}
add_action( 'admin_init', 'rcp_tools_sysinfo_download' );
/**
* Display debug log
*
* @since 2.9
* @return void
*/
function rcp_tools_display_debug() {
$logs = new RCP_Logging();
?>
<div class="postbox">
<h3><?php _e( 'Debug Log', 'rcp' ); ?></h3>
<div class="inside">
<form id="rcp-debug-log" method="post">
<p><label for="rcp-debug-log-contents"><?php _e( 'Any Restrict Content Pro errors that occur will be logged to this file.', 'rcp' ); ?></label></p>
<textarea id="rcp-debug-log-contents" name="rcp-debug-log-contents" class="large-text" rows="15"><?php echo esc_textarea( $logs->get_log() ); ?></textarea>
<p class="submit">
<input type="hidden" name="rcp-action" value="submit_debug_log">
<?php
wp_nonce_field( 'rcp_submit_debug_log', 'rcp_debug_log_nonce' );
submit_button( __( 'Download Debug Log', 'rcp' ), 'primary', 'rcp_download_debug_log', false );
submit_button( __( 'Clear Log', 'rcp' ), 'secondary', 'rcp_clear_debug_log', false );
?>
</p>
</form>
</div>
</div>
<?php
}
add_action( 'rcp_tools_tab_debug', 'rcp_tools_display_debug' );
/**
* Handles submit actions for the debug log
*
* @since 2.9
* @return void
*/
function rcp_submit_debug_log() {
if ( defined( 'DOING_AJAX' ) && DOING_AJAX ) {
return;
}
if ( ! current_user_can( 'rcp_manage_settings' ) ) {
return;
}
if ( ! isset( $_POST['rcp_debug_log_nonce'] ) || ! wp_verify_nonce( $_POST['rcp_debug_log_nonce'], 'rcp_submit_debug_log' ) ) {
return;
}
if ( isset( $_POST['rcp_download_debug_log'] ) ) {
// Download debug log
nocache_headers();
header( 'Content-Type: text/plain' );
header( 'Content-Disposition: attachment; filename="rcp-debug-log.txt"' );
echo wp_strip_all_tags( $_REQUEST['rcp-debug-log-contents'] );
exit;
} elseif ( isset( $_POST['rcp_clear_debug_log'] ) ) {
// Clear debug log.
$logs = new RCP_Logging();
$logs->clear_log();
wp_safe_redirect( admin_url( 'admin.php?page=rcp-tools&tab=debug') );
exit;
}
}
add_action( 'admin_init', 'rcp_submit_debug_log' );
/**
* Displays the batch processing tab on the Tools page.
*
* @since 3.0
*/
function rcp_batch_processing_page() {
$job_id = ! empty( $_GET['rcp-job-id'] ) ? absint( $_GET['rcp-job-id'] ) : 0;
$queue_name = ! empty( $_GET['rcp-queue'] ) ? sanitize_key( $_GET['rcp-queue'] ) : 'rcp_core';
$autostart = ! empty( $_GET['rcp-job-autostart'] );
$jobs = array();
if ( ! empty( $job_id ) ) {
$job = \RCP\Utils\Batch\get_job( $job_id );
if ( ! empty( $job ) ) {
$jobs = array( $job );
}
} elseif( ! empty( $queue_name ) ) {
$jobs = \RCP\Utils\Batch\get_jobs( array(
'queue' => $queue_name,
'status' => 'incomplete'
) );
}
?>
<div class="wrap">
<?php
if( empty( $jobs ) ) {
echo '<p>' . __( 'A valid job queue was not provided.', 'rcp' ) . '</p></div>';
return;
}
/**
* @var \RCP\Utils\Batch\Job $job
*/
foreach( $jobs as $key => $job ) {
if( $job->is_completed() ) {
echo '<p>' . sprintf( __( '%s has already been completed.', 'rcp' ), $job->get_name() ) . '</p></div>';
continue;
} ?>
<table id="rcp-batch-processing-job-<?php echo esc_attr( $job->get_id() ); ?>" class="wp-list-table widefat fixed posts rcp-batch-processing-job-table">
<thead>
<tr>
<th><?php echo ! empty( $job ) ? $job->get_name() : ''; ?></th>
<th><?php _e( 'Progress', 'rcp' ); ?></th>
<th><?php _e( 'Actions', 'rcp' ); ?></th>
</tr>
</thead>
<tbody>
<tr>
<td>
<?php echo esc_html( $job->get_description() ); ?> <br/>
<?php printf( __( 'WP-CLI command: %s', 'rcp' ), '<code>wp rcp batch --id=' . $job->get_id() . '</code>' ); ?>
</td>
<td>
<span class="rcp-batch-processing-job-progress-bar"><span style="width: <?php echo esc_attr( $job->get_percent_complete() ); ?>%;"></span></span>
<span class="rcp-batch-processing-job-progress-text description"><?php printf( __( '%s%% complete', 'rcp' ), '<span class="rcp-batch-processing-job-percent-complete">' . $job->get_percent_complete() . '</span>' ); ?></span>
</td>
<td>
<form class="rcp-batch-form">
<?php if ( 1 === count( $jobs ) && $autostart ) : ?>
<input type="hidden" id="rcp-job-autostart" value="1" />
<?php endif; ?>
<input type="hidden" name="rcp-job-step" class="rcp-batch-processing-job-step" value="<?php echo esc_attr( $job->get_step() ); ?>" />
<input type="hidden" name="rcp-job-id" class="rcp-batch-processing-job-id" value="<?php echo esc_attr( $job->get_id() ); ?>" />
<input type="submit" value="<?php echo $job->get_percent_complete() > 0 ? esc_attr( 'Continue Processing', 'rcp' ) : esc_attr( 'Start Processing', 'rcp' ); ?>" class="button-primary"/>
<span class="spinner"></span>
<span class="rcp-batch-processing-message"></span>
</form>
</td>
</tr>
<tr id="rcp-batch-processing-errors-job-<?php echo esc_attr( $job->get_id() ); ?>" class="rcp-batch-processing-errors" style="display: none;">
<td colspan="3"></td>
</tr>
</tbody>
</table>
<?php
}
?>
</div>
<?php
}
add_action( 'rcp_tools_tab_batch', 'rcp_batch_processing_page' );
/**
* Display importer subnavigation. This allows you to switch between importers.
*
* @since 3.1
* @return void
*/
function rcp_tools_display_import_subnav() {
$importers = rcp_get_csv_importers();
if ( empty( $importers ) ) {
return;
}
// If we only have one importer, don't bother showing the subnav.
if ( 1 === count( $importers ) ) {
return;
}
$current = ( isset( $_GET['rcp-csv-importer'] ) && array_key_exists( $_GET['rcp-csv-importer'], $importers ) ) ? urldecode( $_GET['rcp-csv-importer'] ) : '';
if ( empty( $current ) ) {
$first_importer = $importers;
reset( $first_importer );
$current = key( $first_importer );
}
?>
<ul class="subsubsub rcp-sub-nav">
<li>
<?php foreach ( $importers as $importer_key => $importer_details ) : ?>
<a href="<?php echo esc_url( add_query_arg( 'rcp-csv-importer', urlencode( $importer_key ), admin_url( 'admin.php?page=rcp-tools&tab=import' ) ) ); ?>"<?php echo ( $importer_key === $current ) ? ' class="current"' : ''; ?>><?php echo esc_html( $importer_details['name'] ); ?></a>
<?php endforeach; ?>
</li>
</ul>
<?php
}
add_action( 'rcp_tools_tab_subnav_import', 'rcp_tools_display_import_subnav' );
/**
* Display import tab
*
* @since 3.1
* @return void
*/
function rcp_tools_display_import() {
if ( ! current_user_can( 'rcp_manage_settings' ) ) {
return;
}
$importers = rcp_get_csv_importers();
$current = ( isset( $_GET['rcp-csv-importer'] ) && array_key_exists( $_GET['rcp-csv-importer'], $importers ) ) ? urldecode( $_GET['rcp-csv-importer'] ) : '';
if ( empty( $current ) ) {
// If current one is not specified via query arg, default to the first one in the list.
$first_importer = $importers;
reset( $first_importer );
$current = key( $first_importer );
}
$importer = rcp_get_csv_importer( $current );
?>
<div class="postbox">
<h3><?php printf( __( 'Import %s', 'rcp' ), esc_html( $importer['name'] ) ); ?></h3>
<div class="inside">
<?php if ( ! empty( $importer['description'] ) ) : ?>
<p><?php echo wp_kses_post( $importer['description'] ); ?></p>
<?php endif; ?>
<form id="rcp-import-memberships" class="rcp-import-form" action="<?php echo esc_url( add_query_arg( 'rcp-action', 'upload_import_file', admin_url() ) ); ?>" method="POST" enctype="multipart/form-data">
<table class="form-table rcp-import-file-wrap">
<tbody>
<tr class="rcp-import-file">
<th>
<label for="rcp-<?php echo sanitize_html_class( $importer['key'] ); ?>-import-file"><?php _e( 'CSV File', 'rcp' ); ?></label>
</th>
<td>
<p>
<input id="rcp-<?php echo sanitize_html_class( $importer['key'] ); ?>-import-file" name="import_file" type="file"/>
</p>
</td>
</tr>
<?php
/**
* Use this action hook to insert additional importer settings. All input names
* should be an array with the key `import_settings`. Example:
*
* `import_settings[object_id]`
* `import_settings[status]`
*/
do_action( 'rcp_csv_importer_settings_' . $importer['key'], $importer );
?>
</tbody>
<tfoot>
<tr>
<td colspan="2">
<p id="rcp-import-csv-errors" style="display:none"></p>
<p id="rcp-import-csv-button-wrap" class="submit">
<input type="submit" value="<?php _e( 'Upload CSV', 'rcp' ); ?>" class="button-secondary"/>
<span class="spinner"></span>
</p>
</td>
</tr>
</tfoot>
</table>
<div id="rcp-import-<?php echo sanitize_html_class( $importer['key'] ); ?>-options" class="rcp-import-options" style="display:none;">
<p>
<?php printf( __( 'Each column from your CSV file needs to be mapped to its corresponding Restrict Content Pro field. Select the column that should be mapped to each field below. Any columns not needed can be ignored.', 'rcp' ) ); ?>
</p>
<table class="widefat striped" width="100%" cellpadding="0" cellspacing="0">
<thead>
<tr>
<th><strong><?php _e( 'RCP Field', 'rcp' ); ?></strong></th>
<th><strong><?php _e( 'CSV Column', 'rcp' ); ?></strong></th>
<th><strong><?php _e( 'Data Preview', 'rcp' ); ?></strong></th>
</tr>
</thead>
<tbody>
<?php foreach ( $importer['columns'] as $column_key => $column_value ) : ?>
<tr>
<td><?php echo esc_html( $column_value ); ?></td>
<td>
<select name="rcp_import_field[<?php echo sanitize_html_class( $column_key ); ?>]" class="rcp-import-csv-column" data-field="<?php echo esc_attr( $column_value ); ?>">
<option value=""><?php _e( '- Ignore this field -', 'rcp' ); ?></option>
</select>
</td>
<td class="rcp-import-preview-field"><?php _e( '- select field to preview data -', 'rcp' ); ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<p class="submit">
<button class="rcp-import-proceed button-primary"><?php _e( 'Process Import', 'rcp' ); ?></button>
<span class="spinner"></span>
</p>
</div>
<?php wp_nonce_field( 'rcp_ajax_import', 'rcp_ajax_import_nonce' ); ?>
<input type="hidden" name="importer" value="<?php echo esc_attr( $importer['key'] ); ?>" />
<input type="hidden" name="rcp-action" value="upload_import_file" />
</form>
</div>
</div>
<?php
}
add_action( 'rcp_tools_tab_import', 'rcp_tools_display_import' );
/**
* Display exporter subnavigation. This allows you to switch between exporters.
*
* @since 3.4
* @return void
*/
function rcp_tools_display_export_subnav() {
$exporters = rcp_get_csv_exporters();
if ( empty( $exporters ) ) {
return;
}
// If we only have one exporter, don't bother showing the subnav.
if ( 1 === count( $exporters ) ) {
return;
}
$current = ( isset( $_GET['rcp-csv-exporter'] ) && array_key_exists( $_GET['rcp-csv-exporter'], $exporters ) ) ? urldecode( $_GET['rcp-csv-exporter'] ) : '';
if ( empty( $current ) ) {
$first_exporter = $exporters;
reset( $first_exporter );
$current = key( $first_exporter );
}
?>
<ul class="subsubsub rcp-sub-nav">
<li>
<?php foreach ( $exporters as $exporter_key => $exporter_details ) : ?>
<a href="<?php echo esc_url( add_query_arg( 'rcp-csv-exporter', urlencode( $exporter_key ), admin_url( 'admin.php?page=rcp-tools&tab=export' ) ) ); ?>"<?php echo ( $exporter_key === $current ) ? ' class="current"' : ''; ?>><?php echo esc_html( $exporter_details['name'] ); ?></a>
<?php endforeach; ?>
</li>
</ul>
<?php
}
add_action( 'rcp_tools_tab_subnav_export', 'rcp_tools_display_export_subnav' );
/**
* Display export tab
*
* @since 3.4
* @return void
*/
function rcp_tools_display_export() {
if ( ! rcp_current_user_can_export() ) {
return;
}
$exporters = rcp_get_csv_exporters();
$current = ( isset( $_GET['rcp-csv-exporter'] ) && array_key_exists( $_GET['rcp-csv-exporter'], $exporters ) ) ? urldecode( $_GET['rcp-csv-exporter'] ) : '';
if ( empty( $current ) ) {
// If current one is not specified via query arg, default to the first one in the list.
$first_exporter = $exporters;
reset( $first_exporter );
$current = key( $first_exporter );
}
$exporter = rcp_get_csv_exporter( $current );
?>
<div class="postbox">
<h3><?php printf( __( 'Export %s', 'rcp' ), esc_html( $exporter['name'] ) ); ?></h3>
<div class="inside">
<?php if ( ! empty( $exporter['description'] ) ) : ?>
<p><?php echo wp_kses_post( $exporter['description'] ); ?></p>
<?php endif; ?>
<form id="rcp-export-<?php echo esc_attr( sanitize_html_class( $exporter['key'] ) ); ?>" class="rcp-export-form" action="" method="POST">
<?php
/**
* Use this action hook to insert additional exporter settings. All input names
* should be an array with the key `export_settings`. Example:
*
* `export_settings[object_id]`
* `export_settings[status]`
*
* @param array $exporter Exporter settings.
*
* @since 3.4
*/
do_action( 'rcp_csv_exporter_settings_' . $exporter['key'], $exporter );
wp_nonce_field( 'rcp_batch_export', 'rcp_batch_export_nonce' );
?>
<input type="hidden" name="exporter" value="<?php echo esc_attr( $exporter['key'] ); ?>"/>
<input type="hidden" name="rcp-action" value="add_export_job"/>
<p class="submit">
<button class="rcp-export-proceed button-primary"><?php _e( 'Process Export', 'rcp' ); ?></button>
<span class="spinner"></span>
</p>
</form>
</div>
</div>
<?php
}
add_action( 'rcp_tools_tab_export', 'rcp_tools_display_export' );

View File

@@ -0,0 +1,178 @@
<?php
/**
* Upgrades
*
* @package Restrict Content Pro
* @subpackage Admin/Upgrades
* @copyright Copyright (c) 2017, Restrict Content Pro
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
*/
/**
* Check if upgrade is needed
*
* @return bool
*/
function rcp_check_if_upgrade_needed() {
global $rcp_db_version, $rcp_discounts_db_version, $rcp_payments_db_version;
if( version_compare( RCP_PLUGIN_VERSION, '2.6', '>=' ) && version_compare( get_option( 'rcp_version' ), '2.5', '>=' ) ) {
// New RCP_Upgrades class was introduced with 2.6. See https://github.com/restrictcontentpro/restrict-content-pro/issues/511
return false;
}
if( version_compare( $rcp_db_version, get_option( 'rcp_db_version' ), '>' ) ) {
return true;
}
if( version_compare( $rcp_discounts_db_version, get_option( 'rcp_discounts_db_version' ), '>' ) ) {
return true;
}
if( version_compare( $rcp_payments_db_version, get_option( 'rcp_payments_db_version' ), '>' ) ) {
return true;
}
if( ! get_option( 'rcp_version' ) || version_compare( get_option( 'rcp_version' ), '2.3', '<' ) ) {
return true;
}
return false;
}
add_action( 'admin_init', 'rcp_check_if_upgrade_needed' );
/**
* Run upgrade
*
* @uses rcp_check_if_upgrade_needed()
*
* @return void
*/
function rcp_run_upgrade() {
if( isset( $_GET['rcp-action'] ) && $_GET['rcp-action'] == 'upgrade' && rcp_check_if_upgrade_needed() ) {
rcp_options_upgrade();
wp_redirect( admin_url() ); exit;
}
}
add_action( 'admin_init', 'rcp_run_upgrade' );
/**
* Options upgrade
*
* @param bool $network_wide Whether the plugin is being network activated.
*
* @return void
*/
function rcp_options_upgrade( $network_wide = false ) {
/**
* If the plugin is being network activated, do the upgrades
* on the shutdown hook. Otherwise do it now.
* @see https://github.com/restrictcontentpro/restrict-content-pro/issues/669
*/
if ( $network_wide ) {
add_action( 'shutdown', 'rcp_legacy_db_upgrades' );
} else {
rcp_legacy_db_upgrades();
}
}
register_activation_hook( RCP_PLUGIN_FILE, 'rcp_options_upgrade' );
/**
* This is a one-time function to upgrade database table collation
*
* @return void
*/
function rcp_upgrade_table_collation() {
if( isset( $_GET['rcp-action'] ) && $_GET['rcp-action'] == 'db-collate' ) {
global $wpdb, $rcp_db_name, $rcp_db_version, $rcp_discounts_db_name, $rcp_discounts_db_version, $rcp_payments_db_name, $rcp_payments_db_version;
$wpdb->query( "alter table `" . $rcp_db_name . "` convert to character set utf8 collate utf8_unicode_ci" );
$wpdb->query( "alter table `" . $rcp_discounts_db_name . "` convert to character set utf8 collate utf8_unicode_ci" );
$wpdb->query( "alter table `" . $rcp_payments_db_name . "` convert to character set utf8 collate utf8_unicode_ci" );
wp_safe_redirect( add_query_arg('rcp-db', 'updated', admin_url() ) ); exit;
}
}
add_action( 'admin_init', 'rcp_upgrade_table_collation' );
/**
* Runs the legacy database upgrade routines.
*
* @since 2.7
* @return void
*/
function rcp_legacy_db_upgrades() {
global $wpdb, $rcp_db_version, $rcp_discounts_db_version, $rcp_payments_db_version;
/****************************************
* upgrade discount codes DB
****************************************/
$rcp_discounts_db_name = rcp_get_discounts_db_name();
if( ! $wpdb->query( "SHOW COLUMNS FROM `" . $rcp_discounts_db_name . "` LIKE 'max_uses'" ) ) {
$wpdb->query( "ALTER TABLE `" . $rcp_discounts_db_name . "` ADD `max_uses` mediumint" );
update_option( 'rcp_discounts_db_version', $rcp_discounts_db_version );
}
if( ! $wpdb->query( "SHOW COLUMNS FROM `" . $rcp_discounts_db_name . "` LIKE 'expiration'" ) ) {
$wpdb->query( "ALTER TABLE `" . $rcp_discounts_db_name . "` ADD `expiration` mediumtext" );
update_option( 'rcp_discounts_db_version', $rcp_discounts_db_version );
}
if( ! $wpdb->query( "SHOW COLUMNS FROM `" . $rcp_discounts_db_name . "` LIKE 'subscription_id'" ) ) {
$wpdb->query( "ALTER TABLE `" . $rcp_discounts_db_name . "` ADD `subscription_id` mediumint" );
update_option( 'rcp_discounts_db_version', $rcp_discounts_db_version );
}
/****************************************
* upgrade subscription levels DB
****************************************/
$rcp_db_name = rcp_get_levels_db_name();
if( get_option('rcp_db_version') == '' )
update_option( 'rcp_db_version', $rcp_db_version );
if( ! $wpdb->query( "SHOW COLUMNS FROM `" . $rcp_db_name . "` LIKE 'level'" ) ) {
$wpdb->query( "ALTER TABLE `" . $rcp_db_name . "` ADD `level` mediumtext" );
update_option( 'rcp_db_version', $rcp_db_version );
}
if( ! $wpdb->query( "SHOW COLUMNS FROM `" . $rcp_db_name . "` LIKE 'status'" ) ) {
$wpdb->query( "ALTER TABLE `" . $rcp_db_name . "` ADD `status` tinytext" );
update_option( 'rcp_db_version', $rcp_db_version );
}
if( ! $wpdb->query( "SHOW COLUMNS FROM `" . $rcp_db_name . "` LIKE 'fee'" ) ) {
$wpdb->query( "ALTER TABLE `" . $rcp_db_name . "` ADD `fee` tinytext" );
update_option( 'rcp_db_version', $rcp_db_version );
}
if( ! $wpdb->query( "SHOW COLUMNS FROM `" . $rcp_db_name . "` LIKE 'role'" ) ) {
$wpdb->query( "ALTER TABLE `" . $rcp_db_name . "` ADD `role` tinytext" );
update_option( 'rcp_db_version', $rcp_db_version );
}
if( version_compare( get_option( 'rcp_db_version' ), '1.3', '<' ) ) {
$wpdb->query( "ALTER TABLE " . $rcp_db_name . " MODIFY `duration` smallint" );
update_option( "rcp_db_version", $rcp_db_version );
}
/****************************************
* upgrade payments DB
****************************************/
$rcp_payments_db_name = rcp_get_payments_db_name();
if( get_option( 'rcp_payments_db_version' ) == '1.0' ) {
$wpdb->query( "ALTER TABLE " . $rcp_payments_db_name . " MODIFY `amount` mediumtext" );
update_option( "rcp_payments_db_version", $rcp_payments_db_version );
}
if( ! $wpdb->query( "SHOW COLUMNS FROM `" . $rcp_payments_db_name . "` LIKE 'transaction_id'" ) ) {
$wpdb->query( "ALTER TABLE `" . $rcp_payments_db_name . "` ADD `transaction_id` tinytext" );
update_option( 'rcp_payments_db_version', $rcp_payments_db_version );
}
if( ! $wpdb->query( "SHOW COLUMNS FROM `" . $rcp_payments_db_name . "` LIKE 'status'" ) ) {
$wpdb->query( "ALTER TABLE `" . $rcp_payments_db_name . "` ADD `status` varchar(200)" );
update_option( 'rcp_payments_db_version', $rcp_payments_db_version );
}
/****************************************
* 2.3 upgrades for account pages
***************************************/
if( ! get_option( 'rcp_version' ) || version_compare( get_option( 'rcp_version' ), '2.3', '<' ) ) {
// Update or create plugin pages
rcp_options_install();
}
}

View File

@@ -0,0 +1,255 @@
<?php
/**
* Ajax Actions
*
* Process the front-end ajax actions.
*
* @package Restrict Content Pro
* @copyright Copyright (c) 2017, Restrict Content Pro
* @license http://opensource.org/license/gpl-2.1.php GNU Public License
*/
/**
* Check whether a discount code is valid. Used during registration to validate a discount code on the fly.
*
* @return void
*/
function rcp_validate_discount_with_ajax() {
if( isset( $_POST['code'] ) ) {
$return = array();
$return['valid'] = false;
$return['full'] = false;
$subscription_id = isset( $_POST['subscription_id'] ) ? absint( $_POST['subscription_id'] ) : 0;
rcp_setup_registration( $subscription_id, $_POST['code'] );
if( rcp_validate_discount( wp_unslash( $_POST['code'] ), $subscription_id ) ) {
$code_details = rcp_get_discount_details_by_code( sanitize_text_field( wp_unslash( $_POST['code'] ) ) );
if( ( ! rcp_registration_is_recurring() && rcp_get_registration()->get_recurring_total() == 0.00 ) && rcp_get_registration()->get_total() == 0.00 ) {
// this is a 100% discount
$return['full'] = true;
}
$return['valid'] = true;
$return['amount'] = rcp_discount_sign_filter( $code_details->get_amount(), $code_details->get_unit() );
}
wp_send_json( $return );
}
die();
}
add_action( 'wp_ajax_validate_discount', 'rcp_validate_discount_with_ajax' );
add_action( 'wp_ajax_nopriv_validate_discount', 'rcp_validate_discount_with_ajax' );
/**
* Calls the load_fields() method for gateways when a gateway selection is made
*
* @since 2.1
* @return void
*/
function rcp_load_gateway_fields() {
$gateways = new RCP_Payment_Gateways;
$gateways->load_fields();
die();
}
add_action( 'wp_ajax_rcp_load_gateway_fields', 'rcp_load_gateway_fields' );
add_action( 'wp_ajax_nopriv_rcp_load_gateway_fields', 'rcp_load_gateway_fields' );
/**
* Setup the registration details
*
* @since 2.5
* @return void
*/
function rcp_calc_total_ajax() {
$return = array(
'valid' => false,
'total' => __( 'No available membership levels for your account.', 'rcp' ),
);
if ( ! rcp_is_registration() ) {
wp_send_json( $return );
}
ob_start();
rcp_get_template_part( 'register-total-details' );
$return['total'] = ob_get_clean();
wp_send_json( $return );
}
add_action( 'wp_ajax_rcp_calc_discount', 'rcp_calc_total_ajax' );
add_action( 'wp_ajax_nopriv_rcp_calc_discount', 'rcp_calc_total_ajax' );
/**
* Validates the entire registration state
*
* @param array $args
*
* @since 3.0.6
* @return array|bool
*/
function rcp_validate_registration_state( $args = array() ) {
if( empty( $args ) ) {
return false;
}
/**
* @type int $level_id - ID of the membership level.
* @type string $gateway - Payment gateway slug.
* @type string $gateway_fields - HTML for the payment gateway fields.
* @type bool $show_gateway_fields - Whether or not the gateway fields should be displayed.
* @type string $discount_code - Discount code to apply to the registration.
* @type bool $discount_valid - Whether or not the discount is valid.
* @type float $discount_amount - The dollar amount discounted.
* @type bool $full_discount - Whether or not this is a paid level that has been discounted down to $0 due to discount code, negative fees, or credits.
* @type bool $is_free - Similar to $full_discount, but just for discount codes. Deprecated.
* @type bool $lifetime - Whether or not this is a lifetime membership. Deprecated.
* @type bool $level_has_trial - Whether or not the chosen membership level has a trial.
* @type float $initial_total - Total amount due today.
* @type float $recurring_total - Total recurring amount.
* @type bool $recurring - Whether or not recurring is checked on.
* @type bool $recurring_available - Whether or not the recurring checkbox should even be displayed.
* @type string $total_details_html - The HTML for the total details table.
* @type string $event_type - JavaScript event type.
*/
$return = array(
'level_id' => ! empty( $args['rcp_level'] ) ? absint( $args['rcp_level'] ) : 0,
'gateway' => ! empty( $args['rcp_gateway'] ) ? sanitize_text_field( $args['rcp_gateway'] ) : false,
'gateway_fields' => false,
'show_gateway_fields' => true,
'discount_code' => ! empty( $args['discount_code'] ) ? sanitize_text_field( $args['discount_code'] ) : false,
'discount_valid' => false,
'discount_amount' => false,
'full_discount' => false,
'is_free' => ! empty( $args['is_free'] ) && 'true' == $args['is_free'], // Deprecated
'lifetime' => ! empty( $args['lifetime'] ) && 'true' == $args['lifetime'], // Deprecated
'level_has_trial' => ! empty( $args['level_has_trial'] ) && 'true' == $args['level_has_trial'],
'trial_eligible' => true,
'initial_total' => 0.00,
'recurring_total' => 0.00,
'recurring' => ! empty( $args['rcp_auto_renew'] ) && 'true' == $args['rcp_auto_renew'],
'recurring_available' => false,
'total_details_html' => __( 'No available membership levels for your account.', 'rcp' ),
'event_type' => ! empty( $args['event_type'] ) ? sanitize_text_field( $args['event_type'] ) : false
);
rcp_setup_registration( $return['level_id'], $return['discount_code'] );
/**
* 100% discount
* If auto renew is DISABLED, this checks if the total due today is $0.
* If auto renew is ENABLED, this checks if the total today and recurring total are both $0.
* This may be $0 due to discounts, fees, or credits.
*/
if ( ( ! rcp_registration_is_recurring() && rcp_get_registration()->get_total() == 0.00 )
|| ( rcp_registration_is_recurring() && ( rcp_get_registration()->get_total() + rcp_get_registration()->get_recurring_total() ) == 0.00 )
) {
// this is a 100% discount
$return['full_discount'] = true;
}
/** Discount */
if( ! empty( $return['discount_code'] ) ) {
if( rcp_validate_discount( $return['discount_code'], $return['level_id'] ) ) {
$code_details = rcp_get_discount_details_by_code( $return['discount_code'] );
$return['discount_valid'] = true;
$return['discount_amount'] = rcp_discount_sign_filter( $code_details->get_amount(), $code_details->get_unit() );
}
}
/** Totals */
if ( rcp_is_registration() ) {
$return['initial_total'] = rcp_get_registration()->get_total();
$return['recurring_total'] = rcp_get_registration()->get_recurring_total();
$return['recurring'] = rcp_registration_is_recurring();
ob_start();
rcp_get_template_part( 'register-total-details' );
$return['total_details_html'] = ob_get_clean();
}
/**
* Recurring
* Determine whether or not it's allowed. This is largely a copy of rcp_registration_is_recurring()
* except it doesn't take the user's selection into account. It's just whether or not the checkbox should
* be displayed to the user at all.
*/
// Only proceed if "never auto renew" is NOT selected in settings.
if ( '2' != rcp_get_auto_renew_behavior() ) {
$return['recurring_available'] = true; // default to allowed
// Does the gateway actually support it?
$return['recurring_available'] = rcp_gateway_supports( $return['gateway'], 'recurring' );
// No auto renew for lifetime or free memberships.
if ( ! rcp_get_registration_recurring_total() > 0 ) {
$return['recurring_available'] = false;
}
// If the total today is $0 and the gateway does not support free trials, disable auto renew.
if ( empty( $return['initial_total'] ) && ! rcp_gateway_supports( $return['gateway'], 'trial' ) ) {
$return['recurring_available'] = false;
$return['recurring'] = false;
}
}
/**
* Free trial
* Force auto renew on and disable option if this is a free trial.
*/
$customer = rcp_get_customer(); // current customer
if ( $customer && $customer->has_trialed() ) {
$return['trial_eligible'] = false;
}
if ( $return['level_has_trial'] && $return['trial_eligible'] ) {
$return['recurring'] = rcp_gateway_supports( $return['gateway'], 'trial' );
}
/** Gateway fields */
// Load the fields.
if( ! empty( $return['gateway'] ) ) {
$gateways = new RCP_Payment_Gateways;
$fields = $gateways->get_gateway_fields( $return['gateway'] );
if( ! empty( $fields ) ) {
$return['gateway_fields'] = $fields;
}
}
// Determine whether or not the template should display the fields.
if ( ( empty( $return['initial_total'] ) && ! $return['recurring'] ) || ( empty( $return['initial_total'] ) && empty( $return['recurring_total'] ) ) ) {
// Membership is free.
$return['show_gateway_fields'] = false;
}
return $return;
}
/**
* Ajax callback for validating the registration state.
* @uses rcp_validate_registration_state()
*
* @since 3.0.6
* @return void
*/
function rcp_validate_registration_state_ajax() {
wp_send_json_success( rcp_validate_registration_state( wp_unslash( $_POST ) ) );
exit;
}
add_action( 'wp_ajax_rcp_validate_registration_state', 'rcp_validate_registration_state_ajax' );
add_action( 'wp_ajax_nopriv_rcp_validate_registration_state', 'rcp_validate_registration_state_ajax' );
add_action( 'wp_ajax_rcp_braintree_3ds_validation_fields', 'rcp_braintree_3ds_validation_fields' );
add_action( 'wp_ajax_nopriv_rcp_braintree_3ds_validation_fields', 'rcp_braintree_3ds_validation_fields' );

View File

@@ -0,0 +1,144 @@
<?php
/**
* Abstract Job Callback
*
* @package restrict-content-pro
* @copyright Copyright (c) 2018, Restrict Content Pro team
* @license GPL2+
* @since 3.0
*/
namespace RCP\Utils\Batch;
/**
* Class Abstract_Job_Callback
*
* @package RCP\Utils\Batch
*/
abstract class Abstract_Job_Callback implements Job_Callback_Interface {
/**
* Maximum number of seconds the job can run during each pass
*
* @var int $time_limit
*/
protected $time_limit = 15;
/**
* The time this job started.
*
* @var int $start_time
*/
protected $start_time;
/**
* The job object
*
* @var Job $job
*/
protected $job;
/**
* The offset to use when querying records on each pass.
*
* @var int $offset
*/
protected $offset;
/**
* The number of records to query on each pass.
*
* @var int $size
*/
protected $size = 20;
/**
* Abstract_Job_Callback constructor.
*
* @param Job $job
*
* @since 3.0
*/
public function __construct( $job ) {
$this->job = $job;
}
/**
* Executes the job.
*
* @since 3.0
*/
public function execute() {
/**
* Make sure to call this method via parent::execute() in your extending class
* to update the offset during each batch.
*/
$this->offset = absint( $this->size * ( $this->get_job()->get_step() ) );
}
/**
* Retrieves the amount of records processed per step.
*
* @return int
*/
public function get_amount_per_step() {
return $this->size;
}
/**
* Count the total number of results and save the value.
*
* @since 3.1
* @return int
*/
public function get_total_count() {
$total_count = $this->get_job()->get_total_count();
if ( $total_count ) {
$total_count = 0; // count total here
$this->get_job()->set_total_count( $total_count );
}
return $total_count;
}
/**
* Runs any tasks required to finish a job.
*
* @since 3.0
* @return mixed|void
*/
abstract public function finish();
/**
* Get the associated job object.
*
* @since 3.0
* @return Job
*/
public function get_job() {
return $this->job;
}
/**
* Message to display upon job completion.
*
* @since 3.0
* @return string
*/
public function get_complete_message() {
return sprintf( __( 'Successfully processed %d/%d items. You may now leave the page.', 'rcp' ), $this->get_job()->get_current_count(), $this->get_job()->get_total_count() );
}
/**
* Determines if the job has exceeded its allowed time limit.
*
* @since 3.0
* @return bool
*/
protected function time_exceeded() {
return ( ( time() - $this->start_time ) >= $this->time_limit );
}
}

View File

@@ -0,0 +1,279 @@
<?php
/**
* Batch Functions
*
* @package restrict-content-pro
* @copyright Copyright (c) 2018, Restrict Content Pro team
* @license GPL2+
* @since 3.0
*/
namespace RCP\Utils\Batch;
/**
*
* Adds a batch job for later processing.
*
* @since 3.0
*
* @param array $config {
*
* @type string $name Job name.
* @type string $description Job description.
* @type string $callback Callback used to process the job.
* @type array $data Any extra data needed for processing.
* }
* @return int|\WP_Error Job ID if the job was registered, WP_Error if an invalid configuration was given or the job
* otherwise failed to be added.
*/
function add_batch_job( array $config ) {
$default_args = array(
'queue' => 'rcp_core',
'status' => 'incomplete',
'date_created' => current_time( 'mysql' )
);
$config = wp_parse_args( $config, $default_args );
$error_message = sprintf( __( 'You must supply a valid queue, name, and callback in %s', 'rcp' ), __FUNCTION__ );
try {
$clean_config = array(
'queue' => 'rcp_core',
'name' => '',
'description' => '',
'callback' => '',
'total_count' => 0,
'current_count' => 0,
'step' => 0,
'status' => 'incomplete',
'data' => '',
'date_created' => current_time( 'mysql' ),
'date_completed' => null
);
foreach ( [ 'name', 'callback' ] as $key ) {
if ( empty( $config[$key] ) ) {
throw new \InvalidArgumentException( $error_message );
}
}
foreach ( $config as $key => $value ) {
switch ( $key ) {
case 'queue' :
$clean_config['queue'] = sanitize_text_field( $value );
break;
case 'name':
$clean_config['name'] = sanitize_text_field( $value );
break;
case 'description':
$clean_config['description'] = wp_kses_post( $value );
break;
case 'callback':
$clean_config['callback'] = sanitize_text_field( $value );
break;
case 'total_count' :
case 'current_count' :
case 'step' :
$clean_config[$key] = absint( $value );
break;
case 'status':
$clean_config['status'] = sanitize_key( $config['status'] );
break;
case 'data' :
$clean_config['data'] = is_array( $config['data'] ) ? maybe_serialize( $config['data'] ) : '';
break;
case 'date_created' :
$clean_config['date_created'] = sanitize_text_field( $value );
break;
}
}
$queue_query = new \RCP\Database\Queries\Queue();
$existing = $queue_query->query( array(
'name' => $clean_config['name'],
'queue' => $clean_config['queue']
) );
if ( ! empty( $existing ) ) {
throw new \InvalidArgumentException( sprintf( __( 'Unable to add job %s to the %s queue. It already exists.', 'rcp' ), $clean_config['name'], $clean_config['queue'] ) );
}
$job_id = $queue_query->add_item( array(
'queue' => $clean_config['queue'],
'name' => $clean_config['name'],
'description' => $clean_config['description'],
'callback' => $clean_config['callback'],
'total_count' => $clean_config['total_count'],
'current_count' => $clean_config['current_count'],
'step' => $clean_config['step'],
'status' => $clean_config['status'],
'data' => $clean_config['data'],
'date_created' => $clean_config['date_created'],
'date_completed' => null
) );
} catch ( \InvalidArgumentException $exception ) {
add_action( 'admin_notices', function () use ( $config, $exception ) {
echo '<div class="error"><p>' . sprintf( __( 'There was an error adding job: %s. Error message: %s If this issue persists, please contact the Restrict Content Pro support team.', 'rcp' ), $config['name'], $exception->getMessage() ) . '</p></div>';
} );
return new \WP_Error( 'invalid_job_config', sprintf( __( 'Invalid job configuration: %s', 'rcp' ), $exception->getMessage() ) );
}
if ( empty( $job_id ) ) {
return new \WP_Error( 'error_inserting_job', __( 'Failed to add job to queue', 'rcp' ) );
}
return $job_id;
}
/**
* Retrieve a single job by ID.
*
* @param int $job_id ID of the job to retrieve.
*
* @since 3.0
* @return Job|false
*/
function get_job( $job_id ) {
$queue_query = new \RCP\Database\Queries\Queue();
$job_config = $queue_query->get_item( absint( $job_id ) );
return $job_config;
}
/**
* Update a job
*
* @param int $job_id ID of the job to update.
* @param array $data Data to update.
*
* @since 3.1
* @return bool
*/
function update_job( $job_id, $data = array() ) {
$queue_query = new \RCP\Database\Queries\Queue();
// Maybe serialize the data.
if ( ! empty( $data['data'] ) ) {
$data['data'] = maybe_serialize( $data['data'] );
}
return $queue_query->update_item( $job_id, $data );
}
/**
* Get a single job by a field/value pair.
*
* @param string $field Column to search in.
* @param string $value Value of the row.
*
* @since 3.1
* @return Job|false
*/
function get_job_by( $field = '', $value = '' ) {
$queue_query = new \RCP\Database\Queries\Queue();
return $queue_query->get_item_by( $field, $value );
}
/**
* Get jobs
*
* @param array $args Query arguments to override the defaults.
*
* @since 3.0
* @return array Array of Job objects.
*/
function get_jobs( $args = array() ) {
$args = wp_parse_args( $args, array(
'queue' => 'rcp_core'
) );
$queue_query = new \RCP\Database\Queries\Queue();
return $queue_query->query( $args );
}
/**
* Deletes a job.
*
* @since 3.0
*
* @param int $job_id ID of job to delete.
*
* @return bool True if the job is deleted, false if not.
*/
function delete_batch_job( $job_id ) {
$queue_query = new \RCP\Database\Queries\Queue();
$deleted = $queue_query->delete_item( absint( $job_id ) );
return ! empty( $deleted );
}
/**
* Processes the specified batch job.
*
* @since 3.0
*
* @param int $job_id The ID job to process.
*
* @return bool|\WP_Error True if the batch was successful, WP_Error if not.
*/
function process_batch( $job_id ) {
$job = get_job( $job_id );
if ( empty( $job ) ) {
return new \WP_Error( 'invalid_job_id', __( 'Invalid job ID.', 'rcp' ) );
}
return $job->process_batch();
}
/**
* Display admin notices.
*
* @since 3.0
*
* @return void
*/
function display_admin_notice() {
// Don't show notices on batch processing page.
if ( isset( $_GET['rcp-queue'] ) ) {
return;
}
$queue = get_jobs( array(
'status' => 'incomplete'
) );
if ( ! empty( $queue ) ) {
echo '<div class="notice notice-info"><p>' . __( 'Restrict Content Pro needs to perform system maintenance. This maintenance is <strong>REQUIRED</strong>.', 'rcp' ) . '</p>';
echo '<p>' . sprintf( __( '<a href="%s">Click here</a> to learn more and start the upgrade.', 'rcp' ), esc_url( admin_url( 'admin.php?page=rcp-tools&tab=batch&rcp-queue=rcp_core' ) ) );
echo '</div>';
}
}
add_action( 'admin_notices', __NAMESPACE__ . '\display_admin_notice' );

View File

@@ -0,0 +1,151 @@
"use strict";
let table,
form,
submit_button,
progress_bar,
progress_percent,
message,
error_wrap;
let RCP_Batch = {
/**
* Listens for job submissions and initiates job processing.
*/
listen: function () {
let batch = this;
form = jQuery( '.rcp-batch-form' );
form.on( 'submit', function ( event ) {
event.preventDefault();
table = jQuery( this ).parents( '.rcp-batch-processing-job-table' );
batch.set_vars( table );
submit_button.prop( 'disabled', true ).hide();
table.find( '.spinner' ).addClass( 'is-active' ).show();
error_wrap.hide();
message.text( '' );
let data = {
action: 'rcp_process_batch',
job_id: table.find( '.rcp-batch-processing-job-id' ).val(),
rcp_batch_nonce: rcp_batch_vars.batch_nonce
};
batch.process( data, table.find( '.rcp-batch-processing-job-step' ).val(), table );
} );
if ( form.find( '#rcp-job-autostart' ).length ) {
form.trigger( 'submit' );
}
},
/**
* Set variables.
*
* @param object table
*/
set_vars: function ( table ) {
submit_button = table.find( '.button-primary' );
progress_bar = table.find( '.rcp-batch-processing-job-progress-bar span' );
progress_percent = table.find( '.rcp-batch-processing-job-percent-complete' );
message = table.find( '.rcp-batch-processing-message' );
error_wrap = table.find( '.rcp-batch-processing-errors' );
},
/**
* Process the specified job.
*
* @param {object} data Job data
* @param {int} step Step to process
* @param {object} table Table object for modifying the DOM
*/
process: function ( data, step, table ) {
let batch = this;
data.step = step;
batch.set_vars( table );
jQuery.ajax( {
dataType: 'json',
data: data,
type: 'POST',
url: ajaxurl,
success: function ( response ) {
if ( false === response.success ) {
submit_button.prop( 'disabled', false ).show();
table.find( '.spinner' ).removeClass( 'is-active' ).hide();
message.text( response.data.message + ' ' + rcp_batch_vars.i18n.job_retry );
return;
}
if ( response.data.complete ) {
progress_bar.css( 'width', response.data.percent_complete + '%' );
progress_percent.text( response.data.percent_complete );
table.find( '.spinner' ).removeClass( 'is-active' ).hide();
message.html( response.data.complete_message ).show();
if ( response.data.has_errors ) {
error_wrap.find( 'td' ).empty().html( response.data.errors );
error_wrap.show();
}
} else if ( response.data.error ) {
// TODO: show errors
console.log( 'error processing batch' );
console.log( response.data.error );
} else if ( response.data.next_step ) {
progress_bar.css( 'width', response.data.percent_complete + '%' );
progress_percent.text( response.data.percent_complete );
batch.process( data, response.data.next_step, table );
} else {
// wtf happened
console.log( response );
message.text( response.data.message + ' ' + rcp_batch_vars.i18n.job_retry );
}
},
error: function ( response ) {
console.log( new Date() + ' error' );
console.log( response );
}
} );
}
};
/**
* Loads the job listener.
*/
jQuery( document ).ready( function () {
RCP_Batch.listen();
} );

View File

@@ -0,0 +1,534 @@
<?php
/**
* Job Object
*
* @package restrict-content-pro
* @copyright Copyright (c) 2018, Restrict Content Pro team
* @license GPL2+
* @since 3.0
*/
namespace RCP\Utils\Batch;
use RCP\Base_Object;
// Exit if accessed directly
defined( 'ABSPATH' ) || exit;
/**
* Class Job
*
* @package RCP\Utils\Batch
* @since 3.0
*/
final class Job extends Base_Object {
/**
* @var int
*/
protected $id = 0;
/**
* @var string
*/
protected $queue = 'rcp_core';
/**
* @var string
*/
protected $name = '';
/**
* @var string
*/
protected $description = '';
/**
* @var string
*/
protected $callback = '';
/**
* @var int
*/
protected $total_count = 0;
/**
* @var int
*/
protected $current_count = 0;
/**
* @var int
*/
protected $step = 0;
/**
* @var string
*/
protected $status = 'incomplete';
/**
* @var array
*/
protected $data = array();
/**
* @var string
*/
protected $date_created = '';
/**
* @var string
*/
protected $date_completed = '';
/**
* @var string
*/
protected $error_key = '';
/**
* @var \RCP\Database\Queries\Queue
*/
private $queue_query;
/**
* Job Config constructor.
*
* @param object $config Job row from the database.
*
* @since 3.0
*/
public function __construct( $config = null ) {
if ( null === $config ) {
return;
}
try {
$this->validate( $config );
} catch ( \InvalidArgumentException $exception ) {
}
$config = $this->sanitize( $config );
parent::__construct( $config );
$this->error_key = 'rcp_job_' . $this->get_id() . '_errors';
$this->queue_query = new \RCP\Database\Queries\Queue();
}
/**
* Get the job ID
*
* @since 3.0
* @return int
*/
public function get_id() {
return $this->id;
}
/**
* Get the associated queue
*
* @since 3.0
* @return string
*/
public function get_queue() {
return $this->queue;
}
/**
* Get the job name
*
* @since 3.0
* @return string
*/
public function get_name() {
return $this->name;
}
/**
* Get the job description
*
* @since 3.0
* @return string
*/
public function get_description() {
return $this->description;
}
/**
* Get the callback class name
*
* @since 3.0
* @return string
*/
public function get_callback() {
return $this->callback;
}
/**
* Get the callback object.
*
* @since 3.0
* @return Abstract_Job_Callback|false Callback class on success, false on failure.
*/
public function get_callback_object() {
$class_name = $this->get_callback();
if ( class_exists( $class_name ) ) {
$object = new $class_name( $this );
if ( method_exists( $object, 'execute' ) ) {
return $object;
}
}
return false;
}
/**
* Get the total number of items to be processed
*
* @since 3.0
* @return int
*/
public function get_total_count() {
return $this->total_count;
}
/**
* Get the number of items processed so far
*
* @since 3.0
* @return int
*/
public function get_current_count() {
return $this->current_count;
}
/**
* Set the total count
*
* @param int $count
*
* @since 3.0
*/
public function set_total_count( $count = 0 ) {
$this->total_count = absint( $count );
$this->save();
}
/**
* Set the current count to a specific value
*
* @param int $count
*
* @since 3.1
*/
public function set_current_count( $count = 0 ) {
$this->current_count = $count;
$this->save();
}
/**
* Add to the current count
*
* @param int $amount Amount to add.
*
* @since 3.0
*/
public function adjust_current_count( $amount = 0 ) {
$this->current_count = $this->get_current_count() + (int) $amount;
$this->save();
}
/**
* Get the current step
*
* @since 3.0
* @return int
*/
public function get_step() {
return $this->step;
}
/**
* Set the next step
*
* @param int $step
*
* @since 3.0
*/
public function set_step( $step = 0 ) {
$this->step = absint( $step );
$this->save();
}
/**
* Get the job status
*
* @since 3.0
* @return string
*/
public function get_status() {
return $this->status;
}
/**
* Get job data
*
* @since 3.1
* @return array
*/
public function get_data() {
return ! empty( $this->data ) ? $this->data : array();
}
/**
* Get the date the job was created
*
* @since 3.1.2
* @return string
*/
public function get_date_created() {
return $this->date_created;
}
/**
* Get the date the job was completed
*
* @since 3.1.2
* @return string
*/
public function get_date_completed() {
return $this->date_completed;
}
/**
* Adds additional data to the existing data (merging the two arrays). It does not overwrite.
*
* To overwrite the existing data, use `update_job()`
* @see update_job()
*
* @param array $new_data New data to add.
*
* @since 3.1
*/
public function add_data( $new_data ) {
$existing_data = $this->get_data();
$new_data = array_merge( $existing_data, $new_data );
$this->data = $new_data;
$this->save();
}
/**
* Set the job status
*
* @since 3.0
*
* @param string $status
*/
public function set_status( $status = 'complete' ) {
$this->status = sanitize_key( $status );
if ( 'complete' === $status ) {
$this->date_completed = current_time( 'mysql' );
}
$this->save();
}
/**
* Determines whether or not the job has been completed.
*
* @since 3.0
* @return boolean True if the job is completed, false if not.
*/
public function is_completed() {
return 'complete' === $this->get_status();
}
/**
* Returns the job completion percentage.
*
* @since 3.0
* @return int
*/
public function get_percent_complete() {
$percent_complete = 0;
$total_count = $this->get_total_count();
if ( $total_count > 0 ) {
$percent_complete = (int) ( ( $this->get_current_count() / $total_count ) * 100 );
}
if ( $percent_complete > 100 ) {
$percent_complete = 100;
}
return $percent_complete;
}
/**
* Get error messages
*
* @since 3.0.2
* @return array
*/
public function get_errors() {
$errors = get_option( $this->error_key );
if ( ! is_array( $errors ) ) {
$errors = array();
}
return $errors;
}
/**
* Add an error message
*
* @param string $error
*
* @since 3.0.2
* @return void
*/
public function add_error( $error ) {
$errors = $this->get_errors();
$errors[] = $error;
update_option( $this->error_key, $errors );
}
/**
* Whether or not this job has any errors
*
* @since 3.0.2
* @return bool
*/
public function has_errors() {
$errors = $this->get_errors();
return ! empty( $errors );
}
/**
* Clear error messages
*
* @since 3.0.2
* @return void
*/
public function clear_errors() {
delete_option( $this->error_key );
}
/**
* Process the next batch of this job.
*
* @since 3.0
* @return true|\WP_Error True on success, WP_Error object on failure.
*/
public function process_batch() {
$object = $this->get_callback_object();
if ( empty( $object ) ) {
return new \WP_Error( 'invalid_job_callback', sprintf( __( 'Error processing %s - invalid callback.', 'rcp' ), $this->get_name() ) );
}
$object->execute();
return true;
}
/**
* Save the job
*
* @since 3.0
*/
public function save() {
$args = array(
'queue' => $this->get_queue(),
'name' => $this->get_name(),
'description' => $this->get_description(),
'callback' => $this->get_callback(),
'total_count' => $this->get_total_count(),
'current_count' => $this->get_current_count(),
'step' => $this->get_step(),
'status' => $this->get_status(),
'data' => maybe_serialize( $this->get_data() ),
'date_created' => $this->get_date_created(),
'date_completed' => $this->get_date_completed()
);
$updated = $this->queue_query->update_item( $this->get_id(), $args );
if ( $updated === false ) {
rcp_log( sprintf( 'There was an error saving the job in %s. Job config: %s', __METHOD__, var_export( $args, true ) ), true );
}
}
/**
* Validate the configuration to ensure all requirements are met.
*
* @param object $config
*
* @since 3.0
*/
private function validate( $config ) {
$error = __( 'You must supply a valid name, description, and JobInterface callback when registering a batch job.', 'rcp' );
if ( empty( $config ) ) {
throw new \InvalidArgumentException( $error );
}
if ( empty( $config->name ) || empty( $config->description ) ) {
throw new \InvalidArgumentException( $error );
}
if ( empty( $config->callback ) || ! class_exists( $config->callback ) ) {
throw new \InvalidArgumentException( $error );
}
$interfaces = class_implements( $config->callback );
if ( false === $interfaces || ! in_array( 'RCP\Utils\Batch\JobInterface', $interfaces, true ) ) {
throw new \InvalidArgumentException( $error );
}
}
/**
* Sanitize the configuration.
*
* @param object $config
*
* @since 3.0
* @return array
*/
private function sanitize( $config ) {
return [
'id' => ! empty( $config->id ) ? absint( $config->id ) : false,
'queue' => ! empty( $config->queue ) ? sanitize_key( $config->queue ) : 'rcp_core',
'name' => sanitize_text_field( $config->name ),
'description' => wp_kses_post( $config->description ),
'callback' => $config->callback, // already validated to be a callable class
'total_count' => ! empty( $config->total_count ) ? absint( $config->total_count ) : 0,
'current_count' => ! empty( $config->current_count ) ? absint( $config->current_count ) : 0,
'step' => ! empty( $config->step ) ? absint( $config->step ) : 0,
'status' => empty( $config->status ) ? 'incomplete' : $config->status,
'data' => ! empty( $config->data ) ? maybe_unserialize( $config->data ) : array(),
'date_created' => ! empty( $config->date_created ) ? sanitize_text_field( $config->date_created ) : current_time( 'timestamp' ),
'date_completed' => ! empty( $config->date_completed ) ? sanitize_text_field( $config->date_completed ) : ''
];
}
}

View File

@@ -0,0 +1,272 @@
<?php
/**
* class-batch-csv-export-base.php
*
* @package restrict-content-pro
* @copyright Copyright (c) 2020, Sandhills Development, LLC
* @license GPL2+
*/
namespace RCP\Batch\CSV_Exports;
use RCP\Utils\Batch\Abstract_Job_Callback;
use RCP\Utils\Batch\Job;
/**
* Class Base
*
* @package RCP\Batch\CSV_Exports
*/
abstract class Base extends Abstract_Job_Callback {
/**
* Type of export being performed (`memberships`, `payments`, etc.)
*
* @var string
*/
protected $export_type;
/**
* File the export data is stored in.
*
* @var string
*/
protected $file;
/**
* Settings from the UI form
*
* @var array
*/
protected $settings;
/**
* Base constructor.
*
* @param Job $job
*/
public function __construct( $job ) {
parent::__construct( $job );
$exporter = rcp_get_csv_exporter_by_callback( $this->get_job()->get_callback() );
$this->export_type = ! empty( $exporter['key'] ) ? $exporter['key'] : '';
$job_data = $this->get_job()->get_data();
// Set up the file path.
$this->file = ! empty( $job_data['filepath'] ) ? $job_data['filepath'] : false;
if ( empty( $this->file ) ) {
$this->file = tempnam( get_temp_dir(), 'rcp-' );
$this->get_job()->add_data( array(
'filepath' => tempnam( get_temp_dir(), 'rcp-' )
) );
}
// Get settings from the job data.
$this->settings = ! empty( $job_data['settings'] ) ? $job_data['settings'] : array();
}
/**
* Returns the column headers for the export.
*
* @return array
*/
abstract public function get_columns();
/**
* Returns the total number of records to be exported.
*
* @return int
*/
abstract public function get_total();
/**
* @return $this
*/
public function execute() {
rcp_log( sprintf( 'Batch Processing: Initiating RCP Batch Export %s. Current step: %d; current count: %d; total count: %d.', $this->export_type, $this->get_job()->get_step(), $this->get_job()->get_current_count(), $this->get_job()->get_total_count() ), true );
if ( $this->start_time === null ) {
$this->start_time = time();
}
if ( ! rcp_current_user_can_export() ) {
$this->get_job()->add_error( __( 'You do not have permission to perform this action.', 'rcp' ) );
return $this;
}
if ( $this->time_exceeded() || $this->get_job()->is_completed() ) {
return $this;
}
parent::execute();
// On the first step, clear errors, clean up the file, add headers, calculate total count.
if ( 0 === $this->get_job()->get_step() ) {
$this->get_job()->clear_errors();
$this->process_headers();
$this->get_job()->set_total_count( $this->get_total() );
}
// Get the data for this batch.
$batch = $this->get_batch();
// If we don't have any, we're done.
if ( empty( $batch ) ) {
$this->finish();
return $this;
}
// Otherwise, stash this batch and continue.
$this->process_batch( $batch );
$this->get_job()->adjust_current_count( count( $batch ) );
$current_step = $this->get_job()->get_step();
$current_step++;
$this->get_job()->set_step( $current_step );
return $this;
}
/**
* Retrieves the batch data from the database.
*
* @return array
*/
abstract public function get_batch();
/**
* @inheritDoc
*/
public function finish() {
// Set job to complete.
$this->get_job()->set_status( 'complete' );
$errors = $this->get_job()->get_errors();
rcp_log( sprintf( 'Batch CSV Export: Job complete. Errors: %s', var_export( $errors, true ) ), true );
}
/**
* Processes the CSV column headers and writes the resulting string to the file.
*
* @since 3.4
*/
protected function process_headers() {
$row_data = '';
$columns = $this->get_columns();
$i = 1;
foreach ( $columns as $column_key => $column_name ) {
$row_data .= sprintf( '"%s"', addslashes( $column_name ) );
$row_data .= $i === count( $columns ) ? '' : ',';
$i++;
}
$row_data .= "\r\n";
$this->stash_batch( $row_data, false );
}
/**
* Processes the current batch data to format each row and stash the resulting string in the file.
*
* @param array $batch Current batch of data.
*
* @since 3.4
*/
protected function process_batch( $batch ) {
$row_data = '';
$columns = $this->get_columns();
if ( empty( $batch ) || ! is_array( $batch ) ) {
return;
}
foreach ( $batch as $row ) {
$i = 1;
foreach ( $columns as $column_key => $column_name ) {
if ( array_key_exists( $column_key, $row ) ) {
$row_data .= sprintf( '"%s"', addslashes( preg_replace( "/\"/", "'", $row[ $column_key ] ) ) );
}
$row_data .= $i === count( $columns ) ? '' : ',';
$i++;
}
$row_data .= "\r\n";
}
$this->stash_batch( $row_data );
}
/**
* Retrieves the CSV file contents.
*
* @since 3.4
* @return string
*/
protected function get_file() {
$file = '';
if ( @file_exists( $this->file ) ) {
$file = @file_get_contents( $this->file );
} else {
@file_put_contents( $this->file, '' );
@chmod( $this->file, 0664 );
}
return $file;
}
/**
* Appends the formatted string data to the file and saves the new contents.
*
* @param string $batch Batch data formatted as a comma-separated string.
* @param bool $append Whether to append the new data (true) or override (false).
*
* @since 3.4
*/
protected function stash_batch( $batch, $append = true ) {
$file = $this->get_file();
if ( $append ) {
$file .= $batch;
} else {
$file = $batch;
}
@file_put_contents( $this->file, $file );
}
/**
* Message to display upon job completion.
*
* @since 3.4
* @return string
*/
public function get_complete_message() {
$download_url = wp_nonce_url( add_query_arg( array(
'rcp-action' => 'download_export_file',
'export_id' => urlencode( $this->get_job()->get_id() )
), admin_url() ), 'rcp_download_export_file' );
return '<a href="' . esc_url( $download_url ) . '">' . __( 'Download Export File', 'rcp' ) . '</a>';
}
}

View File

@@ -0,0 +1,166 @@
<?php
/**
* Export Memberships
*
* @package restrict-content-pro
* @copyright Copyright (c) 2020, Sandhills Development, LLC
* @license GPL2+
*/
namespace RCP\Batch\CSV_Exports;
use RCP_Membership;
/**
* Class Memberships
*
* @package RCP\Batch\CSV_Exports
*/
class Memberships extends Base {
/**
* @inheritDoc
*/
public function get_columns() {
$cols = array(
'id' => __( 'Membership ID', 'rcp' ),
'user_id' => __( 'User ID', 'rcp' ),
'user_login' => __( 'User Login', 'rcp' ),
'user_email' => __( 'User Email', 'rcp' ),
'first_name' => __( 'First Name', 'rcp' ),
'last_name' => __( 'Last Name', 'rcp' ),
'subscription' => __( 'Membership Level ID', 'rcp' ),
'membership_level_name' => __( 'Membership Level Name', 'rcp' ),
'subscription_key' => __( 'Subscription Key', 'rcp' ),
'created_date' => __( 'Created Date', 'rcp' ),
'expiration' => __( 'Expiration Date', 'rcp' ),
'status' => __( 'Status', 'rcp' ),
'times_billed' => __( 'Times Billed', 'rcp' ),
'discount_codes' => __( 'Discount Codes', 'rcp' ),
'gateway' => __( 'Gateway', 'rcp' ),
'gateway_customer_id' => __( 'Gateway Customer ID', 'rcp' ),
'profile_id' => __( 'Gateway Subscription ID', 'rcp' ),
'is_recurring' => __( 'Auto Renew', 'rcp' )
);
/**
* Filters the columns to export.
*
* @param array $cols
*
* @since 1.5
*/
return apply_filters( 'rcp_export_csv_cols_members', $cols );
}
/**
* Builds and returns an array of query args to use in count and get functions.
*
* @return array
*/
private function get_query_args() {
$number = $this->get_amount_per_step();
if ( ! empty( $this->settings['number'] ) && $number > $this->settings['number'] ) {
$number = $this->settings['number'];
}
$args = array(
'number' => $number,
'offset' => $this->offset
);
if ( ! empty( $this->settings['level_id'] ) ) {
$args['object_id'] = absint( $this->settings['level_id'] );
}
if ( ! empty( $this->settings['status'] ) && 'all' !== $this->settings['status'] ) {
$args['status'] = strtolower( $this->settings['status'] );
}
return $args;
}
/**
* @inheritDoc
*/
public function get_batch() {
// Bail with no results if a "Maximum Number" has been specified and we've exceeded that.
if ( ! empty( $this->settings['number'] ) && ( $this->get_amount_per_step() * $this->offset ) > $this->settings['number'] ) {
return array();
}
$memberships = rcp_get_memberships( $this->get_query_args() );
$batch = array();
foreach ( $memberships as $membership ) {
$user = get_userdata( $membership->get_user_id() );
$discounts = get_user_meta( $membership->get_user_id(), 'rcp_user_discounts', true );
if ( ! empty( $discounts ) && is_array( $discounts ) && ! $discounts instanceof \stdClass ) {
foreach ( $discounts as $key => $code ) {
if ( ! is_string( $code ) ) {
unset( $discounts[ $key ] );
}
}
$discounts = implode( ' ', $discounts );
}
$membership_data = array(
'id' => $membership->get_id(),
'user_id' => $membership->get_customer()->get_user_id(),
'user_login' => $user->user_login,
'user_email' => $user->user_email,
'first_name' => $user->first_name,
'last_name' => $user->last_name,
'subscription' => $membership->get_object_id(),
'membership_level_name' => $membership->get_membership_level_name(),
'subscription_key' => $membership->get_subscription_key(),
'created_date' => $membership->get_created_date( false ),
'expiration' => $membership->get_expiration_date( false ),
'status' => $membership->get_status(),
'times_billed' => $membership->get_times_billed(),
'discount_codes' => $discounts,
'gateway' => $membership->get_gateway(),
'gateway_customer_id' => $membership->get_gateway_customer_id(),
'profile_id' => $membership->get_gateway_subscription_id(),
'is_recurring' => $membership->is_recurring()
);
if ( has_filter( 'rcp_export_members_get_data_row' ) ) {
$membership_data = apply_filters_deprecated( 'rcp_export_members_get_data_row', array(
$membership_data,
new \RCP_Member( $user->ID )
), '3.0', 'rcp_export_memberships_get_data_row' );
}
/**
* Filters the data row.
*
* @param array $membership_data Membership data for this row.
* @param RCP_Membership $membership Membership object.
*
* @since 3.0
*/
$batch[] = apply_filters( 'rcp_export_memberships_get_data_row', $membership_data, $membership );
}
$batch = apply_filters_deprecated( 'rcp_export_get_data', array( $batch ), '3.4' );
$batch = apply_filters_deprecated( 'rcp_export_get_data_members', array( $batch ), '3.4' );
return $batch;
}
/**
* Counts the total number of expected results.
*
* @return int
*/
public function get_total() {
return rcp_count_memberships( $this->get_query_args() );
}
}

View File

@@ -0,0 +1,152 @@
<?php
/**
* class-export-payments.php
*
* @package restrict-content-pro
* @copyright Copyright (c) 2020, Ashley Gibson
* @license GPL2+
*/
namespace RCP\Batch\CSV_Exports;
use RCP_Payments;
/**
* Class Payments
*
* @package RCP\Batch\CSV_Exports
*/
class Payments extends Base {
/**
* @inheritDoc
*/
public function get_columns() {
$cols = array(
'id' => __( 'ID', 'rcp' ),
'status' => __( 'Status', 'rcp' ),
'object_type' => __( 'Purchase Type', 'rcp' ),
'object_id' => __( 'Membership Level ID', 'rcp' ),
'subscription' => __( 'Membership Level Name', 'rcp' ),
'amount' => __( 'Total Amount', 'rcp' ),
'subtotal' => __( 'Subtotal', 'rcp' ),
'credits' => __( 'Credits', 'rcp' ),
'fees' => __( 'Fees', 'rcp' ),
'discount_amount' => __( 'Discount Amount', 'rcp' ),
'discount_code' => __( 'Discount Code', 'rcp' ),
'user_id' => __( 'User ID', 'rcp' ),
'user_login' => __( 'User Login', 'rcp' ),
'user_email' => __( 'User Email', 'rcp' ),
'customer_id' => __( 'Customer ID', 'rcp' ),
'membership_id' => __( 'Membership ID', 'rcp' ),
'payment_type' => __( 'Payment Type', 'rcp' ),
'gateway' => __( 'Gateway', 'rcp' ),
'subscription_key' => __( 'Subscription Key', 'rcp' ),
'transaction_id' => __( 'Transaction ID', 'rcp' ),
'transaction_type' => __( 'Transaction Type', 'rcp' ),
'date' => __( 'Date', 'rcp' )
);
/**
* Filters the columns to export.
*
* @param array $cols
*
* @since 1.5
*/
return apply_filters( 'rcp_export_csv_cols_payments', $cols );
}
/**
* Builds and returns an array of query args to use in count and get functions.
*
* @return array
*/
private function get_query_args() {
$args = array(
'number' => $this->get_amount_per_step(),
'offset' => $this->offset
);
if ( ! empty( $this->settings['year'] ) ) {
$args['date']['year'] = absint( $this->settings['year'] );
}
if ( ! empty( $this->settings['month'] ) ) {
$args['date']['month'] = absint( $this->settings['month'] );
}
return $args;
}
/**
* @inheritDoc
*/
public function get_batch() {
$batch = array();
$rcp_db = new RCP_Payments;
$payments = $rcp_db->get_payments( $this->get_query_args() );
foreach ( $payments as $payment ) {
$user = get_userdata( $payment->user_id );
$payment_data = array(
'id' => $payment->id,
'status' => $payment->status,
'object_type' => $payment->object_type,
'object_id' => $payment->object_id,
'subscription' => $payment->subscription,
'amount' => $payment->amount,
'subtotal' => $payment->subtotal,
'credits' => $payment->credits,
'fees' => $payment->fees,
'discount_amount' => $payment->discount_amount,
'discount_code' => $payment->discount_code,
'user_id' => $payment->user_id,
'user_login' => isset( $user->user_login ) ? $user->user_login : '',
'user_email' => isset( $user->user_email ) ? $user->user_email : '',
'customer_id' => ! empty( $payment->customer_id ) ? $payment->customer_id : '',
'membership_id' => ! empty( $payment->membership_id ) ? $payment->membership_id : '',
'payment_type' => $payment->payment_type,
'gateway' => $payment->gateway,
'subscription_key' => $payment->subscription_key,
'transaction_id' => $payment->transaction_id,
'transaction_type' => ! empty( $payment->transaction_type ) ? $payment->transaction_type : '',
'date' => $payment->date
);
/**
* Filters the payment information that's exported to this row.
*
* @param array $payment_data
* @param object $payment
*/
$payment_data = apply_filters( 'rcp_export_payments_get_data_row', $payment_data, $payment );
$batch[] = $payment_data;
}
$batch = apply_filters_deprecated( 'rcp_export_get_data', array( $batch ), '3.4' );
$batch = apply_filters_deprecated( 'rcp_export_get_data_payments', array( $batch ), '3.4' );
return $batch;
}
/**
* Counts the total number of expected results.
*
* @return int
*/
public function get_total() {
$rcp_db = new RCP_Payments;
return $rcp_db->count( $this->get_query_args() );
}
}

View File

@@ -0,0 +1 @@
<?php // Silence is golden.

View File

@@ -0,0 +1,307 @@
<?php
/**
* Batch CSV Import Base Class
*
* @since 3.1
* @copyright Copyright (c) 2019, Restrict Content Pro team
* @license GPL2+
* @package restrict-content-pro
*/
use RCP\Utils\Batch\Abstract_Job_Callback;
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Class RCP_Batch_Callback_CSV_Import_Base
*
* @since 3.1
*/
class RCP_Batch_Callback_CSV_Import_Base extends Abstract_Job_Callback {
/**
* Current batch of rows
*
* @var array
*/
protected $rows;
/**
* Path to the file being imported.
*
* @var string
*/
protected $file;
/**
* The parsed CSV file being imported.
*
* @var array
*/
protected $csv;
/**
* Map of CSV column headers -> database fields
*
* @var array
*/
protected $field_map;
/**
* Settings from the UI form
*
* @var array
*/
protected $settings;
/**
* RCP_Batch_Callback_CSV_Import_Base constructor.
*
* @param \RCP\Utils\Batch\Job $job
*/
public function __construct( $job ) {
parent::__construct( $job );
$file = ! empty( $this->get_job()->get_data()['file_path'] ) ? $this->get_job()->get_data()['file_path'] : '';
if ( ! empty( $file ) ) {
$this->set_csv_file( $file );
}
$this->field_map = ! empty( $this->get_job()->get_data()['field_map'] ) ? $this->get_job()->get_data()['field_map'] : array();
$this->settings = ! empty( $this->get_job()->get_data()['settings'] ) ? $this->get_job()->get_data()['settings'] : array();
}
/**
* Set the CSV file path. This then also parses the CSV and populates that property.
*
* @param string $file
*/
public function set_csv_file( $file ) {
$uploads = wp_get_upload_dir();
$this->file = path_join( $uploads['basedir'], $file );
if ( empty( $this->file ) || ! file_exists( $this->file ) ) {
return;
}
$csv = array_map( 'str_getcsv', file( $this->file ) );
array_walk( $csv, function ( &$a ) use ( $csv ) {
/*
* Make sure the two arrays have the same lengths.
* If not, we trim the larger array to match the smaller one.
*/
$min = min( count( $csv[0] ), count( $a ) );
$headers = array_slice( $csv[0], 0, $min );
$values = array_slice( $a, 0, $min );
$a = array_combine( $headers, $values );
} );
array_shift( $csv );
$this->csv = $csv;
}
/**
* Get the column header names
*
* @return array
*/
public function get_columns() {
$columns = array();
if ( isset( $this->csv[0] ) && is_array( $this->csv[0] ) ) {
$columns = array_keys( $this->csv[0] );
}
return $columns;
}
/**
* Get the first row of the CSV file
*
* This is used for showing an example of what the import will look like.
*
* @return array The first row after the header.
*/
public function get_first_row() {
if ( ! is_array( $this->csv ) ) {
return array();
}
return array_map( array( $this, 'trim_preview' ), current( $this->csv ) );
}
/**
* Map the CSV column headers to database fields
*
* @param array $fields
*/
public function map_fields( $fields ) {
$this->field_map = array_map( 'sanitize_text_field', $fields );
$this->get_job()->add_data( array(
'field_map' => $this->field_map
) );
}
/**
* Trims a column value for preview
*
* @param string $string
*
* @return string
*/
protected function trim_preview( $string ) {
if ( ! is_numeric( $string ) ) {
$long = strlen( $string ) >= 30;
$string = substr( $string, 0, 30 );
$string = $long ? $string . '...' : $string;
}
return $string;
}
/**
* @inheritdoc
*/
public function execute() {
rcp_log( sprintf( 'Batch Processing: Initiating RCP_Batch_Callback_CSV_Import_Base. Current step: %d; current count: %d; total count: %d.', $this->get_job()->get_step(), $this->get_job()->get_current_count(), $this->get_job()->get_total_count() ), true );
if ( $this->start_time === null ) {
$this->start_time = time();
}
if ( $this->time_exceeded() || $this->get_job()->is_completed() ) {
return $this;
}
parent::execute();
if ( 0 === $this->get_job()->get_step() ) {
$this->get_job()->clear_errors();
}
if ( ! file_exists( $this->file ) ) {
$this->get_job()->add_error( __( 'Import file not found.', 'rcp' ) );
$this->finish();
return $this;
}
$this->rows = $this->get_batch();
if ( empty( $this->rows ) || $this->get_job()->is_completed() ) {
$this->finish();
return $this;
}
$this->process_batch();
$current_step = $this->get_job()->get_step();
$current_step++;
$this->get_job()->set_step( $current_step );
return $this;
}
/**
* Get the next batch of CSV rows.
*
* @since 3.1
* @return array
*/
private function get_batch() {
$rows = array();
$i = 1;
if ( is_array( $this->csv ) ) {
if ( empty( $this->get_job()->get_total_count() ) ) {
$this->get_job()->set_total_count( count( $this->csv ) );
rcp_log( sprintf( 'Batch CSV Import: Total count: %d.', count( $this->csv ) ), true );
}
foreach ( $this->csv as $row_number => $row ) {
// Skip all rows until we pass our offset.
if ( $row_number + 1 <= $this->offset ) {
continue;
}
// Bail if we're done with this batch.
if ( $i > $this->size ) {
break;
}
/*
* The first real row number will be `0`, which isn't user friendly for most people. So we add `+2` to
* achieve the following:
*
* 1. First, start at `1` instead of `0`.
* 2. Account for the header, which should be row #1. The first actual value starts at #2.
*
* This just improves row number display during error logging.
*/
$adjusted_row_number = $row_number + 2;
$rows[ $adjusted_row_number ] = $row;
$i ++;
}
}
rcp_log( sprintf( 'Batch CSV Import: %d results found in query for LIMIT %d OFFSET %d.', count( $rows ), $this->size, $this->offset ) );
return $rows;
}
/**
* Overwrite this.
*/
public function process_batch() {
global $rcp_options;
// Disable debug mode.
$rcp_options['debug_mode'] = false;
}
/**
* Complete the import
* - Set status to "complete".
* - Delete the CSV file.
*
* @return void
*/
public function finish() {
// Set job to complete.
$this->get_job()->set_status( 'complete' );
$errors = $this->get_job()->get_errors();
rcp_log( sprintf( 'Batch CSV Import: Job complete. Errors: %s', var_export( $errors, true ) ), true );
// Delete the uploaded file.
wp_delete_file( $this->file );
}
}

View File

@@ -0,0 +1,402 @@
<?php
/**
* Import Memberships
*
* @since 3.1
* @copyright Copyright (c) 2019, Restrict Content Pro team
* @license GPL2+
* @package restrict-content-pro
*/
use RCP\Membership_Level;
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Class RCP_Batch_Callback_Import_Memberships
*
* @since 3.1
*/
class RCP_Batch_Callback_Import_Memberships extends RCP_Batch_Callback_CSV_Import_Base {
/**
* Process batch
*/
public function process_batch() {
parent::process_batch();
// Maybe disable notification emails.
if ( ! empty( $this->settings['disable_notification_emails'] ) ) {
remove_action( 'rcp_membership_post_activate', 'rcp_email_on_membership_activation', 10 );
remove_action( 'rcp_membership_post_cancel', 'rcp_email_on_membership_cancellation', 10 );
remove_action( 'rcp_transition_membership_status_expired', 'rcp_email_on_membership_expiration', 10 );
}
$processed = [];
if ( empty( $this->rows ) || $this->time_exceeded() ) {
$this->get_job()->adjust_current_count( count( $processed ) );
return;
}
foreach ( $this->rows as $row_number => $row ) {
/**
* Parse user account.
*/
$user = $this->get_user( $row );
if ( is_wp_error( $user ) ) {
$this->get_job()->add_error( sprintf( __( 'Skipping row #%d. Error code: %s; Error message: %s', 'rcp' ), $row_number, $user->get_error_code(), $user->get_error_message() ) );
continue;
}
/**
* Retrieve or create customer record.
*/
$customer = rcp_get_customer_by_user_id( $user->ID );
if ( empty( $customer ) ) {
$customer_id = rcp_add_customer( array(
'user_id' => absint( $user->ID )
) );
if ( ! empty( $customer_id ) ) {
$customer = rcp_get_customer( $customer_id );
}
}
if ( empty( $customer ) ) {
$this->get_job()->add_error( sprintf( __( 'Skipping row #%d. Error creating or retrieving customer record for user #%d.', 'rcp' ), $row_number, $user->ID ) );
continue;
}
/**
* Gather membership information.
*/
$membership_data = $this->get_membership_data( $row );
if ( is_wp_error( $membership_data ) ) {
$this->get_job()->add_error( sprintf( __( 'Skipping row #%d (user ID #%d). Error code: %s; Error message: %s', 'rcp' ), $row_number, $user->ID, $membership_data->get_error_code(), $membership_data->get_error_message() ) );
continue;
}
$membership_data['customer_id'] = $customer->get_id();
$existing_membership = rcp_get_customer_single_membership( $customer->get_id() );
$new = false;
/*
* Add a new membership if:
* - Multiple memberships is enabled and they've opted to add new records; or
* - The customer doesn't have any membership records yet; or
* - The customer does have an existing membership, but it's for a different level.
*/
if (
( rcp_multiple_memberships_enabled() && ! empty( $this->settings['existing_customers'] ) && 'new' == $this->settings['existing_customers'] )
||
empty( $existing_membership )
||
( ! empty( $existing_membership ) && $existing_membership->get_object_id() != $membership_data['object_id'] )
) {
$new = true;
}
if ( $new ) {
/**
* Insert new membership records.
*/
$membership_id = $customer->add_membership( $membership_data );
if ( empty( $membership_id ) ) {
$this->get_job()->add_error( sprintf( __( 'Error creating membership record for row #%d (user ID #%d).', 'rcp' ), $row_number, $user->ID ) );
continue;
}
} else {
/**
* Update existing membership.
*/
$membership_id = $existing_membership->get_id();
$updated = $existing_membership->update( $membership_data );
if ( empty( $updated ) ) {
$this->get_job()->add_error( sprintf( __( 'Error updating membership record #%d for row #%d.', 'rcp' ), $existing_membership->get_id(), $row_number ) );
continue;
}
}
$new_membership = rcp_get_membership( $membership_id );
/**
* Deprecated action hook from old CSV User Import add-on.
*/
do_action_deprecated( 'rcp_user_import_user_added', array(
$user->ID,
$user,
$new_membership->get_object_id(),
$new_membership->get_status(),
$new_membership->get_expiration_date( false ),
$row
), '3.1.2', 'rcp_csv_import_membership_processed' );
/**
* Triggers after a membership record has been imported / updated.
*
* @param RCP_Membership $new_membership The membership that was imported or updated.
* @param WP_User $user User object associated with the new membership.
* @param array $row Entire CSV row for this membership.
*/
do_action( 'rcp_csv_import_membership_processed', $new_membership, $user, $row );
$processed[] = $row_number;
unset( $this->rows[$row_number] );
}
$this->get_job()->adjust_current_count( count( $processed ) );
if ( $this->get_job()->is_completed() ) {
$this->finish();
}
}
/**
* Parse existing user from the row or create a new one.
*
* @param array $row
*
* @since 3.1
* @return WP_User|WP_Error
*/
private function get_user( $row ) {
$user = false;
$user_login = $email = $first_name = $last_name = $password = '';
// Get user by email.
if ( ! empty( $this->field_map['user_email'] ) && ! empty( $row[$this->field_map['user_email']] ) ) {
$email = $row[$this->field_map['user_email']];
$user = get_user_by( 'email', $email );
}
// Get user by login.
if ( empty( $user ) && ! empty( $this->field_map['user_login'] ) && ! empty( $row[$this->field_map['user_login']] ) ) {
$user_login = $row[$this->field_map['user_login']];
$user = get_user_by( 'login', $user_login );
}
// First name.
if ( ! empty( $this->field_map['first_name'] ) && ! empty( $row[$this->field_map['first_name']] ) ) {
$first_name = $row[$this->field_map['first_name']];
}
// Last name.
if ( ! empty( $this->field_map['last_name'] ) && ! empty( $row[$this->field_map['last_name']] ) ) {
$last_name = $row[$this->field_map['last_name']];
}
// Password
if ( ! empty( $this->field_map['user_password'] ) && ! empty( $row[$this->field_map['user_password']] ) ) {
$password = $row[$this->field_map['user_password']];
} else {
$password = '';
}
if ( ! empty( $user ) ) {
/**
* Check to see if we have a data mismatch.
* For example: if the email in the CSV file doesn't match the email we have for the fetched user.
*/
if ( ! empty( $email ) && $email != $user->user_email ) {
return new WP_Error( 'email_mismatch', sprintf( __( 'Email address provided in the CSV does not match the user email on record for user ID #%d.', 'rcp' ), $user->ID ) );
}
if ( ! empty( $user_login ) && $user_login != $user->user_login ) {
return new WP_Error( 'user_login_mismatch', sprintf( __( 'User login provided in the CSV does not match the user login on record for user ID #%d.', 'rcp' ), $user->ID ) );
}
/**
* Update existing account with new data.
*/
$data_to_update = array();
if ( ! empty( $password ) ) {
$data_to_update['user_pass'] = $password;
}
if ( ! empty( $first_name ) ) {
$data_to_update['first_name'] = sanitize_text_field( $first_name );
}
if ( ! empty( $last_name ) ) {
$data_to_update['last_name'] = sanitize_text_field( $last_name );
}
if ( ! empty( $data_to_update ) ) {
$data_to_update['ID'] = $user->ID;
// Don't update the password of the current user.
if ( $user->ID == get_current_user_id() && isset( $data_to_update['user_pass'] ) ) {
unset( $data_to_update['user_pass'] );
}
wp_update_user( $data_to_update );
}
} else {
/**
* Create new account.
*/
$user_data = array(
'user_login' => ! empty( $user_login ) ? sanitize_text_field( $user_login ) : sanitize_text_field( $email ),
'user_email' => sanitize_text_field( $email ),
'first_name' => sanitize_text_field( $first_name ),
'last_name' => sanitize_text_field( $last_name ),
'user_pass' => ! empty( $password ) ? $password : wp_generate_password( 24 )
);
$user_id = wp_insert_user( $user_data );
if ( is_wp_error( $user_id ) ) {
return $user_id;
}
if ( ! empty( $user_id ) && ! is_wp_error( $user_id ) ) {
$user = get_user_by( 'ID', $user_id );
if ( ! empty( $this->settings['send_set_password_emails'] ) ) {
wp_new_user_notification( $user->ID, null, 'user' );
}
}
}
if ( empty( $user ) ) {
$user = new WP_Error( 'user_error', __( 'Error creating or retrieving user account.', 'rcp' ) );
}
return $user;
}
/**
* Get membership data from the row
*
* @param array $row
*
* @return array|WP_Error
*/
private function get_membership_data( $row ) {
$data = array();
// Membership level.
if ( ! empty( $this->field_map['membership_level_name'] ) && ! empty( $row[$this->field_map['membership_level_name']] ) ) {
$membership_level = rcp_get_membership_level_by( 'name', $row[$this->field_map['membership_level_name']] );
if ( $membership_level instanceof Membership_Level ) {
$data['object_id'] = $membership_level->get_id();
}
} elseif ( ! empty( $this->settings['object_id'] ) ) {
// Get value from settings UI.
$data['object_id'] = absint( $this->settings['object_id'] );
}
if ( empty( $data['object_id'] ) ) {
return new WP_Error( 'missing_membership_level', __( 'Unable to determine membership level.', 'rcp' ) );
}
// Membership status.
if ( ! empty( $this->field_map['status'] ) && ! empty( $row[$this->field_map['status']] ) ) {
$status = sanitize_text_field( strtolower( $row[$this->field_map['status']] ) );
if ( in_array( $status, array( 'active', 'cancelled', 'expired', 'pending' ) ) ) {
$data['status'] = $status;
}
} elseif ( ! empty( $this->settings['status'] ) ) {
// Get value from settings UI.
$data['status'] = sanitize_text_field( $this->settings['status'] );
}
// Created Date
if ( ! empty( $this->field_map['created_date'] ) && ! empty( $row[$this->field_map['created_date']] ) ) {
$data['created_date'] = date( 'Y-m-d H:i:s', strtotime( $row[$this->field_map['created_date']], current_time( 'timestamp' ) ) );
}
// Expiration date.
$expiration_date = $this->settings['expiration_date'];
if ( ! empty( $this->field_map['expiration_date'] ) && ! empty( $row[$this->field_map['expiration_date']] ) ) {
if ( 'none' == strtolower( $row[$this->field_map['expiration_date']] ) ) {
$expiration_date = 'none';
} else {
$expiration_date = $row[$this->field_map['expiration_date']];
}
}
if ( ! empty( $expiration_date ) && 'none' !== strtolower( $expiration_date ) ) {
$data['expiration_date'] = date( 'Y-m-d 23:59:59', strtotime( $expiration_date, current_time( 'timestamp' ) ) );
} elseif ( 'none' === strtolower( $expiration_date ) ) {
$data['expiration_date'] = 'none';
}
// Auto Renew
if ( ! empty( $this->field_map['auto_renew'] ) && ! empty( $row[$this->field_map['auto_renew']] ) ) {
$data['auto_renew'] = 1;
} else {
$data['auto_renew'] = 0;
}
// Times Billed
if ( ! empty( $this->field_map['times_billed'] ) && ! empty( $row[$this->field_map['times_billed']] ) ) {
$data['times_billed'] = absint( $row[$this->field_map['times_billed']] );
}
// Gateway
if ( ! empty( $this->field_map['gateway'] ) && ! empty( $row[$this->field_map['gateway']] ) ) {
$gateway_slug = strtolower( $row[$this->field_map['gateway']] );
if ( array_key_exists( $gateway_slug, rcp_get_payment_gateways() ) ) {
$data['gateway'] = sanitize_text_field( $gateway_slug );
}
}
// We can loop through all the rest of the data.
$fields = array(
'gateway_customer_id',
'gateway_subscription_id',
'subscription_key'
);
foreach ( $fields as $field ) {
if ( ! empty( $this->field_map[$field] ) && ! empty( $row[$this->field_map[$field]] ) ) {
$data[$field] = sanitize_text_field( $row[$this->field_map[$field]] );
}
}
// If gateway value doesn't exist, but we have a gateway_customer_id or gateway_subscription_id, then attempt to guess it.
if ( empty( $data['gateway'] ) && ( ! empty( $data['gateway_customer_id'] ) || ! empty( $data['gateway_subscription_id'] ) ) ) {
$data['gateway'] = rcp_get_gateway_slug_from_gateway_ids( $data );
}
return $data;
}
}

View File

@@ -0,0 +1,247 @@
<?php
/**
* Import Payments
*
* @since 3.4
* @copyright Copyright (c) 2020, Restrict Content Pro team
* @license GPL2+
* @package restrict-content-pro
*/
use RCP\Membership_Level;
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
/**
* Class RCP_Batch_Callback_Import_Payments
*
* @since 3.4
*/
class RCP_Batch_Callback_Import_Payments extends RCP_Batch_Callback_CSV_Import_Base {
/**
* Process batch
*
* @since 3.4
*/
public function process_batch() {
parent::process_batch();
// Disable notification emails.
remove_action( 'rcp_update_payment_status_complete', 'rcp_email_payment_received', 100 );
remove_action( 'rcp_process_manual_signup', 'rcp_email_admin_on_manual_payment', 10 );
$processed = [];
if ( empty( $this->rows ) || $this->time_exceeded() ) {
$this->get_job()->adjust_current_count( count( $processed ) );
return;
}
$payments = new RCP_Payments();
foreach ( $this->rows as $row_number => $row ) {
/**
* Parse user account.
*/
$user = $this->get_user( $row );
if ( is_wp_error( $user ) ) {
$this->get_job()->add_error( sprintf( __( 'Skipping row #%d. Error code: %s; Error message: %s', 'rcp' ), $row_number, $user->get_error_code(), $user->get_error_message() ) );
continue;
}
/**
* Gather payment information.
*/
$payment_data = $this->get_payment_data( $row );
if ( is_wp_error( $payment_data ) ) {
$this->get_job()->add_error( sprintf( __( 'Skipping row #%d. Error code: %s; Error message: %s', 'rcp' ), $row_number, $payment_data->get_error_code(), $payment_data->get_error_message() ) );
continue;
}
// Add user ID.
$payment_data['user_id'] = absint( $user->ID );
// If we don't have a customer record at this point, make one.
if ( empty( $payment_data['customer_id'] ) ) {
$customer = rcp_get_customer_by_user_id( $user->ID );
if ( empty( $customer ) ) {
$customer_id = rcp_add_customer( array(
'user_id' => absint( $user->ID )
) );
if ( ! empty( $customer_id ) ) {
$customer = rcp_get_customer( $customer_id );
}
}
if ( empty( $customer ) ) {
$this->get_job()->add_error( sprintf( __( 'Skipping row #%d. Error creating or retrieving customer record for user #%d.', 'rcp' ), $row_number, $user->ID ) );
continue;
} else {
$payment_data['customer_id'] = $customer->get_id();
}
}
$result = $payments->insert( $payment_data );
if ( empty( $result ) ) {
$this->get_job()->add_error( sprintf( __( 'Skipping row #%d. Error creating payment record.', 'rcp' ), $row_number ) );
continue;
}
$processed[] = $row_number;
unset( $this->rows[ $row_number ] );
}
$this->get_job()->adjust_current_count( count( $processed ) );
if ( $this->get_job()->is_completed() ) {
$this->finish();
}
}
/**
* Parse existing user from the row or create a new one.
*
* @param array $row
*
* @since 3.4
* @return WP_User|WP_Error
*/
private function get_user( $row ) {
$user = false;
// Get user by email.
if ( ! empty( $this->field_map['user_email'] ) && ! empty( $row[ $this->field_map['user_email'] ] ) ) {
$email = $row[ $this->field_map['user_email'] ];
$user = get_user_by( 'email', $email );
}
// Get user by login.
if ( empty( $user ) && ! empty( $this->field_map['user_login'] ) && ! empty( $row[ $this->field_map['user_login'] ] ) ) {
$user_login = $row[ $this->field_map['user_login'] ];
$user = get_user_by( 'login', $user_login );
}
if ( empty( $user ) ) {
$user = new WP_Error( 'user_error', __( 'Error retrieving user account.', 'rcp' ) );
}
return $user;
}
/**
* Get payment data from the row
*
* @param array $row
*
* @since 3.4
* @return array|WP_Error
*/
private function get_payment_data( $row ) {
$data = array();
// Date.
if ( ! empty( $this->field_map['date'] ) && ! empty( $row[ $this->field_map['date'] ] ) ) {
$date = $row[ $this->field_map['membership_level_name'] ];
// Convert it to our desired format.
$data['date'] = date( 'Y-m-d H:i:s', strtotime( $date, current_time( 'timestamp' ) ) );
}
// Membership & object ID
if ( ! empty( $this->field_map['membership_id'] ) && ! empty( $row[ $this->field_map['membership_id'] ] ) ) {
$membership = rcp_get_membership( absint( $row[ $this->field_map['membership_id'] ] ) );
if ( ! empty( $membership ) ) {
$data['membership_id'] = $membership->get_id();
$data['customer_id'] = $membership->get_customer_id();
$data['object_id'] = $membership->get_object_id();
$data['subscription'] = sanitize_text_field( $membership->get_membership_level_name() );
}
}
// Get object ID from explicit value.
if ( empty( $data['object_id'] ) && ! empty( $this->field_map['object_id'] ) && ! empty( $row[ $this->field_map['object_id'] ] ) ) {
$membership_level = rcp_get_membership_level( $row[ $this->field_map['object_id'] ] );
if ( $membership_level instanceof Membership_Level ) {
$data['object_id'] = $membership_level->get_id();
$data['subscription'] = sanitize_text_field( $membership_level->get_name() );
}
}
// Get object ID from membership level name.
if ( empty( $data['subscription'] ) && ! empty( $this->field_map['subscription'] ) && ! empty( $row[ $this->field_map['subscription'] ] ) ) {
$membership_level = rcp_get_membership_level_by( 'name', $row[ $this->field_map['subscription'] ] );
if ( $membership_level instanceof Membership_Level ) {
$data['object_id'] = $membership_level->get_id();
$data['subscription'] = sanitize_text_field( $membership_level->get_name() );
} else {
$data['subscription'] = sanitize_text_field( $row[ $this->field_map['subscription'] ] );
}
}
// Gateway
if ( ! empty( $this->field_map['gateway'] ) && ! empty( $row[ $this->field_map['gateway'] ] ) ) {
$gateway_slug = strtolower( $row[ $this->field_map['gateway'] ] );
if ( array_key_exists( $gateway_slug, rcp_get_payment_gateways() ) ) {
$data['gateway'] = sanitize_text_field( $gateway_slug );
}
}
// Transaction Type
if ( ! empty( $this->field_map['transaction_type'] ) && ! empty( $row[ $this->field_map['transaction_type'] ] ) ) {
$transaction_type = strtolower( $row[ $this->field_map['transaction_type'] ] );
$all_types = array(
'new',
'renewal',
'upgrade',
'downgrade'
);
if ( in_array( $transaction_type, $all_types ) ) {
$data['transaction_type'] = sanitize_text_field( $transaction_type );
}
}
// We can loop through all the rest of the data.
$fields = array(
'amount',
'subtotal',
'credits',
'fees',
'discount_amount',
'discount_code',
'transaction_id'
);
foreach ( $fields as $field ) {
if ( ! empty( $this->field_map[ $field ] ) && ! empty( $row[ $this->field_map[ $field ] ] ) ) {
$data[ $field ] = sanitize_text_field( $row[ $this->field_map[ $field ] ] );
}
}
return $data;
}
}

View File

@@ -0,0 +1 @@
<?php // Silence is golden.

View File

@@ -0,0 +1 @@
<?php // Silence is golden.

View File

@@ -0,0 +1,39 @@
<?php
/**
* Job Callback Interface
*
* @package restrict-content-pro
* @copyright Copyright (c) 2018, Restrict Content Pro team
* @license GPL2+
*/
namespace RCP\Utils\Batch;
/**
* Interface Job_Callback_Interface
*
* @package RCP\Utils\Batch
* @since 3.0
*/
interface Job_Callback_Interface {
/**
* Execute the job
*
* @access public
* @since 3.0
* @return mixed
*/
public function execute();
/**
* Runs any tasks required to finish a job.
*
* @access public
* @since 3.0
* @return mixed|void
*/
public function finish();
}

View File

@@ -0,0 +1,535 @@
<?php
/**
* Migrate Memberships
*
* @package restrict-content-pro
* @copyright Copyright (c) 2018, Restrict Content Pro team
* @license GPL2+
* @since 3.0
*/
use RCP\Membership_Level;
use RCP\Utils\Batch\Abstract_Job_Callback;
/**
* Class Migrate_Memberships_v3
*
* Migrates membership data to the custom memberships table.
*
* @package RCP\Utils\Batch
* @since 3.0
*/
final class RCP_Batch_Callback_Migrate_Memberships_v3 extends Abstract_Job_Callback {
/**
* @var array $memberships The membership data from usermeta
*/
private $memberships;
/**
* @var bool Whether or not RCP is network activated and using global tables.
*/
private $network_active = false;
/**
* @inheritdoc
*/
public function execute() {
rcp_log( sprintf( 'Batch Member Migration: Initiating RCP_Batch_Callback_Migrate_Memberships_v3. Current step: %d; current count: %d; total count: %d.', $this->get_job()->get_step(), $this->get_job()->get_current_count(), $this->get_job()->get_total_count() ), true );
if ( $this->start_time === null ) {
$this->start_time = time();
}
if ( $this->time_exceeded() || $this->get_job()->is_completed() ) {
return $this;
}
parent::execute();
if ( 0 === $this->get_job()->get_step() ) {
$this->get_job()->clear_errors();
}
if (
is_multisite() &&
is_plugin_active_for_network( plugin_basename( RCP_PLUGIN_FILE ) ) &&
( ! defined( 'RCP_NETWORK_SEPARATE_SITES' ) || ! RCP_NETWORK_SEPARATE_SITES )
) {
$this->network_active = true;
}
$this->disable_membership_actions();
$this->memberships = $this->get_batch();
if ( empty( $this->memberships ) || $this->get_job()->is_completed() ) {
$this->finish();
return $this;
}
$this->process_batch();
$current_step = $this->get_job()->get_step();
$current_step++;
$this->get_job()->set_step( $current_step );
return $this;
}
/**
* @inheritdoc
*/
public function finish() {
// Update membership counts.
rcp_check_member_counts();
// Set job to complete.
$this->get_job()->set_status( 'complete' );
$errors = $this->get_job()->get_errors();
rcp_log( sprintf( 'Batch Member Migration: Job complete. Errors: %s', var_export( $errors, true ) ), true );
}
/**
* Disable all membership-related hooks during the migration.
*
* @since 3.0
* @return void
*/
public function disable_membership_actions() {
// Disable activation sequence, as memberships were already activated.
remove_action( 'rcp_new_membership_added', 'rcp_activate_membership_on_insert', 10 );
// Prevent status-related emails from being sent.
remove_action( 'rcp_membership_post_activate', 'rcp_email_on_membership_activation', 10 );
remove_action( 'rcp_membership_post_cancel', 'rcp_email_on_membership_cancellation', 10 );
remove_action( 'rcp_transition_membership_status_expired', 'rcp_email_on_membership_expiration', 10 );
}
/**
* Count the total number of results and save the value.
*
* @since 3.1
* @return int
*/
public function get_total_count() {
global $wpdb;
$usermeta_table = $wpdb->usermeta;
$total_count = $this->get_job()->get_total_count();
if ( empty( $total_count ) ) {
if ( is_multisite() && ! $this->network_active ) {
$blog_id = get_current_blog_id();
$capabilities_key = 1 == $blog_id ? $wpdb->base_prefix . 'capabilities' : $wpdb->base_prefix . $blog_id . '_capabilities';
$total_count = (int) $wpdb->get_var( $wpdb->prepare( "SELECT COUNT(*) FROM {$usermeta_table} m1, {$usermeta_table} m2 WHERE m1.user_id = m2.user_id AND m1.meta_key = 'rcp_status' AND m2.meta_key = %s", $capabilities_key ) );
} else {
$total_count = (int) $wpdb->get_var( "SELECT COUNT(*) FROM {$usermeta_table} WHERE meta_key = 'rcp_status'" );
}
$this->get_job()->set_total_count( $total_count );
rcp_log( sprintf( 'Batch Member Migration: Total count: %d.', $total_count ), true );
}
return $total_count;
}
/**
* Retrieves the batch of membership records from usermeta.
*
* @since 3.0
* @return array Membership data from usermeta.
*/
private function get_batch() {
if ( ! empty( $this->memberships ) ) {
return $this->memberships;
}
global $wpdb;
$usermeta_table = $wpdb->usermeta;
$this->get_total_count();
if ( is_multisite() && ! $this->network_active ) {
$blog_id = get_current_blog_id();
$capabilities_key = 1 == $blog_id ? $wpdb->base_prefix . 'capabilities' : $wpdb->base_prefix . $blog_id . '_capabilities';
$results = $wpdb->get_results( $wpdb->prepare( "SELECT m1.* FROM {$usermeta_table} m1, {$usermeta_table} m2 WHERE m1.user_id = m2.user_id AND m1.meta_key = 'rcp_status' AND m2.meta_key = %s LIMIT %d OFFSET %d", $capabilities_key, $this->size, $this->offset ) );
} else {
$results = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM {$usermeta_table} WHERE meta_key = 'rcp_status' LIMIT %d OFFSET %d", $this->size, $this->offset ) );
}
rcp_log( sprintf( 'Batch Member Migration: %d results found in query for LIMIT %d OFFSET %d.', count( $results ), $this->size, $this->offset ) );
if ( empty( $results ) ) {
return [];
}
return $results;
}
/**
* Processing the batch of memberships.
*/
private function process_batch() {
global $rcp_options;
$rcp_options['debug_mode'] = false;
global $wpdb;
$rcp_payments = new \RCP_Payments();
$processed = [];
if ( empty( $this->memberships ) || $this->time_exceeded() ) {
$this->get_job()->adjust_current_count( count( $processed ) );
return;
}
foreach ( $this->memberships as $key => $membership ) {
$meta_items = $wpdb->get_results( $wpdb->prepare( "SELECT meta_key, meta_value FROM {$wpdb->usermeta} WHERE user_id = %d", $membership->user_id ) );
$user_meta = array();
foreach ( $meta_items as $meta_item ) {
$user_meta[$meta_item->meta_key] = maybe_unserialize( $meta_item->meta_value );
}
$user = get_userdata( $membership->user_id );
$membership_level_id = 0;
$pending_payment = false;
if ( empty( $user ) ) {
$this->get_job()->add_error( sprintf( __( 'Skipped user #%d - unable to locate user account. Possible orphaned user meta.', 'rcp' ), $membership->user_id ) );
continue;
}
if ( ! empty( $user_meta['rcp_subscription_level'] ) ) {
$membership_level_id = $user_meta['rcp_subscription_level'];
} elseif ( ! empty( $user_meta['rcp_pending_payment_id'] ) ) {
$pending_payment = $rcp_payments->get_payment( $user_meta['rcp_pending_payment_id'] );
$membership_level_id = ! empty( $pending_payment->object_id ) ? $pending_payment->object_id : 0;
}
if ( empty( $membership_level_id ) ) {
$this->get_job()->add_error( sprintf( __( 'Skipped user #%d - unable to determine membership level.', 'rcp' ), $user->ID ) );
continue;
}
$membership_level = rcp_get_membership_level( $membership_level_id );
if ( ! $membership_level instanceof Membership_Level ) {
$this->get_job()->add_error( sprintf( __( 'Skipped user #%d - unable to get membership level details for ID #%d.', 'rcp' ), $user->ID, $membership_level_id ) );
continue;
}
/**
* First retrieve or create a new customer record.
*/
// Check email verification status.
if ( ! empty( $user_meta['rcp_pending_email_verification'] ) ) {
// Pending verification.
$email_verification = 'pending';
} elseif ( ! empty( $user_meta['rcp_email_verified'] ) ) {
// Already verified.
$email_verification = 'verified';
} else {
// Verification not required.
$email_verification = 'none';
}
$existing_customer = rcp_get_customer_by_user_id( $user->ID );
if ( ! $existing_customer instanceof RCP_Customer ) {
// Create a new customer.
$customer_data = array(
'user_id' => $user->ID,
'date_registered' => $user->user_registered,
'email_verification' => $email_verification,
'last_login' => '',
'ips' => '',
'notes' => ''
);
$customer_id = rcp_add_customer( $customer_data );
$customer = rcp_get_customer( $customer_id );
} else {
// Update customer if their email verification status has changed.
if ( $email_verification != $existing_customer->get_email_verification_status() ) {
$existing_customer->update( array(
'email_verification' => $email_verification
) );
}
$customer = $existing_customer;
}
if ( ! isset( $customer ) || ! $customer instanceof RCP_Customer ) {
$this->get_job()->add_error( sprintf( __( 'Error inserting customer record for user #%d.', 'rcp' ), $user->ID ) );
continue;
}
/**
* Disable all the customer's memberships. This ensures we don't wind up with any duplicates if
* this migration is run more than once.
*/
$customer->disable_memberships();
/**
* Update all this user's payments to add the new customer ID.
*/
$wpdb->update(
rcp_get_payments_db_name(),
array( 'customer_id' => absint( $customer->get_id() ) ),
array( 'user_id' => $user->ID ),
array( '%d' ),
array( '%d' )
);
/**
* Get the first payment of this membership, if it exists.
*/
$first_membership_payment = $rcp_payments->get_payments( array(
'user_id' => $membership->user_id,
'number' => 1,
'order' => 'ASC',
'subscription' => $membership_level->get_name(),
) );
if ( ! empty( $first_membership_payment ) ) {
$first_membership_payment = reset( $first_membership_payment );
}
$last_membership_payment = $rcp_payments->get_payments( array(
'user_id' => $membership->user_id,
'number' => 1,
'order' => 'DESC',
'subscription' => $membership_level->get_name()
) );
if ( ! empty( $last_membership_payment ) ) {
$last_membership_payment = reset( $last_membership_payment );
}
$times_billed = $rcp_payments->count( [
'user_id' => $membership->user_id,
'status' => 'complete',
'object_id' => $membership_level_id
] );
$gateway_info = $this->get_gateway( $user_meta, $last_membership_payment );
if ( $pending_payment ) {
$expiration_date = rcp_calculate_subscription_expiration( $membership_level_id );
} else {
$expiration_date = ! empty( $user_meta['rcp_expiration'] ) ? $user_meta['rcp_expiration'] : 'none';
}
if ( empty( $expiration_date ) || strtolower( $expiration_date ) === 'none' ) {
$expiration_date = null;
}
if ( ! empty( $expiration_date ) ) {
$date = new \DateTime( $expiration_date, new \DateTimeZone( 'UTC' ) );
$expiration_date = $date->format( 'Y-m-d H:i:s' );
}
// Determine the user's status.
$status = 'free' == $user_meta['rcp_status'] ? 'active' : $user_meta['rcp_status'];
$allowed_statuses = array( 'active', 'expired', 'cancelled', 'pending' );
if ( ! in_array( $status, $allowed_statuses ) ) {
if ( strtotime( 'NOW', current_time( 'timestamp' ) ) > strtotime( $expiration_date, current_time( 'timestamp' ) ) ) {
$status = 'expired';
} else {
$status = 'active';
}
}
// Explicitly set amounts to `0.00` if empty.
$initial_amount = ! empty( $first_membership_payment->amount ) ? $first_membership_payment->amount : ( $membership_level->get_price() + $membership_level->get_fee() );
if ( empty( $initial_amount ) ) {
$initial_amount = 0.00;
}
$recurring_amount = $membership_level->get_price();
if ( empty( $recurring_amount ) ) {
$recurring_amount = 0.00;
}
// Determine the user's join date.
$join_date_meta_key = 'rcp_joined_date_' . $membership_level_id;
$join_date = ! empty( $user_meta[$join_date_meta_key] ) ? $user_meta[$join_date_meta_key] : false;
if ( empty( $join_date ) && ! empty( $first_membership_payment->date ) ) {
$join_date = $first_membership_payment->date;
} elseif ( empty( $join_date ) ) {
$join_date = current_time( 'mysql' );
}
// See if we have a renewal date.
$renewal_date_meta_key = 'rcp_renewed_date_' . $membership_level_id;
$renewal_date = ! empty( $user_meta[$renewal_date_meta_key] ) ? $user_meta[$renewal_date_meta_key] : '';
// Get the subscription key.
if ( $pending_payment ) {
$subscription_key = $pending_payment->subscription_key;
} elseif ( ! empty( $user_meta['rcp_subscription_key'] ) ) {
$subscription_key = $user_meta['rcp_subscription_key'];
} else {
$subscription_key = '';
}
$data = array(
'customer_id' => $customer->get_id(),
'user_id' => $user->ID,
'object_id' => $membership_level_id,
'object_type' => 'membership',
'initial_amount' => $initial_amount,
'recurring_amount' => $recurring_amount,
'created_date' => $join_date,
'trial_end_date' => ! empty( $user_meta['rcp_is_trialing'] ) ? $expiration_date : '',
'renewal_date' => $renewal_date,
'cancellation_date' => '',
'expiration_date' => $expiration_date,
'auto_renew' => ( ! empty( $user_meta['rcp_recurring'] ) && 'no' != $user_meta['rcp_recurring'] ) ? 1 : 0,
'times_billed' => $times_billed,
'maximum_renewals' => 0,
'status' => $status,
'gateway' => $gateway_info['gateway'],
'gateway_customer_id' => $gateway_info['gateway_customer_id'],
'gateway_subscription_id' => $gateway_info['gateway_subscription_id'],
'signup_method' => ! empty( $user_meta['rcp_signup_method'] ) ? $user_meta['rcp_signup_method'] : 'live',
'subscription_key' => $subscription_key,
'notes' => ! empty( $user_meta['rcp_notes'] ) ? $user_meta['rcp_notes'] : '',
);
$membership_id = rcp_add_membership( $data );
if ( empty( $membership_id ) ) {
$this->get_job()->add_error( sprintf( __( 'Error inserting membership record for user #%d.', 'rcp' ), $user->ID ) );
continue;
}
/**
* Update all this user's payments to add this membership ID.
*/
$wpdb->update(
rcp_get_payments_db_name(),
array( 'membership_id' => absint( $membership_id ) ),
array(
'user_id' => $membership->user_id,
'subscription' => $membership_level->get_name()
),
array( '%d' ),
array( '%d', '%s' )
);
$processed[] = $membership_id;
unset( $this->memberships[$key] );
}
$this->get_job()->adjust_current_count( count( $processed ) );
if ( $this->get_job()->is_completed() ) {
$this->finish();
}
}
/**
* Determine the payment gateway used for membership.
*
* @param array $user_meta Array of user meta.
* @param object $payment Payment object.
*
* @access private
* @since 3.0
* @return array
*/
private function get_gateway( $user_meta, $payment ) {
$profile_id = ! empty( $user_meta['rcp_payment_profile_id'] ) ? $user_meta['rcp_payment_profile_id'] : '';
$merchant_sub_id = ! empty( $user_meta['rcp_merchant_subscription_id'] ) ? $user_meta['rcp_merchant_subscription_id'] : '';
$gateway_info = array(
'gateway' => '',
'gateway_customer_id' => '',
'gateway_subscription_id' => ''
);
if ( 'free' == $user_meta['rcp_status'] ) {
return $gateway_info;
}
// Check for Stripe.
if ( false !== strpos( $profile_id, 'cus_' ) ) {
$gateway_info['gateway'] = 'stripe';
$gateway_info['gateway_customer_id'] = $profile_id;
$gateway_info['gateway_subscription_id'] = $merchant_sub_id;
return $gateway_info;
}
// Check for 2Checkout.
if ( false !== strpos( $profile_id, '2co_' ) ) {
$gateway_info['gateway'] = 'twocheckout';
$gateway_info['gateway_subscription_id'] = $profile_id;
return $gateway_info;
}
// Check for Authorize.net.
if ( false !== strpos( $profile_id, 'anet_' ) ) {
$gateway_info['gateway'] = 'authorizenet';
$gateway_info['gateway_subscription_id'] = $profile_id;
return $gateway_info;
}
// Check for Braintree.
if ( false !== strpos( $profile_id, 'bt_' ) ) {
$gateway_info['gateway'] = 'braintree';
$gateway_info['gateway_customer_id'] = $profile_id;
$gateway_info['gateway_subscription_id'] = $merchant_sub_id;
return $gateway_info;
}
// Check for PayPal.
if ( false !== strpos( $profile_id, 'I-' ) ) {
$gateway_info['gateway'] = 'paypal';
$gateway_info['gateway_subscription_id'] = $profile_id;
// Determine which PayPal gateway was used from last payment.
if ( ! empty( $payment->gateway ) ) {
$gateway_info['gateway'] = $payment->gateway;
}
return $gateway_info;
}
// Check for third party gateways.
if ( ! empty( $payment->gateway ) && 'free' != $payment->gateway ) {
$gateway_info['gateway'] = $payment->gateway;
}
$gateway_info['gateway_subscription_id'] = $profile_id;
return $gateway_info;
}
}

View File

@@ -0,0 +1 @@
<?php // Silence is golden.

View File

@@ -0,0 +1,62 @@
<?php
/**
* Block Functions
*
* Handles creation of Block Category, Registering blocks, and providing data to blocks
*
* @package Restrict Content Pro
* @copyright Copyright (c) 2021, Restrict Content Pro
* @license http://opensource.org/license/gpl-2.1.php GNU Public License
*/
/**
* Add the RCP category to the blocks menu
*
* @since 3.5.8 Add the Restrict Content Pro Category
*/
function rcp_add_restrict_content_pro_block_category( $categories ) {
$categories[] = array (
'slug' => 'restrict-content-pro',
'icon' => 'lock',
'title' => __( 'Restrict Content Pro', 'rcp' ),
);
return $categories;
}
if ( rcp_wp_version_compare( '5.8', '<' ) ) {
add_filter( 'block_categories', 'rcp_add_restrict_content_pro_block_category' );
} else {
add_filter( 'block_categories_all', 'rcp_add_restrict_content_pro_block_category' );
}
/**
* Add the global rcp pages to the script for the content upgrade redirect block
*
* @since 3.5.8
*/
function rcp_enqueue_block_editor_assets_for_content_upgrade_redirect() {
$content_redirect_upgrade_editor_script_handle = generate_block_asset_handle(
'restrict-content-pro/content-upgrade-redirect',
'editorScript'
);
global $rcp_options;
$script = 'var rcp_default_registration_page = ' . wp_json_encode( get_permalink( $rcp_options['registration_page'] ) ) . '; ';
$script .= 'var rcp_default_account_page = ' . wp_json_encode( get_permalink( $rcp_options['account_page'] ) ) . '; ';
wp_add_inline_script( $content_redirect_upgrade_editor_script_handle, $script );
}
add_action( 'enqueue_block_editor_assets', 'rcp_enqueue_block_editor_assets_for_content_upgrade_redirect' );
/**
* Registers the RCP blocks so that they can be used in the block editor
*
* @since 3.5.8
*/
function rcp_register_blocks_init() {
// Register the registration redirect block using blocks.json
register_block_type_from_metadata(
RCP_PLUGIN_DIR . '/core/src/blocks/content-upgrade-redirect/',
array ()
);
}
add_action( 'init', 'rcp_register_blocks_init' );

View File

@@ -0,0 +1,157 @@
<?php
/**
* CAPTCHA Functions
*
* Adds CAPTCHA to the registration form and validates the submission.
*
* @package Restrict Content Pro
* @copyright Copyright (c) 2017, Restrict Content Pro
* @license http://opensource.org/license/gpl-2.1.php GNU Public License
*/
/**
* Whether or not reCATPCHA is enabled. The setting must be checked on and
* all keys entered for this to return true.
*
* @since 2.9
* @return bool
*/
function rcp_is_recaptcha_enabled() {
global $rcp_options;
$enabled = ( ! empty( $rcp_options['enable_recaptcha'] ) && ! empty( $rcp_options['recaptcha_public_key'] ) && ! empty( $rcp_options['recaptcha_private_key'] ) );
if ( ! $enabled ) {
return false;
}
/**
* Filters whether reCAPTCHA is enabled.
*
* This can only be used to disable reCAPTCHA if it is presently enabled.
*
* @since 3.4.3
*
* @param bool $enabled True if reCAPTCHA is enabled.
*/
return apply_filters( 'rcp_is_recaptcha_enabled', $enabled );
}
/**
* Get the reCAPTCHA version
*
* @since 3.3
* @return int Either 2 (v2) or 3 (v3)
*/
function rcp_get_recaptcha_version() {
global $rcp_options;
return ! empty( $rcp_options['recaptcha_version'] ) ? absint( $rcp_options['recaptcha_version'] ) : 2;
}
/**
* Add reCAPTCHA to the registration form if it's enabled.
*
* @return void
*/
function rcp_show_captcha() {
global $rcp_options;
// reCaptcha
if ( rcp_is_recaptcha_enabled() ) {
if ( 3 === rcp_get_recaptcha_version() ) {
/**
* v3 markup
*/
?>
<div id="rcp_recaptcha" data-sitekey="<?php echo esc_attr( $rcp_options['recaptcha_public_key'] ); ?>">
<input type="hidden" id="rcp_recaptcha_token" name="g-recaptcha-response" />
<input type="hidden" name="g-recaptcha-remoteip" value=<?php echo esc_attr( rcp_get_ip() ); ?> />
</div>
<?php
} else {
/**
* v2 markup
*/
?>
<div id="rcp_recaptcha" data-callback="rcp_validate_recaptcha" class="g-recaptcha" data-sitekey="<?php echo esc_attr( $rcp_options['recaptcha_public_key'] ); ?>"></div>
<input type="hidden" name="g-recaptcha-remoteip" value=<?php echo esc_attr( rcp_get_ip() ); ?> /><br/>
<?php
}
}
}
add_action( 'rcp_before_registration_submit_field', 'rcp_show_captcha', 100 );
add_action( 'rcp_before_stripe_checkout_submit_field', 'rcp_show_captcha', 100 );
/**
* Validate reCAPTCHA during form submission and throw an error if invalid.
*
* @param array $data Data passed through the registration form.
*
* @return void
*/
function rcp_validate_captcha( $data ) {
global $rcp_options;
if( ! rcp_is_recaptcha_enabled() ) {
return;
}
if ( empty( $data['g-recaptcha-response'] ) || empty( $data['g-recaptcha-remoteip'] ) ) {
rcp_errors()->add( 'invalid_recaptcha', __( 'Registration failed', 'rcp' ), 'register' );
return;
}
// Skip on validation step (to ensure we only do this once).
if ( ! empty( $data['validate_only'] ) ) {
return;
}
$verify = wp_safe_remote_post(
'https://www.google.com/recaptcha/api/siteverify',
array(
'body' => array(
'secret' => trim( $rcp_options['recaptcha_private_key'] ),
'response' => $data['g-recaptcha-response'],
'remoteip' => $data['g-recaptcha-remoteip']
)
)
);
$verify = json_decode( wp_remote_retrieve_body( $verify ) );
if ( 2 === rcp_get_recaptcha_version() ) {
/**
* Validate reCAPTCHA v2 response
*/
if ( empty( $verify->success ) || true !== $verify->success ) {
rcp_errors()->add( 'invalid_recaptcha', __( 'Registration failed', 'rcp' ), 'register' );
}
return;
} else {
/**
* Validate reCAPTCHA v3 response
*/
/**
* Filters the score threshold. Scores lower than this will be rejected.
*/
$score_threshold = apply_filters( 'rcp_recaptcha_score_threshold', 0.5 );
$score = ! empty( $verify->score ) ? $verify->score : 0;
rcp_log( sprintf( 'reCAPTCHA score: %s / %s', $score, $score_threshold ) );
if ( empty( $verify->success ) || true !== $verify->success || empty( $verify->action ) || 'register' !== $verify->action || $score < $score_threshold ) {
rcp_errors()->add( 'invalid_recaptcha', __( 'Registration failed', 'rcp' ), 'register' );
if ( isset( $verify->{'error-codes'} ) ) {
rcp_log( sprintf( 'reCAPTCHA errors: %s', var_export( $verify->{'error-codes'}, true ) ), true );
}
}
}
}
add_action( 'rcp_form_errors', 'rcp_validate_captcha' );

View File

@@ -0,0 +1,74 @@
<?php
/**
* Base Core Object
*
* @package restrict-content-pro
* @copyright Copyright (c) 2018, Restrict Content Pro team
* @license GPL2+
* @since 3.0
*/
namespace RCP;
// Exit if accessed directly
defined( 'ABSPATH' ) || exit;
/**
* Implements a base object to be extended by core objects.
*
* @since 3.0
* @abstract
*/
abstract class Base_Object {
/**
* Object constructor.
*
* @param mixed $args Object to populate members for.
*
* @since 3.0
*/
public function __construct( $args = null ) {
$this->set_vars( $args );
}
/**
* Set class variables from arguments.
*
* @param array $args
*
* @since 3.0
*/
protected function set_vars( $args = array() ) {
// Bail if empty or not an array
if ( empty( $args ) ) {
return;
}
// Cast to an array
if ( ! is_array( $args ) ) {
$args = (array) $args;
}
// Set all properties
foreach ( $args as $key => $value ) {
if ( '0000-00-00 00:00:00' === $value ) {
$value = null;
}
$this->{$key} = $value;
}
}
/**
* Get all object properties as an array
*
* @since 3.4
* @return array
*/
public function export_vars() {
return get_object_vars( $this );
}
}

View File

@@ -0,0 +1,89 @@
<?php
/**
* Roles and Capabilities
*
* @package Restrict Content Pro
* @subpackage Classes/Roles
* @copyright Copyright (c) 2017, Pippin Williamson
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
* @since 2.0
*/
/**
* Affiliate_WP_Roles Class
*
* This class handles the role creation and assignment of capabilities for those roles.
*
* @since 2.0
*/
class RCP_Capabilities {
/**
* Get things going
*
* @since 2.0
*/
public function __construct() { /* Do nothing here */ }
/**
* Add new capabilities
*
* @access public
* @since 2.0
* @global obj $wp_roles
* @return void
*/
public function add_caps() {
global $wp_roles;
if ( class_exists('WP_Roles') )
if ( ! isset( $wp_roles ) )
$wp_roles = new WP_Roles();
if ( is_object( $wp_roles ) ) {
$wp_roles->add_cap( 'administrator', 'rcp_view_members' );
$wp_roles->add_cap( 'administrator', 'rcp_manage_members' );
$wp_roles->add_cap( 'administrator', 'rcp_view_levels' );
$wp_roles->add_cap( 'administrator', 'rcp_manage_levels' );
$wp_roles->add_cap( 'administrator', 'rcp_view_discounts' );
$wp_roles->add_cap( 'administrator', 'rcp_manage_discounts' );
$wp_roles->add_cap( 'administrator', 'rcp_view_payments' );
$wp_roles->add_cap( 'administrator', 'rcp_manage_payments' );
$wp_roles->add_cap( 'administrator', 'rcp_manage_settings' );
$wp_roles->add_cap( 'administrator', 'rcp_export_data' );
$wp_roles->add_cap( 'administrator', 'rcp_view_help' );
}
}
/**
* Remove core post type capabilities (called on uninstall)
*
* @access public
* @since 2.0
* @return void
*/
public function remove_caps() {
if ( class_exists( 'WP_Roles' ) )
if ( ! isset( $wp_roles ) )
$wp_roles = new WP_Roles();
if ( is_object( $wp_roles ) ) {
/** Site Administrator Capabilities */
$wp_roles->remove_cap( 'administrator', 'rcp_view_members' );
$wp_roles->remove_cap( 'administrator', 'rcp_manage_members' );
$wp_roles->remove_cap( 'administrator', 'rcp_view_levels' );
$wp_roles->remove_cap( 'administrator', 'rcp_manage_levels' );
$wp_roles->remove_cap( 'administrator', 'rcp_view_discounts' );
$wp_roles->remove_cap( 'administrator', 'rcp_manage_discounts' );
$wp_roles->remove_cap( 'administrator', 'rcp_view_payments' );
$wp_roles->remove_cap( 'administrator', 'rcp_manage_payments' );
$wp_roles->remove_cap( 'administrator', 'rcp_manage_settings' );
$wp_roles->remove_cap( 'administrator', 'rcp_export_data' );
$wp_roles->remove_cap( 'administrator', 'rcp_view_help' );
}
}
}

View File

@@ -0,0 +1,647 @@
<?php
/**
* RCP WP-CLI
*
* This class provides an integration point with the WP-CLI plugin allowing
* access to RCP from the command line.
*
* @package restrict-content-pro
* @copyright Copyright (c) 2019, Restrict Content Pro team
* @license GPL2+
*/
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
if ( ! defined( 'WP_CLI' ) || ! class_exists( 'WP_CLI' ) ) {
return;
}
WP_CLI::add_command( 'rcp', 'RCP_CLI' );
class RCP_CLI extends WP_CLI_Command {
/**
* RCP_CLI constructor.
*/
public function __construct() {
}
/**
* Run batch processing jobs
*
* ## OPTIONS
*
* --id=<job_id>: The ID of the job to run.
* --name=<job_name>: The name of the job to run.
* --step=<step_number>: A specific step to start on. Default is 0 (beginning).
* --force=<boolean>: If the job should be run even if it has been run already.
*
* @param array $args
* @param array $assoc_args
*/
public function batch( $args, $assoc_args ) {
$job_id = ! empty( $assoc_args['id'] ) ? $assoc_args['id'] : false;
$job_name = ! empty( $assoc_args['name'] ) ? $assoc_args['name'] : false;
$step = ! empty( $assoc_args['step'] ) ? absint( $assoc_args['step'] ) : 0;
$force = isset( $assoc_args['force'] ) ? true : false;
$start = time();
$field = 'id';
$value = absint( $job_id );
if ( empty( $value ) ) {
$field = 'name';
$value = sanitize_text_field( $job_name );
}
if ( empty( $value ) ) {
WP_CLI::error( __( 'You must specify a job ID with the --id argument or a job name with the --name argument.', 'rcp' ) );
}
$job = \RCP\Utils\Batch\get_job_by( $field, $value );
if ( empty( $job ) ) {
WP_CLI::error( __( 'Invalid job.', 'rcp' ) );
}
if ( $job->is_completed() && ! $force ) {
WP_CLI::error( sprintf( __( 'The %s job has already been completed. To run it again anyway, use the --force argument.', 'rcp' ), esc_html( $job->get_name() ) ) );
}
if ( ! empty( $step ) ) {
$job->set_step( $step );
}
if ( $force ) {
$job->set_step( 0 );
$job->set_current_count( 0 );
$job->set_total_count( 0 );
$job->set_status( 'incomplete' );
}
$total_count = $job->get_callback_object()->get_total_count();
$per_step = $job->get_callback_object()->get_amount_per_step();
$total_steps = round( $total_count / $per_step );
$progress = \WP_CLI\Utils\make_progress_bar( sprintf( __( 'Processing Batch Job: %s', 'rcp' ), $job->get_name() ), $total_steps );
while ( ! $job->is_completed() ) {
$job->process_batch();
$progress->tick();
}
$progress->finish();
WP_CLI::log( sprintf( __( 'Job completed in %d seconds.', 'rcp' ), time() - $start ) );
WP_CLI::log( __( 'Old Records: ', 'rcp' ) . $job->get_total_count() );
WP_CLI::log( __( 'New Records: ', 'rcp' ) . $job->get_current_count() );
if ( $job->has_errors() ) {
WP_CLI::error_multi_line( $job->get_errors() );
}
}
/**
* Get or create membership records.
*
* ## OPTIONS
*
* --id=<membership_id>: A specific membership ID to retrieve.
* --email=<customer_email>: Retrieve the memberships for this customer email.
* --create=<number>: The number of arbitrary membership records to create.
* --range=<number>: The range (in number of days) to use for the creation period in new memberships. Default 30.
* --status=<membership_status>: Status to use for created memberships (active, pending, expired, or cancelled).
* Default is a random selection.
* --level=<membership_level_id>: ID of the membership level to assign. Default is a random one.
*
* ## EXAMPLES
*
* wp rcp memberships --id=3
* wp rcp memberships --email=support@restrictcontentpro.com
* wp rcp memberships --create=100 --range=365 --status=active
*
* @param array $args
* @param array $assoc_args
*/
public function memberships( $args, $assoc_args ) {
$membership_id = ! empty( $assoc_args['id'] ) ? absint( $assoc_args['id'] ) : 0;
$email = ! empty( $assoc_args['email'] ) ? $assoc_args['email'] : false;
$create = ! empty( $assoc_args['create'] ) ? absint( $assoc_args['create'] ) : false;
$range = ! empty( $assoc_args['range'] ) ? absint( $assoc_args['range'] ) : 30;
$status = ! empty( $assoc_args['status'] ) ? $assoc_args['status'] : false;
$level_id = ! empty( $assoc_args['level'] ) ? absint( $assoc_args['level'] ) : 0;
if ( $create ) {
/**
* Create new membership records.
*/
global $wpdb;
// Disable email notifications.
remove_action( 'rcp_membership_post_activate', 'rcp_email_on_membership_activation', 10 );
remove_action( 'rcp_membership_post_cancel', 'rcp_email_on_membership_cancellation', 10 );
remove_action( 'rcp_transition_membership_status_expired', 'rcp_email_on_membership_expiration', 10 );
remove_action( 'rcp_update_payment_status_complete', 'rcp_email_payment_received', 100 );
// Get all the active membership level IDs.
$level_ids = rcp_get_membership_levels( array( 'status' => 'active', 'fields' => 'id' ) );
if ( empty( $level_ids ) ) {
WP_CLI::error( __( 'You must have at least one active membership level.', 'rcp' ) );
}
$progress = \WP_CLI\Utils\make_progress_bar( 'Creating memberships', $create );
for ( $i = 0; $i < $create; $i++ ) {
if ( ! $email ) {
// Create a fake email if one wasn't provided.
$this_email = 'customer-' . uniqid() . '@test.com';
} else {
$this_email = $email;
}
// Choose a fake date to use for the created date.
$oldest_time = strtotime( '-' . $range . ' days', current_time( 'timestamp' ) );
$newest_time = current_time( 'timestamp' );
$timestamp = rand( $oldest_time, $newest_time );
$created_date = date( 'Y-m-d H:i:s', $timestamp );
$user = get_user_by( 'email', $this_email );
// Create a new user account if one does not exist.
if ( empty( $user ) ) {
$fname = $this->get_fname();
$lname = $this->get_lname();
$domain = $this->get_domain();
$tld = $this->get_tld();
$this_email = $fname . '.' . $lname . '@' . $domain . '.' . $tld;
$user_id = wp_insert_user( array(
'user_login' => $this_email,
'user_pass' => wp_generate_password(),
'user_email' => $this_email,
'first_name' => $fname,
'last_name' => $lname,
'display_name' => sprintf( '%s %s', $fname, $lname ),
'user_registered' => $created_date
) );
// Add user meta to designate this as a generated customer so we can deleted it later.
add_user_meta( $user_id, 'rcp_generated_via_cli', 1 );
} else {
$user_id = $user->ID;
}
$customer = rcp_get_customer_by_user_id( $user_id );
// Create a new customer record if one does not exist.
if ( empty( $customer ) ) {
$customer_id = rcp_add_customer( array(
'user_id' => absint( $user_id ),
'date_registered' => $created_date
) );
} else {
$customer_id = $customer->get_id();
}
// Now add the membership.
/*
* An array of available statuses, each mapped to a number.
*/
$statuses = array(
1 => 'active', // active
2 => 'pending', // pending
3 => 'expired', // expired
4 => 'cancelled', // cancelled
);
// Choose a random status if omitted.
if ( empty( $status ) || ! in_array( $status, $statuses ) ) {
$this_status = $statuses[rand( 1, 4 )];
} else {
$this_status = $status;
}
$membership_args = array(
'customer_id' => absint( $customer_id ),
'user_id' => $user_id,
'object_id' => ! empty( $level_id ) ? $level_id : $level_ids[array_rand( $level_ids )], // specified or random membership level ID
'status' => $this_status,
'created_date' => $created_date,
'gateway' => 'manual',
'subscription_key' => rcp_generate_subscription_key()
);
switch ( $membership_args['status'] ) {
case 'expired' :
// Set the expiration date to a random date between the start date and yesterday.
$oldest_time = strtotime( $created_date, current_time( 'timestamp' ) );
$newest_time = strtotime( '-1 day', current_time( 'timestamp' ) );
$timestamp = rand( $oldest_time, $newest_time );
$membership_args['expiration_date'] = date( 'Y-m-d H:i:s', $timestamp );
break;
case 'cancelled' :
// Set the cancellation date to a random date between the start date and yesterday.
// Set the expiration date to a random date between the start date and yesterday.
$oldest_time = strtotime( $created_date, current_time( 'timestamp' ) );
$newest_time = strtotime( '-1 day', current_time( 'timestamp' ) );
$timestamp = rand( $oldest_time, $newest_time );
$membership_args['cancellation_date'] = date( 'Y-m-d H:i:s', $timestamp );
break;
}
$membership_id = rcp_add_membership( $membership_args );
// Add membership meta to designate this as a generated record so we can deleted it later.
rcp_add_membership_meta( $membership_id, 'rcp_generated_via_cli', 1 );
$membership = rcp_get_membership( $membership_id );
// Generate a transaction ID.
$auth_key = defined( 'AUTH_KEY' ) ? AUTH_KEY : '';
$transaction_id = strtolower( md5( $membership_args['subscription_key'] . date( 'Y-m-d H:i:s' ) . $auth_key . uniqid( 'rcp', true ) ) );
// Create a corresponding payment record.
$payment_args = array(
'subscription' => rcp_get_subscription_name( $membership_args['object_id'] ),
'object_id' => $membership_args['object_id'],
'date' => $membership_args['created_date'],
'amount' => $membership->get_initial_amount(),
'subtotal' => $membership->get_initial_amount(),
'user_id' => $user_id,
'subscription_key' => $membership_args['subscription_key'],
'transaction_id' => $transaction_id,
'status' => 'pending' == $membership_args['status'] ? 'pending' : 'complete',
'gateway' => 'manual',
'customer_id' => $customer_id,
'membership_id' => $membership_id
);
$rcp_payments = new RCP_Payments();
$payment_id = $rcp_payments->insert( $payment_args );
// Add payment meta to designate this as a generated record so we can delete it later.
$rcp_payments->add_meta( $payment_id, 'rcp_generated_via_cli', 1 );
$progress->tick();
}
$progress->finish();
WP_CLI::success( sprintf( _n( 'Created %d membership record', 'Created %d membership records', $create, 'rcp' ), $create ) );
} elseif ( $membership_id ) {
/**
* Get an individual membership record.
*/
$membership = rcp_get_membership( $membership_id );
if ( empty( $membership ) ) {
WP_CLI::error( __( 'Invalid membership.', 'rcp' ) );
}
$this->print_membership_details( $membership );
} elseif ( $email ) {
/**
* Get all the memberships associated with a specific user email.
*/
$user = get_user_by( 'email', $email );
if ( empty( $user ) ) {
WP_CLI::error( __( 'No customer found with this email address.', 'rcp' ) );
}
$customer = rcp_get_customer_by_user_id( $user->ID );
if ( empty( $customer ) ) {
WP_CLI::error( __( 'No customer found with this email address.', 'rcp' ) );
}
$memberships = $customer->get_memberships();
if ( empty( $memberships ) ) {
WP_CLI::error( __( 'This customer does not have any memberships.', 'rcp' ) );
}
foreach ( $memberships as $membership ) {
$this->print_membership_details( $membership );
}
}
}
/**
* Get a customer record
*
* ## OPTIONS
*
* --id=<customer_id>: A specific customer ID to retrieve.
* --email=<customer_email>: A specific customer to retrieve, by their email address.
*
* ## EXAMPLES
*
* wp rcp customers --id=3
* wp rcp customers --email=support@restrictcontentpro.com
*
* @param array $args
* @param array $assoc_args
*/
public function customers( $args, $assoc_args ) {
$customer_id = ! empty( $assoc_args['id'] ) ? absint( $assoc_args['id'] ) : 0;
$email = ! empty( $assoc_args['email'] ) ? $assoc_args['email'] : false;
$customer = false;
$user = false;
if ( $customer_id ) {
$customer = rcp_get_customer( $customer_id );
} elseif ( $email ) {
$user = get_user_by( 'email', $email );
if ( empty( $user ) ) {
WP_CLI::error( __( 'No customer with this email address.', 'rcp' ) );
}
$customer = rcp_get_customer_by_user_id( $user->ID );
}
if ( empty( $customer ) ) {
WP_CLI::error( __( 'Invalid customer.', 'rcp' ) );
}
if ( empty( $user ) ) {
$user = get_userdata( $customer->get_user_id() );
}
WP_CLI::log( WP_CLI::colorize( '%G' . sprintf( __( 'Customer #%d ( %s )', 'rcp' ), $customer->get_id(), $user->user_email ) . '%N' ) );
WP_CLI::log( sprintf( __( 'User ID: %d', 'rcp' ), $customer->get_user_id() ) );
WP_CLI::log( sprintf( __( 'Username: %s', 'rcp' ), $user->user_login ) );
WP_CLI::log( sprintf( __( 'First Name: %s', 'rcp' ), $user->first_name ) );
WP_CLI::log( sprintf( __( 'Last Name: %s', 'rcp' ), $user->last_name ) );
WP_CLI::log( sprintf( __( 'Registration Date: %s', 'rcp' ), $customer->get_date_registered( false ) ) );
WP_CLI::log( sprintf( __( 'Last Login Date: %s', 'rcp' ), $customer->get_last_login( false ) ) );
$email_verification = $customer->is_pending_verification() ? __( 'yes', 'rcp' ) : __( 'no', 'rcp' );
WP_CLI::log( sprintf( __( 'Pending Email Verification: %s', 'rcp' ), $email_verification ) );
WP_CLI::log( sprintf( __( 'Active Memberships: %d', 'rcp' ), count( $customer->get_memberships( array( 'status' => array( 'active', 'cancelled' ) ) ) ) ) );
WP_CLI::log( sprintf( __( 'Number of Payments: %d', 'rcp' ), count( $customer->get_payments() ) ) );
WP_CLI::log( sprintf( __( 'Lifetime Value: %s', 'rcp' ), $customer->get_lifetime_value() ) );
}
/**
* Delete all data generated by the CLI.
*
* ## OPTIONS
*
* --skip-memberships=<boolean>: Whether to skip deleting generated memberships.
* --skip-customers=<boolean>: Whether to skip deleting generated customers.
* --skip-payments=<boolean>: Whether to skip deleting generated payments.
*
* @param array $args
* @param array $assoc_args
*/
public function delete_generated_data( $args, $assoc_args ) {
global $wpdb;
$skip_memberships = ! empty( $assoc_args['skip-memberships'] );
$skip_customers = ! empty( $assoc_args['skip-customers'] );
$skip_payments = ! empty( $assoc_args['skip-payments'] );
/*
* Payments
*/
if ( ! $skip_payments ) {
$paymentmeta_table_name = rcp_get_payment_meta_db_name();
$payments = new RCP_Payments();
$generated_payments = $wpdb->get_results( "SELECT * FROM {$paymentmeta_table_name} WHERE meta_key = 'rcp_generated_via_cli'" );
if ( $generated_payments ) {
$number_generated_payments = count( $generated_payments );
$payment_progress = \WP_CLI\Utils\make_progress_bar( sprintf( _n( 'Deleting %d generated payment', 'Deleting %d generated payments', $number_generated_payments, 'rcp' ), $number_generated_payments ), $number_generated_payments );
foreach ( $generated_payments as $generated_payment ) {
$payments->delete( $generated_payment->rcp_payment_id );
$payments->delete_meta( $generated_payment->rcp_payment_id, 'rcp_generated_via_cli' );
$payment_progress->tick();
}
$payment_progress->finish();
} else {
WP_CLI::log( __( 'No payments to delete.', 'rcp' ) );
}
}
/*
* Memberships
*/
if ( ! $skip_memberships ) {
$memberships = rcp_get_memberships( array(
'number' => 99999999,
'meta_query' => array(
array(
'key' => 'rcp_generated_via_cli',
'value' => 1
)
)
) );
if ( $memberships ) {
$number_generated_memberships = count( $memberships );
$membership_progress = \WP_CLI\Utils\make_progress_bar( sprintf( _n( 'Deleting %d generated membership', 'Deleting %d generated memberships', $number_generated_memberships, 'rcp' ), $number_generated_memberships ), $number_generated_memberships );
foreach ( $memberships as $membership ) {
if ( rcp_get_membership_meta( $membership->get_id(), 'rcp_generated_via_cli', true ) ) {
rcp_delete_membership_meta( $membership->get_id(), 'rcp_generated_via_cli' );
rcp_delete_membership( $membership->get_id() );
}
$membership_progress->tick();
}
$membership_progress->finish();
} else {
WP_CLI::log( __( 'No memberships to delete.', 'rcp' ) );
}
}
/*
* Customers (user accounts, actually)
*/
if ( ! $skip_customers ) {
$customers = get_users( array(
'fields' => 'ID',
'meta_key' => 'rcp_generated_via_cli',
'meta_value' => 1
) );
if ( $customers ) {
$number_generated_customers = count( $customers );
$customer_progress = \WP_CLI\Utils\make_progress_bar( sprintf( _n( 'Deleting %d generated customer', 'Deleting %d generated customers', $number_generated_customers, 'rcp' ), $number_generated_customers ), $number_generated_customers );
foreach ( $customers as $customer_id ) {
wp_delete_user( $customer_id );
$customer_progress->tick();
}
$customer_progress->finish();
} else {
WP_CLI::log( __( 'No customers to delete.', 'rcp' ) );
}
}
}
/**
* Print details about a membership.
*
* @param RCP_Membership $membership
*/
protected function print_membership_details( $membership ) {
$user_id = $membership->get_user_id();
$user = get_userdata( $user_id );
WP_CLI::log( WP_CLI::colorize( '%G' . sprintf( __( 'Membership #%d ( %s )', 'rcp' ), $membership->get_id(), $user->user_email ) . '%N' ) );
WP_CLI::log( sprintf( __( 'Customer ID: %d', 'rcp' ), $membership->get_customer_id() ) );
WP_CLI::log( sprintf( __( 'Created Date: %d', 'rcp' ), $membership->get_created_date( false ) ) );
WP_CLI::log( sprintf( __( 'Membership Status: %s', 'rcp' ), rcp_print_membership_status( $membership->get_id(), false ) ) );
WP_CLI::log( sprintf( __( 'Membership Level: %s', 'rcp' ), $membership->get_membership_level_name() ) );
WP_CLI::log( sprintf( __( 'Billing Cycle: %s', 'rcp' ), html_entity_decode( $membership->get_formatted_billing_cycle() ) ) );
$maximum_renewals = 0 == $membership->get_maximum_renewals() ? __( 'until cancelled', 'rcp' ) : $membership->get_maximum_renewals();
WP_CLI::log( sprintf( __( 'Times Billed: %s', 'rcp' ), sprintf( '%d / %s', $membership->get_times_billed(), $maximum_renewals ) ) );
$auto_renew = $membership->is_recurring() ? __( 'yes', 'rcp' ) : __( 'no', 'rcp' );
WP_CLI::log( sprintf( __( 'Auto Renew: %s', 'rcp' ), $auto_renew ) );
WP_CLI::log( sprintf( __( 'Expiration Date: %s', 'rcp' ), $membership->get_expiration_date( false ) ) );
if ( $membership->get_renewed_date( false ) ) {
WP_CLI::log( sprintf( __( 'Last Renewed: %s', 'rcp' ), $membership->get_renewed_date( false ) ) );
}
if ( 'cancelled' == $membership->get_status() ) {
WP_CLI::log( sprintf( __( 'Cancellation Date: %s', 'rcp' ), $membership->get_cancellation_date( false ) ) );
}
WP_CLI::log( sprintf( __( 'Gateway: %s', 'rcp' ), $membership->get_gateway() ) );
WP_CLI::log( '' );
}
/**
* Get a random first name
*
* @return string
*/
protected function get_fname() {
$names = array(
'Ilse',
'Emelda',
'Aurelio',
'Chiquita',
'Cheryl',
'Norbert',
'Neville',
'Wendie',
'Clint',
'Synthia',
'Tobi',
'Nakita',
'Marisa',
'Maybelle',
'Onie',
'Donnette',
'Henry',
'Sheryll',
'Leighann',
'Wilson',
);
return $names[rand( 0, ( count( $names ) - 1 ) )];
}
/**
* Get a random last name
*
* @return string
*/
protected function get_lname() {
$names = array(
'Warner',
'Roush',
'Lenahan',
'Theiss',
'Sack',
'Troutt',
'Vanderburg',
'Lisi',
'Lemons',
'Christon',
'Kogut',
'Broad',
'Wernick',
'Horstmann',
'Schoenfeld',
'Dolloff',
'Murph',
'Shipp',
'Hursey',
'Jacobi',
);
return $names[rand( 0, ( count( $names ) - 1 ) )];
}
/**
* Get domain
*
* Used for generating a random email address.
*
* @return string
*/
protected function get_domain() {
$domains = array(
'example',
'edd',
'rcp',
'affwp',
);
return $domains[rand( 0, ( count( $domains ) - 1 ) )];
}
/**
* Get TLD
*
* Used for generating a random email address.
*
* @return string
*/
protected function get_tld() {
$tlds = array(
'local',
'test',
'example',
'localhost',
'invalid',
);
return $tlds[rand( 0, ( count( $tlds ) - 1 ) )];
}
}

View File

@@ -0,0 +1,69 @@
<?php
/**
* Component
*
* @package restrict-content-pro
* @copyright Copyright (c) 2020, Sandhills Development, LLC
* @license GPL2+
* @since 3.4
*/
namespace RCP;
/**
* Class Component
*
* @package RCP
*/
class Component extends Base_Object {
/**
* Array of interface objects
*
* @since 3.4
* @var array
*/
private $interfaces = array();
/**
* Returns an interface object
*
* @param string $key Interface key
*
* @since 3.4
* @return object|false
*/
public function get_interface( $key ) {
return isset( $this->interfaces[ $key ] ) ? $this->interfaces[ $key ] : false;
}
/**
* Set up interfaces
*
* @param array $args
*
* @since 3.4
*/
protected function set_vars( $args = array() ) {
$keys = array(
'schema',
'table',
'query',
'object',
'meta'
);
foreach ( $args as $key => $value ) {
if ( in_array( $key, $keys, true ) && class_exists( $value ) ) {
$this->interfaces[ $key ] = new $value;
} else {
$this->{$key} = $value;
}
}
}
}

View File

@@ -0,0 +1,610 @@
<?php
/**
* Emails
*
* This class handles all emails sent through Restrict Content Pro
*
* @package Restrict Content Pro
* @subpackage Classes/Emails
* @copyright Copyright (c) 2017, Restrict Content Pro
* @license http://opensource.org/license/gpl-2.1.php GNU Public License
* @since 2.7
*/
// Exit if accessed directly
if ( ! defined( 'ABSPATH' ) ) exit;
/**
* RCP_Emails class
*
* @since 2.7
*/
class RCP_Emails {
/**
* Holds the from address
*
* @since 2.7
*/
private $from_address;
/**
* Holds the from name
*
* @since 2.7
*/
private $from_name;
/**
* Holds the email content type
*
* @since 2.7
*/
private $content_type;
/**
* Holds the email headers
*
* @since 2.7
*/
private $headers;
/**
* Whether to send email in HTML
*
* @since 2.7
*/
private $html = true;
/**
* The email template to use
*
* @since 2.7
*/
private $template;
/**
* The header text for the email
*
* @since 2.7
*/
private $heading = '';
/**
* Member ID
*
* @since 2.7
*/
private $member_id;
/**
* Payment ID
*
* @since 2.7
*/
private $payment_id;
/**
* Membership object
*
* @var RCP_Membership
*
* @since 3.0
*/
private $membership;
/**
* Container for storing all tags
*
* @since 2.7
*/
private $tags;
/**
* Get things going
*
* @since 2.7
* @return void
*/
public function __construct() {
if ( 'none' === $this->get_template() ) {
$this->html = false;
}
add_action( 'rcp_email_send_before', array( $this, 'send_before' ) );
add_action( 'rcp_email_send_after', array( $this, 'send_after' ) );
}
/**
* Set a property
*
* @since 2.7
* @return void
*/
public function __set( $key, $value ) {
$this->$key = $value;
}
/**
* Get the email from name
*
* @since 2.7
* @return string The email from name
*/
public function get_from_name() {
global $rcp_options;
if ( ! $this->from_name ) {
$this->from_name = ! empty( $rcp_options['from_name'] ) ? sanitize_text_field( $rcp_options['from_name'] ) : get_option( 'blogname' );
}
return apply_filters( 'rcp_emails_from_name', wp_specialchars_decode( $this->from_name ), $this );
}
/**
* Get the email from address
*
* @since 2.7
* @return string The email from address
*/
public function get_from_address() {
if ( ! $this->from_address ) {
global $rcp_options;
$this->from_address = ! empty( $rcp_options['from_email'] ) ? sanitize_text_field( $rcp_options['from_email'] ) : get_option( 'admin_email' );
}
return apply_filters( 'rcp_emails_from_address', $this->from_address, $this );
}
/**
* Get the email content type
*
* @since 2.7
* @return string The email content type
*/
public function get_content_type() {
if ( ! $this->content_type && $this->html ) {
$this->content_type = apply_filters( 'rcp_email_default_content_type', 'text/html', $this );
} elseif ( ! $this->html ) {
$this->content_type = 'text/plain';
}
return apply_filters( 'rcp_email_content_type', $this->content_type, $this );
}
/**
* Get the corresponding user ID.
*
* @since 3.0.8
* @return int
*/
public function get_user_id() {
return absint( $this->member_id );
}
/**
* Get the corresponding membership object.
*
* @access public
* @since 3.0
* @return RCP_Membership
*/
public function get_membership() {
return $this->membership;
}
/**
* Get the ID of the payment record associated with this email.
*
* @access public
* @since 3.3.9
* @return int|false
*/
public function get_payment_id() {
return ! empty( $this->payment_id ) ? absint( $this->payment_id ) : false;
}
/**
* Get the email headers
*
* @since 2.7
* @return string The email headers
*/
public function get_headers() {
if ( ! $this->headers ) {
$this->headers = "From: {$this->get_from_name()} <{$this->get_from_address()}>\r\n";
$this->headers .= "Reply-To: {$this->get_from_address()}\r\n";
$this->headers .= "Content-Type: {$this->get_content_type()}; charset=utf-8\r\n";
}
return apply_filters( 'rcp_email_headers', $this->headers, $this );
}
/**
* Retrieve email templates
*
* @since 2.7
* @return array The email templates
*/
public function get_templates() {
$templates = array(
'default' => __( 'Default Template', 'rcp' ),
'none' => __( 'No template, plain text only', 'rcp' )
);
return apply_filters( 'rcp_email_templates', $templates );
}
/**
* Get the enabled email template
*
* @since 2.7
* @return string|null
*/
public function get_template() {
if ( ! $this->template ) {
global $rcp_options;
$this->template = ! empty( $rcp_options['email_template'] ) ? sanitize_text_field( $rcp_options['email_template'] ) : 'default';
}
return apply_filters( 'rcp_email_template', $this->template );
}
/**
* Get the header text for the email
*
* @since 2.7
* @return string The header text
*/
public function get_heading() {
if ( ! $this->heading ) {
global $rcp_options;
$this->heading = ! empty( $rcp_options['email_header_text'] ) ? sanitize_text_field( $rcp_options['email_header_text'] ) : __( 'Hello', 'rcp' );
}
return apply_filters( 'rcp_email_heading', $this->heading );
}
/**
* Build the email
*
* @since 2.7
* @param string $message The email message
* @return string
*/
public function build_email( $message ) {
$message = $this->parse_tags( $message );
if ( false === $this->html ) {
return apply_filters( 'rcp_email_message', wp_strip_all_tags( $message ), $this );
}
$message = $this->text_to_html( $message );
ob_start();
rcp_get_template_part( 'emails/header', $this->get_template(), true );
/**
* Hooks into the email header
*
* @since 2.7
*/
do_action( 'rcp_email_header', $this );
rcp_get_template_part( 'emails/body', $this->get_template(), true );
/**
* Hooks into the email body
*
* @since 2.7
*/
do_action( 'rcp_email_body', $this );
rcp_get_template_part( 'emails/footer', $this->get_template(), true );
/**
* Hooks into the email footer
*
* @since 2.7
*/
do_action( 'rcp_email_footer', $this );
$body = ob_get_clean();
$message = str_replace( '{email}', $message, $body );
return apply_filters( 'rcp_email_message', $message, $this );
}
/**
* Send the email
*
* @since 2.7
* @param string|array $to The To address
* @param string $subject The subject line of the email
* @param string $message The body of the email
* @param string|array $attachments Attachments to the email
*
* @return bool Whether the email contents were sent successfully.
*/
public function send( $to, $subject, $message, $attachments = '' ) {
if ( defined( 'RCP_DISABLE_EMAILS' ) && RCP_DISABLE_EMAILS ) {
rcp_log( 'Email not sent - detected RCP_DISABLE_EMAILS constant.', true );
return true;
}
if ( ! did_action( 'init' ) && ! did_action( 'admin_init' ) ) {
_doing_it_wrong( __FUNCTION__, __( 'You cannot send emails with rcp_Emails until init/admin_init has been reached', 'rcp' ), null );
return false;
}
$this->setup_email_tags();
/**
* Hooks before email is sent
*
* @since 2.7
*/
do_action( 'rcp_email_send_before', $this );
$subject = $this->parse_tags( $subject );
$message = $this->build_email( $message );
$attachments = apply_filters( 'rcp_email_attachments', $attachments, $this );
$sent = wp_mail( $to, $subject, $message, $this->get_headers(), $attachments );
/**
* Hooks after the email is sent
*
* @since 2.7
*/
do_action( 'rcp_email_send_after', $this );
if ( false === $sent ) {
rcp_log( 'wp_mail() failure in RCP_Emails class.', true );
}
return $sent;
}
/**
* Generate preview by setting up email tags and inserting message inside email template.
*
* @param string $message
*
* @return string
*/
public function generate_preview( $message = '' ) {
$this->setup_email_tags();
$message = $this->build_email( $message );
return $message;
}
/**
* Add filters/actions before the email is sent
*
* @since 2.7
*/
public function send_before() {
add_filter( 'wp_mail_from', array( $this, 'get_from_address' ) );
add_filter( 'wp_mail_from_name', array( $this, 'get_from_name' ) );
add_filter( 'wp_mail_content_type', array( $this, 'get_content_type' ) );
}
/**
* Remove filters/actions after the email is sent
*
* @since 2.7
*/
public function send_after() {
remove_filter( 'wp_mail_from', array( $this, 'get_from_address' ) );
remove_filter( 'wp_mail_from_name', array( $this, 'get_from_name' ) );
remove_filter( 'wp_mail_content_type', array( $this, 'get_content_type' ) );
// Reset heading to an empty string
$this->heading = '';
}
/**
* Converts text formatted HTML. This is primarily for turning line breaks into <p> and <br/> tags.
*
* @since 2.7
* @return string
*/
public function text_to_html( $message ) {
if ( 'text/html' === $this->content_type || true === $this->html ) {
$message = wpautop( make_clickable( $message ) );
$message = str_replace( '&#038;', '&amp;', $message );
}
return $message;
}
/**
* Search content for email tags and filter email tags through their hooks
*
* @since 2.7
* @param string $content Content to search for email tags
* @return string $content Filtered content
*/
private function parse_tags( $content ) {
// Make sure there's at least one tag
if ( empty( $this->tags ) || ! is_array( $this->tags ) ) {
return $content;
}
$new_content = preg_replace_callback( "/%([A-z0-9\-\_]+)%/s", array( $this, 'do_tag' ), $content );
// Here for backwards compatibility
$new_content = apply_filters( 'rcp_email_tags', $new_content, $this->member_id );
return $new_content;
}
/**
* Setup all registered email tags
*
* @since 2.7
* @return void
*/
private function setup_email_tags() {
$tags = $this->get_tags();
foreach( $tags as $tag ) {
if ( isset( $tag['function'] ) && is_callable( $tag['function'] ) ) {
$this->tags[ $tag['tag'] ] = $tag;
}
}
}
/**
* Retrieve all registered email tags
*
* @since 2.7
* @return array
*/
public function get_tags() {
// Setup default tags array
$email_tags = array(
array(
'tag' => 'name',
'description' => __( 'The full name of the member', 'rcp' ),
'function' => 'rcp_email_tag_name'
),
array(
'tag' => 'username',
'description' => __( 'The user name of the member on the site', 'rcp' ),
'function' => 'rcp_email_tag_user_name'
),
array(
'tag' => 'useremail',
'description' => __( 'The email address of the member', 'rcp' ),
'function' => 'rcp_email_tag_user_email'
),
array(
'tag' => 'firstname',
'description' => __( 'The first name of the member', 'rcp' ),
'function' => 'rcp_email_tag_first_name'
),
array(
'tag' => 'lastname',
'description' => __( 'The last name of the member', 'rcp' ),
'function' => 'rcp_email_tag_last_name'
),
array(
'tag' => 'displayname',
'description' => __( 'The display name of the member', 'rcp' ),
'function' => 'rcp_email_tag_display_name'
),
array(
'tag' => 'expiration',
'description' => __( 'The expiration date of the member', 'rcp' ),
'function' => 'rcp_email_tag_expiration'
),
array(
'tag' => 'subscription_name',
'description' => __( 'The name of the membership level the member is subscribed to', 'rcp' ),
'function' => 'rcp_email_tag_subscription_name'
),
array(
'tag' => 'subscription_key',
'description' => __( 'The unique key of the membership level the member is subscribed to', 'rcp' ),
'function' => 'rcp_email_tag_subscription_key'
),
array(
'tag' => 'amount',
'description' => __( 'The amount of the last payment made by the member', 'rcp' ),
'function' => 'rcp_email_tag_amount'
),
array(
'tag' => 'invoice_url',
'description' => __( 'The URL to the member\'s most recent invoice', 'rcp' ),
'function' => 'rcp_email_tag_invoice_url'
),
array(
'tag' => 'membership_renew_url',
'description' => __( 'The URL to renew the membership associated with the email being sent', 'rcp' ),
'function' => 'rcp_email_tag_membership_renew_url'
),
array(
'tag' => 'membership_change_url',
'description' => __( 'The URL to change (upgrade/downgrade) the membership associated with the email being sent', 'rcp' ),
'function' => 'rcp_email_tag_membership_change_url'
),
array(
'tag' => 'update_billing_card_url',
'description' => __( 'The URL to the "Update Billing Card" page for the latest payment (recommended for use in the Renewal Payment Failed email)', 'rcp' ),
'function' => 'rcp_email_tag_update_billing_card_url'
),
array(
'tag' => 'discount_code',
'description' => __( 'The discount code that was used with the most recent payment', 'rcp' ),
'function' => 'rcp_email_tag_discount_code'
),
array(
'tag' => 'member_id',
'description' => __( 'The member&#8217;s user ID number', 'rcp' ),
'function' => 'rcp_email_tag_member_id'
),
array(
'tag' => 'blogname',
'description' => __( 'The name of this website', 'rcp' ),
'function' => 'rcp_email_tag_site_name'
),
array(
'tag' => 'verificationlink',
'description' => __( 'The email verification URL, only for the Email Verification template', 'rcp' ),
'function' => 'rcp_email_tag_email_verification'
)
);
return apply_filters( 'rcp_email_template_tags', $email_tags, $this );
}
/**
* Parse a specific tag.
*
* @since 2.7
* @param $m Message
*/
private function do_tag( $m ) {
// Get tag
$tag = $m[1];
// Return tag if not set
if ( ! $this->email_tag_exists( $tag ) ) {
return $m[0];
}
return call_user_func( $this->tags[$tag]['function'], $this->member_id, $this->payment_id, $tag, $this->membership );
}
/**
* Check if $tag is a registered email tag
*
* @since 2.7
* @param string $tag Email tag that will be searched
* @return bool True if exists, false otherwise
*/
public function email_tag_exists( $tag ) {
return array_key_exists( $tag, $this->tags );
}
}

View File

@@ -0,0 +1,196 @@
<?php
/**
* Export Class
*
* This is the base class for all export methods. Each data export type (subscribers, payments, etc) extend this class
*
* @package Restrict Content Pro
* @subpackage Export Class
* @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
if ( ! defined( 'ABSPATH' ) ) exit;
class RCP_Export {
/**
* Our export type. Used for export-type specific filters / actions
*
* @access public
* @var string
* @since 1.5
*/
public $export_type = 'default';
/**
* Can we export?
*
* @access public
* @since 1.5
* @return bool
*/
public function can_export() {
return (bool) apply_filters( 'rcp_export_capability', current_user_can( 'rcp_export_data' ) );
}
/**
* Set the export headers
*
* @access public
* @since 1.5
* @return void
*/
public function headers() {
ignore_user_abort( true );
if ( ! rcp_is_func_disabled( 'set_time_limit' ) && ! ini_get( 'safe_mode' ) )
set_time_limit( 0 );
nocache_headers();
header( 'Content-Type: text/csv; charset=utf-8' );
header( 'Content-Disposition: attachment; filename=rcp-export-' . $this->export_type . '-' . date( 'm-d-Y' ) . '.csv' );
header( "Expires: 0" );
}
/**
* Set the CSV columns
*
* @access public
* @since 1.5
* @return array
*/
public function csv_cols() {
$cols = array(
'id' => __( 'ID', 'rcp' ),
'date' => __( 'Date', 'rcp' )
);
return $cols;
}
/**
* Retrieve CSV columns
*
* @access public
* @since 1.5
* @return array
*/
public function get_csv_cols() {
$cols = $this->csv_cols();
return apply_filters( 'rcp_export_csv_cols_' . $this->export_type, $cols );
}
/**
* Output the CSV columns
*
* @access public
* @since 1.5
* @return void
*/
public function csv_cols_out() {
$cols = $this->get_csv_cols();
$i = 1;
foreach( $cols as $col_id => $column ) {
echo '"' . $column . '"';
echo $i == count( $cols ) ? '' : ',';
$i++;
}
echo "\r\n";
}
/**
* Get the data being exported
*
* @access public
* @since 1.5
* @return array $data
*/
public function get_data() {
// Just a sample data array
$data = array(
0 => array(
'id' => '',
'data' => date( 'F j, Y' )
),
1 => array(
'id' => '',
'data' => date( 'F j, Y' )
)
);
$data = apply_filters( 'rcp_export_get_data', $data );
$data = apply_filters( 'rcp_export_get_data_' . $this->export_type, $data );
return $data;
}
/**
* Output the CSV rows
*
* @access public
* @since 1.5
* @return void
*/
public function csv_rows_out() {
$data = $this->get_data();
$cols = $this->get_csv_cols();
// Output each row
foreach ( $data as $row ) {
$i = 1;
foreach ( $row as $col_id => $column ) {
// Make sure the column is valid
if ( array_key_exists( $col_id, $cols ) ) {
echo '"' . $this->esc_field( $column ) . '"';
echo $i == count( $cols ) + 1 ? '' : ',';
}
$i++;
}
echo "\r\n";
}
}
/**
* Escape a string to be used in a CSV context
*
* @param string $field
*
* @access public
* @since 2.6.4
* @return string
*/
public function esc_field( $field ) {
$field = addslashes( preg_replace( "/\"/","'", $field ) );
return $field;
}
/**
* Perform the export
*
* @access public
* @since 1.5
* @return void
*/
public function export() {
if( ! $this->can_export() )
wp_die( __( 'You do not have permission to export data.', 'rcp' ), __( 'Error', 'rcp' ) );
// Set headers
$this->headers();
// Output CSV columns (headers)
$this->csv_cols_out();
// Output CSV rows
$this->csv_rows_out();
exit;
}
}

View File

@@ -0,0 +1,67 @@
<?php
/**
* RCP Integrations class
*
* This class handles loading integration files.
*
* @package Restrict Content Pro
* @subpackage Classes/Integrations
* @copyright Copyright (c) 2017, Restrict Content Pro
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
*/
class RCP_Integrations {
/**
* Load plugin integrations.
*
* @access public
* @return void
*/
public function __construct() {
add_action( 'plugins_loaded', array( $this, 'load' ) );
}
/**
* Get a list of available integrations.
*
* @access public
* @return array
*/
public function get_integrations() {
return apply_filters( 'rcp_integrations', array(
'woocommerce' => 'WooCommerce',
'google-authenticator' => 'Google Authenticator',
'wp-approve-user' => 'WP Approve User',
'easy-digital-downloads' => 'Easy Digital Downloads'
) );
}
/**
* Load integration files.
*
* @access public
* @return void
*/
public function load() {
do_action( 'rcp_integrations_load' );
foreach( $this->get_integrations() as $filename => $integration ) {
if( file_exists( RCP_PLUGIN_DIR . 'core/includes/integrations/class-rcp-' . $filename . '.php' ) ) {
require_once RCP_PLUGIN_DIR . 'core/includes/integrations/class-rcp-' . $filename . '.php';
}
}
do_action( 'rcp_integrations_loaded' );
}
}
new RCP_Integrations;

View File

@@ -0,0 +1,453 @@
<?php
/**
* RCP Membership Levels class
*
* This class handles querying, inserting, updating, and removing membership levels
* Also includes other membership level helper functions
*
* @package Restrict Content Pro
* @subpackage Classes/Membership Levels
* @copyright Copyright (c) 2017, Restrict Content Pro
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
* @since 1.5
*/
/**
* Class RCP_Levels
*
* @deprecated 3.4
*/
class RCP_Levels {
/**
* Holds the name of our levels database table
*
* @access public
* @since 1.5
*/
public $db_name;
/**
* Holds the name of our level meta database table
*
* @access public
* @since 2.6
*/
public $meta_db_name;
/**
* Holds the version number of our levels database table
*
* @access public
* @since 1.5
*/
public $db_version;
/**
* Get things started
*
* @since 1.5
* @return void
*/
function __construct() {
$this->db_name = rcp_get_levels_db_name();
$this->meta_db_name = rcp_get_level_meta_db_name();
$this->db_version = '1.6';
}
/**
* Retrieve a specific membership level from the database
*
* @deprecated 3.4 In favour of `rcp_get_membership_level()`
* @see rcp_get_membership_level()
*
* @param int $level_id ID of the level to retrieve.
*
* @access public
* @since 1.5
* @return object
*/
public function get_level( $level_id = 0 ) {
_deprecated_function( __METHOD__, '3.4', 'rcp_get_membership_level' );
return rcp_get_membership_level( $level_id );
}
/**
* Retrieve a specific membership level from the database
*
* @deprecated 3.4 In favour of `rcp_get_membership_level_by()`
* @see rcp_get_membership_level_by()
*
* @param string $field Name of the field to check against.
* @param mixed $value Value of the field.
*
* @access public
* @since 1.8.2
* @return object|null
*/
public function get_level_by( $field = 'name', $value = '' ) {
_deprecated_function( __METHOD__, '3.4', 'rcp_get_membership_level_by' );
return rcp_get_membership_level_by( $field, $value );
}
/**
* Retrieve all membership levels from the database
*
* @deprecated 3.4 In favour of `rcp_get_membership_levels()`
* @see rcp_get_membership_levels()
*
* @param array $args Query arguments to override the defaults.
*
* @access public
* @since 1.5
* @return array|false Array of level objects or false if none are found.
*/
public function get_levels( $args = array() ) {
_deprecated_function( __METHOD__, '3.4', 'rcp_get_membership_levels' );
$args = wp_parse_args( $args, array(
'status' => 'all',
'limit' => null,
'offset' => 0,
'orderby' => 'list_order'
) );
if ( 'all' === $args['status'] ) {
unset( $args['status'] ); // It's "all" by default.
}
if ( ! empty( $args['limit'] ) ) {
$args['number'] = absint( $args['limit'] );
}
unset( $args['limit'] );
return rcp_get_membership_levels( $args );
}
/**
* Count the total number of membership levels in the database
*
* @deprecated 3.4 In favour of `rcp_count_membership_levels()`
* @see rcp_count_membership_levels()
*
* @param array $args Query arguments to override the defaults.
*
* @access public
* @return int
*/
public function count( $args = array() ) {
_deprecated_function( __METHOD__, '3.4', 'rcp_count_membership_levels' );
$args = wp_parse_args( $args, array(
'status' => 'all'
) );
if ( 'all' === $args['status'] ) {
unset( $args['status'] ); // It's "all" by default.
}
return rcp_count_membership_levels( $args );
}
/**
* Retrieve a field for a membership level
*
* @deprecated 3.4
*
* @param int $level_id ID of the level.
* @param string $field Name of the field to retrieve the value for.
*
* @access public
* @since 1.5
* @return mixed
*/
public function get_level_field( $level_id = 0, $field = '' ) {
_deprecated_function( __METHOD__, '3.4' );
$level = rcp_get_membership_level( $level_id );
if ( ! method_exists( $level, 'get_' . $field ) ) {
return false;
}
$value = call_user_func( array( $level, 'get_' . $field ) );
/**
* Filters the level field.
*
* @deprecated 3.4
*/
return apply_filters_deprecated( 'rcp_get_level_field', array( $value, $level_id, $field ), '3.4' );
}
/**
* Insert a membership level into the database
*
* @deprecated 3.4 In favour of `rcp_add_membership_level()`
* @see rcp_add_membership_level()
*
* @param array $args Arguments to override the defaults.
*
* @access public
* @since 1.5
* @return int|WP_Error ID of the newly created level or WP_Error on failure.
*/
public function insert( $args = array() ) {
_deprecated_function( __METHOD__, '3.4', 'rcp_add_membership_level' );
return rcp_add_membership_level( $args );
}
/**
* Update an existing membership level
*
* @deprecated 3.4 In favour of `rcp_update_membership_level()`
* @see rcp_update_membership_level()
*
* @param int $level_id ID of the level to update.
* @param array $args Fields and values to update.
*
* @access public
* @since 1.5
* @return true|WP_Error True if the update was successful, WP_Error on failure.
*/
public function update( $level_id = 0, $args = array() ) {
_deprecated_function( __METHOD__, '3.4', 'rcp_update_membership_level' );
return rcp_update_membership_level( $level_id, $args );
}
/**
* Delete a membership level
*
* @deprecated 3.4 In favour of `rcp_delete_membership_level()`
* @see rcp_delete_membership_level()
*
* @param int $level_id ID of the level to delete.
*
* @access public
* @since 1.5
* @return void
*/
public function remove( $level_id = 0 ) {
_deprecated_function( __METHOD__, '3.4', 'rcp_delete_membership_level' );
rcp_delete_membership_level( $level_id );
}
/**
* Retrieve level meta field for a membership level.
*
* @param int $level_id Membership level ID.
* @param string $meta_key The meta key to retrieve.
* @param bool $single Whether to return a single value.
*
* @access public
* @since 2.6
* @return mixed Single metadata value, or array of values
*/
public function get_meta( $level_id = 0, $meta_key = '', $single = false ) {
return get_metadata( 'level', $level_id, $meta_key, $single );
}
/**
* Add meta data field to a membership level.
*
* @param int $level_id Membership level ID.
* @param string $meta_key Metadata name.
* @param mixed $meta_value Metadata value.
* @param bool $unique Optional, default is false. Whether the same key should not be added.
*
* @access public
* @since 2.6
* @since 3.5.10 Removing default values for $level_id and $meta_key
*
* @return int|false The meta ID on success, false on failure.
*/
public function add_meta( $level_id, $meta_key, $meta_value, $unique = false ) {
return add_metadata( 'level', $level_id, $meta_key, $meta_value, $unique );
}
/**
* Update level meta field based on membership level ID.
*
* Use the $prev_value parameter to differentiate between meta fields with the
* same key and membership level ID.
*
* If the meta field for the membership level does not exist, it will be added.
*
* @param int $level_id Membership level ID.
* @param string $meta_key Metadata key.
* @param mixed $meta_value Metadata value.
* @param mixed $prev_value Optional. Previous value to check before removing.
*
* @access public
* @since 2.6
* @since 3.5.10 Removing default values for $level_id and $meta_key
*
* @return int|bool Meta ID if the key didn't exist, true on successful update, false on failure.
*/
public function update_meta( $level_id, $meta_key, $meta_value, $prev_value = '' ) {
return update_metadata( 'level', $level_id, $meta_key, $meta_value, $prev_value );
}
/**
* Remove metadata matching criteria from a membership level.
*
* You can match based on the key, or key and value. Removing based on key and
* value, will keep from removing duplicate metadata with the same key. It also
* allows removing all metadata matching key, if needed.
*
* @param int $level_id Membership level ID.
* @param string $meta_key Metadata name.
* @param mixed $meta_value Optional. Metadata value.
*
* @access public
* @since 2.6
* @return bool True on successful delete, false on failure.
*/
public function delete_meta( $level_id = 0, $meta_key = '', $meta_value = '' ) {
return delete_metadata( 'level', $level_id, $meta_key, $meta_value );
}
/**
* Removes all metadata for the specified membership level.
*
* @since 2.6.6
* @uses wpdb::query()
* @uses wpdb::prepare()
*
* @param int $level_id membership level ID.
* @return int|false Number of rows affected/selected or false on error.
*/
public function remove_all_meta_for_level_id( $level_id = 0 ) {
global $wpdb;
if ( empty( $level_id ) ) {
return;
}
$wpdb->query( $wpdb->prepare( "DELETE FROM {$wpdb->levelmeta} WHERE level_id = %d", absint( $level_id ) ) );
}
/**
* Validates that the amount is a valid format.
*
* Private for now until we finish validation for all fields.
*
* @since 2.7
* @access private
* @return boolean true if valid, false if not.
*/
private function valid_amount( $amount ) {
return filter_var( $amount, FILTER_VALIDATE_FLOAT );
}
/**
* Determines if the specified membership level has a trial option.
*
* @deprecated 3.4 In favour of `RCP\Membership_Level::has_trial()`
* @see RCP\Membership_Level::has_trial()
*
* @access public
* @since 2.7
*
* @param int $level_id The membership level ID.
*
* @return boolean true if the level has a trial option, false if not.
*/
public function has_trial( $level_id = 0 ) {
_deprecated_function( __METHOD__, '3.4', 'RCP\Membership_Level::has_trial' );
$level = rcp_get_membership_level( $level_id );
if ( ! $level instanceof RCP\Membership_Level ) {
return false;
}
return $level->has_trial();
}
/**
* Retrieves the trial duration for the specified membership level.
*
* @deprecated 3.4 In favour of `RCP\Membership_Level::get_trial_duration()`
* @see RCP\Membership_Level::get_trial_duration()
*
* @access public
* @since 2.7
*
* @param int $level_id The membership level ID.
*
* @return int The duration of the trial. 0 if there is no trial.
*/
public function trial_duration( $level_id = 0 ) {
_deprecated_function( __METHOD__, '3.4', 'RCP\Membership_Level::get_trial_duration' );
$level = rcp_get_membership_level( $level_id );
if ( ! $level instanceof RCP\Membership_Level ) {
return 0;
}
return $level->get_trial_duration();
}
/**
* Retrieves the trial duration unit for the specified membership level.
*
* @deprecated 3.4 In favour of `RCP\Membership_Level::get_trial_duration_unit()`
* @see RCP\Membership_Level::get_trial_duration_unit()
*
* @access public
* @since 2.7
*
* @param int $level_id The membership level ID.
*
* @return string The duration unit of the trial.
*/
public function trial_duration_unit( $level_id = 0 ) {
_deprecated_function( __METHOD__, '3.4', 'RCP\Membership_Level::get_trial_duration_unit' );
$level = rcp_get_membership_level( $level_id );
if ( ! $level instanceof RCP\Membership_Level ) {
return 'day';
}
return $level->get_trial_duration_unit();
}
}

View File

@@ -0,0 +1,147 @@
<?php
/**
* Debug Logging class
*
* @package restrict-content-pro
* @subpackage Classes/Logging
* @copyright Copyright (c) 2017, Restrict Content Pro
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
* @since 2.9
*/
class RCP_Logging {
/**
* Full path to the file
*
* @var string
* @access public
* @since 2.9
*/
public $file = '';
/**
* Get things started
*
* @param array $args Arguments to override the defaults.
*
* @access public
* @since 2.9
* @return void
*/
public function __construct( $args = array() ) {
$upload_dir = wp_upload_dir();
$defaults = array(
'file' => trailingslashit( $upload_dir['basedir'] ) . 'rcp-debug.log'
);
$args = wp_parse_args( $args, $defaults );
$this->file = $args['file'];
}
/**
* Checks if the file is writable
*
* @access public
* @since 2.0
* @return bool
*/
public function is_writable() {
return is_writable( $this->file );
}
/**
* Retrieve the log data
*
* @access public
* @since 2.9
* @return string
*/
public function get_log() {
return $this->get_file();
}
/**
* Log message to file
*
* @param string $message Message to log.
*
* @access public
* @since 2.9
* @return void
*/
public function log( $message = '' ) {
$message = current_time( 'Y-n-d H:i:s' ) . ' - ' . $message . "\r\n";
$this->write_to_log( $message );
}
/**
* Retrieve the file
*
* @access protected
* @since 2.9
* @return string
*/
protected function get_file() {
$file = '';
if ( @file_exists( $this->file ) ) {
$file = @file_get_contents( $this->file );
}
return $file;
}
/**
* Write the log message
*
* If the file doesn't exist yet, it's also created.
*
* @param string $message Message to log.
*
* @access protected
* @since 2.9
* @return void
*/
protected function write_to_log( $message = '' ) {
if ( ! @file_exists( $this->file ) ) {
@file_put_contents( $this->file, '' );
@chmod( $this->file, 0664 );
}
if ( ! $this->is_writable() ) {
return;
}
$file = $this->get_file();
$file .= $message;
@file_put_contents( $this->file, $file );
}
/**
* Clear the log
*
* @access public
* @since 2.9
* @return void
*/
public function clear_log() {
if ( ! $this->is_writable() ) {
return;
}
@unlink( $this->file );
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,735 @@
<?php
use RCP\Membership_Level;
/**
* RCP Registration Class
*
* @package Restrict Content Pro
* @subpackage Classes/Registration
* @copyright Copyright (c) 2017, Restrict Content Pro
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
* @since 2.5
*/
class RCP_Registration {
/**
* Store the membership level ID for the registration
*
* @since 2.5
* @var int
*/
protected $subscription = 0;
/**
* Membership level object for the registration
*
* @since 3.4
* @var Membership_Level|false
*/
protected $membership_level = false;
/**
* Type of registration: new, renewal, upgrade
*
* @since 3.1
* @var string
*/
protected $registration_type = 'new';
/**
* Current membership, if this is a renewal or upgrade
*
* @since 3.1
* @var RCP_Membership|false
*/
protected $membership = false;
/**
* Payment object from the database if we're recovering a pending/abandoned/failed payment.
*
* @since 3.2.2
* @var object|bool
*/
protected $recovered_payment = false;
/**
* Store the discounts for the registration
*
* @since 2.5
* @var array
*/
protected $discounts = array();
/**
* Store the fees/credits for the registration. Credits are negative fees.
*
* @since 2.5
* @var array
*/
protected $fees = array();
/**
* Get things started.
*
* @param int $level_id ID of the membership level for this registration.
* @param null|string $discount Discount code to apply to this registration.
*
* @return void
*/
public function __construct( $level_id = 0, $discount = null ) {
if ( $level_id ) {
$this->set_subscription( $level_id );
}
$this->set_registration_type();
$this->maybe_recover_payment();
$this->maybe_add_signup_fee();
if ( $level_id && $discount ) {
$this->add_discount( strtolower( $discount ) );
}
do_action( 'rcp_registration_init', $this );
}
/**
* Set the subscription for this registration
*
* @since 2.5
*
* @param $membership_level
*
* @return bool
*/
public function set_subscription( $membership_level ) {
$this->membership_level = rcp_get_membership_level( $membership_level );
if ( ! $this->membership_level instanceof Membership_Level ) {
return false;
}
$this->subscription = $membership_level;
return true;
}
/**
* Add a signup fee if this is not a "renewal".
*
* @since 3.1
* @return void
*/
protected function maybe_add_signup_fee() {
if ( ! $this->membership_level instanceof Membership_Level ) {
return;
}
if ( empty( $this->membership_level->get_fee() ) ) {
return;
}
$add_signup_fee = 'renewal' != $this->get_registration_type();
/**
* Filters whether or not the signup fee should be applied.
*
* @param bool $add_signup_fee Whether or not to add the signup fee.
* @param Membership_Level $membership_level Membership level object.
* @param RCP_Registration $this Registration object.
*
* @since 3.1
*/
$add_signup_fee = apply_filters( 'rcp_apply_signup_fee_to_registration', $add_signup_fee, $this->membership_level, $this );
if ( ! $add_signup_fee ) {
return;
}
$description = ( $this->membership_level->get_fee() > 0 ) ? __( 'Signup Fee', 'rcp' ) : __( 'Signup Credit', 'rcp' );
$this->add_fee( $this->membership_level->get_fee(), $description );
}
/**
* Get registration subscription
*
* @deprecated 3.0 Use `RCP_Registration::get_membership_level_id()` instead.
* @see RCP_Registration::get_membership_level_id()
*
* @since 2.5
* @return int
*/
public function get_subscription() {
_deprecated_function( __METHOD__, '3.0', __CLASS__ . ':get_membership_level_id' );
return $this->get_membership_level_id();
}
/**
* Get the ID number of the membership level this registration is for.
*
* @access public
* @since 3.0
* @return int ID of the membership level.
*/
public function get_membership_level_id() {
return $this->subscription;
}
/**
* Set registration type
*
* This is based on the following query strings:
*
* - $_REQUEST['registration_type'] - Will either be "renewal" or "upgrade". If empty, we assume "new".
* - $_REQUEST['membership_id'] - This must be provided for renewals and upgrades so we know which membership
* to work with.
*
* @since 3.1
* @return void
*/
public function set_registration_type() {
$this->registration_type = 'new'; // default;
if ( ! empty( $_REQUEST['registration_type'] ) && 'new' != $_REQUEST['registration_type'] && ! empty( $_REQUEST['membership_id'] ) ) {
/**
* The `registration_type` query arg is set, it's NOT `new`, and we have a membership ID.
*/
$membership = rcp_get_membership( absint( $_REQUEST['membership_id'] ) );
if ( ! empty( $membership ) && $membership->get_user_id() == get_current_user_id() ) {
$this->membership = $membership;
$this->registration_type = sanitize_text_field( $_REQUEST['registration_type'] );
}
} elseif ( ! rcp_multiple_memberships_enabled() && $this->get_membership_level_id() ) {
/**
* Multiple memberships not enabled, and we have a selected membership level ID on the form.
* We determine if it's a renewal or upgrade based on the user's current membership level and
* the one they've selected on the registration form.
*/
$customer = rcp_get_customer();
$previous_membership = ! empty( $customer ) ? rcp_get_customer_single_membership( $customer->get_id() ) : false;
if ( ! empty( $previous_membership ) ) {
$this->membership = $previous_membership;
if ( $this->membership->get_object_id() == $this->get_membership_level_id() ) {
$this->registration_type = 'renewal';
} else {
$this->registration_type = 'upgrade';
}
}
}
if ( 'upgrade' == $this->registration_type && is_object( $this->membership ) && $this->membership_level instanceof Membership_Level ) {
/**
* If we have the type listed as an "upgrade", we'll run a few extra checks to determine
* if we should change this to "downgrade".
*/
// Figure out if this is a downgrade instead.
$previous_membership_level = rcp_get_membership_level( $this->membership->get_object_id() );
// If the previous membership level is invalid (maybe it's been deleted), then treat this as a new registration.
if ( ! $previous_membership_level instanceof Membership_Level ) {
rcp_log( sprintf( 'Previous membership level (#%d) is invalid. Treating this as a new registration.', $this->membership->get_object_id() ) );
$this->registration_type = 'new';
return;
}
$days_in_old_cycle = rcp_get_days_in_cycle( $previous_membership_level->get_duration_unit(), $previous_membership_level->get_duration() );
$days_in_new_cycle = rcp_get_days_in_cycle( $this->membership_level->get_duration_unit(), $this->membership_level->get_duration() );
$old_price_per_day = $days_in_old_cycle > 0 ? $previous_membership_level->get_price() / $days_in_old_cycle : $previous_membership_level->get_price();
$new_price_per_day = $days_in_new_cycle > 0 ? $this->get_recurring_total( true, false ) / $days_in_new_cycle : $this->get_recurring_total( true, false );
rcp_log( sprintf( 'Old price per day: %s (ID #%d); New price per day: %s (ID #%d)', $old_price_per_day, $previous_membership_level->get_id(), $new_price_per_day, $this->membership_level->get_id() ) );
if ( $old_price_per_day > $new_price_per_day ) {
$this->registration_type = 'downgrade';
}
}
}
/**
* Get the registration type
*
* @since 3.1
* @return string
*/
public function get_registration_type() {
return $this->registration_type;
}
/**
* Get the existing membership object that is being renewed or upgraded
*
* @since 3.1
* @return RCP_Membership|false
*/
public function get_membership() {
return $this->membership;
}
/**
* Determine whether or not the level being registered for has a trial that the current user is eligible
* for. This will return false if there is a trial but the user is not eligible for it.
*
* @access public
* @since 3.0.6
* @return bool
*/
public function is_trial() {
if ( ! $this->membership_level instanceof Membership_Level ) {
return false;
}
if ( ! $this->membership_level->has_trial() ) {
return false;
}
// There is a trial, but let's check eligibility.
$customer = rcp_get_customer_by_user_id();
// No customer, which means they're brand new, which means they're eligible.
if ( empty( $customer ) ) {
return true;
}
return ! $customer->has_trialed();
}
/**
* Attempt to recover an existing pending / abandoned / failed payment.
*
* First we look in the request for `rcp_registration_payment_id`. If that doesn't exist then we try to recover
* automatically. This will only work if the current membership (located via `set_registration_type()`)
* has a pending payment ID. This will be the case if someone was attempting to sign up or manually renew,
* didn't complete payment, then immediately reattempted.
*
* If a payment is located, then this payment is used for the registration instead of creating a new one.
* This will also used the existing membership record associated with this payment.
*
* Requirements:
* - The payment status is `pending`, `abandoned`, or `failed`.
* - Transaction ID is empty.
* - There is an associated membership record (it's okay if it's disabled, it just needs to exist).
*
* @link https://github.com/restrictcontentpro/restrict-content-pro/issues/2230
*
* @since 3.2.2
* @return void
*/
protected function maybe_recover_payment() {
// First get payment ID from request. This will be set when explicitly clicking a "Complete Payment" link.
$pending_payment_id = ! empty( $_REQUEST['rcp_registration_payment_id'] ) ? absint( $_REQUEST['rcp_registration_payment_id'] ) : 0;
/*
* Or, try to get a pending payment ID from the current membership's meta.
* This will be set if trying to renew the current membership a second time when the first time failed.
*/
if ( empty( $pending_payment_id ) && ! empty( $this->membership ) ) {
$pending_payment_id = rcp_get_membership_meta( $this->membership->get_id(), 'pending_payment_id', true );
}
if ( empty( $pending_payment_id ) ) {
return;
}
/**
* @var RCP_Payments $rcp_payments_db
*/
global $rcp_payments_db;
$payment = $rcp_payments_db->get_payment( $pending_payment_id );
// We can't use this if there's already a transaction ID.
if ( ! empty( $payment->transaction_id ) ) {
return;
}
// We can't use this if there's a user ID mismatch.
if ( $payment->user_id != get_current_user_id() ) {
return;
}
// We can't use this if there's no associated membership.
if ( empty( $payment->membership_id ) || ! $membership = rcp_get_membership( $payment->membership_id ) ) {
return;
}
// We can't use this if the membership level ID being signed up for is now different from the recovered payment level ID.
if ( $this->get_membership_level_id() && $payment->object_id != $this->get_membership_level_id() ) {
return;
}
$this->recovered_payment = $payment;
// Use the same `transaction_type` as the recovered payment.
$this->registration_type = $this->recovered_payment->transaction_type;
rcp_log( sprintf( 'Using recovered payment #%d for registration. Transaction type: %s.', $this->recovered_payment->id, $this->recovered_payment->transaction_type ) );
}
/**
* Get the recovered payment object.
*
* @since 3.2.3
* @return object|false Payment object if set, false if not.
*/
public function get_recovered_payment() {
return $this->recovered_payment;
}
/**
* Add discount to the registration
*
* @since 2.5
*
* @param $code
* @param bool $recurring
*
* @return bool
*/
public function add_discount( $code, $recurring = true ) {
if ( ! rcp_validate_discount( $code, $this->subscription ) ) {
return false;
}
$this->discounts[ $code ] = $recurring;
return true;
}
/**
* Get registration discounts
*
* @since 2.5
* @return array|bool
*/
public function get_discounts() {
if ( empty( $this->discounts ) ) {
return false;
}
return $this->discounts;
}
/**
* Add fee to the registration. Use negative fee for credit.
*
* @since 2.5
*
* @param float $amount
* @param null $description
* @param bool $recurring
* @param bool $proration
*
* @return bool
*/
public function add_fee( $amount, $description = null, $recurring = false, $proration = false ) {
$fee = array(
'amount' => floatval( $amount ),
'description' => sanitize_text_field( $description ),
'recurring' => (bool) $recurring,
'proration' => (bool) $proration,
);
$id = md5( serialize( $fee ) );
if ( isset( $this->fees[ $id ] ) ) {
return false;
}
$this->fees[ $id ] = apply_filters( 'rcp_registration_add_fee', $fee, $this );
return true;
}
/**
* Get registration fees
*
* @since 2.5
* @return array|bool
*/
public function get_fees() {
if ( empty( $this->fees ) ) {
return false;
}
return $this->fees;
}
/**
* Get the total number of fees
*
* @since 2.5
*
* @param null $total
* @param bool $only_recurring | set to only get fees that are recurring
*
* @return float
*/
public function get_total_fees( $total = null, $only_recurring = false ) {
if ( ! $this->get_fees() ) {
return 0;
}
$fees = 0;
foreach ( $this->get_fees() as $fee ) {
if ( $only_recurring && ! $fee['recurring'] ) {
continue;
}
$fees += $fee['amount'];
}
// if total is present, make sure that any negative fees are not
// greater than the total.
if ( $total && ( $fees + $total ) < 0 ) {
$fees = -1 * $total;
}
return apply_filters( 'rcp_registration_get_total_fees', (float) $fees, $total, $only_recurring, $this );
}
/**
* Get the signup fees
*
* @since 2.5
*
* @return float
*/
public function get_signup_fees() {
if ( ! $this->get_fees() ) {
return 0;
}
$fees = 0;
foreach ( $this->get_fees() as $fee ) {
if ( $fee['proration'] ) {
continue;
}
if ( $fee['recurring'] ) {
continue;
}
$fees += $fee['amount'];
}
return apply_filters( 'rcp_registration_get_signup_fees', (float) $fees, $this );
}
/**
* Get the total proration amount
*
* @since 2.5
*
* @return float
*/
public function get_proration_credits() {
if ( ! $this->get_fees() ) {
return 0;
}
$proration = 0;
foreach ( $this->get_fees() as $fee ) {
if ( ! $fee['proration'] ) {
continue;
}
$proration += $fee['amount'];
}
return apply_filters( 'rcp_registration_get_proration_fees', (float) $proration, $this );
}
/**
* Get the total discounts
*
* @since 2.5
*
* @param null $total
* @param bool $only_recurring | set to only get discounts that are recurring
*
* @return int|mixed
*/
public function get_total_discounts( $total = null, $only_recurring = false ) {
global $rcp_options;
if ( ! $registration_discounts = $this->get_discounts() ) {
return 0;
}
if ( ! $total && $this->membership_level instanceof Membership_Level ) {
$total = $this->membership_level->get_price();
// If fees get discounted too, then we need to add those on to our total.
if ( ! empty( $rcp_options['discount_fees'] ) ) {
$total += $this->get_total_fees( null, $only_recurring );
}
}
$original_total = $total;
foreach ( $registration_discounts as $registration_discount => $recurring ) {
if ( $only_recurring && ! $recurring ) {
continue;
}
$discount_obj = rcp_get_discount_by( 'code', $registration_discount );
if ( $only_recurring && is_object( $discount_obj ) && ! empty( $discount_obj->is_one_time() ) ) {
continue;
}
if ( is_object( $discount_obj ) ) {
// calculate the after-discount price
$total = rcp_get_discounted_price( $total, $discount_obj->get_amount(), $discount_obj->get_unit(), false );
}
}
// make sure the discount is not > 100%
if ( 0 > $total ) {
$total = 0;
}
$total = round( $total, rcp_currency_decimal_filter() );
return apply_filters( 'rcp_registration_get_total_discounts', (float) ( $original_total - $total ), $original_total, $only_recurring, $this );
}
/**
* Get the registration total due today
*
* @param bool $discounts | Include discounts?
* @param bool $fees | Include fees?
*
* @since 2.5
* @return float
*/
public function get_total( $discounts = true, $fees = true ) {
global $rcp_options;
if ( $this->is_trial() ) {
return 0;
}
$total = $this->membership_level instanceof Membership_Level ? $this->membership_level->get_price() : 0;
if ( $discounts && empty( $rcp_options['discount_fees'] ) ) {
$total -= $this->get_total_discounts( $total );
}
if ( 0 > $total ) {
$total = 0;
}
if ( $fees ) {
$total += $this->get_signup_fees();
$total += $this->get_proration_credits();
}
if ( $discounts && ! empty( $rcp_options['discount_fees'] ) ) {
$total -= $this->get_total_discounts( $total );
}
if ( 0 > $total ) {
$total = 0;
}
$total = round( $total, rcp_currency_decimal_filter() );
/**
* Filter the "initial amount" total.
*
* @param float $total Total amount due today.
* @param RCP_Registration Registration object.
* @param bool $discounts Whether or not discounts are included in the value.
* @param bool $fees Whether or not fees are included in the value.
*/
return apply_filters( 'rcp_registration_get_total', floatval( $total ), $this, $discounts, $fees );
}
/**
* Get the registration recurring total
*
* @param bool $discounts | Include discounts?
* @param bool $fees | Include fees?
*
* @since 2.5
* @return float
*/
public function get_recurring_total( $discounts = true, $fees = true ) {
global $rcp_options;
$total = ( $this->membership_level instanceof Membership_Level && ! $this->membership_level->is_lifetime() ) ? $this->membership_level->get_price() : 0;
if ( $discounts && empty( $rcp_options['discount_fees'] ) ) {
$total -= $this->get_total_discounts( $total, true );
}
if ( $fees ) {
$total += $this->get_total_fees( $total, true );
}
if ( $discounts && ! empty( $rcp_options['discount_fees'] ) ) {
$total -= $this->get_total_discounts( $total, true );
}
if ( 0 > $total ) {
$total = 0;
}
$total = round( $total, rcp_currency_decimal_filter() );
/**
* Filters the "recurring amount" total.
*
* @param float $total Recurring amount.
* @param RCP_Registration Registration object.
* @param bool $discounts Whether or not discounts are included in the value.
* @param bool $fees Whether or not fees are included in the value.
*/
return apply_filters( 'rcp_registration_get_recurring_total', floatval( $total ), $this, $discounts, $fees );
}
}

View File

@@ -0,0 +1,405 @@
<?php
/**
* Renewal and Expiration Reminders Class
*
* @package Restrict Content Pro
* @subpackage Admin/Reminders
* @copyright Copyright (c) 2017, Restrict Content Pro
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
* @since 2.9
*/
final class RCP_Reminders {
/**
* Get things started
*
* @access public
* @since 2.9
* @return void
*/
public function __construct() {
}
/**
* Retrieve reminder notices periods
*
* @access public
* @since 2.9
* @return array reminder notice periods
*/
public function get_notice_periods() {
$periods = array(
'today' => __( 'The day of the renewal/expiration', 'rcp' ),
'+1day' => __( 'One day before renewal/expiration', 'rcp' ),
'+2days' => __( 'Two days before renewal/expiration', 'rcp' ),
'+3days' => __( 'Three days before renewal/expiration', 'rcp' ),
'+4days' => __( 'Four days before renewal/expiration', 'rcp' ),
'+5days' => __( 'Five days before renewal/expiration', 'rcp' ),
'+6days' => __( 'Six days before renewal/expiration', 'rcp' ),
'+1week' => __( 'One week before renewal/expiration', 'rcp' ),
'+2weeks' => __( 'Two weeks before renewal/expiration', 'rcp' ),
'+3weeks' => __( 'Three weeks before renewal/expiration', 'rcp' ),
'+1month' => __( 'One month before renewal/expiration', 'rcp' ),
'+2months' => __( 'Two months before renewal/expiration', 'rcp' ),
'+3months' => __( 'Three months before renewal/expiration', 'rcp' ),
'-1day' => __( 'One day after expiration', 'rcp' ),
'-2days' => __( 'Two days after expiration', 'rcp' ),
'-3days' => __( 'Three days after expiration', 'rcp' ),
'-1week' => __( 'One week after expiration', 'rcp' ),
'-2weeks' => __( 'Two weeks after expiration', 'rcp' ),
'-1month' => __( 'One month after expiration', 'rcp' ),
'-2months' => __( 'Two months after expiration', 'rcp' ),
'-3months' => __( 'Three months after expiration', 'rcp' )
);
/**
* Filters the available notice periods.
*
* @param array $periods
*
* @since 2.9.8
*/
return apply_filters( 'rcp_reminder_notice_periods', $periods );
}
/**
* Retrieve the reminder label for a notice
*
* @param int $notice_id ID of the notice to get the label for.
*
* @access public
* @since 2.9
* @return String
*/
public function get_notice_period_label( $notice_id = 0 ) {
$notice = $this->get_notice( $notice_id );
$periods = $this->get_notice_periods();
$label = $periods[ $notice['send_period'] ];
return $label;
//return apply_filters( 'rcp_reminder_notice_period_label', $label, $notice_id );
}
/**
* Retrieve reminder notices types
*
* @access public
* @since 2.9
* @return array reminder notice types
*/
public function get_notice_types() {
$types = array(
'renewal' => __( 'Renewal', 'rcp' ),
'expiration' => __( 'Expiration', 'rcp' ),
);
return $types;
//return apply_filters( 'rcp_reminder_notice_types', $types );
}
/**
* Retrieve the reminder type label for a notice
*
* @param int $notice_id ID of the notice to get the label for.
*
* @access public
* @since 2.9
* @return String
*/
public function get_notice_type_label( $notice_id = 0 ) {
$notice = $this->get_notice( $notice_id );
$types = $this->get_notice_types();
$label = $types[ $notice['type'] ];
return $label;
//return apply_filters( 'rcp_reminder_notice_type_label', $label, $notice_id );
}
/**
* Retrieve a reminder notice
*
* @param int $notice_id ID of the notice to retrieve.
*
* @access public
* @since 2.9
* @return array|false Reminder notice details or false if notice ID is invalid.
*/
public function get_notice( $notice_id = 0 ) {
$notices = $this->get_notices();
$notice = isset( $notices[ $notice_id ] ) ? $notices[ $notice_id ] : false;
return $notice;
//return apply_filters( 'rcp_reminder_notice', $notice, $notice_id );
}
/**
* Retrieve reminder notice periods
*
* @param string $type Type of notices to get (renewal, expiration, or all).
*
* @access public
* @since 2.9
* @return array Reminder notices defined in settings
*/
public function get_notices( $type = 'all' ) {
$notices = get_option( 'rcp_reminder_notices', array() );
if ( $type != 'all' ) {
$notices_hold = array();
foreach ( $notices as $key => $notice ) {
if ( $notice['type'] == $type ) {
$notices_hold[ $key ] = $notice;
}
}
$notices = $notices_hold;
}
return $notices;
//return apply_filters( 'rcp_reminder_notices', $notices, $type );
}
/**
* Retrieve the default notice settings
*
* @param string $type Notice type to retrieve, either 'renewal' or 'expiration'.
*
* @access public
* @since 2.9
* @return array
*/
public function get_default_notice( $type = 'renewal' ) {
$settings = array(
'send_period' => '+1month',
'enabled' => false
);
if ( 'expiration' == $type ) {
// Expiration notice
$settings['type'] = 'expiration';
$settings['subject'] = __( 'Your Subscription is About to Expire', 'rcp' );
$settings['message'] = 'Hello %name%,
Your subscription for %subscription_name% will expire on %expiration%.';
} else {
// Renewal notice
$settings['type'] = 'renewal';
$settings['subject'] = __( 'Your Subscription is About to Renew', 'rcp' );
$settings['message'] = 'Hello %name%,
Your subscription for %subscription_name% will renew on %expiration%.';
}
return $settings;
}
/**
* Send reminder emails
*
* @access public
* @since 2.9
* @return void
*/
public function send_reminders() {
do_action( 'rcp_after_send_reminder_emails', $this );
}
/**
* Retrieve all members to send notices to
*
* @param string $period Reminder period.
* @param string $type Type of notice to get the subscriptions for (renewal or expiration).
* @param string|array $levels Membership level ID(s) to filter by.
*
* @access public
* @since 2.9
* @return RCP_Membership[]|false Subscribers whose subscriptions are renewing or expiring within the defined period. False if
* none are found.
*/
public function get_reminder_subscriptions( $period = '+1month', $type = 'renewal', $levels = 'all' ) {
if ( ! $type ) {
return false;
}
$args = array(
'number' => 9999,
);
// Filter by membership level.
if ( is_array( $levels ) && count( $levels ) > 1 ) {
$args['object_id__in'] = $levels;
} elseif ( is_array( $levels ) && count( $levels ) === 1 ) {
$args['object_id'] = $levels[0];
}
switch ( $type ) {
case 'renewal' :
$args['status'] = 'active';
$args['auto_renew'] = 1;
$args['expiration_date_query'] = array(
'after' => date( 'Y-m-d H:i:s', strtotime( $period . ' midnight', current_time( 'timestamp' ) ) ),
'before' => date( 'Y-m-d H:i:s', strtotime( $period . ' midnight', current_time( 'timestamp' ) ) + ( DAY_IN_SECONDS - 1 ) ),
'inclusive' => true
);
break;
case 'expiration' :
$args['auto_renew'] = 0;
if ( 0 === strpos( $period, '-' ) ) {
$args['status__in'] = array( 'expired', 'cancelled' ); // If after expiration, their status may be expired.
} else {
$args['status__in'] = array( 'active', 'cancelled' );
}
$args['expiration_date_query'] = array(
'after' => date( 'Y-m-d H:i:s', strtotime( $period . ' midnight', current_time( 'timestamp' ) ) ),
'before' => date( 'Y-m-d H:i:s', strtotime( $period . ' midnight', current_time( 'timestamp' ) ) + ( DAY_IN_SECONDS - 1 ) ),
'inclusive' => true
);
break;
}
/**
* Filters the membership query arguments for getting relevant subscriptions.
*
* @param array $args Query arguments.
* @param string $period Reminder period.
* @param string $type Type of notice to get the subscriptions for (renewal or expiration).
*
* @since 2.9.2
*/
$args = apply_filters( 'rcp_reminder_subscription_args', $args, $period, $type );
/*
* Backwards compatibility for making this snippet still work:
* https://github.com/restrictcontentpro/library/blob/master/rcp-limit-reminders-to-level.php
*/
if ( isset( $args['meta_query'] ) ) {
$args = $this->convert_user_meta_query_args( $args );
}
$memberships = rcp_get_memberships( $args );
if ( ! empty( $memberships ) ) {
return $memberships;
}
return false;
}
/**
* Convert old WP_User_Query args into an appropriate format for a memberships custom table query.
*
* @todo Consider adding support for more meta keys.
*
* @param array $args
*
* @access private
* @since 3.0
* @return array
*/
private function convert_user_meta_query_args( $args ) {
if ( ! isset( $args['meta_query'] ) || ! is_array( $args['meta_query'] ) ) {
return $args;
}
$meta_query = $args['meta_query'];
unset( $args['meta_query'] );
foreach ( $meta_query as $query ) {
switch ( $query['key'] ) {
case 'rcp_subscription_level' :
$args['object_id'] = absint( $query['value'] );
break;
}
}
return $args;
}
/**
* Setup and send test email for a reminder
*
* @param int $notice_id ID of the notice to test.
*
* @access public
* @since 2.9
* @return void
*/
public function send_test_notice( $notice_id = 0 ) {
$notice = $this->get_notice( $notice_id );
$emails = new RCP_Emails;
$current_user = wp_get_current_user();
$email_to = $current_user->user_email;
$message = ! empty( $notice['message'] ) ? $notice['message'] : __( "**THIS IS A DEFAULT TEST MESSAGE - Notice message was not retrieved.**\n\nHello %name%,\n\nYour subscription for %subscription_name% will renew or expire on %expiration%.", 'rcp' );
$message = $this->filter_test_notice( $message );
$subject = ! empty( $notice['subject'] ) ? $notice['subject'] : __( 'Default Subject Message - Your Subscription is About to Renew or Expire', 'rcp' );
$subject = $this->filter_test_notice( $subject );
$emails->member_id = $current_user->ID;
$emails->send( $email_to, stripslashes( $subject ), $message );
}
/**
* Filter template tags for test email.
*
* @param string $text
*
* @access public
* @since 2.9
* @return string
*/
public function filter_test_notice( $text = '' ) {
$text = str_replace( '%name%', 'NAME GOES HERE', $text );
$text = str_replace( '%subscription_name%', 'SUBSCRIPTION NAME', $text );
$text = str_replace( '%expiration%', date( 'F j, Y', strtotime( 'today' ) ), $text );
return $text;
}
}

View File

@@ -0,0 +1,361 @@
<?php
/**
* Collects RCP information and add it to the site health with telemetry.
*
* @since 3.5.28
* @package RCP
*/
/**
* Collects RCP information and add it to the site health with telemetry.
*
* @since 3.5.28
*/
class RCP_Telemetry_Info {
/**
* RCP Options from Database.
*
* @var array $rcp_options The options.
*/
private $rcp_options = [];
/**
* The constructor that initializes the RCP settings
*
* @since 3.5.28
*/
public function __construct() {
$this->rcp_options = get_option( 'rcp_settings' );
}
/**
* The version RCP was updated from.
*
* @since 3.5.28
*
* @return string The version.
*/
public function rcp_last_updated() : string {
return get_option( 'rcp_version_upgraded_on', '(unknown date)' );
}
/**
* Get the total Membership Levels.
*
* @since 3.5.28
*
* @return int 0 if not found, the total otherwise.
*/
public function total_membership_levels() : int {
$levels = rcp_get_membership_levels( array( 'number' => 999 ) );
if ( is_array( $levels ) ) {
return count( $levels );
} else {
return 0;
}
}
/**
* Get the total Paid Membership Levels.
*
* @since 3.5.28
*
* @return int 0 if not found, the total otherwise.
*/
public function total_paid_membership_levels() : int {
$paid_membership = rcp_get_paid_levels();
if ( is_array( $paid_membership ) ) {
return count( $paid_membership );
} else {
return 0;
}
}
/**
* Get the total Free Membership Levels.
*
* @since 3.5.28
*
* @return int 0 if not found, the total otherwise.
*/
public function total_free_membership_levels(): int {
$free_levels = rcp_get_membership_levels(
array(
'price__in' => array( 0 ),
'status' => 'active',
'number' => 9999,
)
);
if ( is_array( $free_levels ) ) {
return count( $free_levels );
} else {
return 0;
}
}
/**
* One-Time membership are those that the duration is set to 0.
*
* @since 3.5.28
* @link https://help.ithemes.com/hc/en-us/articles/1260807007649-Can-I-Create-a-One-Time-Payment-
*
* @return int 0 if not found, the total otherwise.
*/
public function total_one_time_membership_levels() : int {
$one_time_levels = rcp_get_membership_levels(
array(
'duration' => 0,
'status' => 'active',
'number' => 9999,
)
);
if ( is_array( $one_time_levels ) ) {
return count( $one_time_levels );
} else {
return 0;
}
}
/**
* Get the total Recurring Membership Levels.
*
* @since 3.5.28
*
* @return int 0 if not found, the total otherwise.
*/
public function total_recurring_membership_levels() : int {
global $wpdb;
// Array of values that will be use by the prepared method.
$data = array(
'status' => 'active',
'duration' => 0,
);
$sql = "SELECT * FROM {$wpdb->prefix}restrict_content_pro WHERE status = %s AND duration > %d LIMIT 9999";
// phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
$prepare = $wpdb->prepare( $sql, $data );
// Execute the query with the prepared statements.
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared
$recurring_levels = $wpdb->get_results( $prepare, ARRAY_A );
if ( null !== $recurring_levels ) {
return count( $recurring_levels );
} else {
return 0;
}
}
/**
* Get the total Paying customers.
*
* @since 3.5.28
*
* @return int 0 if not found, the total otherwise.
*/
public function total_paying_customers() : int {
global $wpdb;
// Array of values that will be use by the prepared method.
$data = array(
'status' => 'active',
'disabled' => 0,
'gateway' => 'free',
);
$sql = "SELECT * FROM {$wpdb->prefix}rcp_memberships WHERE status = %s AND disabled = %d AND gateway <> %s";
// phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
$prepare = $wpdb->prepare( $sql, $data );
// Execute the query with the prepared statements.
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared
$paying_customers = $wpdb->get_results( $prepare, ARRAY_A );
if ( null !== $paying_customers ) {
return count( $paying_customers );
} else {
return 0;
}
}
/**
* Get the total Free customers.
* Customers who have always had free memberships and have never ever paid for anything. Customers who have expired or canceled memberships should not show up here. Gold-star Free users only.
*
* @since 3.5.28
*
* @return int 0 if not found, the total otherwise.
*/
public function total_free_customers() : int {
global $wpdb;
$sql = "SELECT * FROM {$wpdb->prefix}rcp_memberships m INNER JOIN {$wpdb->prefix}restrict_content_pro r
ON m.object_id = r.id
WHERE m.status = 'active' AND m.disabled = 0 AND m.gateway IN ('free','manual')
AND r.price = 0 AND m.customer_id NOT IN (
SELECT customer_id FROM {$wpdb->prefix}rcp_memberships WHERE status = 'active' AND gateway NOT IN ('free','manual') and disabled = 0 GROUP BY customer_id
)";
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared
$paying_customers = $wpdb->get_results( $sql, ARRAY_A );
if ( null !== $paying_customers ) {
return count( $paying_customers );
} else {
return 0;
}
}
/**
* Get the total No Membership customers.
* Customers with expired or canceled memberships. Customers who also have a free membership alongside their canceled or expired ones will show up here.
*
* @since 3.5.28
*
* @return int 0 if not found, the total otherwise.
*/
public function total_no_membership_customers() : int {
global $wpdb;
$sql = "SELECT m.customer_id FROM {$wpdb->prefix}rcp_memberships m
INNER JOIN {$wpdb->prefix}rcp_customers c ON m.customer_id = c.id
WHERE status IN ('expired','cancelled') OR m.customer_id IN (
SELECT m.customer_id FROM {$wpdb->prefix}rcp_memberships m INNER JOIN {$wpdb->prefix}restrict_content_pro r
ON m.object_id = r.id
WHERE m.status = 'active' AND m.disabled = 0 AND m.gateway IN ('free','manual')
AND r.price = 0 AND m.customer_id NOT IN (
SELECT customer_id FROM {$wpdb->prefix}rcp_memberships WHERE status = 'active' AND gateway NOT IN ('free','manual') and disabled = 0 GROUP BY customer_id
)
)
GROUP BY m.customer_id;";
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared
$no_membership_customers = $wpdb->get_results( $sql, ARRAY_A );
if ( null !== $no_membership_customers ) {
return count( $no_membership_customers );
} else {
return 0;
}
}
/**
* Get the Multiple Membership status.
*
* @since 3.5.28
*
* @return bool True if enabled, False otherwise.
*/
public function is_multiple_memberships() : bool {
// phpcs:ignore WordPress.PHP.StrictComparisons.LooseComparison
return isset( $this->rcp_options['multiple_memberships'] ) && $this->rcp_options['multiple_memberships'] == '1';
}
/**
* Get the Monthly Revenue. This always returns the revenue of the current month.
*
* @since 3.5.28
*
* @return float The revenue.
*/
public function monthly_revenue(): float {
$payments_db = new RCP_Payments();
$earnings = (float) 0.00; // Total earnings for time period shown.
$current_month = gmdate( 'm' );
$current_year = gmdate( 'Y' );
// Args that will be used to query the Payments table.
$args['date'] = [
'month' => $current_month,
'year' => $current_year,
];
$payments = $payments_db->get_earnings( $args );
$earnings += $payments;
return $earnings;
}
/**
* Get the active memberships and builds an array with the number of memberships and the name for each gateway.
*
* @since 3.5.28
*
* @return array The array with the gateways' info.
*/
public function payment_gateways() : array {
$payment_gateways = new RCP_Payment_Gateways();
$gateways = [
'total' => 0,
'enabled_gateways' => [],
];
$enabled_gateways = [];
if ( is_array( $payment_gateways->enabled_gateways ) ) {
$gateways['total'] = count( $payment_gateways->enabled_gateways );
foreach ( $payment_gateways->enabled_gateways as $gateway ) {
$enabled_gateways[] = $gateway['admin_label'];
}
$gateways['enabled_gateways'] = $enabled_gateways;
}
return $gateways;
}
/**
* Get the active RCP add-ons.
*
* @since 3.5.28
*
* @return array The array with the active add-ons.
*/
public function active_addons() : array {
// Get plugins that have an update.
$plugins = get_plugins();
$active_plugins = get_option( 'active_plugins', array() );
$active_addons = [];
$rcp_found_addons = [];
$rcp_addons = rcp_get_addons_list();
foreach ( $active_plugins as $plugin ) {
$plugin_path = explode( '/', $plugin );
$plugin_slug = $plugin_path[0];
if ( array_key_exists( $plugin_slug, $rcp_addons ) ) {
$rcp_found_addons[] = $plugin_slug;
}
}
foreach ( $rcp_found_addons as $addon ) {
$active_addons[] = [
'add_on' => $addon,
'name' => $rcp_addons[ $addon ],
];
}
return $active_addons;
}
/**
* Get the inactive RCP add-ons.
*
* @since 3.5.28
*
* @return array The array with the inactive add-ons.
*/
public function deactivated_addons() : array {
// Get plugins that have an update.
$plugins = get_plugins();
$active_plugins = get_option( 'active_plugins', array() );
$inactive_plugins = [];
$inactive_addons = [];
$rcp_found_addons = [];
$rcp_addons = rcp_get_addons_list();
foreach ( $plugins as $plugin_path => $plugin ) {
$a = $plugin;
if ( ! in_array( $plugin_path, $active_plugins, true ) ) {
$inactive_plugins[] = $plugin_path;
}
}
foreach ( $inactive_plugins as $plugin ) {
$plugin_path = explode( '/', $plugin );
$plugin_slug = $plugin_path[0];
if ( array_key_exists( $plugin_slug, $rcp_addons ) ) {
$rcp_found_addons[] = $plugin_slug;
}
}
foreach ( $rcp_found_addons as $addon ) {
$inactive_addons[] = [
'add_on' => $addon,
'name' => $rcp_addons[ $addon ],
];
}
return $inactive_addons;
}
}

View File

@@ -0,0 +1,588 @@
<?php
/**
* Restrict Content Pro Base Class
*
* @package restrict-content-pro
* @copyright Copyright (c) 2020, Sandhills Development, LLC
* @license GPL2+
*/
use RCP\Database\Tables\Customers;
use RCP\Database\Tables\Discounts;
use RCP\Database\Tables\Membership_Counts;
use RCP\Database\Tables\Membership_Meta;
use RCP\Database\Tables\Memberships;
use RCP\Database\Tables\Queue;
// Exit if accessed directly.
defined( 'ABSPATH' ) || exit;
if ( ! class_exists( 'Restrict_Content_Pro' ) ) :
/**
* Class Restrict_Content_Pro
*
* @since 3.0
*/
final class Restrict_Content_Pro {
const VERSION = '3.5.36';
/**
* Stores the base slug for the extension.
*
* @since 3.5.18
*
* @var string
*/
const FILE = RCP_PLUGIN_FILE;
/**
* @var Restrict_Content_Pro The one true Restrict_Content_Pro
*
* @since 3.0
*/
private static $instance;
/**
* RCP loader file.
*
* @since 3.0
* @var string
*/
private $file = '';
/**
* @var Customers
*/
public $customers_table;
/**
* @var Discounts
*/
public $discounts_table;
/**
* @var Memberships
*/
public $memberships_table;
/**
* @var Membership_Meta
*/
public $membership_meta_table;
/**
* @var Queue
*/
public $queue_table;
/**
* @var Membership_Counts
*/
public $membership_counts_table;
/**
* @var \RCP\Component[]
*/
public $components;
/**
* @var boolean
*/
private $is_pro;
/**
* Main Restrict_Content_Pro Instance.
*
* Insures that only one instance of Restrict_Content_Pro exists in memory at any one
* time. Also prevents needing to define globals all over the place.
*
* @since 3.0
*
* @static
* @staticvar array $instance
*
* @uses Restrict_Content_Pro::setup_constants() Setup constants.
* @uses Restrict_Content_Pro::setup_files() Setup required files.
* @see restrict_content_pro()
*
* @param string $file Main plugin file path.
*
* @return Restrict_Content_Pro The one true Restrict_Content_Pro
*/
public static function instance( $file = '' ) {
// Return if already instantiated
if ( self::is_instantiated() ) {
return self::$instance;
}
// Setup the singleton
self::setup_instance( $file );
// Bootstrap
self::$instance->setup_constants();
self::$instance->setup_files();
self::$instance->setup_globals();
self::$instance->setup_application();
// Backwards compat globals
self::$instance->backcompat_globals();
// Return the instance
return self::$instance;
}
/**
* Throw error on object clone.
*
* The whole idea of the singleton design pattern is that there is a single
* object therefore, we don't want the object to be cloned.
*
* @since 3.0
* @return void
*/
public function __clone() {
// Cloning instances of the class is forbidden.
_doing_it_wrong( __FUNCTION__, __( 'Cheatin&#8217; huh?', 'rcp' ), '3.0' );
}
/**
* Disable un-serializing of the class.
*
* @since 3.0
* @return void
*/
public function __wakeup() {
// Unserializing instances of the class is forbidden.
_doing_it_wrong( __FUNCTION__, __( 'Cheatin&#8217; huh?', 'rcp' ), '3.0' );
}
/**
* Return whether the main loading class has been instantiated or not.
*
* @access private
* @since 3.0
* @return boolean True if instantiated. False if not.
*/
private static function is_instantiated() {
// Return true if instance is correct class
if ( ! empty( self::$instance ) && ( self::$instance instanceof Restrict_Content_Pro ) ) {
return true;
}
// Return false if not instantiated correctly
return false;
}
/**
* Setup the singleton instance
*
* @param string $file Path to main plugin file.
*
* @access private
* @since 3.0
*/
private static function setup_instance( $file = '' ) {
self::$instance = new Restrict_Content_Pro();
self::$instance->file = $file;
}
/**
* Setup plugin constants.
*
* @access private
* @since 3.0
* @return void
*/
private function setup_constants() {
if ( ! defined( 'RCP_PLUGIN_VERSION' ) ) {
define( 'RCP_PLUGIN_VERSION', self::VERSION );
}
if ( ! defined( 'RCP_PLUGIN_FILE' ) ) {
define( 'RCP_PLUGIN_FILE', $this->file );
}
if ( ! defined( 'RCP_PLUGIN_DIR' ) ) {
define( 'RCP_PLUGIN_DIR', plugin_dir_path( RCP_PLUGIN_FILE ) );
}
if ( ! defined( 'RCP_PLUGIN_URL' ) ) {
define( 'RCP_PLUGIN_URL', plugin_dir_url( RCP_PLUGIN_FILE ) );
}
if ( ! defined( 'CAL_GREGORIAN' ) ) {
define( 'CAL_GREGORIAN', 1 );
}
}
/**
* Setup globals
*
* @access private
* @since 3.0.1
* @return void
*/
private function setup_globals() {
$GLOBALS['rcp_options'] = get_option( 'rcp_settings', array() );
}
/**
* Include required files.
*
* @access private
* @since 3.0
* @return void
*/
private function setup_files() {
$this->include_files();
// Admin
if ( is_admin() || ( defined( 'WP_CLI' ) && WP_CLI ) ) {
$this->include_admin();
} else {
$this->include_frontend();
}
}
/**
* Setup the rest of the application
*
* @since 3.0
*/
private function setup_application() {
rcp_setup_components();
self::$instance->customers_table = $this->components['customers']->get_interface( 'table' );
self::$instance->discounts_table = $this->components['discounts']->get_interface( 'table' );
self::$instance->memberships_table = $this->components['memberships']->get_interface( 'table' );
self::$instance->membership_meta_table = $this->components['memberships']->get_interface( 'meta' );
self::$instance->queue_table = $this->components['queue']->get_interface( 'table' );
self::$instance->membership_counts_table = $this->components['membership_counts']->get_interface( 'table' );
}
/** Includes **************************************************************/
/**
* Include global files
*
* @access public
* @since 3.0
*/
private function include_files() {
// Components
require_once RCP_PLUGIN_DIR . 'core/includes/class-rcp-base-object.php';
require_once RCP_PLUGIN_DIR . 'core/includes/component-functions.php';
require_once RCP_PLUGIN_DIR . 'core/includes/class-rcp-component.php';
// Database
require_once RCP_PLUGIN_DIR . 'core/includes/database/engine/class-base.php';
require_once RCP_PLUGIN_DIR . 'core/includes/database/engine/class-table.php';
require_once RCP_PLUGIN_DIR . 'core/includes/database/engine/class-compare.php';
require_once RCP_PLUGIN_DIR . 'core/includes/database/engine/class-date.php';
require_once RCP_PLUGIN_DIR . 'core/includes/database/engine/class-query.php';
require_once RCP_PLUGIN_DIR . 'core/includes/database/engine/class-column.php';
require_once RCP_PLUGIN_DIR . 'core/includes/database/engine/class-row.php';
require_once RCP_PLUGIN_DIR . 'core/includes/database/engine/class-schema.php';
// Tables
require_once RCP_PLUGIN_DIR . 'core/includes/database/customers/class-customers-table.php';
require_once RCP_PLUGIN_DIR . 'core/includes/database/discounts/class-discounts-table.php';
require_once RCP_PLUGIN_DIR . 'core/includes/database/logs/class-logs-table.php';
require_once RCP_PLUGIN_DIR . 'core/includes/database/membership-counts/class-membership-counts-table.php';
require_once RCP_PLUGIN_DIR . 'core/includes/database/membership-levels/class-membership-levels-table.php';
require_once RCP_PLUGIN_DIR . 'core/includes/database/memberships/class-memberships-table.php';
require_once RCP_PLUGIN_DIR . 'core/includes/database/memberships/class-membership-meta-table.php';
require_once RCP_PLUGIN_DIR . 'core/includes/database/queue/class-queue-table.php';
// Queries
require_once RCP_PLUGIN_DIR . 'core/includes/database/customers/class-customer-query.php';
require_once RCP_PLUGIN_DIR . 'core/includes/database/discounts/class-discount-query.php';
require_once RCP_PLUGIN_DIR . 'core/includes/database/logs/class-log-query.php';
require_once RCP_PLUGIN_DIR . 'core/includes/database/membership-counts/class-membership-count-query.php';
require_once RCP_PLUGIN_DIR . 'core/includes/database/membership-levels/class-membership-level-query.php';
require_once RCP_PLUGIN_DIR . 'core/includes/database/memberships/class-membership-query.php';
require_once RCP_PLUGIN_DIR . 'core/includes/database/queue/class-queue-query.php';
// Schemas
require_once RCP_PLUGIN_DIR . 'core/includes/database/customers/class-customers-schema.php';
require_once RCP_PLUGIN_DIR . 'core/includes/database/discounts/class-discounts-schema.php';
require_once RCP_PLUGIN_DIR . 'core/includes/database/logs/class-logs-schema.php';
require_once RCP_PLUGIN_DIR . 'core/includes/database/membership-counts/class-membership-counts-schema.php';
require_once RCP_PLUGIN_DIR . 'core/includes/database/membership-levels/class-membership-levels-schema.php';
require_once RCP_PLUGIN_DIR . 'core/includes/database/memberships/class-memberships-schema.php';
require_once RCP_PLUGIN_DIR . 'core/includes/database/queue/class-queue-schema.php';
// Payment Gateway
require_once( RCP_PLUGIN_DIR . 'core/includes/gateways/class-rcp-payment-gateway.php' );
require_once( RCP_PLUGIN_DIR . 'core/includes/gateways/class-rcp-payment-gateway-manual.php' );
require_once( RCP_PLUGIN_DIR . 'core/includes/gateways/class-rcp-payment-gateways.php' );
require_once( RCP_PLUGIN_DIR . 'core/includes/gateways/gateway-actions.php' );
require_once( RCP_PLUGIN_DIR . 'core/includes/gateways/gateway-functions.php' );
rcp_load_gateway_files();
// Membership Levels
require_once( RCP_PLUGIN_DIR . 'core/includes/membership-levels/class-rcp-membership-level.php' );
require_once( RCP_PLUGIN_DIR . 'core/includes/membership-levels/membership-level-functions.php' );
require_once( RCP_PLUGIN_DIR . 'core/includes/levels/level-actions.php' );
require_once( RCP_PLUGIN_DIR . 'core/includes/levels/meta.php' );
// Memberships
require_once( RCP_PLUGIN_DIR . 'core/includes/memberships/class-rcp-membership.php' );
require_once( RCP_PLUGIN_DIR . 'core/includes/memberships/membership-actions.php' );
require_once( RCP_PLUGIN_DIR . 'core/includes/memberships/membership-functions.php' );
require_once( RCP_PLUGIN_DIR . 'core/includes/memberships/meta.php' );
// Membership Counts
require_once( RCP_PLUGIN_DIR . 'core/includes/membership-counts/class-rcp-membership-count.php' );
require_once( RCP_PLUGIN_DIR . 'core/includes/membership-counts/membership-count-functions.php' );
// Member
require_once( RCP_PLUGIN_DIR . 'core/includes/member-forms.php' );
require_once( RCP_PLUGIN_DIR . 'core/includes/member-functions.php' );
// Discounts
require_once( RCP_PLUGIN_DIR . 'core/includes/discounts/class-rcp-discount.php');
require_once( RCP_PLUGIN_DIR . 'core/includes/discounts/discount-functions.php');
// @todo can this be improved?
require( RCP_PLUGIN_DIR . 'core/includes/install.php' );
require_once( RCP_PLUGIN_DIR . 'core/includes/class-rcp-capabilities.php' );
if ( defined( 'WP_CLI' ) && WP_CLI ) {
require_once( RCP_PLUGIN_DIR . 'core/includes/class-rcp-cli.php' );
require_once( RCP_PLUGIN_DIR . 'core/includes/membership-levels/membership-level-commands.php' );
}
require_once( RCP_PLUGIN_DIR . 'core/includes/class-rcp-emails.php' );
require_once( RCP_PLUGIN_DIR . 'core/includes/class-rcp-integrations.php' );
require_once( RCP_PLUGIN_DIR . 'core/includes/class-rcp-levels.php' );
require_once( RCP_PLUGIN_DIR . 'core/includes/class-rcp-logging.php' );
require_once( RCP_PLUGIN_DIR . 'core/includes/class-rcp-member.php' );
require_once( RCP_PLUGIN_DIR . 'core/includes/class-rcp-payments.php' );
require_once( RCP_PLUGIN_DIR . 'core/includes/class-rcp-registration.php' );
require_once( RCP_PLUGIN_DIR . 'core/includes/class-rcp-reminders.php' );
require_once( RCP_PLUGIN_DIR . 'core/includes/scripts.php' );
require_once( RCP_PLUGIN_DIR . 'core/includes/ajax-actions.php' );
require_once( RCP_PLUGIN_DIR . 'core/includes/captcha-functions.php' );
require_once( RCP_PLUGIN_DIR . 'core/includes/cron-functions.php' );
require_once( RCP_PLUGIN_DIR . 'core/includes/compat/class-base.php' );
require_once( RCP_PLUGIN_DIR . 'core/includes/compat/class-member.php' );
require_once( RCP_PLUGIN_DIR . 'core/includes/customers/class-rcp-customer.php' );
require_once( RCP_PLUGIN_DIR . 'core/includes/customers/customer-actions.php' );
require_once( RCP_PLUGIN_DIR . 'core/includes/customers/customer-functions.php' );
require_once( RCP_PLUGIN_DIR . 'core/includes/email-functions.php' );
require_once( RCP_PLUGIN_DIR . 'core/includes/invoice-functions.php' );
require_once( RCP_PLUGIN_DIR . 'core/includes/login-functions.php' );
require_once( RCP_PLUGIN_DIR . 'core/includes/logs/class-log.php' );
require_once( RCP_PLUGIN_DIR . 'core/includes/logs/log-functions.php' );
require_once( RCP_PLUGIN_DIR . 'core/includes/payments/meta.php' );
require_once( RCP_PLUGIN_DIR . 'core/includes/misc-functions.php' );
require_once( RCP_PLUGIN_DIR . 'core/includes/payments/payment-actions.php' );
require_once( RCP_PLUGIN_DIR . 'core/includes/payments/payment-functions.php' );
require_once( RCP_PLUGIN_DIR . 'core/includes/registration-functions.php' );
require_once( RCP_PLUGIN_DIR . 'core/includes/error-tracking.php' );
require_once( RCP_PLUGIN_DIR . 'core/includes/shortcodes.php' );
require_once( RCP_PLUGIN_DIR . 'core/includes/template-functions.php' );
// Batch
require_once RCP_PLUGIN_DIR . 'core/includes/batch/interface-job-callback.php';
require_once RCP_PLUGIN_DIR . 'core/includes/batch/abstract-job-callback.php';
require_once RCP_PLUGIN_DIR . 'core/includes/batch/batch-functions.php';
require_once RCP_PLUGIN_DIR . 'core/includes/batch/class-job.php';
// Deprecated
require_once( RCP_PLUGIN_DIR . 'core/includes/deprecated/class-rcp-discounts.php' );
require_once( RCP_PLUGIN_DIR . 'core/includes/deprecated/subscription-functions.php' );
require_once( RCP_PLUGIN_DIR . 'core/includes/deprecated/functions.php' );
// @todo remove
if ( ! class_exists( 'WP_Logging' ) ) {
require_once( RCP_PLUGIN_DIR . 'core/includes/deprecated/class-wp-logging.php' );
}
// Stripe
require_once( RCP_PLUGIN_DIR . 'core/includes/gateways/class-rcp-payment-gateway-stripe.php' );
require_once( RCP_PLUGIN_DIR . 'core/includes/gateways/stripe/functions.php' );
// @todo load this only when needed
require_once RCP_PLUGIN_DIR . 'core/includes/batch/v3/class-migrate-memberships.php';
// block functions
require_once RCP_PLUGIN_DIR . 'core/includes/block-functions.php';
// Integrations.
require_once RCP_PLUGIN_DIR . 'core/includes/integrations/class-rcp-telemetry.php';
require_once RCP_PLUGIN_DIR . 'core/includes/class-rcp-telemetry-info.php';
if ( file_exists( RCP_PLUGIN_DIR . 'pro/class-restrict-content-pro.php') ) {
require_once( RCP_PLUGIN_DIR . 'pro/class-restrict-content-pro.php' );
include_pro_files();
}
}
/**
* Setup administration
*
* @since 3.0
*/
private function include_admin() {
global $rcp_options;
require_once( RCP_PLUGIN_DIR . 'core/includes/admin/upgrades.php' );
require_once( RCP_PLUGIN_DIR . 'core/includes/admin/class-list-table.php' );
require_once( RCP_PLUGIN_DIR . 'core/includes/admin/class-rcp-upgrades.php' );
require_once( RCP_PLUGIN_DIR . 'core/includes/admin/admin-actions.php' );
require_once( RCP_PLUGIN_DIR . 'core/includes/admin/admin-pages.php' );
require_once( RCP_PLUGIN_DIR . 'core/includes/admin/admin-notices.php' );
require_once( RCP_PLUGIN_DIR . 'core/includes/admin/admin-ajax-actions.php' );
require_once( RCP_PLUGIN_DIR . 'core/includes/admin/class-rcp-add-on-updater.php' );
require_once( RCP_PLUGIN_DIR . 'core/includes/admin/customers/customer-actions.php' );
require_once( RCP_PLUGIN_DIR . 'core/includes/admin/customers/customers-page.php' );
require_once( RCP_PLUGIN_DIR . 'core/includes/admin/screen-options.php' );
require_once( RCP_PLUGIN_DIR . 'core/includes/admin/members/member-actions.php' );
require_once( RCP_PLUGIN_DIR . 'core/includes/admin/members/members-page.php' );
require_once( RCP_PLUGIN_DIR . 'core/includes/admin/memberships/membership-actions.php' );
require_once( RCP_PLUGIN_DIR . 'core/includes/admin/reminders/subscription-reminders.php' );
require_once( RCP_PLUGIN_DIR . 'core/includes/admin/settings/settings.php' );
require_once( RCP_PLUGIN_DIR . 'core/includes/admin/subscriptions/subscription-actions.php' );
require_once( RCP_PLUGIN_DIR . 'core/includes/admin/subscriptions/subscription-levels.php' );
require_once( RCP_PLUGIN_DIR . 'core/includes/admin/payments/payment-actions.php' );
require_once( RCP_PLUGIN_DIR . 'core/includes/admin/payments/payments-page.php' );
require_once( RCP_PLUGIN_DIR . 'core/includes/admin/export.php' );
require_once( RCP_PLUGIN_DIR . 'core/includes/admin/export/export-actions.php' );
require_once( RCP_PLUGIN_DIR . 'core/includes/admin/tools/tools-page.php' );
require_once( RCP_PLUGIN_DIR . 'core/includes/admin/import/import-actions.php' );
require_once( RCP_PLUGIN_DIR . 'core/includes/admin/import/import-functions.php' );
require_once( RCP_PLUGIN_DIR . 'core/includes/admin/help/help-menus.php' );
require_once( RCP_PLUGIN_DIR . 'core/includes/admin/metabox.php' );
require_once( RCP_PLUGIN_DIR . 'core/includes/admin/add-ons.php' );
require_once( RCP_PLUGIN_DIR . 'core/includes/admin/terms.php' );
require_once( RCP_PLUGIN_DIR . 'core/includes/admin/post-types/restrict-post-type.php' );
require_once( RCP_PLUGIN_DIR . 'core/includes/user-page-columns.php' );
require_once( RCP_PLUGIN_DIR . 'core/includes/export-functions.php' );
require_once( RCP_PLUGIN_DIR . 'core/includes/deactivation.php' );
require_once( RCP_PLUGIN_DIR . 'core/includes/admin/deprecated-admin-functions.php' );
// batch processing
require_once RCP_PLUGIN_DIR . 'core/includes/admin/batch/ajax-actions.php';
if ( file_exists( RCP_PLUGIN_DIR . 'pro/class-restrict-content-pro.php') ) {
require_once( RCP_PLUGIN_DIR . 'pro/class-restrict-content-pro.php' );
include_pro_admin_files();
}
}
/**
* Setup front-end specific code
*
* @since 3.0
*/
private function include_frontend() {
require_once( RCP_PLUGIN_DIR . 'core/includes/content-filters.php' );
require_once( RCP_PLUGIN_DIR . 'core/includes/query-filters.php' );
require_once( RCP_PLUGIN_DIR . 'core/includes/redirects.php' );
}
/**
* Backwards compatibility for old global values
*
* @since 3.0
*/
private function backcompat_globals() {
global $wpdb, $rcp_payments_db, $rcp_levels_db, $rcp_discounts_db;
// the plugin base directory
global $rcp_base_dir; // not used any more, but just in case someone else is
$rcp_base_dir = dirname( __FILE__ );
global $rcp_db_name;
$rcp_db_name = rcp_get_levels_db_name();
global $rcp_db_version;
$rcp_db_version = '1.6';
global $rcp_discounts_db_name;
$rcp_discounts_db_name = rcp_get_discounts_db_name();
global $rcp_discounts_db_version;
$rcp_discounts_db_version = '1.2';
global $rcp_payments_db_name;
$rcp_payments_db_name = rcp_get_payments_db_name();
global $rcp_payments_db_version;
$rcp_payments_db_version = '1.5';
/* database table query globals */
$rcp_payments_db = new RCP_Payments;
$rcp_levels_db = new RCP_Levels;
$rcp_discounts_db = new RCP_Discounts;
$wpdb->levelmeta = $rcp_levels_db->meta_db_name;
$wpdb->rcp_paymentmeta = $rcp_payments_db->meta_db_name;
/* settings page globals */
global $rcp_members_page;
global $rcp_subscriptions_page;
global $rcp_discounts_page;
global $rcp_payments_page;
global $rcp_settings_page;
global $rcp_reports_page;
global $rcp_export_page;
global $rcp_help_page;
}
/**
* Check if the current instance is PRO. This does not fully determine if the actual code is PRO.
* The main purpose of this function is for labels.
*
* @since 3.5.28
* @return bool
*/
public function is_pro() {
if( false === has_action('admin_menu','include_pro_pages') ) {
return false;
}
return true;
}
}
endif; // End if class_exists check.
/**
* Returns the instance of Restrict_Content_Pro.
*
* The main function responsible for returning the one true Restrict_Content_Pro
* instance to functions everywhere.
*
* Use this function like you would a global variable, except without needing
* to declare the global.
*
* Example: <?php $rcp = restrict_content_pro(); ?>
*
* @since 3.0
* @return Restrict_Content_Pro The one true Restrict_Content_Pro instance.
*/
function restrict_content_pro() {
return Restrict_Content_Pro::instance();
}

Some files were not shown because too many files have changed in this diff Show More