Test Failed
Push — issues/1944 ( e0f33c...23166d )
by Ravinder
04:25
created

Give_Donors_Query::get_where_query()   B

Complexity

Conditions 2
Paths 2

Size

Total Lines 24
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 16
nc 2
nop 0
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 {
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
82
	 * the query is run to convert them to the proper syntax.
83
	 *
84
	 * @since  1.8.14
85
	 * @access public
86
	 *
87
	 * @param  $args array The array of arguments that can be passed in and used for setting up this payment query.
88
	 */
89
	public function __construct( $args = array() ) {
90
		$defaults = array(
91
			'number'     => 20,
92
			'offset'     => 0,
93
			'paged'      => 1,
94
			'orderby'    => 'id',
95
			'order'      => 'DESC',
96
			'user'       => null,
97
			'email'      => null,
98
			'donor'      => null,
99
			'meta_query' => array(),
0 ignored issues
show
introduced by
Detected usage of meta_query, possible slow query.
Loading history...
100
			'date_query' => array(),
101
			's'          => null,
102
			'fields'     => 'all', // Support donors (all fields) or valid column  as string or array list
103
			'count'      => false,
104
			// 'form'       => array(),
105
		);
106
107
		$this->args = wp_parse_args( $args, $defaults );
108
109
		$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...
110
		$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...
111
		$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...
112
	}
113
114
	/**
115
	 * Modify the query/query arguments before we retrieve donors.
116
	 *
117
	 * @since  1.8.14
118
	 * @access public
119
	 *
120
	 * @return void
121
	 */
122
	public function init() {
123
	}
124
125
126
	/**
127
	 * Retrieve donors.
128
	 *
129
	 * The query can be modified in two ways; either the action before the
130
	 * query is run, or the filter on the arguments (existing mainly for backwards
131
	 * compatibility).
132
	 *
133
	 * @since  1.8.14
134
	 * @access public
135
	 *
136
	 * @global wpdb $wpdb
137
	 *
138
	 * @return array
139
	 */
140
	public function get_donors() {
141
		global $wpdb;
142
143
		/**
144
		 * Fires before retrieving donors.
145
		 *
146
		 * @since 1.8.14
147
		 *
148
		 * @param Give_Donors_Query $this Donors query object.
149
		 */
150
		do_action( 'give_pre_get_donors', $this );
151
152
		$cache_key        = 'give_donor_' . substr( md5( serialize( $this->get_sql() ) ), 0, 15 );
153
		$cache_gruop_name = Give_Cache::get_key( 'give-db-queries' );
154
155
		if ( ! ( $this->donors = Give_Cache::get_group( $cache_key, $cache_gruop_name ) ) ) {
0 ignored issues
show
Documentation Bug introduced by
It seems like \Give_Cache::get_group($...key, $cache_gruop_name) of type * is incompatible with the declared type array of property $donors.

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...
156
			if ( empty( $this->args['count'] ) ) {
157
				$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...
158
			} else {
159
				$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...
160
			}
161
162
			Give_Cache::set_group( $cache_key, $this->donors, $cache_gruop_name );
163
		}
164
0 ignored issues
show
Coding Style introduced by
Functions must not contain multiple empty lines in a row; found 2 empty lines
Loading history...
165
166
		/**
167
		 * Fires after retrieving donors.
168
		 *
169
		 * @since 1.8.14
170
		 *
171
		 * @param Give_Donors_Query $this Donors query object.
172
		 */
173
		do_action( 'give_post_get_donors', $this );
174
175
		return $this->donors;
176
	}
177
178
	/**
179
	 * Get sql query from queried array.
180
	 *
181
	 * @since  2.0
182
	 * @access public
183
	 *
184
	 * @global wpdb $wpdb
185
	 * @return string
186
	 */
187
	public function get_sql() {
188
		global $wpdb;
189
190
		if ( $this->args['number'] < 1 ) {
191
			$this->args['number'] = 999999999999;
192
		}
193
194
		$where = $this->get_where_query();
195
0 ignored issues
show
Coding Style introduced by
Functions must not contain multiple empty lines in a row; found 2 empty lines
Loading history...
196
197
		// Set offset.
198
		if ( empty( $this->args['offset'] ) && ( 0 < $this->args['paged'] ) ) {
199
			$this->args['offset'] = $this->args['number'] * ( $this->args['paged'] - 1 );
200
		}
201
202
		// Set fields.
203
		$fields = "{$this->table_name}.*";
204
		if ( ! empty( $this->args['fields'] ) && 'all' !== $this->args['fields'] ) {
205
			if ( is_string( $this->args['fields'] ) ) {
206
				$fields = "{$this->table_name}.{$this->args['fields']}";
207
			} elseif ( is_array( $this->args['fields'] ) ) {
208
				$fields = "{$this->table_name}." . implode( " , {$this->table_name}.", $this->args['fields'] );
209
			}
210
		}
211
212
		// Set count.
213
		if ( ! empty( $this->args['count'] ) ) {
214
			$fields = "COUNT({$this->table_name}.id)";
215
		}
216
217
		$orderby = $this->get_order_query();
218
219
		$sql = $wpdb->prepare(
220
			"SELECT {$fields} FROM {$this->table_name} LIMIT %d,%d;",
221
			absint( $this->args['offset'] ),
222
			absint( $this->args['number'] )
223
		);
224
225
		// $where, $orderby and order already prepared query they can generate notice if you re prepare them in above.
226
		// WordPress consider LIKE condition as placeholder if start with s,f, or d.
227
		$sql = str_replace( 'LIMIT', "{$where} {$orderby} {$this->args['order']} LIMIT", $sql );
228
229
		return $sql;
230
	}
231
232
	/**
233
	 * Set query where clause.
234
	 *
235
	 * @since  1.8.14
236
	 * @access private
237
	 *
238
	 * @global wpdb $wpdb
239
	 * @return string
240
	 */
241
	private function get_where_query() {
242
		$where = '';
243
244
		// Get sql query for meta.
245
		if ( ! empty( $this->args['meta_query'] ) ) {
246
			$meta_query_object = new WP_Meta_Query( $this->args['meta_query'] );
247
			$meta_query        = $meta_query_object->get_sql(
248
				$this->meta_type,
249
				$this->table_name,
250
				'id'
251
			);
252
253
			$where = implode( '', $meta_query );
254
		}
255
256
		$where .= 'WHERE 1=1 ';
257
		$where .= $this->get_where_search();
258
		$where .= $this->get_where_email();
259
		$where .= $this->get_where_donor();
260
		$where .= $this->get_where_user();
261
		$where .= $this->get_where_date();
262
263
		return trim( $where );
264
	}
265
266
	/**
267
	 * Set email where clause.
268
	 *
269
	 * @since  1.8.14
270
	 * @access private
271
	 *
272
	 * @global wpdb $wpdb
273
	 * @return string
274
	 */
275
	private function get_where_email() {
276
		global $wpdb;
277
278
		$where = '';
279
280
		if ( ! empty( $this->args['email'] ) ) {
281
282
			if ( is_array( $this->args['email'] ) ) {
283
284
				$emails_count       = count( $this->args['email'] );
285
				$emails_placeholder = array_fill( 0, $emails_count, '%s' );
286
				$emails             = implode( ', ', $emails_placeholder );
287
288
				$where .= $wpdb->prepare( "AND {$this->table_name}.email IN( $emails )", $this->args['email'] );
289
			} else {
290
				$where .= $wpdb->prepare( "AND {$this->table_name}.email = %s", $this->args['email'] );
291
			}
292
		}
293
294
		return $where;
295
	}
296
297
	/**
298
	 * Set donor where clause.
299
	 *
300
	 * @since  1.8.14
301
	 * @access private
302
	 *
303
	 * @global wpdb $wpdb
304
	 * @return string
305
	 */
306 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...
307
		$where = '';
308
309
		// Specific donors.
310
		if ( ! empty( $this->args['donor'] ) ) {
311
			if ( ! is_array( $this->args['donor'] ) ) {
312
				$this->args['donor'] = explode( ',', $this->args['donor'] );
313
			}
314
			$donor_ids = implode( ',', array_map( 'intval', $this->args['donor'] ) );
315
316
			$where .= "AND {$this->table_name}.id IN( {$donor_ids} )";
317
		}
318
319
		return $where;
320
	}
