Test Failed
Push — issues/2101 ( d7edc6...30f91a )
by Ravinder
05:02
created

Give_Donors_Query::__construct()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 24
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 19
nc 1
nop 1
dl 0
loc 24
rs 8.9713
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 extends Give_Stats {
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
	 * Search
171
	 *
172
	 * @since  1.8.14
173
	 * @access public
174
	 *
175
	 * @return void
176
	 */
177
	public function search() {
178
179
		if ( ! isset( $this->args['s'] ) ) {
180
			return;
181
		}
182
183
		$search = trim( $this->args['s'] );
184
185
		if ( empty( $search ) ) {
186
			return;
187
		}
188
189
		// @todo setup search logic
190
	}
191
192
	/**
193
	 * Get sql query from queried array.
194
	 *
195
	 * @since  2.0
196
	 * @access public
197
	 *
198
	 * @global wpdb $wpdb
199
	 * @return string
200
	 */
201
	public function get_sql() {
202
		global $wpdb;
203
204
		if ( $this->args['number'] < 1 ) {
205
			$this->args['number'] = 999999999999;
206
		}
207
208
		$where = $this->get_where_query();
209
0 ignored issues
show
Coding Style introduced by
Functions must not contain multiple empty lines in a row; found 2 empty lines
Loading history...
210
211
		// Set offset.
212
		if ( empty( $this->args['offset'] ) && ( 0 < $this->args['paged'] ) ) {
213
			$this->args['offset'] = $this->args['number'] * ( $this->args['paged'] - 1 );
214
		}
215
216
		// Set fields.
217
		$fields = "{$this->table_name}.*";
218
		if ( ! empty( $this->args['fields'] ) && 'all' !== $this->args['fields'] ) {
219
			if ( is_string( $this->args['fields'] ) ) {
220
				$fields = "{$this->table_name}.{$this->args['fields']}";
221
			} else if ( is_array( $this->args['fields'] ) ) {
222
				$fields = "{$this->table_name}." . implode( " , {$this->table_name}.", $this->args['fields'] );
223
			}
224
		}
225
226
		// Set count.
227
		if ( ! empty( $this->args['count'] ) ) {
228
			$fields = "COUNT({$this->table_name}.id)";
229
		}
230
231
		$orderby = $this->get_order_query();
232
233
		return $wpdb->prepare(
234
			"SELECT {$fields} FROM {$this->table_name} {$where} {$orderby} {$this->args['order']} LIMIT %d,%d;",
235
			absint( $this->args['offset'] ),
236
			absint( $this->args['number'] )
237
		);
238
	}
239
240
	/**
241
	 * Set query where clause.
242
	 *
243
	 * @since  1.8.14
244
	 * @access private
245
	 *
246
	 * @global wpdb $wpdb
247
	 * @return string
248
	 */
249
	private function get_where_query() {
250
		$where = '';
251
252
		// Get sql query for meta.
253
		if ( ! empty( $this->args['meta_query'] ) ) {
254
			$meta_query_object = new WP_Meta_Query( $this->args['meta_query'] );
255
			$meta_query        = $meta_query_object->get_sql(
256
				$this->meta_type,
257
				$this->table_name,
258
				'id'
259
			);
260
			$where             = implode( '', $meta_query );
261
		}
262
263
		$where .= 'WHERE 1=1';
264
		$where .= $this->get_where_search();
265
		$where .= $this->get_where_email();
266
		$where .= $this->get_where_donor();
267
		$where .= $this->get_where_user();
268
		$where .= $this->get_where_date();
269
270
		return $where;
271
	}
272
273
	/**
274
	 * Set email where clause.
275
	 *
276
	 * @since  1.8.14
277
	 * @access private
278
	 *
279
	 * @global wpdb $wpdb
280
	 * @return string
281
	 */
282
	private function get_where_email() {
283
		global $wpdb;
284
285
		$where = '';
286
287
		if ( ! empty( $this->args['email'] ) ) {
288
289
			if ( is_array( $this->args['email'] ) ) {
290
291
				$emails_count       = count( $this->args['email'] );
292
				$emails_placeholder = array_fill( 0, $emails_count, '%s' );
293
				$emails             = implode( ', ', $emails_placeholder );
294
295
				$where .= $wpdb->prepare( " AND `email` IN( $emails ) ", $this->args['email'] );
296
			} else {
297
				$where .= $wpdb->prepare( " AND `email` = %s ", $this->args['email'] );
0 ignored issues
show
Coding Style Comprehensibility introduced by
The string literal AND `email` = %s does not require double quotes, as per coding-style, please use single quotes.

PHP provides two ways to mark string literals. Either with single quotes 'literal' or with double quotes "literal". The difference between these is that string literals in double quotes may contain variables with are evaluated at run-time as well as escape sequences.

String literals in single quotes on the other hand are evaluated very literally and the only two characters that needs escaping in the literal are the single quote itself (\') and the backslash (\\). Every other character is displayed as is.

Double quoted string literals may contain other variables or more complex escape sequences.

<?php

$singleQuoted = 'Value';
$doubleQuoted = "\tSingle is $singleQuoted";

print $doubleQuoted;

will print an indented: Single is Value

If your string literal does not contain variables or escape sequences, it should be defined using single quotes to make that fact clear.

For more information on PHP string literals and available escape sequences see the PHP core documentation.

Loading history...
298
			}
299
		}
300
301
		return $where;
302
	}
303
304
	/**
305
	 * Set donor where clause.
306
	 *
307
	 * @since  1.8.14
308
	 * @access private
309
	 *
310
	 * @global wpdb $wpdb
311
	 * @return string
312
	 */
313 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...
314
		$where = '';
315
316
		// Specific donors.
317
		if ( ! empty( $this->args['donor'] ) ) {
318
			if ( ! is_array( $this->args['donor'] ) ) {
319
				$this->args['donor'] = explode( ',', $this->args['donor'] );
320
			}
321
			$log_ids = implode( ',', array_map( 'intval', $this->args['donor'] ) );
322
323
			$where .= " AND {$this->table_name}.id IN( {$log_ids} ) ";
324
		}
325
326
		return $where;
327
	}
328
329
	/**
330
	 * Set date where clause.
331
	 *
332
	 * @since  1.8.14
333
	 * @access private
334
	 *
335
	 * @global wpdb $wpdb
336
	 * @return string
337
	 */
338
	private function get_where_date() {
339
		$where = '';
340
341
		// Donors created for a specific date or in a date range
342
		if ( ! empty( $this->args['date_query'] ) ) {
343
			$date_query_object = new WP_Date_Query(
344
				$this->args['date_query'],
345
				"{$this->table_name}.date_created"
346
			);
347
348
			$where .= $date_query_object->get_sql();
349
		}
350
351
		return $where;
352
	}
353
354
	/**
355
	 * Set search where clause.
356
	 *
357
	 * @since  1.8.14
358
	 * @access private
359
	 *
360
	 * @global wpdb $wpdb
361
	 * @return string
362
	 */
363
	private function get_where_search() {
364
		$where = '';
365
366
		// Donors created for a specific date or in a date range
367
		if ( ! empty( $this->args['s'] ) && false !== strpos( $this->args['s'], ':' ) ) {
368
			$search_parts = explode( ':', $this->args['s'] );
369
370
			if ( ! empty( $search_parts[0] ) ) {
371
				switch ( $search_parts[0] ) {
372
					case 'name':
373
						$where = " AND {$this->table_name}.name LIKE '%{$search_parts[1]}%' ";
374
						break;
375
376
					case 'note':
377
						$where = " AND {$this->table_name}.notes LIKE '%{$search_parts[1]}%' ";
378
						break;
379
				}
380
			}
381
		}
382
383
		return $where;
384
	}
385
386
	/**
387
	 * Set user where clause.
388
	 *
389
	 * @since  1.8.14
390
	 * @access private
391
	 *
392
	 * @global wpdb $wpdb
393
	 * @return string
394
	 */
395 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...
396
		$where = '';
397
398
		// Donors create for specific wp user.
399
		if ( ! empty( $this->args['user'] ) ) {
400
			if ( ! is_array( $this->args['user'] ) ) {
401
				$this->args['user'] = explode( ',', $this->args['user'] );
402
			}
403
			$user_ids = implode( ',', array_map( 'intval', $this->args['user'] ) );
404
405
			$where .= " AND {$this->table_name}.user_id IN( {$user_ids} ) ";
406
		}
407
408
		return $where;
409
	}
410
411
	/**
412
	 * Set orderby query
413
	 *
414
	 * @since  1.8.14
415
	 * @access private
416
	 *
417
	 * @return string
418
	 */
419
	private function get_order_query() {
420
		$table_columns = Give()->donors->get_columns();
421
422
		$this->args['orderby'] = ! array_key_exists( $this->args['orderby'], $table_columns ) ?
423
			'id' :
424
			$this->args['orderby'];
425
426
		$this->args['orderby'] = esc_sql( $this->args['orderby'] );
427
		$this->args['order']   = esc_sql( $this->args['order'] );
428
429
		switch ( $table_columns[ $this->args['orderby'] ] ) {
430
			case '%d':
431
			case '%f':
432
				$query = "ORDER BY {$this->table_name}.{$this->args['orderby']}+0";
433
				break;
434
435
			default:
436
				$query = "ORDER BY {$this->table_name}.{$this->args['orderby']}";
437
		}
438
439
		return $query;
440
	}
441
}
442