Test Failed
Push — master ( 25adfe...70178c )
by Devin
01:46
created

Give_Donors_Query::init()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 2
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * Donors Query
4
 *
5
 * @package     Give
6
 * @subpackage  Classes/Stats
7
 * @copyright   Copyright (c) 2017, WordImpress
8
 * @license     https://opensource.org/licenses/gpl-license GNU Public License
9
 * @since       1.8.14
10
 */
11
12
// Exit if accessed directly.
13
if ( ! defined( 'ABSPATH' ) ) {
14
	exit;
15
}
16
17
/**
18
 * Give_Donors_Query Class
19
 *
20
 * This class is for retrieving donors data.
21
 *
22
 * Donors can be retrieved for date ranges and pre-defined periods.
23
 *
24
 * @since 1.8.14
25
 */
26
class Give_Donors_Query {
27
28
	/**
29
	 * The args to pass to the give_get_donors() query
30
	 *
31
	 * @since  1.8.14
32
	 * @access public
33
	 *
34
	 * @var    array
35
	 */
36
	public $args = array();
37
38
	/**
39
	 * The donors found based on the criteria set
40
	 *
41
	 * @since  1.8.14
42
	 * @access public
43
	 *
44
	 * @var    array
45
	 */
46
	public $donors = array();
47
48
	/**
49
	 * The donors found based on the criteria set
50
	 *
51
	 * @since  1.8.14
52
	 * @access public
53
	 *
54
	 * @var    array
55
	 */
56
	public $table_name = '';
57
58
	/**
59
	 * The donors found based on the criteria set
60
	 *
61
	 * @since  1.8.14
62
	 * @access public
63
	 *
64
	 * @var    array
65
	 */
66
	public $meta_table_name = '';
67
68
	/**
69
	 * The donors found based on the criteria set
70
	 *
71
	 * @since  1.8.14
72
	 * @access public
73
	 *
74
	 * @var    array
75
	 */
76
	public $meta_type = '';
77
78
	/**
79
	 * Default query arguments.
80
	 *
81
	 * Not all of these are valid arguments that can be passed to WP_Query. The ones that are not, are modified before the query is run to convert them to the proper syntax.
82
	 *
83
	 * @since  1.8.14
84
	 * @access public
85
	 *
86
	 * @param  $args array The array of arguments that can be passed in and used for setting up this payment query.
87
	 */
88
	public function __construct( $args = array() ) {
89
		$defaults = array(
90
			'number'     => 20,
91
			'offset'     => 0,
92
			'paged'      => 1,
93
			'orderby'    => 'id',
94
			'order'      => 'DESC',
95
			'user'       => null,
96
			'email'      => null,
97
			'donor'      => null,
98
			'meta_query' => array(),
0 ignored issues
show
introduced by
Detected usage of meta_query, possible slow query.
Loading history...
99
			'date_query' => array(),
100
			's'          => null,
101
			'fields'     => 'all', // Support donors (all fields) or valid column  as string or array list
102
			'count'      => false,
103
			// 'form'       => array(),
104
		);
105
106
		$this->args = wp_parse_args( $args, $defaults );
107
108
		$this->table_name      = Give()->donors->table_name;
0 ignored issues
show
Documentation Bug introduced by
It seems like Give()->donors->table_name of type string is incompatible with the declared type array of property $table_name.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
109
		$this->meta_table_name = Give()->donor_meta->table_name;
0 ignored issues
show
Documentation Bug introduced by
It seems like Give()->donor_meta->table_name of type string is incompatible with the declared type array of property $meta_table_name.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
110
		$this->meta_type       = Give()->donor_meta->meta_type;
0 ignored issues
show
Documentation Bug introduced by
It seems like Give()->donor_meta->meta_type of type string is incompatible with the declared type array of property $meta_type.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
111
	}
112
113
	/**
114
	 * Modify the query/query arguments before we retrieve donors.
115
	 *
116
	 * @since  1.8.14
117
	 * @access public
118
	 *
119
	 * @return void
120
	 */
121
	public function init() {
122
	}
123
124
125
	/**
126
	 * Retrieve donors.
127
	 *
128
	 * The query can be modified in two ways; either the action before the
129
	 * query is run, or the filter on the arguments (existing mainly for backwards
130
	 * compatibility).
131
	 *
132
	 * @since  1.8.14
133
	 * @access public
134
	 *
135
	 * @global wpdb $wpdb
136
	 *
137
	 * @return array
138
	 */
139
	public function get_donors() {
140
		global $wpdb;
141
142
		/**
143
		 * Fires before retrieving donors.
144
		 *
145
		 * @since 1.8.14
146
		 *
147
		 * @param Give_Donors_Query $this Donors query object.
148
		 */
149
		do_action( 'give_pre_get_donors', $this );
150
151
		if ( empty( $this->args['count'] ) ) {
152
			$this->donors = $wpdb->get_results( $this->get_sql() );
0 ignored issues
show
introduced by
Usage of a direct database call is discouraged.
Loading history...
introduced by
Usage of a direct database call without caching is prohibited. Use wp_cache_get / wp_cache_set.
Loading history...
153
		} else {
154
			$this->donors = $wpdb->get_var( $this->get_sql() );
0 ignored issues
show
introduced by
Usage of a direct database call is discouraged.
Loading history...
introduced by
Usage of a direct database call without caching is prohibited. Use wp_cache_get / wp_cache_set.
Loading history...
155
		}
156
157
		/**
158
		 * Fires after retrieving donors.
159
		 *
160
		 * @since 1.8.14
161
		 *
162
		 * @param Give_Donors_Query $this Donors query object.
163
		 */
164
		do_action( 'give_post_get_donors', $this );
165
166
		return $this->donors;
167
	}
168
169
	/**
170
	 * Get sql query from queried array.
171
	 *
172
	 * @since  2.0
173
	 * @access public
174
	 *
175
	 * @global wpdb $wpdb
176
	 * @return string
177
	 */
178
	public function get_sql() {
179
		global $wpdb;
180
181
		if ( $this->args['number'] < 1 ) {
182
			$this->args['number'] = 999999999999;
183
		}
184
185
		$where = $this->get_where_query();
186
0 ignored issues
show
Coding Style introduced by
Functions must not contain multiple empty lines in a row; found 2 empty lines
Loading history...
187
188
		// Set offset.
189
		if ( empty( $this->args['offset'] ) && ( 0 < $this->args['paged'] ) ) {
190
			$this->args['offset'] = $this->args['number'] * ( $this->args['paged'] - 1 );
191
		}
192
193
		// Set fields.
194
		$fields = "{$this->table_name}.*";
195
		if ( ! empty( $this->args['fields'] ) && 'all' !== $this->args['fields'] ) {
196
			if ( is_string( $this->args['fields'] ) ) {
197
				$fields = "{$this->table_name}.{$this->args['fields']}";
198
			} else if ( is_array( $this->args['fields'] ) ) {
199
				$fields = "{$this->table_name}." . implode( " , {$this->table_name}.", $this->args['fields'] );
200
			}
201
		}
202
203
		// Set count.
204
		if ( ! empty( $this->args['count'] ) ) {
205
			$fields = "COUNT({$this->table_name}.id)";
206
		}
207
208
		$orderby = $this->get_order_query();
209
210
		return $wpdb->prepare(
211
			"SELECT {$fields} FROM {$this->table_name} {$where} {$orderby} {$this->args['order']} LIMIT %d,%d;",
212
			absint( $this->args['offset'] ),
213
			absint( $this->args['number'] )
214
		);
215
	}
216
217
	/**
218
	 * Set query where clause.
219
	 *
220
	 * @since  1.8.14
221
	 * @access private
222
	 *
223
	 * @global wpdb $wpdb
224
	 * @return string
225
	 */
226
	private function get_where_query() {
227
		$where = '';
228
229
		// Get sql query for meta.
230
		if ( ! empty( $this->args['meta_query'] ) ) {
231
			$meta_query_object = new WP_Meta_Query( $this->args['meta_query'] );
232
			$meta_query        = $meta_query_object->get_sql(
233
				$this->meta_type,
234
				$this->table_name,
235
				'id'
236
			);
237
			$where             = implode( '', $meta_query );
238
		}
239
240
		$where .= 'WHERE 1=1';
241
		$where .= $this->get_where_search();
242
		$where .= $this->get_where_email();
243
		$where .= $this->get_where_donor();
244
		$where .= $this->get_where_user();
245
		$where .= $this->get_where_date();
246
247
		return $where;
248
	}
249
250
	/**
251
	 * Set email where clause.
252
	 *
253
	 * @since  1.8.14
254
	 * @access private
255
	 *
256
	 * @global wpdb $wpdb
257
	 * @return string
258
	 */
259
	private function get_where_email() {
260
		global $wpdb;
261
262
		$where = '';
263
264
		if ( ! empty( $this->args['email'] ) ) {
265
266
			if ( is_array( $this->args['email'] ) ) {
267
268
				$emails_count       = count( $this->args['email'] );
269
				$emails_placeholder = array_fill( 0, $emails_count, '%s' );
270
				$emails             = implode( ', ', $emails_placeholder );
271
272
				$where .= $wpdb->prepare( " AND {$this->table_name}.email IN( $emails ) ", $this->args['email'] );
273
			} else {
274
				$where .= $wpdb->prepare( " AND {$this->table_name}.email = %s ", $this->args['email'] );
275
			}
276
		}
277
278
		return $where;
279
	}
280
281
	/**
282
	 * Set donor where clause.
283
	 *
284
	 * @since  1.8.14
285
	 * @access private
286
	 *
287
	 * @global wpdb $wpdb
288
	 * @return string
289
	 */
290 View Code Duplication
	private function get_where_donor() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
291
		$where = '';
292
293
		// Specific donors.
294
		if ( ! empty( $this->args['donor'] ) ) {
295
			if ( ! is_array( $this->args['donor'] ) ) {
296
				$this->args['donor'] = explode( ',', $this->args['donor'] );
297
			}
298
			$log_ids = implode( ',', array_map( 'intval', $this->args['donor'] ) );
299
300
			$where .= " AND {$this->table_name}.id IN( {$log_ids} ) ";
301
		}
302
303
		return $where;
304
	}
