'paid', 'cancel' => 'cancelled', 'refund' => 'refunded', ); $done = 0; $fail = 0; foreach ( array_filter( $ids ) as $id ) { $order = Paygrab_Orders::get( $id ); if ( ! $order ) { continue; } if ( 'reset' === $do ) { Paygrab_Downloads::reset( $order ); ++$done; continue; } if ( ! isset( $map[ $do ] ) ) { continue; } // Payments and refunds of gateways like Stripe are confirmed by the gateway, not by hand. $gateway = Paygrab_Gateways::get( $order->gateway ); if ( in_array( $do, array( 'paid', 'refund' ), true ) && $gateway && $gateway->confirms_payments() ) { ++$fail; continue; } $result = Paygrab_Orders::set_status( $order, $map[ $do ], array( 'notify' => $notify, 'by' => 'admin', ) ); is_wp_error( $result ) ? ++$fail : ++$done; } wp_safe_redirect( add_query_arg( array( 'paygrab_done' => $do, 'n' => $done, 'f' => $fail, ), $back ) ); exit; } /** * Result notices after an action. * * @return void */ public static function notices() { // phpcs:disable WordPress.Security.NonceVerification.Recommended // Shown on the orders list and on the dashboard (where "Confirm payment" returns). if ( empty( $_GET['paygrab_done'] ) || empty( $_GET['page'] ) || ! in_array( $_GET['page'], array( Paygrab_Admin::ORDERS, Paygrab_Admin::SLUG ), true ) ) { return; } $do = sanitize_key( wp_unslash( $_GET['paygrab_done'] ) ); $done = isset( $_GET['n'] ) ? absint( $_GET['n'] ) : 0; $fail = isset( $_GET['f'] ) ? absint( $_GET['f'] ) : 0; // phpcs:enable $texts = array( /* translators: %d: number of orders */ 'paid' => _n( 'Marked %d order as paid.', 'Marked %d orders as paid.', $done, 'paygrab' ), /* translators: %d: number of orders */ 'cancel' => _n( 'Cancelled %d order.', 'Cancelled %d orders.', $done, 'paygrab' ), /* translators: %d: number of orders */ 'refund' => _n( 'Marked %d order as refunded.', 'Marked %d orders as refunded.', $done, 'paygrab' ), /* translators: %d: number of orders */ 'reset' => _n( 'Reset the downloads of %d order.', 'Reset the downloads of %d orders.', $done, 'paygrab' ), ); if ( $done && isset( $texts[ $do ] ) ) { printf( '

%s

', esc_html( sprintf( $texts[ $do ], $done ) ) ); } if ( $fail ) { /* translators: %d: number of orders */ printf( '

%s

', esc_html( sprintf( _n( '%d order could not be changed because its status does not allow it.', '%d orders could not be changed because their status does not allow it.', $fail, 'paygrab' ), $fail ) ) ); } } /** * Page callback. * * @return void */ public static function render() { if ( ! current_user_can( 'manage_options' ) ) { return; } // phpcs:ignore WordPress.Security.NonceVerification.Recommended $id = isset( $_GET['order'] ) ? absint( $_GET['order'] ) : 0; if ( $id ) { $order = Paygrab_Orders::get( $id ); if ( $order ) { self::render_order( $order ); return; } } self::render_list(); } /** * Days left until a deadline (negative when passed). * * @param string $gmt UTC datetime. * @return int */ private static function days_left( $gmt ) { $tz = wp_timezone(); $today = new DateTimeImmutable( 'today', $tz ); $deadline = ( new DateTimeImmutable( $gmt, new DateTimeZone( 'UTC' ) ) )->setTimezone( $tz )->setTime( 0, 0 ); return (int) $today->diff( $deadline )->format( '%r%a' ); } /** * Deadline text for the list ("Due 11/3 (7 days left)"). * * @param Paygrab_Order $order Order. * @return string HTML. */ private static function deadline_html( Paygrab_Order $order ) { if ( ! $order->pay_deadline ) { return ''; } $left = self::days_left( $order->pay_deadline ); if ( $left > 1 ) { /* translators: %d: days */ $when = sprintf( __( '%d days left', 'paygrab' ), $left ); $class = 'paygrab-due'; } elseif ( 1 === $left ) { $when = __( 'tomorrow', 'paygrab' ); $class = 'paygrab-due is-soon'; } elseif ( 0 === $left ) { $when = __( 'today', 'paygrab' ); $class = 'paygrab-due is-soon'; } else { $when = __( 'passed', 'paygrab' ); $class = 'paygrab-due is-soon'; } /* translators: 1: date, 2: e.g. "7 days left" */ return '' . esc_html( sprintf( __( 'Due %1$s (%2$s)', 'paygrab' ), paygrab_date( $order->pay_deadline, 'n/j' ), $when ) ) . ''; } /** * Status label for the admin. * * @param string $status Status. * @return string HTML. */ public static function badge( $status ) { return '' . esc_html( paygrab_status_label( $status ) ) . ''; } /** * Confirmation text for the "Confirm payment" button. * * @param Paygrab_Order $order Order. * @return string */ private static function confirm_paid_text( Paygrab_Order $order ) { if ( 'bank_manual' === $order->gateway ) { /* translators: 1: amount, 2: transfer number, 3: buyer name */ return sprintf( __( "Confirm the payment?\n\nAmount: %1\$s\nTransfer number: %2\$s\nCustomer: %3\$s\n\nThe customer can download the product right away.", 'paygrab' ), paygrab_price( $order->total ), $order->transfer_code, $order->billing_name ); } /* translators: 1: amount, 2: buyer name */ return sprintf( __( "Mark this order as paid?\n\nAmount: %1\$s\nCustomer: %2\$s", 'paygrab' ), paygrab_price( $order->total ), $order->billing_name ); } /** * Hidden fields of an action form. * * @param string $do Action. * @param int[] $ids Orders. * @param string $back Return URL. * @return void */ private static function form_fields( $do, array $ids, $back ) { echo ''; echo ''; echo ''; foreach ( $ids as $id ) { echo ''; } wp_nonce_field( 'paygrab_order_action' ); } /** * The order list. * * @return void */ private static function render_list() { // phpcs:disable WordPress.Security.NonceVerification.Recommended $status = isset( $_GET['status'] ) ? sanitize_key( wp_unslash( $_GET['status'] ) ) : ''; $search = isset( $_GET['s'] ) ? sanitize_text_field( wp_unslash( $_GET['s'] ) ) : ''; $paged = isset( $_GET['paged'] ) ? max( 1, absint( $_GET['paged'] ) ) : 1; $user = isset( $_GET['user'] ) ? absint( $_GET['user'] ) : 0; // phpcs:enable $per = 20; $result = Paygrab_Orders::query( array( 'status' => $status, 'search' => $search, 'paged' => $paged, 'per_page' => $per, 'user_id' => $user, ) ); $counts = Paygrab_Orders::count_by_status(); $back = self::url( array_filter( compact( 'status' ) + array( 's' => $search, 'paged' => $paged > 1 ? $paged : '' ) ) ); ?>


%d order is awaiting payment.', '%d orders are awaiting payment.', $counts['pending'], 'paygrab' ), $counts['pending'] ), array( 'strong' => array() ) ); echo ' '; esc_html_e( 'Match the 6-digit number in front of the transfer name in your bank book with the “Transfer no.” column, then press “Confirm payment”.', 'paygrab' ); ?>

$order->id ) ); ?>
order_number ); ?>status ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
billing_name ); ?>
billing_email ); ?>
summary() ); ?> total ) ); ?> is_pending() && 'bank_manual' === $order->gateway ? '' . esc_html( $order->transfer_code ) . '' : '—'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?> status ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?> created_at, 'Y/m/d' ) ); ?>
is_pending() ) { echo self::deadline_html( $order ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped } elseif ( $order->paid_at ) { /* translators: %s: date */ echo '' . esc_html( sprintf( __( 'Paid %s', 'paygrab' ), paygrab_date( $order->paid_at, 'n/j' ) ) ) . ''; } ?>
is_pending() && ! ( Paygrab_Gateways::get( $order->gateway ) && Paygrab_Gateways::get( $order->gateway )->confirms_payments() ) ) : ?>
is_pending() ) : ?>
id ), $back ); ?>
1 ) { echo '
'; echo paginate_links( // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped array( 'base' => add_query_arg( 'paged', '%#%', $back ), 'format' => '', 'current' => $paged, 'total' => $pages, ) ); echo '
'; } ?>
$order->id ) ); $downloads = Paygrab_Downloads::for_order( $order->id ); $user = get_userdata( $order->user_id ); $count = Paygrab_Orders::query( array( 'user_id' => $order->user_id, 'per_page' => 1 ) )['total']; ?>

