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

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

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

1240 lines
33 KiB
PHP

<?php
use RCP\Membership_Level;
/**
* RCP Payments class
*
* This class handles querying, inserting, updating, and removing payments
* Also handles calculating earnings
*
* @package Restrict Content Pro
* @subpackage Classes/Payments
* @copyright Copyright (c) 2017, Restrict Content Pro
* @license http://opensource.org/licenses/gpl-2.0.php GNU Public License
* @since 1.5
*/
class RCP_Payments {
/**
* Holds the name of our payments database table
*
* @access public
* @since 1.5
*/
public $db_name;
/**
* Holds the name of our payment meta database table
*
* @access public
* @since 2.6
*/
public $meta_db_name;
/**
* Holds the version number of our discounts database table
*
* @access public
* @since 1.5
*/
public $db_version;
/**
* Get things going.
*
* @return void
*/
function __construct() {
$this->db_name = rcp_get_payments_db_name();
$this->meta_db_name = rcp_get_payment_meta_db_name();
$this->db_version = '1.5';
}
/**
* Add a payment to the database
*
* @access public
* @param array $payment_data Array All of the payment data, such as amount, date, user ID, etc
* @since 1.5
* @return int|false ID of the newly created payment, or false on failure.
*/
public function insert( $payment_data = array() ) {
global $wpdb;
$defaults = array(
'subscription' => '',
'object_id' => 0,
'object_type' => 'subscription',
'date' => date( 'Y-m-d H:i:s', current_time( 'timestamp' ) ),
'amount' => 0.00, // Total amount after fees/credits/discounts are added.
'user_id' => 0,
'customer_id' => 0,
'membership_id' => 0,
'payment_type' => '',
'transaction_type' => 'new',
'subscription_key' => '',
'transaction_id' => '',
'status' => 'complete',
'gateway' => '',
'subtotal' => 0.00, // Base price of the membership level.
'credits' => 0.00, // Proration credits.
'fees' => 0.00, // Fees.
'discount_amount' => 0.00, // Discount amount from discount code.
'discount_code' => ''
);
$args = wp_parse_args( $payment_data, $defaults );
if( ! empty( $args['transaction_id'] ) && $this->payment_exists( $args['transaction_id'] ) ) {
return false;
}
// Backwards compatibility: make sure we store the subscription ID as well.
if ( empty( $args['object_id'] ) && ! empty( $args['subscription'] ) ) {
$membership_level = rcp_get_membership_level_by( 'name', $args['subscription'] );
if ( $membership_level instanceof Membership_Level ) {
$args['object_id'] = $membership_level->get_id();
}
}
// Backwards compatibility: include customer ID.
if ( empty( $args['customer_id'] ) && ! empty( $args['user_id'] ) ) {
$customer = rcp_get_customer_by_user_id( $args['user_id'] );
if ( ! empty( $customer ) ) {
$args['customer_id'] = $customer->get_id();
}
}
// Backwards compatibility: update pending payment instead of creating a new one.
if ( ! empty( $args['user_id'] ) && 'complete' == $args['status'] ) {
$last_pending_payment = get_user_meta( $args['user_id'], 'rcp_pending_payment_id', true );
$pending_payment = ! empty( $last_pending_payment ) ? $this->get_payment( $last_pending_payment ) : false;
if ( ! empty( $pending_payment ) && $args['amount'] == $pending_payment->amount && $args['subscription'] == $pending_payment->subscription ) {
$this->update( $pending_payment->id, $args );
return $pending_payment->id;
}
}
$add = $wpdb->insert( $this->db_name, $args, array( '%s', '%d', '%s', '%s', '%s', '%d', '%d', '%d', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s', '%s' ) );
// if insert was successful, return the payment ID
if( $add ) {
$payment_id = $wpdb->insert_id;
// clear the payment caches
delete_transient( 'rcp_earnings' );
delete_transient( 'rcp_payments_count' );
// Remove trialing status, if it exists
delete_user_meta( $args['user_id'], 'rcp_is_trialing' );
/**
* Triggers when the payment's status is changed. This is here to spoof a status
* change when a payment is first inserted.
*
* @see RCP_Payment::update() - Action is also run here when status is changed.
*
* @param string $new_status New status being set.
* @param int $payment_id ID of the payment.
*
* @since 2.9
*/
do_action( 'rcp_update_payment_status', $args['status'], $payment_id );
do_action( 'rcp_update_payment_status_' . $args['status'], $payment_id );
if ( 'complete' == $args['status'] ) {
/**
* Runs only when a new payment is inserted as "complete". This is to
* ensure backwards compatibility from before payments were inserted
* as "pending" before payment is taken.
*
* @deprecated 2.9 - Use rcp_create_payment to run actions whenever a payment is
* inserted, regardless of status.
*
* @see RCP_Payment::update() - Action is also run here when status is updated to complete.
*
* @param int $payment_id ID of the payment that was just inserted.
* @param array $args Array of all payment information.
* @param float $amount Amount the payment was for.
*/
do_action( 'rcp_insert_payment', $payment_id, $args, $args['amount'] );
}
/**
* Runs when a new payment is successfully inserted.
*
* @param int $payment_id ID of the payment that was just inserted.
* @param array $args Array of all payment information.
*
* @since 2.9
*/
do_action( 'rcp_create_payment', $payment_id, $args );
rcp_log( sprintf( 'New payment inserted. ID: %d; User ID: %d; Amount: %.2f; Subscription: %s; Status: %s', $payment_id, $args['user_id'], $args['amount'], $args['subscription'], $args['status'] ) );
return $payment_id;
} else {
rcp_log( 'Failed inserting new payment into database.', true );
}
return false;
}
/**
* Checks if a payment exists in the DB
*
* @param string $transaction_id The transaction ID of the payment record.
*
* @access public
* @since 1.5
* @return bool
*/
public function payment_exists( $transaction_id = '' ) {
global $wpdb;
$found = $wpdb->get_var(
$wpdb->prepare(
"SELECT id FROM " . $this->db_name . " WHERE `transaction_id`='%s' LIMIT 1;",
$transaction_id
)
);
return (bool) $found;
}
/**
* Update a payment in the datbase.
*
* @param int $payment_id ID of the payment record to update.
* @param array $payment_data Array of all payment data to update.
*
* @access public
* @since 1.5
* @return int|false The number of rows updated, or false on error.
*/
public function update( $payment_id = 0, $payment_data = array() ) {
global $wpdb;
do_action( 'rcp_update_payment', $payment_id, $payment_data );
rcp_log( sprintf( 'Updating payment #%d with new data: %s', $payment_id, var_export( $payment_data, true ) ) );
if ( array_key_exists( 'status', $payment_data ) ) {
delete_transient( md5( 'rcp_payments_count_' . serialize( array( 'user_id' => 0, 'status' => '', 's' => '' ) ) ) );
delete_transient( md5( 'rcp_payments_count_' . serialize( array( 'user_id' => 0, 'status' => 'pending', 's' => '' ) ) ) );
delete_transient( md5( 'rcp_payments_count_' . serialize( array( 'user_id' => 0, 'status' => 'complete', 's' => '' ) ) ) );
delete_transient( md5( 'rcp_payments_count_' . serialize( array( 'user_id' => 0, 'status' => 'refunded', 's' => '' ) ) ) );
}
$updated = $wpdb->update( $this->db_name, $payment_data, array( 'id' => $payment_id ) );
if ( $updated && array_key_exists( 'status', $payment_data ) ) {
$payment = $this->get_payment( $payment_id );
/**
* Triggers when the payment's status is changed.
*
* @param string $new_status New status being set.
* @param int $payment_id ID of the payment.
*
* @since 2.9
*/
do_action( 'rcp_update_payment_status', $payment_data['status'], $payment_id );
do_action( 'rcp_update_payment_status_' . $payment_data['status'], $payment_id );
if ( 'complete' == $payment_data['status'] ) {
$amount = ! empty( $payment->amount ) ? $payment->amount : 0.00;
/**
* Runs only when a payment is updated to "complete". This is to
* ensure backwards compatibility from before payments were inserted
* as "pending" before payment is taken.
*
* @deprecated 2.9 - Use rcp_create_payment to run actions whenever a payment is
* inserted, regardless of status.
*
* @see RCP_Payments::insert() - Action is also run here.
*
* @param int $payment_id ID of the payment that was just updated.
* @param array $args Array of payment information that was just updated.
* @param float $amount Amount the payment was for.
*/
do_action( 'rcp_insert_payment', $payment_id, (array) $payment, $amount );
}
}
return $updated;
}
/**
* Delete a payment from the datbase.
*
* @param int $payment_id ID of the payment to delete.
*
* @access public
* @since 1.5
* @return void
*/
public function delete( $payment_id = 0 ) {
global $wpdb;
do_action( 'rcp_delete_payment', $payment_id );
rcp_log( sprintf( 'Deleted payment #%d.', $payment_id ) );
$wpdb->query( $wpdb->prepare( "DELETE FROM {$this->db_name} WHERE `id` = '%d';", absint( $payment_id ) ) );
}
/**
* Retrieve a specific payment
*
* @param int $payment_id ID of the payment to retrieve.
*
* @access public
* @since 1.5
* @return object|null Database object or null if payment not found.
*/
public function get_payment( $payment_id = 0 ) {
global $wpdb;
$payment = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$this->db_name} WHERE id = %d", absint( $payment_id ) ) );
if ( is_object( $payment ) ) {
if ( empty( $payment->status ) ) {
$payment->status = 'complete';
}
$payment = $this->backfill_payment_data( $payment );
}
return $payment;
}
/**
* Attempt to guess the payment gateway from the "Payment Type"
*
* @param int|object $_payment_id_or_object Payment ID or database object.
*
* @access private
* @since 2.9
* @return string|false
*/
private function get_payment_gateway( $_payment_id_or_object ) {
if ( is_object( $_payment_id_or_object ) ) {
$payment = $_payment_id_or_object;
} elseif ( is_numeric( $_payment_id_or_object ) ) {
$payment = $this->get_payment( $_payment_id_or_object );
}
if ( empty( $payment ) ) {
return false;
}
$type = strtolower( $payment->payment_type );
$gateway = false;
// If we already have a gateway in the DB, use that.
if ( ! empty( $payment->gateway ) ) {
return $payment->gateway;
}
// If "Payment Type" isn't set, we can't get the gateway.
if ( empty( $type ) ) {
return $gateway;
}
switch ( $type ) {
case 'web_accept' :
case 'paypal express one time' :
case 'recurring_payment' :
case 'subscr_payment' :
case 'recurring_payment_profile_created' :
$gateway = 'paypal';
break;
case 'credit card' :
case 'credit card one time' :
if ( false !== strpos( $payment->transaction_id, 'ch_' ) ) {
$gateway = 'stripe';
} elseif ( false !== strpos( $payment->transaction_id, 'anet_' ) ) {
$gateway = 'authorizenet';
} elseif ( is_numeric( $payment->transaction_id ) ) {
$gateway = 'twocheckout';
}
break;
case 'braintree credit card one time' :
case 'braintree credit card initial payment' :
case 'braintree credit card' :
$gateway = 'braintree';
break;
case 'manual' :
$gateway = 'manual';
break;
}
return $gateway;
}
/**
* Retrieve a specific payment by a field
*
* @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
*/
public function get_payment_by( $field = 'id', $value = '' ) {
global $wpdb;
$query = $wpdb->prepare( "SELECT * FROM {$this->db_name} WHERE {$field} = %s", sanitize_text_field( $value ) );
$payment = $wpdb->get_row( $query );
if( is_object( $payment ) && empty( $payment->status ) ) {
$payment->status = 'complete';
}
return $payment;
}
/**
* Retrieve payments from the database
*
* @param array $args Query arguments to override the defaults.
*
* @access public
* @since 1.5
* @return array Array of objects.
*/
public function get_payments( $args = array() ) {
global $wpdb;
$defaults = array(
'number' => 20,
'offset' => 0,
'subscription' => 0,
'user_id' => 0,
'customer_id' => 0,
'membership_id' => 0,
'date' => array(),
'fields' => false,
'status' => '',
's' => '',
'order' => 'DESC',
'orderby' => 'id',
'object_type' => '',
'object_id' => '',
'transaction_type' => '',
'gateway' => ''
);
$args = wp_parse_args( $args, $defaults );
$where = ' WHERE 1=1 ';
$values = array();
// payments for a specific membership level
if( ! empty( $args['subscription'] ) ) {
$where .= " AND `subscription`= %s ";
$values[] = $args['subscription'];
}
// payments for specific users
if( ! empty( $args['user_id'] ) ) {
if( is_array( $args['user_id'] ) ) {
$user_ids = implode( ',', array_map( 'absint', $args['user_id'] ) );
} else {
$user_ids = intval( $args['user_id'] );
}
$where .= " AND `user_id` IN( {$user_ids} ) ";
}
// payments for specific customers
if( ! empty( $args['customer_id'] ) ) {
if( is_array( $args['customer_id'] ) ) {
$customer_ids = implode( ',', array_map( 'absint', $args['customer_id'] ) );
} else {
$customer_ids = intval( $args['customer_id'] );
}
$where .= " AND `customer_id` IN( {$customer_ids} ) ";
}
// payments for specific memberships
if( ! empty( $args['membership_id'] ) ) {
if( is_array( $args['membership_id'] ) ) {
$membership_ids = implode( ',', array_map( 'absint', $args['membership_id'] ) );
} else {
$membership_ids = intval( $args['membership_id'] );
}
$where .= " AND `membership_id` IN( {$membership_ids} ) ";
}
// payments for specific statuses
if( ! empty( $args['status'] ) ) {
if( is_array( $args['status'] ) ) {
$status_count = count( $args['status'] );
$status_placeholder = array_fill( 0, $status_count, '%s' );
$statuses = implode( ', ', $status_placeholder );
$where .= "AND `status` IN ( $statuses )";
$values = $values + $args['status'];
} else {
$where .= "AND `status` = %s";
$values[] = $args['status'];
}
}
// Setup the date query
if( ! empty( $args['date'] ) && is_array( $args['date'] ) ) {
if ( ! empty( $args['date']['start'] ) || ! empty( $args['date']['end'] ) ) {
if ( ! empty( $args['date']['start'] ) ) {
$start = date( 'Y-m-d 00:00:00', strtotime( $args['date']['start'] ) );
$where .= " AND `date` >= %s";
$values[] = $start;
}
if ( ! empty( $args['date']['end'] ) ) {
$end = date( 'Y-m-d 23:59:59', strtotime( $args['date']['end'] ) );
$where .= " AND `date` <= %s";
$values[] = $end;
}
} else {
$day = ! empty( $args['date']['day'] ) ? absint( $args['date']['day'] ) : null;
$month = ! empty( $args['date']['month'] ) ? absint( $args['date']['month'] ) : null;
$year = ! empty( $args['date']['year'] ) ? absint( $args['date']['year'] ) : null;
$date_where = '';
$date_where .= ! is_null( $year ) ? $year . " = YEAR ( date ) " : '';
if ( ! is_null( $month ) ) {
$date_where = $month . " = MONTH ( date ) AND " . $date_where;
}
if ( ! is_null( $day ) ) {
$date_where = $day . " = DAY ( date ) AND " . $date_where;
}
$where .= " AND (" . $date_where . ")";
}
}
// Fields to return
if( $args['fields'] ) {
$fields = $args['fields'];
} else {
$fields = '*';
}
// Search
if( ! empty( $args['s'] ) ) {
// Search by email
if( is_email( $args['s'] ) ) {
$user = get_user_by( 'email', $args['s'] );
if ( is_a( $user, 'WP_User' ) ) {
$where .= " AND `user_id` = %d";
$values[] = $user->ID;
}
} else {
// Search by subscription key
if( strlen( $args['s'] ) == 32 ) {
$where .= " AND `subscription_key` = %s";
$values[] = $args['s'];
} elseif( rcp_get_membership_level_by( 'name', $args['s'] ) ) {
// Matching membership level found so search for payments with this level
$where .= " AND `subscription` = %s";
$values[] = $args['s'];
} else {
$where .= " AND `transaction_id` = %s";
$values[] = $args['s'];
}
}
}
if ( ! empty( $args['object_type'] ) ) {
$where .= " AND `object_type` = %s";
$values[] = $args['object_type'];
}
if ( ! empty( $args['object_id'] ) ) {
$where .= " AND `object_id` = %d AND `object_id` != 0";
$values[] = $args['object_id'];
}
if ( ! empty( $args['transaction_type'] ) ) {
$where .= " AND `transaction_type` = %s";
$values[] = $args['transaction_type'];
}
if ( ! empty( $args['gateway'] ) ) {
$where .= " AND `gateway` = %s";
$values[] = $args['gateway'];
}
if ( 'DESC' === strtoupper( $args['order'] ) ) {
$order = 'DESC';
} else {
$order = 'ASC';
}
$columns = array(
'id',
'user_id',
'subscription',
'subscription_key',
'transaction_id',
'status',
'date'
);
$orderby = array_key_exists( $args['orderby'], $columns ) ? $args['orderby'] : 'id';
$values[] = absint( $args['offset'] );
$values[] = absint( $args['number'] );
$payments = $wpdb->get_results( $wpdb->prepare( "SELECT {$fields} FROM " . $this->db_name . " {$where} ORDER BY {$orderby} {$order} LIMIT %d,%d;", $values ) );
foreach ( $payments as $key => $payment ) {
if ( '*' === $fields ) {
$payment = $this->backfill_payment_data( $payment );
}
$payments[ $key ] = $payment;
}
return $payments;
}
/**
* Backfills any missing payment data introduced in RCP 2.9+
* and updates the payment record accordingly.
*
* @access private
* @since 2.9
*
* @param stdClass $payment The payment object.
*
* @return stdClass The updated payment object.
*/
private function backfill_payment_data( $payment ) {
$data_to_update = array();
/** Backfill the membership level ID. */
if ( empty( $payment->object_id ) && ! empty( $payment->subscription ) ) {
$membership_level = rcp_get_membership_level_by( 'name', $payment->subscription );
if ( $membership_level instanceof Membership_Level ) {
$payment->object_id = $membership_level->get_id();
$data_to_update['object_id'] = $membership_level->get_id();
}
}
/** Backfill the gateway */
if ( empty( $payment->gateway ) && ! empty( $payment->payment_type ) ) {
$gateway = $this->get_payment_gateway( $payment );
if ( ! empty( $gateway ) ) {
$payment->gateway = $gateway;
$data_to_update['gateway'] = $gateway;
}
}
/** Backfill empty subtotal */
if ( ! property_exists( $payment, 'subtotal' ) || '' === $payment->subtotal || null === $payment->subtotal ) {
$payment->subtotal = $payment->amount;
$data_to_update['subtotal'] = $payment->amount;
}
/** Backfill empty credits */
if ( ! property_exists( $payment, 'credits' ) || '' === $payment->credits || null === $payment->credits ) {
$payment->credits = 0;
$data_to_update['credits'] = 0;
}
/** Backfill empty fees */
if ( ! property_exists( $payment, 'fees' ) || '' === $payment->fees || null === $payment->fees ) {
$payment->fees = 0;
$data_to_update['fees'] = 0;
}
/** Backfill empty discount_amount */
if ( ! property_exists( $payment, 'discount_amount' ) || '' === $payment->discount_amount || null === $payment->discount_amount ) {
$payment->discount_amount = 0;
$data_to_update['discount_amount'] = 0;
}
/** Backfill customer ID */
if ( ! empty( $payment->user_id ) && empty( $payment->customer_id ) ) {
$customer = rcp_get_customer_by_user_id( $payment->user_id );
if ( ! empty( $customer ) ) {
$data_to_update['customer_id'] = $customer->get_id();
}
}
if ( ! empty( $data_to_update ) ) {
$this->update( $payment->id, $data_to_update );
}
return $payment;
}
/**
* Count the total number of payments in the database
*
* @param array $args Query arguments to override the defaults.
*
* @access public
* @since 1.5
* @return int
*/
public function count( $args = array() ) {
global $wpdb;
$defaults = array(
'user_id' => 0,
'date' => array(),
'status' => '',
's' => '',
'object_id' => '',
'object_type' => '',
'transaction_type' => '',
'gateway' => ''
);
$args = wp_parse_args( $args, $defaults );
$where = ' WHERE 1=1 ';
$values = array();
// Filter by user ID
if( ! empty( $args['user_id'] ) ) {
if( is_array( $args['user_id'] ) ) {
$user_ids = implode( ',', array_map( 'absint', $args['user_id'] ) );
} else {
$user_ids = intval( $args['user_id'] );
}
$where .= " AND `user_id` IN( {$user_ids} ) ";
}
// Setup the date query
if( ! empty( $args['date'] ) && is_array( $args['date'] ) ) {
if ( ! empty( $args['date']['start'] ) || ! empty( $args['date']['end'] ) ) {
if ( ! empty( $args['date']['start'] ) ) {
$start = date( 'Y-m-d 00:00:00', strtotime( $args['date']['start'] ) );
$where .= " AND `date` >= %s";
$values[] = $start;
}
if ( ! empty( $args['date']['end'] ) ) {
$end = date( 'Y-m-d 23:59:59', strtotime( $args['date']['end'] ) );
$where .= " AND `date` <= %s";
$values[] = $end;
}
} else {
$day = ! empty( $args['date']['day'] ) ? absint( $args['date']['day'] ) : null;
$month = ! empty( $args['date']['month'] ) ? absint( $args['date']['month'] ) : null;
$year = ! empty( $args['date']['year'] ) ? absint( $args['date']['year'] ) : null;
$date_where = '';
$date_where .= ! is_null( $year ) ? $year . " = YEAR ( date ) " : '';
if ( ! is_null( $month ) ) {
$date_where = $month . " = MONTH ( date ) AND " . $date_where;
}
if ( ! is_null( $day ) ) {
$date_where = $day . " = DAY ( date ) AND " . $date_where;
}
$where .= " AND (" . $date_where . ")";
}
}
// Filter by status
if( ! empty( $args['status'] ) ) {
if( is_array( $args['status'] ) ) {
$status_count = count( $args['status'] );
$status_placeholder = array_fill( 0, $status_count, '%s' );
$statuses = implode( ', ', $status_placeholder );
$where .= "AND `status` IN ( $statuses )";
$values = $values + $args['status'];
} else {
$where .= "AND `status` = %s";
$values[] = $args['status'];
}
}
// Search
if( ! empty( $args['s'] ) ) {
// Search by email
if( is_email( $args['s'] ) ) {
$user = get_user_by( 'email', $args['s'] );
if ( is_a( $user, 'WP_User' ) ) {
$where .= " AND `user_id` = %d";
$values[] = $user->ID;
}
} else {
// Search by subscription key
if( strlen( $args['s'] ) == 32 ) {
$where .= " AND `subscription_key` = %s";
$values[] = $args['s'];
} elseif( rcp_get_membership_level_by( 'name', $args['s'] ) ) {
// Matching membership level found so search for payments with this level
$where .= " AND `subscription` = %s";
$values[] = $args['s'];
} else {
$where .= " AND `transaction_id` = %s";
$values[] = $args['s'];
}
}
}
// Object type
if ( ! empty( $args['object_type'] ) ) {
$where .= " AND `object_type` = %s";
$values[] = $args['object_type'];
}
// Object ID
if ( ! empty( $args['object_id'] ) ) {
$where .= " AND `object_id` = %d AND `object_id` != 0";
$values[] = $args['object_id'];
}
// Transaction type (new, renewal, upgrade, downgrade)
if ( ! empty( $args['transaction_type'] ) ) {
$where .= " AND `transaction_type` = %s";
$values[] = $args['transaction_type'];
}
// Gateway
if ( ! empty( $args['gateway'] ) ) {
$where .= " AND `gateway` = %s";
$values[] = $args['gateway'];
}
$key = md5( 'rcp_payments_count_' . serialize( $args ) );
$count = get_transient( $key );
if( $count === false ) {
$query = "SELECT COUNT(ID) FROM " . $this->db_name . "{$where};";
if ( ! empty( $values ) ) {
$query = $wpdb->prepare( $query, $values );
}
$count = $wpdb->get_var( $query );
set_transient( $key, $count, 10800 );
}
return absint( $count );
}
/**
* Calculate the total earnings of all payments in the database
*
* @param array $args Query arguments to override the defaults.
*
* @access public
* @since 1.5
* @return float
*/
public function get_earnings( $args = array() ) {
global $wpdb;
$defaults = array(
'earnings' => 1, // Just for the cache key
'subscription' => 0,
'user_id' => 0,
'date' => array()
);
$args = wp_parse_args( $args, $defaults );
$cache_args = $args;
$cache_args['user_id'] = is_array( $args['user_id'] ) ? implode( ',', $args['user_id'] ) : $args['user_id'];
$cache_args['date'] = implode( ',', $args['date'] );
$cache_key = md5( implode( ',', $cache_args ) );
$where = ' WHERE 1=1 ';
// payments for a specific membership level
if( ! empty( $args['subscription'] ) ) {
$where .= " AND `subscription` = %s ";
$values[] = $args['subscription'];
}
// payments for specific users
if( ! empty( $args['user_id'] ) ) {
if( is_array( $args['user_id'] ) )
$user_ids = implode( ',', array_map( 'absint', $args['user_id'] ) );
else
$user_ids = intval( $args['user_id'] );
$where .= " AND `user_id` IN( {$user_ids} ) ";
}
// Setup the date query
if( ! empty( $args['date'] ) && is_array( $args['date'] ) ) {
if ( ! empty( $args['date']['start'] ) || ! empty( $args['date']['end'] ) ) {
if ( ! empty( $args['date']['start'] ) ) {
$start = date( 'Y-m-d 00:00:00', strtotime( $args['date']['start'] ) );
$where .= " AND `date` >= %s";
$values[] = $start;
}
if ( ! empty( $args['date']['end'] ) ) {
$end = date( 'Y-m-d 23:59:59', strtotime( $args['date']['end'] ) );
$where .= " AND `date` <= %s";
$values[] = $end;
}
} else {
$day = ! empty( $args['date']['day'] ) ? absint( $args['date']['day'] ) : null;
$month = ! empty( $args['date']['month'] ) ? absint( $args['date']['month'] ) : null;
$year = ! empty( $args['date']['year'] ) ? absint( $args['date']['year'] ) : null;
$date_where = '';
$date_where .= ! is_null( $year ) ? $year . " = YEAR ( date ) " : '';
if ( ! is_null( $month ) ) {
$date_where = $month . " = MONTH ( date ) AND " . $date_where;
}
if ( ! is_null( $day ) ) {
$date_where = $day . " = DAY ( date ) AND " . $date_where;
}
$where .= " AND (" . $date_where . ")";
}
}
// Exclude refunded payments
$where .= " AND ( `status` = 'complete' OR `status` IS NULL OR `status` = '' )";
$earnings = get_transient( $cache_key );
if( empty( $earnings ) ) {
$query = "SELECT SUM(amount) FROM " . $this->db_name . " {$where};";
if ( ! empty( $values ) ) {
$query = $wpdb->prepare( $query, $values );
}
$earnings = $wpdb->get_var( $query );
set_transient( $cache_key, $earnings, 3600 );
}
$earnings = empty( $earnings ) ? 0 : $earnings;
return round( $earnings, 2 );
}
/**
* Calculate the total refunds of all payments in the database
*
* @param array $args Query arguments to override the defaults.
*
* @access public
* @since 2.5
* @return float
*/
public function get_refunds( $args = array() ) {
global $wpdb;
$defaults = array(
'refunds' => 2, // Just for the cache key
'subscription' => 0,
'user_id' => 0,
'date' => array()
);
$args = wp_parse_args( $args, $defaults );
$cache_args = $args;
$cache_args['date'] = implode( ',', $args['date'] );
$cache_key = md5( implode( ',', $cache_args ) );
$where = '';
// refunds for a specific membership level
if( ! empty( $args['subscription'] ) ) {
$where .= "WHERE `subscription`= '{$args['subscription']}' ";
}
// refunds for specific users
if( ! empty( $args['user_id'] ) ) {
if( is_array( $args['user_id'] ) )
$user_ids = implode( ',', $args['user_id'] );
else
$user_ids = intval( $args['user_id'] );
if( ! empty( $args['subscription'] ) ) {
$where .= "`user_id` IN( {$user_ids} ) ";
} else {
$where .= "WHERE `user_id` IN( {$user_ids} ) ";
}
}
// Setup the date query
if( ! empty( $args['date'] ) && is_array( $args['date'] ) ) {
$day = ! empty( $args['date']['day'] ) ? absint( $args['date']['day'] ) : null;
$month = ! empty( $args['date']['month'] ) ? absint( $args['date']['month'] ) : null;
$year = ! empty( $args['date']['year'] ) ? absint( $args['date']['year'] ) : null;
$date_where = '';
$date_where .= ! is_null( $year ) ? $year . " = YEAR ( date ) " : '';
if( ! is_null( $month ) ) {
$date_where = $month . " = MONTH ( date ) AND " . $date_where;
}
if( ! is_null( $day ) ) {
$date_where = $day . " = DAY ( date ) AND " . $date_where;
}
if( ! empty( $args['user_id'] ) || ! empty( $args['subscription'] ) ) {
$where .= "AND (" . $date_where . ") ";
} else {
$where .= "WHERE ( " . $date_where . " ) ";
}
}
// Exclude refunded payments
if( false !== strpos( $where, 'WHERE' ) ) {
$where .= "AND ( `status` = 'refunded' )";
} else {
$where .= "WHERE ( `status` = 'refunded' )";
}
$refunds = get_transient( $cache_key );
if( $refunds === false ) {
$refunds = $wpdb->get_var( "SELECT SUM(amount) FROM " . $this->db_name . " {$where};" );
set_transient( $cache_key, $refunds, 3600 );
}
return round( $refunds, 2 );
}
/**
* Retrieves the last payment made by a user
*
* @param int $user_id ID of the user to check.
*
* @access public
* @since 1.5
* @return int|float|false Amount of last payment or false if none is found.
*/
public function last_payment_of_user( $user_id = 0 ) {
global $wpdb;
$query = $wpdb->get_results( $wpdb->prepare( "SELECT * FROM " . $this->db_name . " WHERE `user_id`='%d' ORDER BY id DESC LIMIT 1;", $user_id ) );
if( $query )
return $query[0]->amount;
return false;
}
/**
* Retrieve payment meta field for a payment.
*
* @param int $payment_id Payment 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 Will be an array if $single is false. Will be value of meta data field if $single is true.
*/
public function get_meta( $payment_id = 0, $meta_key = '', $single = false ) {
return get_metadata( 'rcp_payment', $payment_id, $meta_key, $single );
}
/**
* Add meta data field to a payment.
*
* @param int $payment_id Payment 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 $payment_id and $meta_key
*
* @return bool False for failure. True for success.
*/
public function add_meta( $payment_id, $meta_key, $meta_value, $unique = false ) {
return add_metadata( 'rcp_payment', $payment_id, $meta_key, $meta_value, $unique );
}
/**
* Update payment meta field based on Payment ID.
*
* Use the $prev_value parameter to differentiate between meta fields with the
* same key and Payment ID.
*
* If the meta field for the payment does not exist, it will be added.
*
* @param int $payment_id Payment 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 value from $payment_id and $meta_key
*
* @return bool False on failure, true if success.
*/
public function update_meta( $payment_id, $meta_key, $meta_value, $prev_value = '' ) {
return update_metadata( 'rcp_payment', $payment_id, $meta_key, $meta_value, $prev_value );
}
/**
* Remove metadata matching criteria from a payment.
*
* 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 $payment_id Payment ID.
* @param string $meta_key Metadata name.
* @param mixed $meta_value Optional. Metadata value.
*
* @access public
* @since 2.6
* @return bool False for failure. True for success.
*/
public function delete_meta( $payment_id = 0, $meta_key = '', $meta_value = '' ) {
return delete_metadata( 'rcp_payment', $payment_id, $meta_key, $meta_value );
}
}