305
306
	/**
307
	 * Set date where clause.
308
	 *
309
	 * @since  1.8.14
310
	 * @access private
311
	 *
312
	 * @global wpdb $wpdb
313
	 * @return string
314
	 */
315
	private function get_where_date() {
316
		$where = '';
317
318
		// Donors created for a specific date or in a date range
319
		if ( ! empty( $this->args['date_query'] ) ) {
320
			$date_query_object = new WP_Date_Query(
321
				$this->args['date_query'],
322
				"{$this->table_name}.date_created"
323
			);
324
325
			$where .= $date_query_object->get_sql();
326
		}
327
328
		return $where;
329
	}
330
331
	/**
332
	 * Set search where clause.
333
	 *
334
	 * @since  1.8.14
335
	 * @access private
336
	 *
337
	 * @global wpdb $wpdb
338
	 * @return string
339
	 */
340
	private function get_where_search() {
341
		$where = '';
342
343
		// Donors created for a specific date or in a date range
344
		if ( ! empty( $this->args['s'] ) && false !== strpos( $this->args['s'], ':' ) ) {
345
			$search_parts = explode( ':', $this->args['s'] );
346
347
			if ( ! empty( $search_parts[0] ) ) {
348
				switch ( $search_parts[0] ) {
349
					case 'name':
350
						$where = " AND {$this->table_name}.name LIKE '%{$search_parts[1]}%' ";
351
						break;
352
353
					case 'note':
354
						$where = " AND {$this->table_name}.notes LIKE '%{$search_parts[1]}%' ";
355
						break;
356
				}
357
			}
358
		}
359
360
		return $where;
361
	}
