Completed
Push — issues/611 ( 661115...758b1c )
by Ravinder
21:11
created

admin/reporting/class-donor-reports-table.php (2 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/**
3
 * Donor Reports Table Class
4
 *
5
 * @package     Give
6
 * @subpackage  Admin/Reports
7
 * @copyright   Copyright (c) 2016, WordImpress
8
 * @license     https://opensource.org/licenses/gpl-license GNU Public License
9
 * @since       1.0
10
 */
11
12
// Exit if accessed directly.
13
if ( ! defined( 'ABSPATH' ) ) {
14
	exit;
15
}
16
17
// Load WP_List_Table if not loaded
18
if ( ! class_exists( 'WP_List_Table' ) ) {
19
	require_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php';
20
}
21
22
/**
23
 * Give_Donor_Reports_Table Class
24
 *
25
 * Renders the Donor Reports table
26
 *
27
 * @since 1.0
28
 */
29
class Give_Donor_Reports_Table extends WP_List_Table {
30
31
	/**
32
	 * Number of items per page
33
	 *
34
	 * @var int
35
	 * @since 1.0
36
	 */
37
	public $per_page = 30;
38
39
	/**
40
	 * Number of donors found
41
	 *
42
	 * @var int
43
	 * @since 1.0
44
	 */
45
	public $count = 0;
46
47
	/**
48
	 * Total donors
49
	 *
50
	 * @var int
51
	 * @since 1.0
52
	 */
53
	public $total = 0;
54
55
	/**
56
	 * Get things started
57
	 *
58
	 * @since 1.0
59
	 * @see   WP_List_Table::__construct()
60
	 */
61
	public function __construct() {
62
		global $status, $page;
63
64
		// Set parent defaults
65
		parent::__construct( array(
66
			'singular' => esc_html__( 'Donor', 'give' ),     // Singular name of the listed records
67
			'plural'   => esc_html__( 'Donors', 'give' ),    // Plural name of the listed records
68
			'ajax'     => false,// Does this table support ajax?
69
		) );
70
71
	}
72
73
	/**
74
	 * Remove default search field in favor for repositioned location
75
	 *
76
	 * Reposition the search field
77
	 *
78
	 * @since       1.0
79
	 * @access      public
80
	 *
81
	 * @param string $text     Label for the search box
82
	 * @param string $input_id ID of the search box
83
	 *
84
	 * @return false
0 ignored issues
show
Should the return type not be boolean?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
85
	 */
86
	public function search_box( $text, $input_id ) {
87
		return false;
88
	}
89
90
	/**
91
	 * Show the search field
92
	 *
93
	 * @since  1.0
94
	 * @access public
95
	 *
96
	 * @param string $text     Label for the search box
97
	 * @param string $input_id ID of the search box
98
	 *
99
	 * @return void
100
	 */
101
	public function give_search_box( $text, $input_id ) {
102
		$input_id = $input_id . '-search-input';
103
104
		if ( ! empty( $_REQUEST['orderby'] ) ) {
105
			echo '<input type="hidden" name="orderby" value="' . esc_attr( $_REQUEST['orderby'] ) . '" />';
106
		}
107
		if ( ! empty( $_REQUEST['order'] ) ) {
108
			echo '<input type="hidden" name="order" value="' . esc_attr( $_REQUEST['order'] ) . '" />';
109
		}
110
		?>
111
		<p class="search-box donor-search" role="search">
112
			<label class="screen-reader-text" for="<?php echo $input_id ?>"><?php echo $text; ?>:</label>
113
			<input type="search" id="<?php echo $input_id ?>" name="s" value="<?php _admin_search_query(); ?>" />
114
			<?php submit_button( $text, 'button', false, false, array( 'ID' => 'search-submit' ) ); ?>
115
		</p>
116
	<?php
117
	}
118
119
	/**
120
	 * Generate the table navigation above or below the table
121
	 *
122
	 * @since  1.0
123
	 * @access protected
124
	 *
125
	 * @param string $which
126
	 */
127
	protected function display_tablenav( $which ) {
128
129
		if ( 'top' === $which ) {
130
			wp_nonce_field( 'bulk-' . $this->_args['plural'] );
131
		}
132
		?>
133
		<div class="tablenav give-clearfix <?php echo esc_attr( $which ); ?>">
134
135
			<?php if ( 'top' === $which ) { ?>
136
				<h3 class="alignleft reports-earnings-title">
137
					<span><?php esc_html_e( 'Donors Report', 'give' ); ?></span>
138
				</h3>
139
			<?php } ?>
140
141
			<div class="alignright tablenav-right">
142
				<div class="actions bulkactions">
143
					<?php
144
					if ( 'top' === $which ) {
145
						$this->give_search_box( esc_html__( 'Search Donors', 'give' ), 'give-donors-report-search' );
146
					}
147
148
					$this->bulk_actions( $which ); ?>
149
150
				</div>
151
				<?php
152
				$this->extra_tablenav( $which );
153
				$this->pagination( $which );
154
				?>
155
			</div>
156
157
158
			<br class="clear"/>
159
160
		</div>
161
		<?php
162
	}
163
164
	/**
165
	 * This function renders most of the columns in the list table.
166
	 *
167
	 * @access public
168
	 * @since  1.0
169
	 *
170
	 * @param array  $item        Contains all the data of the donors
171
	 * @param string $column_name The name of the column
172
	 *
173
	 * @return string Column Name
174
	 */
175
	public function column_default( $item, $column_name ) {
176
177
		switch ( $column_name ) {
178
179
			case 'name' :
180
				$name = '#' . $item['id'] . ' ';
181
				$name .= ! empty( $item['name'] ) ? $item['name'] : '<em>' . esc_html__( 'Unnamed Donor', 'give' ) . '</em>';
182
				$view_url = admin_url( 'edit.php?post_type=give_forms&page=give-donors&view=overview&id=' . $item['id'] );
183
				$value    = '<a href="' . esc_url( $view_url ) . '">' . $name . '</a>';
184
				break;
185
186
			case 'num_donations' :
187
				$value = '<a href="' .
188
				         admin_url( 'edit.php?post_type=give_forms&page=give-payment-history&user=' . urlencode( $item['email'] )
189
				         ) . '">' . esc_html( $item['num_donations'] ) . '</a>';
190
				break;
191
192
			case 'amount_spent' :
193
				$value = give_currency_filter( give_format_amount( $item[ $column_name ] ) );
194
				break;
195
196
			default:
197
				$value = isset( $item[ $column_name ] ) ? $item[ $column_name ] : null;
198
				break;
199
		}
200
201
		return apply_filters( "give_report_column_{$column_name}", $value, $item['id'] );
202
	}
203
204
	/**
205
	 * Retrieve the table columns
206
	 *
207
	 * @access public
208
	 * @since  1.0
209
	 * @return array $columns Array of all the list table columns
210
	 */
211
	public function get_columns() {
212
		$columns = array(
213
			'name'          => esc_html__( 'Name', 'give' ),
214
			'email'         => esc_html__( 'Email', 'give' ),
215
			'num_donations' => esc_html__( 'Donations', 'give' ),
216
			'amount_spent'  => esc_html__( 'Total Donated', 'give' ),
217
		);
218
219
		return apply_filters( 'give_report_donor_columns', $columns );
220
221
	}
222
223
	/**
224
	 * Get the sortable columns
225
	 *
226
	 * @access public
227
	 * @since  1.0
228
	 * @return array Array of all the sortable columns
229
	 */
230
	public function get_sortable_columns() {
231
		return array(
232
			'id'            => array( 'id', true ),
233
			'name'          => array( 'name', true ),
234
			'num_donations' => array( 'purchase_count', false ),
235
			'amount_spent'  => array( 'purchase_value', false ),
236
		);
237
	}
238
239
	/**
240
	 * Outputs the reporting views
241
	 *
242
	 * @access public
243
	 * @since  1.0
244
	 * @return void
245
	 */
246
	public function bulk_actions( $which = '' ) {
247
248
	}
249
250
	/**
251
	 * Retrieve the current page number
252
	 *
253
	 * @access public
254
	 * @since  1.0
255
	 * @return int Current page number
256
	 */
257
	public function get_paged() {
258
		return isset( $_GET['paged'] ) ? absint( $_GET['paged'] ) : 1;
259
	}
260
261
	/**
262
	 * Retrieves the search query string
263
	 *
264
	 * @access public
265
	 * @since  1.0
266
	 * @return mixed string If search is present, false otherwise
267
	 */
268
	public function get_search() {
269
		return ! empty( $_GET['s'] ) ? urldecode( trim( $_GET['s'] ) ) : false;
270
	}
271
272
	/**
273
	 * Build all the reports data
274
	 *
275
	 * @access public
276
	 * @since  1.0
277
	 * @global object $wpdb Used to query the database using the WordPress
278
	 *                      Database API
279
	 * @return array $reports_data All the data for donor reports
280
	 */
281
	public function reports_data() {
282
		global $wpdb;
283
284
		$data = array();
285
286
		// Get donor query.
287
		$args   = $this->get_donor_query();
288
		$donors = Give()->customers->get_customers( $args );
289
290
		if ( $donors ) {
291
292
			$this->count = count( $donors );
293
294
			foreach ( $donors as $donor ) {
295
296
				$user_id = ! empty( $donor->user_id ) ? absint( $donor->user_id ) : 0;
297
298
				$data[] = array(
299
					'id'            => $donor->id,
300
					'user_id'       => $user_id,
301
					'name'          => $donor->name,
302
					'email'         => $donor->email,
303
					'num_donations' => $donor->purchase_count,
304
					'amount_spent'  => $donor->purchase_value,
305
				);
306
			}
307
		}
308
309
		return $data;
310
	}
311
312
	/**
313
	 * Get donor count.
314
	 *
315
	 * @since 1.8.1
316
	 * @access private
317
	 */
318
	private function get_donor_count() {
319
		// Get donor query.
320
		$_donor_query = $this->get_donor_query();
321
322
		$_donor_query['number'] = -1;
323
		$donors = Give()->customers->get_customers( $_donor_query );
324
325
		return count( $donors );
326
	}
327
328
	/**
329
	 * Get donor query.
330
	 *
331
	 * @since  1.8.1
332
	 * @access public
333
	 * @return array
334
	 */
335
	public function get_donor_query() {
336
		$paged   = $this->get_paged();
337
		$offset  = $this->per_page * ( $paged - 1 );
338
		$search  = $this->get_search();
339
		$order   = isset( $_GET['order'] ) ? sanitize_text_field( $_GET['order'] ) : 'DESC';
340
		$orderby = isset( $_GET['orderby'] ) ? sanitize_text_field( $_GET['orderby'] ) : 'id';
341
342
		$args = array(
343
			'number'  => $this->per_page,
344
			'offset'  => $offset,
345
			'order'   => $order,
346
			'orderby' => $orderby,
347
		);
348
349
		if( $search ) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $search of type string|false is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
350
			if ( is_email( $search ) ) {
351
				$args['email'] = $search;
352
			} elseif ( is_numeric( $search ) ) {
353
				$args['id'] = $search;
354
			} else {
355
				$args['name'] = $search;
356
			}
357
		}
358
359
		return $args;
360
	}
361
362
	/**
363
	 * Setup the final data for the table
364
	 *
365
	 * @access public
366
	 * @since  1.0
367
	 * @uses   Give_Donor_Reports_Table::get_columns()
368
	 * @uses   WP_List_Table::get_sortable_columns()
369
	 * @uses   Give_Donor_Reports_Table::get_pagenum()
370
	 * @uses   Give_Donor_Reports_Table::get_total_donors()
371
	 * @return void
372
	 */
373
	public function prepare_items() {
374
375
		$columns  = $this->get_columns();
376
		$hidden   = array(); // No hidden columns
377
		$sortable = $this->get_sortable_columns();
378
379
		$this->_column_headers = array( $columns, $hidden, $sortable );
380
381
		$this->items = $this->reports_data();
382
383
		$this->total = $this->get_donor_count();
384
385
		$this->set_pagination_args( array(
386
			'total_items' => $this->total,
387
			'per_page'    => $this->per_page,
388
			'total_pages' => ceil( $this->total / $this->per_page ),
389
		) );
390
	}
391
}
392