utils->date( 'now', null, true )->timestamp; // Parse args. $order_data = wp_parse_args( $args, array( 'downloads' => array(), 'adjustments' => array(), 'subtotal' => 0.00, 'tax' => 0.00, 'total' => 0.00, 'discount' => 0.00, 'edd-payment-status' => 'complete', 'payment_key' => '', 'gateway' => '', 'transaction_id' => '', 'receipt' => '', 'edd-payment-date' => date( 'Y-m-d', $now ), 'edd-payment-time-hour' => date( 'G', $now ), 'edd-payment-time-min' => date( 'i', $now ), 'edd-unlimited-downloads' => 0, ) ); /** Customer data *********************************************************/ // Defaults. $customer_id = 0; $user_id = 0; $email = ''; $name = ''; // Create a new customer record. if ( isset( $order_data['edd-new-customer'] ) && 1 === absint( $order_data['edd-new-customer'] ) ) { // Sanitize first name. $first_name = isset( $order_data['edd-new-customer-first-name'] ) ? sanitize_text_field( $order_data['edd-new-customer-first-name'] ) : ''; // Sanitize last name. $last_name = isset( $order_data['edd-new-customer-last-name'] ) ? sanitize_text_field( $order_data['edd-new-customer-last-name'] ) : ''; // Combine. $name = trim( $first_name . ' ' . $last_name ); // Sanitize the email address. $email = isset( $order_data['edd-new-customer-email'] ) ? sanitize_email( $order_data['edd-new-customer-email'] ) : ''; $new_customer_args = array( 'name' => $name, 'email' => $email, ); // Determine if there is an existing user with this email address. $possible_user = get_user_by( 'email', $email ); if ( $possible_user instanceof WP_User ) { $new_customer_args['user_id'] = $possible_user->ID; } // Save to database. $customer_id = edd_add_customer( $new_customer_args ); $customer = edd_get_customer( $customer_id ); // Existing customer. } elseif ( isset( $order_data['edd-new-customer'] ) && 0 === absint( $order_data['edd-new-customer'] ) && isset( $order_data['customer-id'] ) ) { $customer_id = absint( $order_data['customer-id'] ); $customer = edd_get_customer( $customer_id ); if ( $customer ) { $email = $customer->email; $user_id = $customer->user_id; $name = $customer->name; } } /** Insert order **********************************************************/ // Parse order status. $status = sanitize_text_field( $order_data['edd-payment-status'] ); if ( empty( $status ) || ! in_array( $status, array_keys( edd_get_payment_statuses() ), true ) ) { $status = 'complete'; } // Get the date string. $date_string = EDD()->utils->get_date_string( sanitize_text_field( $order_data['edd-payment-date'] ), sanitize_text_field( $order_data['edd-payment-time-hour'] ), sanitize_text_field( $order_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' ); // Get mode $mode = edd_is_test_mode() ? 'test' : 'live'; // Amounts $order_subtotal = floatval( $order_data['subtotal'] ); $order_tax = floatval( $order_data['tax'] ); $order_discount = floatval( $order_data['discount'] ); $order_total = floatval( $order_data['total'] ); $tax_rate = false; // If taxes are enabled, get the tax rate for the order location. if ( edd_use_taxes() ) { $country = ! empty( $order_data['edd_order_address']['country'] ) ? $order_data['edd_order_address']['country'] : false; $region = ! empty( $order_data['edd_order_address']['region'] ) ? $order_data['edd_order_address']['region'] : false; $tax_rate = edd_get_tax_rate_by_location( array( 'country' => $country, 'region' => $region, ) ); } // Add the order ID $order_id = edd_add_order( array( 'status' => 'pending', // Always insert as pending initially. 'user_id' => $user_id, 'customer_id' => $customer_id, 'email' => $email, 'ip' => sanitize_text_field( $order_data['ip'] ), 'gateway' => sanitize_text_field( $order_data['gateway'] ), 'mode' => $mode, 'currency' => edd_get_currency(), 'payment_key' => $order_data['payment_key'] ? sanitize_text_field( $order_data['payment_key'] ) : edd_generate_order_payment_key( $email ), 'tax_rate_id' => ! empty( $tax_rate->id ) ? $tax_rate->id : null, 'subtotal' => $order_subtotal, 'tax' => $order_tax, 'discount' => $order_discount, 'total' => $order_total, 'date_created' => $date, 'order_number' => edd_set_order_number(), ) ); // Attach order to the customer record. if ( ! empty( $customer ) ) { $customer->attach_payment( $order_id, false ); } // If we have tax, but no tax rate, manually save the percentage. if ( empty( $tax_rate->id ) && $order_tax > 0 ) { $tax_rate_percentage = $order_data['tax_rate']; if ( ! empty( $tax_rate_percentage ) ) { if ( $tax_rate_percentage > 0 && $tax_rate_percentage < 1 ) { $tax_rate_percentage = $tax_rate_percentage * 100; } edd_update_order_meta( $order_id, 'tax_rate', $tax_rate_percentage ); } } /** Insert order address **************************************************/ if ( isset( $order_data['edd_order_address'] ) ) { // Parse args $address = wp_parse_args( $order_data['edd_order_address'], array( 'name' => $name, 'address' => '', 'address2' => '', 'city' => '', 'postal_code' => '', 'country' => '', 'region' => '', ) ); $order_address_data = $address; $order_address_data['order_id'] = $order_id; // Remove empty data. $order_address_data = array_filter( $order_address_data ); // Add to edd_order_addresses table. edd_add_order_address( $order_address_data ); // Maybe add the address to the edd_customer_addresses. $customer_address_data = $order_address_data; // We don't need to pass this data to edd_maybe_add_customer_address(). unset( $customer_address_data['order_id'] ); edd_maybe_add_customer_address( $customer->id, $customer_address_data ); } /** Insert order items ****************************************************/ // Any adjustments specific to an order item need to be added to the item. foreach ( $order_data['adjustments'] as $key => $adjustment ) { if ( 'order_item' === $adjustment['object_type'] ) { $order_data['downloads'][ $adjustment['object_id'] ]['adjustments'][] = $adjustment; unset( $order_data['adjustments'][ $key ] ); } } if ( ! empty( $order_data['downloads'] ) ) { // Re-index downloads. $order_data['downloads'] = array_values( $order_data['downloads'] ); $downloads = array_reverse( $order_data['downloads'] ); foreach ( $downloads as $cart_key => $download ) { $d = edd_get_download( absint( $download['id'] ) ); // Skip if download no longer exists if ( empty( $d ) ) { continue; } // Quantity. $quantity = isset( $download['quantity'] ) ? absint( $download['quantity'] ) : 1; // Price ID. $price_id = isset( $download['price_id'] ) && is_numeric( $download['price_id'] ) ? absint( $download['price_id'] ) : null; // Amounts. $amount = isset( $download[ 'amount' ] ) ? floatval( $download[ 'amount' ] ) : 0.00; $subtotal = isset( $download[ 'subtotal' ] ) ? floatval( $download[ 'subtotal' ] ) : 0.00; $discount = isset( $download[ 'discount' ] ) ? floatval( $download[ 'discount' ] ) : 0.00; $tax = isset( $download[ 'tax' ] ) ? floatval( $download[ 'tax' ] ) : 0.00; $total = isset( $download[ 'total' ] ) ? floatval( $download[ 'total' ] ) : 0.00; // Add to edd_order_items table. $order_item_id = edd_add_order_item( array( 'order_id' => $order_id, 'product_id' => absint( $download['id'] ), 'product_name' => edd_get_download_name( $download['id'], absint( $price_id ) ), 'price_id' => $price_id, 'cart_index' => $cart_key, 'type' => 'download', 'status' => 'complete', 'quantity' => $quantity, 'amount' => $amount, 'subtotal' => $subtotal, 'discount' => $discount, 'tax' => $tax, 'total' => $total, ) ); if ( false !== $order_item_id ) { if ( isset( $download['adjustments'] ) ) { $order_item_adjustments = array_reverse( $download['adjustments'] ); foreach ( $order_item_adjustments as $index => $order_item_adjustment ) { // Discounts are not tracked at the Order Item level. if ( 'discount' === $order_item_adjustment['type'] ) { continue; } $type_key = ! empty( $order_item_adjustment['description'] ) ? sanitize_text_field( strtolower( sanitize_title( $order_item_adjustment['description'] ) ) ) : $index; $order_item_adjustment_subtotal = floatval( $order_item_adjustment['subtotal'] ); $order_item_adjustment_tax = floatval( $order_item_adjustment['tax'] ); $order_item_adjustment_total = floatval( $order_item_adjustment['total'] ); edd_add_order_adjustment( array( 'object_id' => $order_item_id, 'object_type' => 'order_item', 'type' => sanitize_text_field( $order_item_adjustment['type'] ), 'type_key' => $type_key, 'description' => sanitize_text_field( $order_item_adjustment['description'] ), 'subtotal' => $order_item_adjustment_subtotal, 'tax' => $order_item_adjustment_tax, 'total' => $order_item_adjustment_total, ) ); } } } } } /** Insert adjustments ****************************************************/ // Adjustments. if ( isset( $order_data['adjustments'] ) ) { $adjustments = array_reverse( $order_data['adjustments'] ); foreach ( $adjustments as $index => $adjustment ) { if ( 'order_item' === $adjustment['object_type'] ) { continue; } $type_key = ! empty( $adjustment['description'] ) ? sanitize_text_field( strtolower( sanitize_title( $adjustment['description'] ) ) ) : $index; $adjustment_subtotal = floatval( $adjustment['subtotal'] ); $adjustment_tax = floatval( $adjustment['tax'] ); $adjustment_total = floatval( $adjustment['total'] ); edd_add_order_adjustment( array( 'object_id' => $order_id, 'object_type' => 'order', 'type' => sanitize_text_field( $adjustment['type'] ), 'type_key' => $type_key, 'description' => sanitize_text_field( $adjustment['description'] ), 'subtotal' => $adjustment_subtotal, 'tax' => $adjustment_tax, 'total' => $adjustment_total, ) ); } } // Discounts. if ( isset( $order_data['discounts'] ) ) { $discounts = array_reverse( $order_data['discounts'] ); foreach ( $discounts as $discount ) { $d = edd_get_discount( absint( $discount['type_id'] ) ); if ( empty( $d ) ) { continue; } $discount_subtotal = floatval( $discount['subtotal'] ); $discount_total = floatval( $discount['total'] ); // Store discount. edd_add_order_adjustment( array( 'object_id' => $order_id, 'object_type' => 'order', 'type_id' => intval( $discount['type_id'] ), 'type' => 'discount', 'description' => sanitize_text_field( $discount['code'] ), 'subtotal' => $discount_subtotal, 'total' => $discount_total, ) ); } } // Insert transaction ID. if ( ! empty( $order_data['transaction_id'] ) ) { edd_add_order_transaction( array( 'object_id' => $order_id, 'object_type' => 'order', 'transaction_id' => sanitize_text_field( $order_data['transaction_id'] ), 'gateway' => sanitize_text_field( $order_data['gateway'] ), 'status' => 'complete', 'total' => $order_total, ) ); } // Unlimited downloads. if ( isset( $order_data['edd-unlimited-downloads'] ) && 1 === (int) $order_data['edd-unlimited-downloads'] ) { edd_update_order_meta( $order_id, 'unlimited_downloads', 1 ); } // Stop purchase receipt from being sent. if ( ! isset( $order_data['edd_order_send_receipt'] ) ) { remove_action( 'edd_complete_purchase', 'edd_trigger_purchase_receipt', 999 ); } // Trigger edd_complete_purchase. if ( 'complete' === $status ) { edd_update_order_status( $order_id, $status ); } /** * Action hook which runs after a manual order has been added to the database. * * @since 3.0 * @param int $order_id The new order ID. * @param array $order_data The array of order data. * @param array $args The original form data. */ do_action( 'edd_post_add_manual_order', $order_id, $order_data, $args ); // Redirect to `Edit Order` page. edd_redirect( edd_get_admin_url( array( 'page' => 'edd-payment-history', 'view' => 'view-order-details', 'id' => urlencode( $order_id ), 'edd-message' => 'order_added', ) ) ); } add_action( 'edd_add_order', 'edd_add_manual_order' );