1 <?php
2 3 4 5 6 7 8 9 10
11
12
13 if ( ! defined( 'ABSPATH' ) ) exit;
14
15
16 if ( ! class_exists( 'WP_List_Table' ) ) {
17 require_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php';
18 }
19
20 21 22 23 24 25 26
27 class EDD_Payment_History_Table extends WP_List_Table {
28 29 30 31 32 33
34 public $per_page = 30;
35
36 37 38 39 40 41
42 public $base_url;
43
44 45 46 47 48 49
50 public $total_count;
51
52 53 54 55 56 57
58 public $complete_count;
59
60 61 62 63 64 65
66 public $pending_count;
67
68 69 70 71 72 73
74 public $refunded_count;
75
76 77 78 79 80 81
82 public $failed_count;
83
84 85 86 87 88 89
90 public $revoked_count;
91
92 93 94 95 96 97 98 99 100
101 public function __construct() {
102 global $status, $page;
103
104
105 parent::__construct( array(
106 'singular' => edd_get_label_singular(),
107 'plural' => edd_get_label_plural(),
108 'ajax' => false
109 ) );
110
111 $this->get_payment_counts();
112
113 $this->base_url = admin_url( 'edit.php?post_type=download&page=edd-payment-history' );
114 }
115
116 117 118 119 120 121 122 123 124 125 126
127 public function search_box( $text, $input_id ) {
128 if ( empty( $_REQUEST['s'] ) && !$this->has_items() )
129 return;
130
131 $input_id = $input_id . '-search-input';
132
133 if ( ! empty( $_REQUEST['orderby'] ) )
134 echo '<input type="hidden" name="orderby" value="' . esc_attr( $_REQUEST['orderby'] ) . '" />';
135 if ( ! empty( $_REQUEST['order'] ) )
136 echo '<input type="hidden" name="order" value="' . esc_attr( $_REQUEST['order'] ) . '" />';
137 ?>
138 <p class="search-box">
139 <?php do_action( 'edd_payment_history_search' ); ?>
140 <label class="screen-reader-text" for="<?php echo $input_id ?>"><?php echo $text; ?>:</label>
141 <input type="search" id="<?php echo $input_id ?>" name="s" value="<?php _admin_search_query(); ?>" />
142 <?php submit_button( $text, 'button', false, false, array('ID' => 'search-submit') ); ?>
143 </p>
144 <?php
145 }
146
147 148 149 150 151 152 153
154 public function get_views() {
155 $base = $this->base_url;
156
157 $current = isset( $_GET['status'] ) ? $_GET['status'] : '';
158 $total_count = ' <span class="count">(' . $this->total_count . ')</span>';
159 $complete_count = ' <span class="count">(' . $this->complete_count . ')</span>';
160 $pending_count = ' <span class="count">(' . $this->pending_count . ')</span>';
161 $refunded_count = ' <span class="count">(' . $this->refunded_count . ')</span>';
162 $failed_count = ' <span class="count">(' . $this->failed_count . ')</span>';
163 $revoked_count = ' <span class="count">(' . $this->revoked_count . ')</span>';
164
165 $views = array(
166 'all' => sprintf( '<a href="%s"%s>%s</a>', remove_query_arg( 'status', $base ), $current === 'all' || $current == '' ? ' class="current"' : '', __('All', 'edd') . $total_count ),
167 'publish' => sprintf( '<a href="%s"%s>%s</a>', add_query_arg( 'status', 'publish', $base ), $current === 'publish' ? ' class="current"' : '', __('Completed', 'edd') . $complete_count ),
168 'pending' => sprintf( '<a href="%s"%s>%s</a>', add_query_arg( 'status', 'pending', $base ), $current === 'pending' ? ' class="current"' : '', __('Pending', 'edd') . $pending_count ),
169 'refunded' => sprintf( '<a href="%s"%s>%s</a>', add_query_arg( 'status', 'refunded', $base ), $current === 'refunded' ? ' class="current"' : '', __('Refunded', 'edd') . $refunded_count ),
170 'revoked' => sprintf( '<a href="%s"%s>%s</a>', add_query_arg( 'status', 'revoked', $base ), $current === 'revoked' ? ' class="current"' : '', __('Revoked', 'edd') . $revoked_count ),
171 'failed' => sprintf( '<a href="%s"%s>%s</a>', add_query_arg( 'status', 'failed', $base ), $current === 'failed' ? ' class="current"' : '', __('Failed', 'edd') . $failed_count )
172 );
173
174 return apply_filters( 'edd_payments_table_views', $views );
175 }
176
177 178 179 180 181 182 183
184 public function get_columns() {
185 $columns = array(
186 'cb' => '<input type="checkbox" />',
187 'ID' => __( 'ID', 'edd' ),
188 'email' => __( 'Email', 'edd' ),
189 'details' => __( 'Details', 'edd' ),
190 'amount' => __( 'Amount', 'edd' ),
191 'date' => __( 'Date', 'edd' ),
192 'user' => __( 'User', 'edd' ),
193 'status' => __( 'Status', 'edd' )
194 );
195
196 return apply_filters( 'edd_payments_table_columns', $columns );
197 }
198
199 200 201 202 203 204 205
206 public function get_sortable_columns() {
207 $columns = array(
208 'ID' => array( 'ID', true ),
209 'amount' => array( 'amount', false ),
210 'date' => array( 'date', false )
211 );
212 return apply_filters( 'edd_payments_table_sortable_columns', $columns );
213 }
214
215 216 217 218 219 220 221 222 223 224 225
226 public function column_default( $item, $column_name ) {
227 switch ( $column_name ) {
228 case 'amount' :
229 $value = edd_currency_filter( edd_format_amount( $item[ $column_name ] ) );
230 break;
231 case 'date' :
232 $date = strtotime( $item[ $column_name ] );
233 $value = date_i18n( get_option( 'date_format' ), $date );
234 break;
235 case 'status' :
236 $payment = get_post( $item['ID'] );
237 $value = edd_get_payment_status( $payment, true );
238 break;
239 default:
240 $value = isset( $item[ $column_name ] ) ? $item[ $column_name ] : '';
241 break;
242
243 }
244 return apply_filters( 'edd_payments_table_column', $value, $item['ID'], $column_name );
245 }
246
247 248 249 250 251 252 253 254
255 public function column_email( $item ) {
256 $payment = get_post( $item['ID'] );
257
258 $row_actions = array();
259
260 $row_actions['edit'] = '<a href="' . add_query_arg( array( 'edd-action' => 'edit-payment', 'purchase_id' => $payment->ID ), $this->base_url ) . '">' . __( 'Edit', 'edd' ) . '</a>';
261
262 if ( edd_is_payment_complete( $payment->ID ) )
263 $row_actions['email_links'] = '<a href="' . add_query_arg( array( 'edd-action' => 'email_links', 'purchase_id' => $payment->ID ), $this->base_url ) . '">' . __( 'Resend Purchase Receipt', 'edd' ) . '</a>';
264
265 $row_actions['delete'] = '<a href="' . wp_nonce_url( add_query_arg( array( 'edd-action' => 'delete_payment', 'purchase_id' => $payment->ID ), $this->base_url ), 'edd_payment_nonce') . '">' . __( 'Delete', 'edd' ) . '</a>';
266
267 $row_actions = apply_filters( 'edd_payment_row_actions', $row_actions, $payment );
268
269 $value = $item['email'] . $this->row_actions( $row_actions );
270
271 return apply_filters( 'edd_payments_table_column', $value, $item['ID'], 'email' );
272 }
273
274 275 276 277 278 279 280 281
282 public function column_cb( $item ) {
283 return sprintf(
284 '<input type="checkbox" name="%1$s[]" value="%2$s" />',
285 $this->_args['singular'],
286 $item['ID']
287 );
288 }
289
290 291 292 293 294 295 296 297
298 public function column_details( $item ) {
299 $details = "<a href='#TB_inline?width=640&inlineId=purchased-files-" . $item['ID'] . "' class='thickbox' title='" . sprintf( __( 'Purchase Details for Payment #%s', 'edd' ), $item['ID'] ) . "'>" . __( 'View Order Details', 'edd' ) . "</a>";
300
301 ob_start();
302 ?>
303 <div id="purchased-files-<?php echo $item['ID']; ?>" style="display: none;">
304 <?php
305 $payment_meta = edd_get_payment_meta( $item['ID'] );
306 $cart_items = isset( $payment_meta['cart_details'] ) ? maybe_unserialize( $payment_meta['cart_details'] ) : false;
307 if ( empty( $cart_items ) || ! $cart_items ) {
308 $cart_items = maybe_unserialize( $payment_meta['downloads'] );
309 }
310 ?>
311 <h4><?php echo _n( __( 'Purchased File', 'edd' ), __( 'Purchased Files', 'edd' ), count( $cart_items ) ); ?></h4>
312 <ul class="purchased-files-list">
313 <?php
314 if ( $cart_items ) {
315 foreach ( $cart_items as $key => $cart_item ) {
316 echo '<li>';
317
318 $id = isset( $payment_meta['cart_details'] ) ? $cart_item['id'] : $cart_item;
319
320
321 $price_override = isset( $payment_meta['cart_details'] ) ? $cart_item['price'] : null;
322
323
324 $user_info = edd_get_payment_meta_user_info( $item['ID'] );
325
326
327 $price = edd_get_download_final_price( $id, $user_info, $price_override );
328
329
330 echo '<a href="' . admin_url( 'post.php?post=' . $id . '&action=edit' ) . '" target="_blank">' . get_the_title( $id ) . '</a>';
331
332 echo ' - ';
333
334 if ( isset( $cart_items[ $key ]['item_number'])) {
335 $price_options = $cart_items[ $key ]['item_number']['options'];
336
337 if ( isset( $price_options['price_id'] ) ) {
338 echo edd_get_price_option_name( $id, $price_options['price_id'], $item['ID'] );
339 echo ' - ';
340 }
341 }
342
343 echo edd_currency_filter( edd_format_amount( $price ) );
344 echo '</li>';
345 }
346 }
347 ?>
348 </ul>
349 <?php $payment_date = strtotime( $item['date'] ); ?>
350 <p><?php echo __( 'Date and Time:', 'edd' ) . ' ' . date_i18n( get_option( 'date_format' ), $payment_date ) . ' ' . date_i18n( get_option( 'time_format' ), $payment_date ) ?>
351 <p><?php echo __( 'Discount used:', 'edd' ) . ' '; if ( isset( $user_info['discount'] ) && $user_info['discount'] != 'none' ) { echo $user_info['discount']; } else { _e( 'none', 'edd' ); } ?>
352 <?php
353 $fees = edd_get_payment_fees( $item['ID'] );
354 if( ! empty( $fees ) ) : ?>
355 <ul class="payment-fees">
356 <?php foreach( $fees as $fee ) : ?>
357 <li><?php echo $fee['label'] . ': ' . edd_currency_filter( $fee['amount'] ); ?></li>
358 <?php endforeach; ?>
359 </ul>
360 <?php endif; ?>
361 <p><?php echo __( 'Total:', 'edd' ) . ' ' . edd_currency_filter( edd_format_amount( edd_get_payment_amount( $item['ID'] ) ) ); ?></p>
362
363 <div class="purchase-personal-details">
364 <h4><?php _e( 'Buyer\'s Personal Details:', 'edd' ); ?></h4>
365 <ul>
366 <li><?php echo __( 'Name:', 'edd' ) . ' ' . $user_info['first_name'] . ' ' . $user_info['last_name']; ?></li>
367 <li><?php echo __( 'Email:', 'edd' ) . ' ' . $payment_meta['email']; ?></li>
368 <?php do_action( 'edd_payment_personal_details_list', $payment_meta, $user_info ); ?>
369 </ul>
370 </div>
371 <div class="payment-notes">
372 <h4><?php _e( 'Payment Notes', 'edd' ); ?></h4>
373 <?php
374 $notes = edd_get_payment_notes( $item['ID'] );
375 if ( ! empty( $notes ) ) :
376 echo '<ul id="payment-notes">';
377 foreach ( $notes as $note ):
378 if ( ! empty( $note->user_id ) ) {
379 $user = get_userdata( $note->user_id );
380 $user = $user->display_name;
381 } else {
382 $user = __( 'EDD Bot', 'edd' );
383 }
384 echo '<div class="edd-payment-note"><strong>' . $user . '</strong> <em>' . $note->comment_date . '</em> —' . $note->comment_content . '</div>';
385 endforeach;
386 echo '</ul>';
387 else :
388 echo '<p>' . __( 'No payment notes', 'edd' ) . '</p>';
389 endif;
390 ?>
391 </div>
392 <?php
393 $gateway = edd_get_payment_gateway( $item['ID'] );
394 if ( $gateway ) { ?>
395 <div class="payment-method">
396 <h4><?php _e('Payment Method:', 'edd'); ?></h4>
397 <span class="payment-method-name"><?php echo edd_get_gateway_admin_label( $gateway ); ?></span>
398 </div>
399 <?php } ?>
400 <div class="purchase-key-wrap">
401 <h4><?php _e('Purchase Key', 'edd'); ?></h4>
402 <span class="purchase-key"><?php echo $payment_meta['key']; ?></span>
403 </div>
404
405 <?php do_action( 'edd_payment_view_details', $item['ID'] ); ?>
406
407 <p><a id="edd-close-purchase-details" class="button-secondary" onclick="tb_remove();" title="<?php _e( 'Close', 'edd' ); ?>"><?php _e( 'Close', 'edd' ); ?></a></p>
408
409
410 </div>
411 <?php
412 $details .= ob_get_clean();
413 return $details;
414 }
415
416 417 418 419 420 421 422 423
424 public function column_user( $item ) {
425 $user_info = edd_get_payment_meta_user_info( $item['ID'] );
426 $user_id = isset( $user_info['id'] ) && $user_info['id'] != -1 ? $user_info['id'] : $user_info['email'];
427
428 if ( is_numeric( $user_id ) ) {
429 $user = get_userdata( $user_id ) ;
430 $display_name = is_object( $user ) ? $user->display_name : __( 'guest', 'edd' );
431 } else {
432 $display_name = __( 'guest', 'edd' );
433 }
434
435 $value = '<a href="' . remove_query_arg( 'paged', add_query_arg( 'user', $user_id ) ) . '">' . $display_name . '</a>';
436 return apply_filters( 'edd_payments_table_column', $value, $item['ID'], 'user' );
437 }
438
439 440 441 442 443 444 445
446 public function get_bulk_actions() {
447 $actions = array(
448 'delete' => __( 'Delete', 'edd' )
449 );
450
451 return apply_filters( 'edd_payments_table_bulk_actions', $actions );
452 }
453
454 455 456 457 458 459 460
461 public function process_bulk_action() {
462 $ids = isset( $_GET['download'] ) ? $_GET['download'] : false;
463
464 if ( ! is_array( $ids ) )
465 $ids = array( $ids );
466
467 foreach ( $ids as $id ) {
468
469 if ( 'delete' === $this->current_action() ) {
470 edd_delete_purchase( $id );
471 }
472 do_action( 'edd_payments_table_do_bulk_action', $id, $this->current_action() );
473 }
474 }
475
476 477 478 479 480 481 482
483 public function get_payment_counts() {
484 $payment_count = wp_count_posts( 'edd_payment' );
485
486 $this->complete_count = $payment_count->publish;
487 $this->pending_count = $payment_count->pending;
488 $this->refunded_count = $payment_count->refunded;
489 $this->failed_count = $payment_count->failed;
490 $this->revoked_count = $payment_count->revoked;
491 $this->total_count = $payment_count->publish + $payment_count->pending + $payment_count->refunded + $payment_count->failed + $payment_count->trash;
492 }
493
494 495 496 497 498 499 500
501 public function payments_data() {
502 $payments_data = array();
503
504 if ( isset( $_GET['paged'] ) ) $page = $_GET['paged']; else $page = 1;
505
506 $per_page = $this->per_page;
507 $mode = edd_is_test_mode() ? 'test' : 'live';
508 $orderby = isset( $_GET['orderby'] ) ? $_GET['orderby'] : 'ID';
509 $order = isset( $_GET['order'] ) ? $_GET['order'] : 'DESC';
510 $order_inverse = $order == 'DESC' ? 'ASC' : 'DESC';
511 $order_class = strtolower( $order_inverse );
512 $user = isset( $_GET['user'] ) ? $_GET['user'] : null;
513 $status = isset( $_GET['status'] ) ? $_GET['status'] : 'any';
514 $meta_key = isset( $_GET['meta_key'] ) ? $_GET['meta_key'] : null;
515 $year = isset( $_GET['year'] ) ? $_GET['year'] : null;
516 $month = isset( $_GET['m'] ) ? $_GET['m'] : null;
517 $day = isset( $_GET['day'] ) ? $_GET['day'] : null;
518 $search = isset( $_GET['s'] ) ? sanitize_text_field( $_GET['s'] ) : null;
519
520 $payments = edd_get_payments( array(
521 'number' => $per_page,
522 'page' => isset( $_GET['paged'] ) ? $_GET['paged'] : null,
523 'mode' => $mode,
524 'orderby' => $orderby,
525 'order' => $order,
526 'user' => $user,
527 'status' => $status,
528 'meta_key' => $meta_key,
529 'year' => $year,
530 'month' => $month,
531 'day' => $day,
532 's' => $search
533 ) );
534
535 if ( $payments ) {
536 foreach ( $payments as $payment ) {
537 $user_info = edd_get_payment_meta_user_info( $payment->ID );
538 $cart_details = edd_get_payment_meta_cart_details( $payment->ID );
539
540 $user_id = isset( $user_info['ID'] ) && $user_info['ID'] != -1 ? $user_info['ID'] : $user_info['email'];
541
542 $payments_data[] = array(
543 'ID' => $payment->ID,
544 'email' => edd_get_payment_user_email( $payment->ID ),
545 'products' => $cart_details,
546 'amount' => edd_get_payment_amount( $payment->ID ),
547 'date' => $payment->post_date,
548 'user' => $user_id,
549 'status' => $payment->post_status
550 );
551 }
552 }
553 return $payments_data;
554 }
555
556 557 558 559 560 561 562 563 564 565 566 567 568
569 public function prepare_items() {
570 $per_page = $this->per_page;
571
572 $columns = $this->get_columns();
573
574 $hidden = array();
575
576 $sortable = $this->get_sortable_columns();
577
578 $this->_column_headers = array( $columns, $hidden, $sortable );
579
580 $this->process_bulk_action();
581
582 $data = $this->payments_data();
583
584 $current_page = $this->get_pagenum();
585
586 $status = isset( $_GET['status'] ) ? $_GET['status'] : 'any';
587
588 switch ( $status ) {
589 case 'publish':
590 $total_items = $this->complete_count;
591 break;
592 case 'pending':
593 $total_items = $this->pending_count;
594 break;
595 case 'refunded':
596 $total_items = $this->refunded_count;
597 break;
598 case 'failed':
599 $total_items = $this->failed_count;
600 break;
601 case 'revoked':
602 $total_items = $this->revoked_count;
603 break;
604 case 'any':
605 $total_items = $this->total_count;
606 break;
607 default:
608
609 $count = wp_count_posts( 'edd_payment' );
610 $total_items = $count->{$status};
611 }
612
613 $this->items = $data;
614
615 $this->set_pagination_args( array(
616 'total_items' => $total_items,
617 'per_page' => $per_page,
618 'total_pages' => ceil( $total_items / $per_page )
619 )
620 );
621 }
622 }