321
322
	/**
323
	 * Set date where clause.
324
	 *
325
	 * @since  1.8.14
326
	 * @access private
327
	 *
328
	 * @global wpdb $wpdb
329
	 * @return string
330
	 */
331
	private function get_where_date() {
332
		$where = '';
333
334
		// Donors created for a specific date or in a date range
335
		if ( ! empty( $this->args['date_query'] ) ) {
336
			$date_query_object = new WP_Date_Query(
337
				is_array( $this->args['date_query'] ) ? $this->args['date_query'] : wp_parse_args( $this->args['date_query'] ),
338
				"{$this->table_name}.date_created"
339
			);
340
341
			$where .= str_replace(
342
				array(
343
					"\n",
344
					'(   (',
345
					'))',
346
				),
347
				array(
348
					'',
349
					'( (',
350
					') )',
351
				),
352
				$date_query_object->get_sql()
353
			);
354
		}
355
356
		return $where;
357
	}
358
359
	/**
360
	 * Set search where clause.
361
	 *
362
	 * @since  1.8.14
363
	 * @access private
364
	 *
365
	 * @global wpdb $wpdb
366
	 * @return string
367
	 */
368
	private function get_where_search() {
369
		$where = '';
370
371
		// Donors created for a specific date or in a date range
372
		if ( ! empty( $this->args['s'] ) && false !== strpos( $this->args['s'], ':' ) ) {
373
			$search_parts = explode( ':', $this->args['s'] );
374
375
			if ( ! empty( $search_parts[0] ) ) {
376
				switch ( $search_parts[0] ) {
377
					case 'name':
378
						$where = "AND {$this->table_name}.name LIKE '%{$search_parts[1]}%'";
379
						break;
380
381
					case 'note':
382
						$where = "AND {$this->table_name}.notes LIKE '%{$search_parts[1]}%'";
383
						break;
384
				}
385
			}
386
		}
387
388
		return $where;
389
	}
