2022-11-27 15:03:07 +00:00
< ? php
/**
* Admin Payment Actions
*
* @ package EDD
* @ subpackage Admin / Payments
* @ copyright Copyright ( c ) 2018 , Easy Digital Downloads , LLC
* @ license http :// opensource . org / licenses / gpl - 2.0 . php GNU Public License
* @ since 1.9
*/
// Exit if accessed directly
defined ( 'ABSPATH' ) || exit ;
/**
* Handle order item changes
*
* @ since 3.0
*
* @ param array $request
*
* @ return boolean
*/
function edd_handle_order_item_change ( $request = array () ) {
// Bail if missing necessary properties
if (
empty ( $request [ '_wpnonce' ] ) ||
empty ( $request [ 'id' ] ) ||
empty ( $request [ 'order_item' ] )
) {
return false ;
}
// Bail if nonce check fails
if ( ! wp_verify_nonce ( $request [ '_wpnonce' ], 'edd_order_item_nonce' ) ) {
return false ;
}
// Default data
$data = array ();
// Maybe add status to data to update
if ( ! empty ( $request [ 'status' ] ) && ( 'inherit' === $request [ 'status' ] ) || in_array ( $request [ 'status' ], array_keys ( edd_get_payment_statuses () ), true )) {
$data [ 'status' ] = sanitize_key ( $request [ 'status' ] );
}
// Update order item
if ( ! empty ( $data ) ) {
edd_update_order_item ( $request [ 'order_item' ], $data );
edd_redirect ( edd_get_admin_url ( array (
'page' => 'edd-payment-history' ,
'view' => 'view-order-details' ,
'id' => absint ( $request [ 'id' ] )
) ) );
}
}
add_action ( 'edd_handle_order_item_change' , 'edd_handle_order_item_change' );
/**
* Process the changes from the `View Order Details` page .
*
* @ since 1.9
* @ since 3.0 Refactored to use new core objects and query methods .
*
* @ param array $data Order data .
*/
function edd_update_payment_details ( $data = array () ) {
// Bail if an empty array is passed.
if ( empty ( $data ) ) {
wp_die ( esc_html__ ( 'You do not have permission to edit this payment record' , 'easy-digital-downloads' ), esc_html__ ( 'Error' , 'easy-digital-downloads' ), array ( 'response' => 403 ) );
}
// Bail if the user does not have the correct permissions.
if ( ! current_user_can ( 'edit_shop_payments' , $data [ 'edd_payment_id' ] ) ) {
wp_die ( esc_html__ ( 'You do not have permission to edit this payment record' , 'easy-digital-downloads' ), esc_html__ ( 'Error' , 'easy-digital-downloads' ), array ( 'response' => 403 ) );
}
check_admin_referer ( 'edd_update_payment_details_nonce' );
// Retrieve the order ID and set up the order.
$order_id = absint ( $data [ 'edd_payment_id' ] );
$order = edd_get_order ( $order_id );
$order_update_args = array ();
$unlimited = isset ( $data [ 'edd-unlimited-downloads' ] ) ? '1' : null ;
$new_status = sanitize_key ( $data [ 'edd-payment-status' ] );
$date_string = EDD () -> utils -> get_date_string (
sanitize_text_field ( $data [ 'edd-payment-date' ] ),
sanitize_text_field ( $data [ 'edd-payment-time-hour' ] ),
sanitize_text_field ( $data [ 'edd-payment-time-min' ] )
);
// The date is entered in the WP timezone. We need to convert it to UTC prior to saving now.
$date = edd_get_utc_equivalent_date ( EDD () -> utils -> date ( $date_string , edd_get_timezone_id (), false ) );
$date = $date -> format ( 'Y-m-d H:i:s' );
$order_update_args [ 'date_created' ] = $date ;
// Customer
$curr_customer_id = sanitize_text_field ( $data [ 'current-customer-id' ] );
$new_customer_id = sanitize_text_field ( $data [ 'customer-id' ] );
// Create a new customer.
if ( isset ( $data [ 'edd-new-customer' ] ) && 1 === ( int ) $data [ 'edd-new-customer' ] ) {
$email = isset ( $data [ 'edd-new-customer-email' ] )
? sanitize_text_field ( $data [ 'edd-new-customer-email' ] )
: '' ;
// Sanitize first name
$first_name = isset ( $data [ 'edd-new-customer-first-name' ] )
? sanitize_text_field ( $data [ 'edd-new-customer-first-name' ] )
: '' ;
// Sanitize last name
$last_name = isset ( $data [ 'edd-new-customer-last-name' ] )
? sanitize_text_field ( $data [ 'edd-new-customer-last-name' ] )
: '' ;
// Combine
$name = $first_name . ' ' . $last_name ;
if ( empty ( $email ) || empty ( $name ) ) {
wp_die ( esc_html__ ( 'New Customers require a name and email address' , 'easy-digital-downloads' ) );
}
$customer = new EDD_Customer ( $email );
if ( empty ( $customer -> id ) ) {
$customer_data = array (
'name' => $name ,
'email' => $email ,
);
$user_id = email_exists ( $email );
if ( false !== $user_id ) {
$customer_data [ 'user_id' ] = $user_id ;
}
if ( ! $customer -> create ( $customer_data ) ) {
$customer = new EDD_Customer ( $curr_customer_id );
edd_set_error ( 'edd-payment-new-customer-fail' , __ ( 'Error creating new customer' , 'easy-digital-downloads' ) );
}
} else {
wp_die ( sprintf ( __ ( 'A customer with the email address %s already exists. Please go back and assign this payment to them.' , 'easy-digital-downloads' ), $email ) );
}
$previous_customer = new EDD_Customer ( $curr_customer_id );
} elseif ( $curr_customer_id !== $new_customer_id ) {
$customer = new EDD_Customer ( $new_customer_id );
$previous_customer = new EDD_Customer ( $curr_customer_id );
} else {
$customer = new EDD_Customer ( $curr_customer_id );
}
// Remove the stats and payment from the previous customer and attach it to the new customer
if ( isset ( $previous_customer ) ) {
$previous_customer -> remove_payment ( $order_id , false );
$customer -> attach_payment ( $order_id , false );
// If purchase was completed and not ever refunded, adjust stats of customers
if ( 'revoked' === $new_status || 'complete' === $new_status ) {
$previous_customer -> recalculate_stats ();
if ( ! empty ( $customer ) ) {
$customer -> recalculate_stats ();
}
}
$order_update_args [ 'customer_id' ] = $customer -> id ;
}
$order_update_args [ 'user_id' ] = $customer -> user_id ;
$order_update_args [ 'email' ] = $customer -> email ;
// Address.
$address = $data [ 'edd_order_address' ];
$order_address_id = absint ( $address [ 'address_id' ] );
$order_address_details = array (
'name' => $customer -> name ,
'address' => $address [ 'address' ],
'address2' => $address [ 'address2' ],
'city' => $address [ 'city' ],
'region' => $address [ 'region' ],
'postal_code' => $address [ 'postal_code' ],
'country' => $address [ 'country' ],
);
if ( empty ( $order_address_id ) ) {
// Unset the address_id which is 0.
unset ( $address [ 'address_id' ] );
// Add the $order_id to the arguments to create this order address.
$order_address_details [ 'order_id' ] = $order_id ;
edd_add_order_address ( $order_address_details );
} else {
edd_update_order_address ( $order_address_id , $order_address_details );
}
// Unlimited downloads.
if ( 1 === ( int ) $unlimited ) {
edd_update_order_meta ( $order_id , 'unlimited_downloads' , $unlimited );
} else {
edd_delete_order_meta ( $order_id , 'unlimited_downloads' );
}
// Don't set the status in the update call (for back compat)
unset ( $order_update_args [ 'status' ] );
// Attempt to update the order
$updated = edd_update_order ( $order_id , $order_update_args );
// Bail if an error occurred
if ( false === $updated ) {
wp_die ( __ ( 'Error updating order.' , 'easy-digital-downloads' ), __ ( 'Error' , 'easy-digital-downloads' ), array ( 'response' => 400 ) );
}
// Check if the status has changed, if so, we need to invoke the pertinent
// status processing method (for back compat)
if ( $new_status !== $order -> status ) {
edd_update_order_status ( $order_id , $new_status );
}
do_action ( 'edd_updated_edited_purchase' , $order_id );
edd_redirect ( edd_get_admin_url ( array (
'page' => 'edd-payment-history' ,
'view' => 'view-order-details' ,
'edd-message' => 'payment-updated' ,
'id' => absint ( $order_id ),
) ) );
}
add_action ( 'edd_update_payment_details' , 'edd_update_payment_details' );
/**
* New in 3.0 , permanently destroys an order , and all its data , and related data .
*
* @ since 3.0
*
* @ param array $data Arguments passed .
*/
function edd_trigger_destroy_order ( $data ) {
if ( wp_verify_nonce ( $data [ '_wpnonce' ], 'edd_payment_nonce' ) ) {
$payment_id = absint ( $data [ 'purchase_id' ] );
if ( ! current_user_can ( 'delete_shop_payments' , $payment_id ) ) {
wp_die ( esc_html__ ( 'You do not have permission to edit this order.' , 'easy-digital-downloads' ), esc_html__ ( 'Error' , 'easy-digital-downloads' ), array ( 'response' => 403 ) );
}
edd_destroy_order ( $payment_id );
$redirect_link = add_query_arg (
array (
'page' => 'edd-payment-history' ,
'edd-message' => 'payment_deleted' ,
'status' => 'trash' ,
),
edd_get_admin_base_url ()
);
edd_redirect ( $redirect_link );
}
}
add_action ( 'edd_delete_order' , 'edd_trigger_destroy_order' );
/**
* Trigger the action of moving an order to the 'trash' status
*
* @ since 3.0
*
* @ param $data
* @ return void
*/
function edd_trigger_trash_order ( $data ) {
if ( wp_verify_nonce ( $data [ '_wpnonce' ], 'edd_payment_nonce' ) ) {
$payment_id = absint ( $data [ 'purchase_id' ] );
if ( ! current_user_can ( 'delete_shop_payments' , $payment_id ) ) {
wp_die ( __ ( 'You do not have permission to edit this payment record' , 'easy-digital-downloads' ), __ ( 'Error' , 'easy-digital-downloads' ), array ( 'response' => 403 ) );
}
edd_trash_order ( $payment_id );
$redirect = edd_get_admin_url ( array (
'page' => 'edd-payment-history' ,
'edd-message' => 'order_trashed' ,
'order_type' => esc_attr ( $data [ 'order_type' ] ),
) );
edd_redirect ( $redirect );
}
}
add_action ( 'edd_trash_order' , 'edd_trigger_trash_order' );
/**
* Trigger the action of restoring an order from the 'trash' status
*
* @ since 3.0
*
* @ param $data
* @ return void
*/
function edd_trigger_restore_order ( $data ) {
if ( wp_verify_nonce ( $data [ '_wpnonce' ], 'edd_payment_nonce' ) ) {
$payment_id = absint ( $data [ 'purchase_id' ] );
if ( ! current_user_can ( 'delete_shop_payments' , $payment_id ) ) {
wp_die ( __ ( 'You do not have permission to edit this payment record' , 'easy-digital-downloads' ), __ ( 'Error' , 'easy-digital-downloads' ), array ( 'response' => 403 ) );
}
edd_restore_order ( $payment_id );
$redirect = edd_get_admin_url ( array (
'page' => 'edd-payment-history' ,
'edd-message' => 'order_restored' ,
'order_type' => esc_attr ( $data [ 'order_type' ] ),
) );
edd_redirect ( $redirect );
}
}
add_action ( 'edd_restore_order' , 'edd_trigger_restore_order' );
/**
* Retrieves a new download link for a purchased file
*
* @ since 2.0
* @ return string
*/
function edd_ajax_generate_file_download_link () {
$customer_view_role = apply_filters ( 'edd_view_customers_role' , 'view_shop_reports' );
if ( ! current_user_can ( $customer_view_role ) ) {
die ( '-1' );
}
$payment_id = absint ( $_POST [ 'payment_id' ] );
$download_id = absint ( $_POST [ 'download_id' ] );
$price_id = isset ( $_POST [ 'price_id' ] ) && is_numeric ( $_POST [ 'price_id' ] ) ? absint ( $_POST [ 'price_id' ] ) : null ;
if ( empty ( $payment_id ) ) {
die ( '-2' );
}
if ( empty ( $download_id ) ) {
die ( '-3' );
}
$limit = edd_get_file_download_limit ( $download_id );
if ( ! empty ( $limit ) ) {
// Increase the file download limit when generating new links
edd_set_file_download_limit_override ( $download_id , $payment_id );
}
$files = edd_get_download_files ( $download_id , $price_id );
if ( ! $files ) {
die ( '-4' );
}
2023-03-17 22:34:04 +00:00
$order = edd_get_order ( $payment_id );
2022-11-27 15:03:07 +00:00
$file_urls = '' ;
2023-03-17 22:34:04 +00:00
foreach ( $files as $file_key => $file ) {
$file_urls .= edd_get_download_file_url ( $order , $order -> email , $file_key , $download_id , $price_id );
2022-11-27 15:03:07 +00:00
$file_urls .= " \n \n " ;
}
die ( $file_urls );
}
add_action ( 'wp_ajax_edd_get_file_download_link' , 'edd_ajax_generate_file_download_link' );
/**
* Renders the refund form that is used to process a refund .
*
* @ since 3.0
*
* @ return void
*/
function edd_ajax_generate_refund_form () {
// Verify we have a logged user.
if ( ! is_user_logged_in () ) {
$return = array (
'success' => false ,
'message' => __ ( 'You must be logged in to perform this action.' , 'easy-digital-downloads' ),
);
wp_send_json ( $return , 401 );
}
// Verify the logged in user has permission to edit shop payments.
if ( ! current_user_can ( 'edit_shop_payments' ) ) {
$return = array (
'success' => false ,
'message' => __ ( 'Your account does not have permission to perform this action.' , 'easy-digital-downloads' ),
);
wp_send_json ( $return , 401 );
}
$order_id = isset ( $_POST [ 'order_id' ] ) && is_numeric ( $_POST [ 'order_id' ] ) ? absint ( $_POST [ 'order_id' ] ) : false ;
if ( empty ( $order_id ) ) {
$return = array (
'success' => false ,
'message' => __ ( 'Invalid order ID' , 'easy-digital-downloads' ),
);
wp_send_json ( $return , 400 );
}
$order = edd_get_order ( $order_id );
if ( empty ( $order ) ) {
$return = array (
'success' => false ,
'message' => __ ( 'Invalid order' , 'easy-digital-downloads' ),
);
wp_send_json ( $return , 404 );
}
if ( 'refunded' === $order -> status ) {
$return = array (
'success' => false ,
'message' => __ ( 'Order is already refunded' , 'easy-digital-downloads' ),
);
wp_send_json ( $return , 404 );
}
if ( 'refund' === $order -> type ) {
$return = array (
'success' => false ,
'message' => __ ( 'Cannot refund an order that is already refunded.' , 'easy-digital-downloads' ),
);
wp_send_json ( $return , 404 );
}
// Output buffer the form before we include it in the JSON response.
ob_start ();
?>
< div id = " edd-submit-refund-status " style = " display: none; " >
< span class = " edd-submit-refund-message " ></ span >
< a class = " edd-submit-refund-url " href = " " >< ? php _e ( 'View Refund' , 'easy-digital-downloads' ); ?> </a>
</ div >
< form id = " edd-submit-refund-form " method = " POST " >
< ? php
// Load list table if not already loaded
if ( ! class_exists ( '\\EDD\\Admin\\Refund_Items_Table' ) ) {
require_once 'class-refund-items-table.php' ;
}
$refund_items = new EDD\Admin\Refund_Items_Table ();
$refund_items -> prepare_items ();
$refund_items -> display ();
?>
</ form >
< ? php
$html = trim ( ob_get_clean () );
$return = array (
'success' => true ,
'html' => $html ,
);
wp_send_json ( $return , 200 );
}
add_action ( 'wp_ajax_edd_generate_refund_form' , 'edd_ajax_generate_refund_form' );
/**
* Processes the results from the Submit Refund form
*
* @ since 3.0
* @ return void
*/
function edd_ajax_process_refund_form () {
// Verify we have a logged user.
if ( ! is_user_logged_in () ) {
wp_send_json_error ( __ ( 'You must be logged in to perform this action.' , 'easy-digital-downloads' ), 401 );
}
// Verify the logged in user has permission to edit shop payments.
if ( ! current_user_can ( 'edit_shop_payments' ) ) {
wp_send_json_error ( __ ( 'Your account does not have permission to perform this action.' , 'easy-digital-downloads' ), 401 );
}
if ( empty ( $_POST [ 'data' ] ) || empty ( $_POST [ 'order_id' ] ) ) {
wp_send_json_error ( __ ( 'Missing form data or order ID.' , 'easy-digital-downloads' ), 400 );
}
// Get our data out of the serialized string.
parse_str ( $_POST [ 'data' ], $form_data );
// Verify the nonce.
$nonce = ! empty ( $form_data [ 'edd_process_refund' ] ) ? sanitize_text_field ( $form_data [ 'edd_process_refund' ] ) : false ;
if ( empty ( $nonce ) || ! wp_verify_nonce ( $nonce , 'edd_process_refund' ) ) {
wp_send_json_error ( __ ( 'Nonce validation failed when submitting refund.' , 'easy-digital-downloads' ), 401 );
}
// Collect selected order items.
$order_items = array ();
if ( ! empty ( $form_data [ 'refund_order_item' ] ) && is_array ( $form_data [ 'refund_order_item' ] ) ) {
foreach ( $form_data [ 'refund_order_item' ] as $order_item_id => $order_item ) {
// If there's no quantity or subtotal - bail.
if ( empty ( $order_item [ 'quantity' ] ) || empty ( $order_item [ 'subtotal' ] ) ) {
continue ;
}
$order_items [] = array (
'order_item_id' => absint ( $order_item_id ),
'quantity' => intval ( $order_item [ 'quantity' ] ),
'subtotal' => edd_sanitize_amount ( $order_item [ 'subtotal' ] ),
'tax' => ! empty ( $order_item [ 'tax' ] ) ? edd_sanitize_amount ( $order_item [ 'tax' ] ) : 0.00
);
}
}
// Collect selected adjustments.
$adjustments = array ();
if ( ! empty ( $form_data [ 'refund_order_adjustment' ] ) && is_array ( $form_data [ 'refund_order_adjustment' ] ) ) {
foreach ( $form_data [ 'refund_order_adjustment' ] as $adjustment_id => $adjustment ) {
// If there's no quantity or subtotal - bail.
if ( empty ( $adjustment [ 'quantity' ] ) || empty ( $adjustment [ 'subtotal' ] ) ) {
continue ;
}
$adjustments [] = array (
'adjustment_id' => absint ( $adjustment_id ),
'quantity' => intval ( $adjustment [ 'quantity' ] ),
'subtotal' => floatval ( edd_sanitize_amount ( $adjustment [ 'subtotal' ] ) ),
'tax' => ! empty ( $adjustment [ 'tax' ] ) ? floatval ( edd_sanitize_amount ( $adjustment [ 'tax' ] ) ) : 0.00
);
}
}
$order_id = absint ( $_POST [ 'order_id' ] );
$refund_id = edd_refund_order ( $order_id , $order_items , $adjustments );
if ( is_wp_error ( $refund_id ) ) {
wp_send_json_error ( $refund_id -> get_error_message () );
} elseif ( ! empty ( $refund_id ) ) {
$return = array (
'refund_id' => $refund_id ,
'message' => sprintf ( __ ( 'Refund successfully processed.' , 'easy-digital-downloads' ) ),
'refund_url' => edd_get_admin_url (
array (
'page' => 'edd-payment-history' ,
'view' => 'view-refund-details' ,
'id' => urlencode ( $refund_id ),
)
)
);
wp_send_json_success ( $return , 200 );
} else {
wp_send_json_error ( __ ( 'Unable to process refund.' , 'easy-digital-downloads' ), 401 );
}
}
add_action ( 'wp_ajax_edd_process_refund_form' , 'edd_ajax_process_refund_form' );
/**
* Process Orders list table bulk actions . This is necessary because we need to
* redirect to ensure filters do not get applied when bulk actions are being
* processed . This processing cannot happen within the `EDD_Payment_History_Table`
* class as at that point , it is too late to do a redirect .
*
* @ since 3.0
*/
function edd_orders_list_table_process_bulk_actions () {
// Bail if this method was called directly.
if ( 'load-download_page_edd-payment-history' !== current_action () ) {
_doing_it_wrong ( __FUNCTION__ , 'This method is not meant to be called directly.' , 'EDD 3.0' );
}
$action = isset ( $_REQUEST [ 'action' ] ) // WPCS: CSRF ok.
? sanitize_text_field ( $_REQUEST [ 'action' ] )
: '' ;
2023-03-17 22:34:04 +00:00
// If this is a 'delete' action, the capability changes from edit to delete.
$cap = 'delete' === $action ? 'delete_shop_payments' : 'edit_shop_payments' ;
// Check the current user's capability.
if ( ! current_user_can ( $cap ) ) {
return ;
}
2022-11-27 15:03:07 +00:00
// Bail if we aren't processing bulk actions.
if ( '-1' === $action ) {
return ;
}
$ids = isset ( $_GET [ 'order' ] ) // WPCS: CSRF ok.
? $_GET [ 'order' ]
: false ;
if ( ! is_array ( $ids ) ) {
$ids = array ( $ids );
}
if ( empty ( $action ) ) {
return ;
}
check_admin_referer ( 'bulk-orders' );
$ids = wp_parse_id_list ( $ids );
foreach ( $ids as $id ) {
switch ( $action ) {
case 'trash' :
edd_trash_order ( $id );
break ;
case 'restore' :
edd_restore_order ( $id );
break ;
2023-03-17 22:34:04 +00:00
case 'delete' :
edd_destroy_order ( $id );
break ;
2022-11-27 15:03:07 +00:00
case 'set-status-complete' :
edd_update_payment_status ( $id , 'complete' );
break ;
case 'set-status-pending' :
edd_update_payment_status ( $id , 'pending' );
break ;
case 'set-status-processing' :
edd_update_payment_status ( $id , 'processing' );
break ;
case 'set-status-revoked' :
edd_update_payment_status ( $id , 'revoked' );
break ;
case 'set-status-failed' :
edd_update_payment_status ( $id , 'failed' );
break ;
case 'set-status-abandoned' :
edd_update_payment_status ( $id , 'abandoned' );
break ;
case 'set-status-preapproval' :
edd_update_payment_status ( $id , 'preapproval' );
break ;
case 'set-status-cancelled' :
edd_update_payment_status ( $id , 'cancelled' );
break ;
case 'resend-receipt' :
edd_email_purchase_receipt ( $id , false );
break ;
}
do_action ( 'edd_payments_table_do_bulk_action' , $id , $action );
}
wp_safe_redirect ( wp_get_referer () );
}
add_action ( 'load-download_page_edd-payment-history' , 'edd_orders_list_table_process_bulk_actions' );