362
363
	/**
364
	 * Set user where clause.
365
	 *
366
	 * @since  1.8.14
367
	 * @access private
368
	 *
369
	 * @global wpdb $wpdb
370
	 * @return string
371
	 */
372 View Code Duplication
	private function get_where_user() {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
373
		$where = '';
374
375
		// Donors create for specific wp user.
376
		if ( ! empty( $this->args['user'] ) ) {
377
			if ( ! is_array( $this->args['user'] ) ) {
378
				$this->args['user'] = explode( ',', $this->args['user'] );
379
			}
380
			$user_ids = implode( ',', array_map( 'intval', $this->args['user'] ) );
381
382
			$where .= " AND {$this->table_name}.user_id IN( {$user_ids} ) ";
383
		}
384
385
		return $where;
386
	}
387
388
	/**
389
	 * Set orderby query
390
	 *
391
	 * @since  1.8.14
392
	 * @access private
393
	 *
394
	 * @return string
395
	 */
396
	private function get_order_query() {
397
		$table_columns = Give()->donors->get_columns();
398
399
		$this->args['orderby'] = ! array_key_exists( $this->args['orderby'], $table_columns ) ?
400
			'id' :
401
			$this->args['orderby'];
402
403
		$this->args['orderby'] = esc_sql( $this->args['orderby'] );
404
		$this->args['order']   = esc_sql( $this->args['order'] );
405
406
		switch ( $table_columns[ $this->args['orderby'] ] ) {
407
			case '%d':
408
			case '%f':
409
				$query = "ORDER BY {$this->table_name}.{$this->args['orderby']}+0";
410
				break;
411
412
			default:
413
				$query = "ORDER BY {$this->table_name}.{$this->args['orderby']}";
414
		}
415
416
		return $query;
417
	}
418
}
419