order_number ) ); ?>

status ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?> ←

created_at, 'Y/m/d H:i' ) ); ?>
payment_label() ); ?>
pay_deadline && $order->is_pending() ) : ?>
pay_deadline, 'Y/m/d' ) ); ?>
paid_at ) : ?>
paid_at, 'Y/m/d H:i' ) ); ?>
cancelled_at ) : ?>
cancelled_at, 'Y/m/d H:i' ) ); ?>
refunded_at ) : ?>
refunded_at, 'Y/m/d H:i' ) ); ?>
gateway ) : ?>
transfer_code ); ?>
transfer_name_example() ); ?>
items() as $item ) : ?> discount ) : ?>
product_id ) ? '' . esc_html( $item->name ) . '' : esc_html( $item->name ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?> quantity ); ?> unit_price * $item->quantity ) ); ?>
-discount ) ); ?>
tax_breakdown() as $rate => $part ) { /* translators: 1: rate, 2: tax */ $parts[] = sprintf( __( 'tax %1$d%%: %2$s', 'paygrab' ), $rate, paygrab_price( $part['tax'] ) ); } echo esc_html( __( 'Total', 'paygrab' ) . paygrab_open() . implode( paygrab_comma(), $parts ) . paygrab_close() ); ?> total ) ); ?>

