MS_Helper_ListTable_TransactionLog

List of transaction protocol entries.

Defined (1)

The class is defined in the following location(s).

/app/helper/listtable/class-ms-helper-listtable-transactionlog.php  
  1. class MS_Helper_ListTable_TransactionLog extends MS_Helper_ListTable { 
  2.  
  3. /** 
  4. * This ID is used as class-name for the list output and also in various 
  5. * filter names in MS_Helper_ListTable. 
  6. * @var string 
  7. */ 
  8. protected $id = 'transactionlog'; 
  9.  
  10. /** 
  11. * Constructor, defines general list table attributes. 
  12. * @since 1.0.0 
  13. */ 
  14. public function __construct() { 
  15. // 'singular' just added for fun... 
  16. // 'plural' is used as class name for the list. 
  17. parent::__construct( 
  18. array( 
  19. 'singular' => 'transaction',  
  20. 'plural' => 'transactions',  
  21. ); 
  22.  
  23. /** 
  24. * Defines the columns of the list table 
  25. * @since 1.0.0 
  26. * @return array 
  27. */ 
  28. public function get_columns() { 
  29. $currency = MS_Plugin::instance()->settings->currency; 
  30.  
  31. $columns = apply_filters( 
  32. 'ms_helper_listtable_transactionlog_columns',  
  33. array( 
  34. 'id' => __( 'ID', 'membership2' ),  
  35. 'date' => __( 'Time', 'membership2' ),  
  36. 'status' => '',  
  37. 'method' => '',  
  38. 'gateway' => __( 'Gateway', 'membership2' ),  
  39. 'amount' => __( 'Amount', 'membership2' ),  
  40. 'invoice' => __( 'Invoice', 'membership2' ),  
  41. 'note' => __( 'Details', 'membership2' ),  
  42. ); 
  43.  
  44. $columns = apply_filters( 
  45. 'ms_helper_listtable_transactionlog_get_columns',  
  46. $columns,  
  47. $currency 
  48. ); 
  49.  
  50. return $columns; 
  51.  
  52. /** 
  53. * Defines, which columns should be output as hidden columns. 
  54. * @since 1.0.0 
  55. * @return array 
  56. */ 
  57. public function get_hidden_columns() { 
  58. return apply_filters( 
  59. 'ms_helper_listtable_transactionlog_hidden_columns',  
  60. array() 
  61. ); 
  62.  
  63. /** 
  64. * Defines, which columns can be sorted. 
  65. * @since 1.0.0 
  66. * @return array 
  67. */ 
  68. public function get_sortable_columns() { 
  69. return apply_filters( 
  70. 'ms_helper_listtable_transactionlog_sortable_columns',  
  71. array() 
  72. ); 
  73.  
  74. /** 
  75. * Defines available bulk actions. 
  76. * @since 1.0.0 
  77. * @return array 
  78. */ 
  79. public function get_bulk_actions() { 
  80. return apply_filters( 
  81. 'ms_helper_listtable_transactionlog_bulk_actions',  
  82. array() 
  83. ); 
  84.  
  85. /** 
  86. * Loads the items that are displayed on the current list page. 
  87. * @since 1.0.0 
  88. */ 
  89. public function prepare_items() { 
  90. $this->_column_headers = array( 
  91. $this->get_columns(),  
  92. $this->get_hidden_columns(),  
  93. $this->get_sortable_columns(),  
  94. ); 
  95.  
  96. $per_page = $this->get_items_per_page( 
  97. 'transactionlog_per_page',  
  98. 50 
  99. ); 
  100.  
  101. $current_page = $this->get_pagenum(); 
  102.  
  103. $args = array( 
  104. 'posts_per_page' => $per_page,  
  105. 'offset' => ( $current_page - 1 ) * $per_page,  
  106. 'meta_query' => array(),  
  107. ); 
  108.  
  109. if ( ! empty( $_GET['state'] ) ) { 
  110. $args['state'] = $_GET['state']; 
  111.  
  112. if ( ! empty( $_GET['id'] ) ) { 
  113. $args['post__in'] = explode( ', ', $_GET['id'] ); 
  114.  
  115. if ( ! empty( $_GET['invoice'] ) ) { 
  116. $args['meta_query']['invoice_id'] = array( 
  117. 'key' => 'invoice_id',  
  118. 'value' => explode( ', ', $_GET['invoice'] ),  
  119. 'compare' => 'IN',  
  120. ); 
  121.  
  122. if ( ! empty( $_GET['gateway_id'] ) ) { 
  123. $args['meta_query']['gateway_id'] = array( 
  124. 'key' => 'gateway_id',  
  125. 'value' => $_GET['gateway_id'],  
  126. ); 
  127.  
  128. $total_items = MS_Model_Transactionlog::get_item_count( $args ); 
  129.  
  130. $this->items = apply_filters( 
  131. 'ms_helper_listtable_transactionlog_items',  
  132. MS_Model_Transactionlog::get_items( $args ) 
  133. ); 
  134.  
  135. $this->set_pagination_args( 
  136. array( 
  137. 'total_items' => $total_items,  
  138. 'per_page' => $per_page,  
  139. ); 
  140.  
  141. /** 
  142. * Displays a custom search box for this list. 
  143. * @since 1.0.0 
  144. */ 
  145. public function search_box( $text = null, $input_id = 'search' ) { 
  146. // Do not display anything. 
  147. // Transaction logs cannot be searched currently 
  148.  
  149. /** 
  150. * Defines predefines filters for this list table. 
  151. * @since 1.0.0 
  152. * @return array 
  153. */ 
  154. public function get_views() { 
  155. $views = array(); 
  156. $base_url = remove_query_arg( array( 'state', 'id', 'invoice' ) ); 
  157.  
  158. $views['all'] = array( 
  159. 'label' => __( 'All', 'membership2' ),  
  160. 'url' => $base_url,  
  161. 'count' => MS_Model_Transactionlog::get_item_count(),  
  162. ); 
  163.  
  164. $views['ok'] = array( 
  165. 'label' => __( 'Successful', 'membership2' ),  
  166. 'url' => add_query_arg( 'state', 'ok', $base_url ),  
  167. 'count' => MS_Model_Transactionlog::get_item_count( 
  168. array( 'state' => 'ok' ) 
  169. ),  
  170. ); 
  171.  
  172. $views['err'] = array( 
  173. 'label' => __( 'Failed', 'membership2' ),  
  174. 'url' => add_query_arg( 'state', 'err', $base_url ),  
  175. 'count' => MS_Model_Transactionlog::get_item_count( 
  176. array( 'state' => 'err' ) 
  177. ),  
  178. ); 
  179.  
  180. $views['ignore'] = array( 
  181. 'label' => __( 'Ignored', 'membership2' ),  
  182. 'url' => add_query_arg( 'state', 'ignore', $base_url ),  
  183. 'count' => MS_Model_Transactionlog::get_item_count( 
  184. array( 'state' => 'ignore' ) 
  185. ),  
  186. ); 
  187.  
  188. return apply_filters( 
  189. 'ms_helper_listtable_transactionlog_views',  
  190. $views 
  191. ); 
  192.  
  193. /** 
  194. * Returns the row-class to be used for the specified table item. 
  195. * @param object $item The current item. 
  196. * @return string Class to be added to the table row. 
  197. */ 
  198. protected function single_row_class( $item ) { 
  199. $class = 'log-' . $item->state; 
  200.  
  201. if ( $item->is_manual ) { 
  202. $class .= ' is-manual'; 
  203.  
  204. return $class; 
  205.  
  206. /** 
  207. * Output column content 
  208. * @since 1.0.0 
  209. * @param object $item The item that is displayed. 
  210. * @return string The HTML code to output. 
  211. */ 
  212. public function column_id( $item, $column_name ) { 
  213. $html = $item->id; 
  214. return $html; 
  215.  
  216. /** 
  217. * Output column content 
  218. * @since 1.0.0 
  219. * @param object $item The item that is displayed. 
  220. * @return string The HTML code to output. 
  221. */ 
  222. public function column_date( $item, $column_name ) { 
  223. $html = MS_Helper_Period::format_date( $item->date, 'Y-m-d H:i' ); 
  224.  
  225. return $html; 
  226.  
  227. /** 
  228. * Output column content 
  229. * @since 1.0.0 
  230. * @param object $item The item that is displayed. 
  231. * @return string The HTML code to output. 
  232. */ 
  233. public function column_status( $item, $column_name ) { 
  234. $html = '<span class="log-status"><i class="wpmui-fa log-status-icon"></i></span>'; 
  235.  
  236. return $html; 
  237.  
  238. /** 
  239. * Output column content 
  240. * @since 1.0.0 
  241. * @param object $item The item that is displayed. 
  242. * @return string The HTML code to output. 
  243. */ 
  244. public function column_method( $item, $column_name ) { 
  245. $html = '<span class="log-method" data-info="%2$s"><i class="wpmui-fa wpmui-%1$s"></i></span>'; 
  246. $icon = ''; 
  247. $info = __( 'Unknown method', 'membership2' ); 
  248.  
  249. switch ( $item->method ) { 
  250. case 'handle': 
  251. $icon = 'fa-cloud-download'; 
  252. $info = __( 'Gateway called the IPN URL', 'membership2' ); 
  253. break; 
  254.  
  255. case 'request': 
  256. $icon = 'fa-refresh'; 
  257. $info = __( 'Plugin requested a recuring payment', 'membership2' ); 
  258. break; 
  259.  
  260. case 'process': 
  261. $icon = 'fa-shopping-cart'; 
  262. $info = __( 'User entered payment details', 'membership2' ); 
  263. break; 
  264.  
  265. $html = sprintf( $html, $icon, $info ); 
  266.  
  267. return $html; 
  268.  
  269. /** 
  270. * Output column content 
  271. * @since 1.0.0 
  272. * @param object $item The item that is displayed. 
  273. * @return string The HTML code to output. 
  274. */ 
  275. public function column_gateway( $item, $column_name ) { 
  276. $html = MS_Model_Gateway::get_name( $item->gateway_id, true ); 
  277. return $html; 
  278.  
  279. /** 
  280. * Output column content 
  281. * @since 1.0.0 
  282. * @param object $item The item that is displayed. 
  283. * @return string The HTML code to output. 
  284. */ 
  285. public function column_amount( $item, $column_name ) { 
  286. $html = MS_Helper_Billing::format_price( $item->amount ); 
  287.  
  288. return $html; 
  289.  
  290. /** 
  291. * Output column content 
  292. * @since 1.0.0 
  293. * @param object $item The item that is displayed. 
  294. * @return string The HTML code to output. 
  295. */ 
  296. public function column_invoice( $item, $column_name ) { 
  297. if ( $item->invoice_id ) { 
  298. $invoice_url = MS_Controller_Plugin::get_admin_url( 
  299. 'billing',  
  300. array( 'action' => 'edit', 'invoice_id' => $item->invoice_id ) 
  301. ); 
  302.  
  303. $html = sprintf( 
  304. '<a href="%1$s">%2$s</a>',  
  305. $invoice_url,  
  306. $item->invoice_id 
  307. ); 
  308. } else { 
  309. $html = '-'; 
  310.  
  311. return $html; 
  312.  
  313. /** 
  314. * Output column content 
  315. * @since 1.0.0 
  316. * @param object $item The item that is displayed. 
  317. * @return string The HTML code to output. 
  318. */ 
  319. public function column_note( $item, $column_name ) { 
  320. $extra_infos = ''; 
  321. $row_actions = ''; 
  322. $nonce_action = ''; 
  323. $detail_lines = array(); 
  324. $actions = array(); 
  325. $ind = 0; 
  326.  
  327. // 1. Prepare the "Additional Details" popup. 
  328. $detail_lines = self::get_details( $item ); 
  329.  
  330. if ( count( $detail_lines ) ) { 
  331. $icon_class = ''; 
  332. $post_data = $item->post; 
  333. if ( ! $post_data ) { 
  334. $icon_class = 'no-post'; 
  335.  
  336. $extra_infos = sprintf( 
  337. '<div class="more-details %3$s">%2$s<div class="post-data"><div class="inner">%1$s</div></div></div>',  
  338. implode( '<br>', $detail_lines ),  
  339. '<i class="wpmui-fa wpmui-fa-info-circle"></i>',  
  340. $icon_class 
  341. ); 
  342.  
  343. // 2. Prepare the row actions. 
  344. if ( 'err' == $item->state ) { 
  345. $actions = array( 
  346. 'action-link' => __( 'Link', 'membership2' ),  
  347. 'action-ignore' => __( 'Ignore', 'membership2' ),  
  348. ); 
  349.  
  350. // We can only re-process the transaction if we have POST data. 
  351. $postdata = $item->post; 
  352. if ( is_array( $postdata ) && ! empty( $postdata ) ) { 
  353. $actions['action-retry'] = __( 'Retry', 'membership2' ); 
  354. } elseif ( 'ignore' == $item->state && $item->is_manual ) { 
  355. $actions = array( 
  356. 'action-clear' => __( 'Reset', 'membership2' ),  
  357. ); 
  358. $nonce_action = MS_Controller_Billing::AJAX_ACTION_TRANSACTION_LINK; 
  359.  
  360. if ( count( $actions ) ) { 
  361. $nonces = array(); 
  362. $nonces[] = wp_nonce_field( 
  363. MS_Controller_Billing::AJAX_ACTION_TRANSACTION_UPDATE,  
  364. 'nonce_update',  
  365. false,  
  366. false 
  367. ); 
  368. $nonces[] = wp_nonce_field( 
  369. MS_Controller_Billing::AJAX_ACTION_TRANSACTION_LINK,  
  370. 'nonce_link',  
  371. false,  
  372. false 
  373. ); 
  374. $nonces[] = wp_nonce_field( 
  375. MS_Controller_Import::AJAX_ACTION_RETRY,  
  376. 'nonce_retry',  
  377. false,  
  378. false 
  379. ); 
  380. $action_tags = array(); 
  381. foreach ( $actions as $class => $label ) { 
  382. $action_tags[] = sprintf( 
  383. '<a href="#" class="%s">%s</a>',  
  384. $class,  
  385. $label 
  386. ); 
  387.  
  388. $row_actions = sprintf( 
  389. '<div class="actions %1$s-actions">%2$s %3$s</div>',  
  390. $item->state,  
  391. implode( '', $nonces ),  
  392. implode( ' | ', $action_tags ) 
  393. ); 
  394.  
  395. // 3. Combine the prepared parts. 
  396. $html = sprintf( 
  397. '<div class="detail-block">%s <span class="txt">%s</span> %s</div>',  
  398. $extra_infos,  
  399. $item->description,  
  400. $row_actions 
  401. ); 
  402.  
  403. return $html; 
  404.  
  405. /** 
  406. * Returns an array with additional details about the transaction. 
  407. * This function is used in the note-column and is shared in the objects for 
  408. * TransactionLog and TransactionMatching. 
  409. * @since 1.0.1.2 
  410. * @param MS_Model_Transaction $item Transaction object. 
  411. * @return array The transaction details. 
  412. */ 
  413. static public function get_details( $item ) { 
  414. $detail_lines = array(); 
  415.  
  416. if ( $item->is_manual ) { 
  417. $detail_lines[] = __( 'Transaction state manually changed', 'membership2' ); 
  418. $detail_lines[] = sprintf( 
  419. __( 'Modified on: %s', 'membership2' ),  
  420. $item->manual_date 
  421. ); 
  422. $detail_lines[] = sprintf( 
  423. __( 'Modified by: %s', 'membership2' ),  
  424. $item->get_manual_user()->display_name 
  425. ); 
  426.  
  427. $postdata = $item->post; 
  428. $group = array(); 
  429. if ( ! empty( $postdata ) && is_array( $postdata ) ) { 
  430. $id_fields = array(); 
  431. switch ( $item->gateway_id ) { 
  432. case MS_Gateway_Paypalstandard::ID: 
  433. if ( isset( $postdata['invoice'] ) ) { 
  434. $id_fields[] = 'invoice'; 
  435. } elseif ( isset( $postdata['custom'] ) ) { 
  436. $id_fields[] = 'custom'; 
  437. $detail_lines[] = __( 'Imported subscription from old Membership plugin.', 'membership2' ); 
  438. } elseif ( isset( $postdata['btn_id'] ) ) { 
  439. $id_fields[] = 'btn_id'; 
  440. $id_fields[] = 'payer_email'; 
  441. $detail_lines[] = __( 'Payment via a PayPal Payment button.', 'membership2' ); 
  442. } elseif ( isset( $postdata['txn_type'] ) ) { 
  443. // Highlight invalid transactions. 
  444. if ( 'send_money' == $postdata['txn_type'] ) { 
  445. $id_fields[] = 'txn_type'; 
  446. $detail_lines[] = __( 'Someone sent you money inside PayPal or PayPal re-sent a previous payment.<br>Plugin did not attempt to match payment to a subscription.', 'membership2' ); 
  447. break; 
  448.  
  449. if ( count( $detail_lines ) ) { 
  450. $detail_lines[] = '<hr />'; 
  451. ksort( $postdata ); 
  452. $ind = 0; 
  453. foreach ( $postdata as $key => $value ) { 
  454. if ( strpos( $key, ':' ) > 0 ) { 
  455. $parts = explode( ':', $key ); 
  456. if ( ! isset( $groups[ $parts[0] ] ) ) { 
  457. $groups[ $parts[0] ] = array(); 
  458. $groups[ $parts[0] ][ $parts[1] ] = $value; 
  459. continue; 
  460.  
  461. if ( 0 === $ind ) { 
  462. $detail_lines[] = __( 'POST data:', 'membership2' ); 
  463.  
  464. $ind += 1; 
  465.  
  466. $line_class = ''; 
  467. if ( in_array( $key, $id_fields ) ) { 
  468. $line_class = 'is-id'; 
  469.  
  470. $detail_lines[] = sprintf( 
  471. '<span class="line %s"><small class="line-num">%s</small> <span class="line-key">%s</span> <span class="line-val">%s</span></span>',  
  472. $line_class,  
  473. $ind,  
  474. $key,  
  475. htmlspecialchars( $value ) 
  476. ); 
  477.  
  478. foreach ( $groups as $group => $values ) { 
  479. $ind = 0; 
  480. foreach ( $values as $key => $value ) { 
  481. if ( 0 === $ind ) { 
  482. $detail_lines[] = '<hr />'; 
  483. $detail_lines[] = $group . ':'; 
  484.  
  485. $ind += 1; 
  486.  
  487. $detail_lines[] = sprintf( 
  488. '<span class="line"><small class="line-num">%s</small> <span class="line-key">%s</span> <span class="line-val">%s</span></span>',  
  489. $ind,  
  490. $key,  
  491. htmlspecialchars( $value ) 
  492. ); 
  493.  
  494. $headers = $item->headers; 
  495. $cookies = false; 
  496. if ( ! empty( $headers ) && is_array( $headers ) ) { 
  497. if ( count( $detail_lines ) ) { 
  498. $detail_lines[] = '<hr />'; 
  499. ksort( $headers ); 
  500. $ind = 0; 
  501. $detail_lines[] = __( 'HTTP Headers:', 'membership2' ); 
  502. foreach ( $headers as $key => $value ) { 
  503. if ( 'Cookie' == $key ) { 
  504. $cookies = explode( ';', $value ); 
  505. continue; 
  506. $ind += 1; 
  507.  
  508. $detail_lines[] = sprintf( 
  509. '<span class="line"><small class="line-num">%s</small> <span class="line-key">%s</span> <span class="line-val">%s</span></span>',  
  510. $ind,  
  511. $key,  
  512. htmlspecialchars( $value ) 
  513. ); 
  514.  
  515. if ( ! empty( $cookies ) && is_array( $cookies ) ) { 
  516. if ( count( $detail_lines ) ) { 
  517. $detail_lines[] = '<hr />'; 
  518. ksort( $cookies ); 
  519. $ind = 0; 
  520. $detail_lines[] = __( 'Cookies:', 'membership2' ); 
  521. foreach ( $cookies as $key => $value ) { 
  522. $ind += 1; 
  523. $parts = explode( '=', $value ); 
  524. if ( count( $parts ) < 2 ) { continue; } 
  525.  
  526. $detail_lines[] = sprintf( 
  527. '<span class="line"><small class="line-num">%s</small> <span class="line-key">%s</span> <span class="line-val">%s</span></span>',  
  528. $ind,  
  529. array_shift( $parts ),  
  530. htmlspecialchars( implode( '=', $parts ) ) 
  531. ); 
  532.  
  533. if ( count( $detail_lines ) ) { 
  534. $detail_lines[] = '<hr />'; 
  535.  
  536. $detail_lines[] = __( 'Logged in user:', 'membership2' ); 
  537. $user_id = $item->user_id; 
  538. if ( $user_id ) { 
  539. $user = get_user_by( 'id', $user_id ); 
  540. $detail_lines[] = sprintf( 
  541. '<span class="line"><small class="line-num">%s</small><span class="line-key">%s</span> <span class="line-val">%s</span></span>',  
  542. 1,  
  543. __( 'User ID', 'membership2' ),  
  544. $user_id 
  545. ); 
  546. $detail_lines[] = sprintf( 
  547. '<span class="line"><small class="line-num">%s</small><span class="line-key">%s</span> <span class="line-val">%s</span></span>',  
  548. 2,  
  549. __( 'Username', 'membership2' ),  
  550. $user->user_login 
  551. ); 
  552. $detail_lines[] = sprintf( 
  553. '<span class="line"><small class="line-num">%s</small><span class="line-key">%s</span> <span class="line-val">%s</span></span>',  
  554. 3,  
  555. __( 'Email', 'membership2' ),  
  556. $user->user_email 
  557. ); 
  558. } else { 
  559. $detail_lines[] = sprintf( 
  560. '<span class="line"><small class="line-num">%s</small><span class="line-key">%s</span> <span class="line-val">%s</span></span>',  
  561. 1,  
  562. __( 'Guest', 'membership2' ),  
  563. __( 'Could not determine a logged in user', 'membership2' ) 
  564. ); 
  565.  
  566. $req_url = $item->url; 
  567. if ( ! empty( $req_url ) ) { 
  568. if ( count( $detail_lines ) ) { 
  569. $detail_lines[] = '<hr />'; 
  570. $detail_lines[] = sprintf( 
  571. '<span class="line"><span class="line-key">%s</span> <span class="line-val">%s</span></span>',  
  572. __( 'Request URL', 'membership2' ),  
  573. $req_url 
  574. ); 
  575.  
  576. return $detail_lines; 
  577.