390
391
	/**
392
	 * Set user where clause.
393
	 *
394
	 * @since  1.8.14
395
	 * @access private
396
	 *
397
	 * @global wpdb $wpdb
398
	 * @return string
399
	 */
400 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...
401
		$where = '';
402
403
		// Donors create for specific wp user.
404
		if ( ! empty( $this->args['user'] ) ) {
405
			if ( ! is_array( $this->args['user'] ) ) {
406
				$this->args['user'] = explode( ',', $this->args['user'] );
407
			}
408
			$user_ids = implode( ',', array_map( 'intval', $this->args['user'] ) );
409
410
			$where .= "AND {$this->table_name}.user_id IN( {$user_ids} )";
411
		}
412
413
		return $where;
414
	}
415
416
	/**
417
	 * Set orderby query
418
	 *
419
	 * @since  1.8.14
420
	 * @access private
421
	 *
422
	 * @return string
423
	 */
424
	private function get_order_query() {
425
		$table_columns = Give()->donors->get_columns();
426
427
		$this->args['orderby'] = ! array_key_exists( $this->args['orderby'], $table_columns ) ?
428
			'id' :
429
			$this->args['orderby'];
430
431
		$this->args['orderby'] = esc_sql( $this->args['orderby'] );
432
		$this->args['order']   = esc_sql( $this->args['order'] );
433
434
		switch ( $table_columns[ $this->args['orderby'] ] ) {
435
			case '%d':
436
			case '%f':
437
				$query = "ORDER BY {$this->table_name}.{$this->args['orderby']}+0";
438
				break;
439
440
			default:
441
				$query = "ORDER BY {$this->table_name}.{$this->args['orderby']}";
442
		}
443
444
		return $query;
445
	}
446
}
447