billing_name ); ?>ID ) ) . '">' . esc_html__( 'View user', 'paygrab' ) . '' . esc_html( paygrab_close() ) : ''; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
billing_email ); ?>

active ? '' : ' (' . esc_html__( 'stopped', 'paygrab' ) . ')'; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?> download_limit ? $row->download_count . ' / ∞' : $row->download_count . ' / ' . $row->download_limit ); ?> expires_at ? paygrab_date( $row->expires_at, 'Y/m/d' ) : __( 'No limit', 'paygrab' ) ); ?> last_downloaded_at ? paygrab_date( $row->last_downloaded_at, 'Y/m/d H:i' ) : '—' ); ?>

    id ) as $event ) : ?> type, '_' ) ) { continue; // Internal marks (e.g. "completion screen seen"), not history. } ?>
  1. created_at, 'Y/m/d H:i' ) ); ?> message ); ?> actor_id ? get_userdata( $event->actor_id ) : null; if ( $actor && (int) $event->actor_id !== $order->user_id ) { echo '' . esc_html( paygrab_open() . $actor->display_name . paygrab_close() ) . ''; } ?>

gateway ) && Paygrab_Gateways::get( $order->gateway )->confirms_payments(); ?> is_pending() ) : ?> gateway ) : ?>

%1$s with the number %2$s in your bank book.', 'paygrab' ), esc_html( paygrab_price( $order->total ) ), esc_html( $order->transfer_code ) ), array( 'strong' => array() ) ); ?>

id ), $back ); ?>

id ), $back ); ?>
is_paid() ) : ?>
id ), $back ); ?>

id ), $back ); ?>