1
|
|
|
<?php |
2
|
|
|
/** |
3
|
|
|
* GetPaid_Customers_Query class |
4
|
|
|
* |
5
|
|
|
* Contains core class used to query for customers. |
6
|
|
|
* |
7
|
|
|
* @since 1.0.19 |
8
|
|
|
*/ |
9
|
|
|
|
10
|
|
|
/** |
11
|
|
|
* Main class used for querying customers. |
12
|
|
|
* |
13
|
|
|
* @since 1.0.19 |
14
|
|
|
* |
15
|
|
|
* @see GetPaid_Subscriptions_Query::prepare_query() for information on accepted arguments. |
16
|
|
|
*/ |
17
|
|
|
class GetPaid_Customers_Query { |
18
|
|
|
|
19
|
|
|
/** |
20
|
|
|
* Query vars, after parsing |
21
|
|
|
* |
22
|
|
|
* @since 1.0.19 |
23
|
|
|
* @var array |
24
|
|
|
*/ |
25
|
|
|
public $query_vars = array(); |
26
|
|
|
|
27
|
|
|
/** |
28
|
|
|
* List of found customers. |
29
|
|
|
* |
30
|
|
|
* @since 1.0.19 |
31
|
|
|
* @var array |
32
|
|
|
*/ |
33
|
|
|
private $results; |
34
|
|
|
|
35
|
|
|
/** |
36
|
|
|
* Total number of found customers for the current query |
37
|
|
|
* |
38
|
|
|
* @since 1.0.19 |
39
|
|
|
* @var int |
40
|
|
|
*/ |
41
|
|
|
private $total_customers = 0; |
42
|
|
|
|
43
|
|
|
/** |
44
|
|
|
* The SQL query used to fetch matching customers. |
45
|
|
|
* |
46
|
|
|
* @since 1.0.19 |
47
|
|
|
* @var string |
48
|
|
|
*/ |
49
|
|
|
public $request; |
50
|
|
|
|
51
|
|
|
// SQL clauses |
52
|
|
|
|
53
|
|
|
/** |
54
|
|
|
* Contains the 'FIELDS' sql clause |
55
|
|
|
* |
56
|
|
|
* @since 1.0.19 |
57
|
|
|
* @var string |
58
|
|
|
*/ |
59
|
|
|
public $query_fields; |
60
|
|
|
|
61
|
|
|
/** |
62
|
|
|
* Contains the 'FROM' sql clause |
63
|
|
|
* |
64
|
|
|
* @since 1.0.19 |
65
|
|
|
* @var string |
66
|
|
|
*/ |
67
|
|
|
public $query_from; |
68
|
|
|
|
69
|
|
|
/** |
70
|
|
|
* Contains the 'WHERE' sql clause |
71
|
|
|
* |
72
|
|
|
* @since 1.0.19 |
73
|
|
|
* @var string |
74
|
|
|
*/ |
75
|
|
|
public $query_where; |
76
|
|
|
|
77
|
|
|
/** |
78
|
|
|
* Contains the 'ORDER BY' sql clause |
79
|
|
|
* |
80
|
|
|
* @since 1.0.19 |
81
|
|
|
* @var string |
82
|
|
|
*/ |
83
|
|
|
public $query_orderby; |
84
|
|
|
|
85
|
|
|
/** |
86
|
|
|
* Contains the 'LIMIT' sql clause |
87
|
|
|
* |
88
|
|
|
* @since 1.0.19 |
89
|
|
|
* @var string |
90
|
|
|
*/ |
91
|
|
|
public $query_limit; |
92
|
|
|
|
93
|
|
|
/** |
94
|
|
|
* Class constructor. |
95
|
|
|
* |
96
|
|
|
* @since 1.0.19 |
97
|
|
|
* |
98
|
|
|
* @param null|string|array $query Optional. The query variables. |
99
|
|
|
*/ |
100
|
|
|
public function __construct( $query = null ) { |
101
|
|
|
if ( ! is_null( $query ) ) { |
102
|
|
|
$this->prepare_query( $query ); |
103
|
|
|
$this->query(); |
104
|
|
|
} |
105
|
|
|
} |
106
|
|
|
|
107
|
|
|
/** |
108
|
|
|
* Fills in missing query variables with default values. |
109
|
|
|
* |
110
|
|
|
* @since 1.0.19 |
111
|
|
|
* |
112
|
|
|
* @param string|array $args Query vars, as passed to `GetPaid_Subscriptions_Query`. |
113
|
|
|
* @return array Complete query variables with undefined ones filled in with defaults. |
114
|
|
|
*/ |
115
|
|
|
public static function fill_query_vars( $args ) { |
116
|
|
|
$defaults = array( |
117
|
|
|
'include' => array(), |
118
|
|
|
'exclude' => array(), |
119
|
|
|
'orderby' => 'id', |
120
|
|
|
'order' => 'DESC', |
121
|
|
|
'offset' => '', |
122
|
|
|
'number' => 10, |
123
|
|
|
'paged' => 1, |
124
|
|
|
'count_total' => true, |
125
|
|
|
'fields' => 'all', |
126
|
|
|
's' => '', |
127
|
|
|
); |
128
|
|
|
|
129
|
|
|
foreach ( GetPaid_Customer_Data_Store::get_database_fields() as $field => $type ) { |
130
|
|
|
$defaults[ $field ] = 'any'; |
131
|
|
|
|
132
|
|
|
if ( '%f' === $type || '%d' === $type ) { |
133
|
|
|
$defaults[ $field . '_min' ] = ''; |
134
|
|
|
$defaults[ $field . '_max' ] = ''; |
135
|
|
|
} |
136
|
|
|
} |
137
|
|
|
|
138
|
|
|
return wp_parse_args( $args, $defaults ); |
|
|
|
|
139
|
|
|
} |
140
|
|
|
|
141
|
|
|
/** |
142
|
|
|
* Prepare the query variables. |
143
|
|
|
* |
144
|
|
|
* @since 1.0.19 |
145
|
|
|
* |
146
|
|
|
* @see self::fill_query_vars() For allowede args and their defaults. |
147
|
|
|
*/ |
148
|
|
|
public function prepare_query( $query = array() ) { |
149
|
|
|
global $wpdb; |
150
|
|
|
|
151
|
|
|
if ( empty( $this->query_vars ) || ! empty( $query ) ) { |
152
|
|
|
$this->query_limit = null; |
153
|
|
|
$this->query_vars = $this->fill_query_vars( $query ); |
154
|
|
|
} |
155
|
|
|
|
156
|
|
|
if ( ! empty( $this->query_vars['fields'] ) && 'all' !== $this->query_vars['fields'] ) { |
157
|
|
|
$this->query_vars['fields'] = wpinv_parse_list( $this->query_vars['fields'] ); |
158
|
|
|
} |
159
|
|
|
|
160
|
|
|
do_action( 'getpaid_pre_get_customers', array( &$this ) ); |
161
|
|
|
|
162
|
|
|
// Ensure that query vars are filled after 'getpaid_pre_get_customers'. |
163
|
|
|
$qv = & $this->query_vars; |
164
|
|
|
$qv = $this->fill_query_vars( $qv ); |
165
|
|
|
$table = $wpdb->prefix . 'getpaid_customers'; |
166
|
|
|
$this->query_from = "FROM $table"; |
167
|
|
|
|
168
|
|
|
// Prepare query fields. |
169
|
|
|
$this->prepare_query_fields( $qv, $table ); |
170
|
|
|
|
171
|
|
|
// Prepare query where. |
172
|
|
|
$this->prepare_query_where( $qv, $table ); |
173
|
|
|
|
174
|
|
|
// Prepare query order. |
175
|
|
|
$this->prepare_query_order( $qv, $table ); |
176
|
|
|
|
177
|
|
|
// limit |
178
|
|
|
if ( isset( $qv['number'] ) && $qv['number'] > 0 ) { |
179
|
|
|
if ( $qv['offset'] ) { |
180
|
|
|
$this->query_limit = $wpdb->prepare( 'LIMIT %d, %d', $qv['offset'], $qv['number'] ); |
181
|
|
|
} else { |
182
|
|
|
$this->query_limit = $wpdb->prepare( 'LIMIT %d, %d', $qv['number'] * ( $qv['paged'] - 1 ), $qv['number'] ); |
183
|
|
|
} |
184
|
|
|
} |
185
|
|
|
|
186
|
|
|
do_action_ref_array( 'getpaid_after_customers_query', array( &$this ) ); |
187
|
|
|
} |
188
|
|
|
|
189
|
|
|
/** |
190
|
|
|
* Prepares the query fields. |
191
|
|
|
* |
192
|
|
|
* @since 1.0.19 |
193
|
|
|
* |
194
|
|
|
* @param array $qv Query vars. |
195
|
|
|
* @param string $table Table name. |
196
|
|
|
*/ |
197
|
|
|
protected function prepare_query_fields( &$qv, $table ) { |
198
|
|
|
|
199
|
|
|
if ( is_array( $qv['fields'] ) ) { |
200
|
|
|
$qv['fields'] = array_unique( $qv['fields'] ); |
201
|
|
|
$allowed_fields = array_keys( GetPaid_Customer_Data_Store::get_database_fields() ); |
202
|
|
|
|
203
|
|
|
$query_fields = array(); |
204
|
|
|
foreach ( $qv['fields'] as $field ) { |
205
|
|
|
if ( ! in_array( $field, $allowed_fields ) ) { |
206
|
|
|
continue; |
207
|
|
|
} |
208
|
|
|
|
209
|
|
|
$field = sanitize_key( $field ); |
210
|
|
|
$query_fields[] = "$table.`$field`"; |
211
|
|
|
} |
212
|
|
|
$this->query_fields = implode( ',', $query_fields ); |
213
|
|
|
} else { |
214
|
|
|
$this->query_fields = "$table.*"; |
215
|
|
|
} |
216
|
|
|
|
217
|
|
|
if ( isset( $qv['count_total'] ) && $qv['count_total'] ) { |
218
|
|
|
$this->query_fields = 'SQL_CALC_FOUND_ROWS ' . $this->query_fields; |
219
|
|
|
} |
220
|
|
|
|
221
|
|
|
} |
222
|
|
|
|
223
|
|
|
/** |
224
|
|
|
* Prepares the query where. |
225
|
|
|
* |
226
|
|
|
* @since 1.0.19 |
227
|
|
|
* |
228
|
|
|
* @param array $qv Query vars. |
229
|
|
|
* @param string $table Table name. |
230
|
|
|
*/ |
231
|
|
|
protected function prepare_query_where( &$qv, $table ) { |
232
|
|
|
global $wpdb; |
233
|
|
|
$this->query_where = 'WHERE 1=1'; |
234
|
|
|
|
235
|
|
|
// Fields. |
236
|
|
|
foreach ( GetPaid_Customer_Data_Store::get_database_fields() as $field => $type ) { |
237
|
|
|
if ( 'any' !== $qv[ $field ] ) { |
238
|
|
|
|
239
|
|
|
// In. |
240
|
|
|
if ( is_array( $qv[ $field ] ) ) { |
241
|
|
|
$in = join( ',', array_fill( 0, count( $qv[ $field ] ), $type ) ); |
242
|
|
|
$this->query_where .= $wpdb->prepare( " AND $table.`status` IN ( $in )", $qv[ $field ] ); |
243
|
|
|
} elseif ( ! empty( $qv[ $field ] ) ) { |
244
|
|
|
$this->query_where .= $wpdb->prepare( " AND $table.`$field` = $type", $qv[ $field ] ); |
245
|
|
|
} |
246
|
|
|
} |
247
|
|
|
|
248
|
|
|
// Min/Max. |
249
|
|
|
if ( '%f' === $type || '%d' === $type ) { |
250
|
|
|
|
251
|
|
|
// Min. |
252
|
|
|
if ( is_numeric( $qv[ $field . '_min' ] ) ) { |
253
|
|
|
$this->query_where .= $wpdb->prepare( " AND $table.`$field` >= $type", $qv[ $field . '_min' ] ); |
254
|
|
|
} |
255
|
|
|
|
256
|
|
|
// Max. |
257
|
|
|
if ( is_numeric( $qv[ $field . '_max' ] ) ) { |
258
|
|
|
$this->query_where .= $wpdb->prepare( " AND $table.`$field` <= $type", $qv[ $field . '_max' ] ); |
259
|
|
|
} |
260
|
|
|
} |
261
|
|
|
} |
262
|
|
|
|
263
|
|
|
if ( ! empty( $qv['include'] ) ) { |
264
|
|
|
$include = implode( ',', wp_parse_id_list( $qv['include'] ) ); |
265
|
|
|
$this->query_where .= " AND $table.`id` IN ($include)"; |
266
|
|
|
} elseif ( ! empty( $qv['exclude'] ) ) { |
267
|
|
|
$exclude = implode( ',', wp_parse_id_list( $qv['exclude'] ) ); |
268
|
|
|
$this->query_where .= " AND $table.`id` NOT IN ($exclude)"; |
269
|
|
|
} |
270
|
|
|
|
271
|
|
|
// Date queries are allowed for the customer creation date. |
272
|
|
|
if ( ! empty( $qv['date_created_query'] ) && is_array( $qv['date_created_query'] ) ) { |
273
|
|
|
$date_created_query = new WP_Date_Query( $qv['date_created_query'], "$table.date_created" ); |
274
|
|
|
$this->query_where .= $date_created_query->get_sql(); |
275
|
|
|
} |
276
|
|
|
|
277
|
|
|
// Search. |
278
|
|
|
if ( ! empty( $qv['s'] ) ) { |
279
|
|
|
$this->query_where .= $this->get_search_sql( $qv['s'] ); |
280
|
|
|
} |
281
|
|
|
} |
282
|
|
|
|
283
|
|
|
/** |
284
|
|
|
* Used internally to generate an SQL string for searching across multiple columns |
285
|
|
|
* |
286
|
|
|
* @since 1.2.7 |
287
|
|
|
* |
288
|
|
|
* @global wpdb $wpdb WordPress database abstraction object. |
289
|
|
|
* |
290
|
|
|
* @param string $string The string to search for. |
291
|
|
|
* @return string |
292
|
|
|
*/ |
293
|
|
|
protected function get_search_sql( $string ) { |
294
|
|
|
global $wpdb; |
295
|
|
|
|
296
|
|
|
$searches = array(); |
297
|
|
|
$string = trim( $string, '%' ); |
298
|
|
|
$like = '%' . $wpdb->esc_like( $string ) . '%'; |
299
|
|
|
|
300
|
|
|
foreach ( array_keys( GetPaid_Customer_Data_Store::get_database_fields() ) as $col ) { |
301
|
|
|
if ( 'id' === $col || 'user_id' === $col ) { |
302
|
|
|
$searches[] = $wpdb->prepare( "$col = %s", $string ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared |
303
|
|
|
} else { |
304
|
|
|
$searches[] = $wpdb->prepare( "$col LIKE %s", $like ); // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared |
305
|
|
|
} |
306
|
|
|
} |
307
|
|
|
|
308
|
|
|
return ' AND (' . implode( ' OR ', $searches ) . ')'; |
309
|
|
|
} |
310
|
|
|
|
311
|
|
|
/** |
312
|
|
|
* Prepares the query order. |
313
|
|
|
* |
314
|
|
|
* @since 1.0.19 |
315
|
|
|
* |
316
|
|
|
* @param array $qv Query vars. |
317
|
|
|
* @param string $table Table name. |
318
|
|
|
*/ |
319
|
|
|
protected function prepare_query_order( &$qv, $table ) { |
320
|
|
|
|
321
|
|
|
// sorting. |
322
|
|
|
$qv['order'] = isset( $qv['order'] ) ? strtoupper( $qv['order'] ) : ''; |
323
|
|
|
$order = $this->parse_order( $qv['order'] ); |
324
|
|
|
|
325
|
|
|
// Default order is by 'id' (latest customers). |
326
|
|
|
if ( empty( $qv['orderby'] ) ) { |
327
|
|
|
$qv['orderby'] = array( 'id' ); |
328
|
|
|
} |
329
|
|
|
|
330
|
|
|
// 'orderby' values may be an array, comma- or space-separated list. |
331
|
|
|
$ordersby = array_filter( wpinv_parse_list( $qv['orderby'] ) ); |
332
|
|
|
|
333
|
|
|
$orderby_array = array(); |
334
|
|
|
foreach ( $ordersby as $_key => $_value ) { |
335
|
|
|
|
336
|
|
|
if ( is_int( $_key ) ) { |
337
|
|
|
// Integer key means this is a flat array of 'orderby' fields. |
338
|
|
|
$_orderby = $_value; |
339
|
|
|
$_order = $order; |
340
|
|
|
} else { |
341
|
|
|
// Non-integer key means that the key is the field and the value is ASC/DESC. |
342
|
|
|
$_orderby = $_key; |
343
|
|
|
$_order = $_value; |
344
|
|
|
} |
345
|
|
|
|
346
|
|
|
$parsed = $this->parse_orderby( $_orderby, $table ); |
347
|
|
|
|
348
|
|
|
if ( $parsed ) { |
349
|
|
|
$orderby_array[] = $parsed . ' ' . $this->parse_order( $_order ); |
350
|
|
|
} |
351
|
|
|
} |
352
|
|
|
|
353
|
|
|
// If no valid clauses were found, order by id. |
354
|
|
|
if ( empty( $orderby_array ) ) { |
355
|
|
|
$orderby_array[] = "id $order"; |
356
|
|
|
} |
357
|
|
|
|
358
|
|
|
$this->query_orderby = 'ORDER BY ' . implode( ', ', $orderby_array ); |
359
|
|
|
|
360
|
|
|
} |
361
|
|
|
|
362
|
|
|
/** |
363
|
|
|
* Execute the query, with the current variables. |
364
|
|
|
* |
365
|
|
|
* @since 1.0.19 |
366
|
|
|
* |
367
|
|
|
* @global wpdb $wpdb WordPress database abstraction object. |
368
|
|
|
*/ |
369
|
|
|
public function query() { |
370
|
|
|
global $wpdb; |
371
|
|
|
|
372
|
|
|
$qv =& $this->query_vars; |
373
|
|
|
|
374
|
|
|
// Return a non-null value to bypass the default GetPaid customers query and remember to set the |
375
|
|
|
// total_customers property. |
376
|
|
|
$this->results = apply_filters_ref_array( 'getpaid_customers_pre_query', array( null, &$this ) ); |
377
|
|
|
|
378
|
|
|
if ( null === $this->results ) { |
379
|
|
|
$this->request = "SELECT $this->query_fields $this->query_from $this->query_where $this->query_orderby $this->query_limit"; |
380
|
|
|
|
381
|
|
|
if ( ( is_array( $qv['fields'] ) && 1 !== count( $qv['fields'] ) ) || 'all' === $qv['fields'] ) { |
382
|
|
|
$this->results = $wpdb->get_results( $this->request ); |
383
|
|
|
} else { |
384
|
|
|
$this->results = $wpdb->get_col( $this->request ); |
385
|
|
|
} |
386
|
|
|
|
387
|
|
|
if ( isset( $qv['count_total'] ) && $qv['count_total'] ) { |
388
|
|
|
$found_customers_query = apply_filters( 'getpaid_found_customers_query', 'SELECT FOUND_ROWS()', $this ); |
389
|
|
|
$this->total_customers = (int) $wpdb->get_var( $found_customers_query ); |
390
|
|
|
} |
391
|
|
|
} |
392
|
|
|
|
393
|
|
|
if ( 'all' === $qv['fields'] ) { |
394
|
|
|
foreach ( $this->results as $key => $customer ) { |
395
|
|
|
$this->set_cache( $customer->id, $customer, 'getpaid_customers' ); |
396
|
|
|
$this->set_cache( $customer->user_id, $customer->id, 'getpaid_customer_ids_by_user_id' ); |
397
|
|
|
$this->set_cache( $customer->email, $customer->id, 'getpaid_customer_ids_by_email' ); |
398
|
|
|
$this->results[ $key ] = new GetPaid_Customer( $customer ); |
399
|
|
|
} |
400
|
|
|
} |
401
|
|
|
|
402
|
|
|
} |
403
|
|
|
|
404
|
|
|
/** |
405
|
|
|
* Set cache |
406
|
|
|
* |
407
|
|
|
* @param string $id |
408
|
|
|
* @param mixed $data |
409
|
|
|
* @param string $group |
410
|
|
|
* @param integer $expire |
411
|
|
|
* @return boolean |
412
|
|
|
*/ |
413
|
|
|
public function set_cache( $key, $data, $group = '', $expire = 0 ) { |
414
|
|
|
|
415
|
|
|
if ( empty( $key ) ) { |
416
|
|
|
return false; |
417
|
|
|
} |
418
|
|
|
|
419
|
|
|
wp_cache_set( $key, $data, $group, $expire ); |
420
|
|
|
} |
421
|
|
|
|
422
|
|
|
/** |
423
|
|
|
* Retrieve query variable. |
424
|
|
|
* |
425
|
|
|
* @since 1.0.19 |
426
|
|
|
* |
427
|
|
|
* @param string $query_var Query variable key. |
428
|
|
|
* @return mixed |
429
|
|
|
*/ |
430
|
|
|
public function get( $query_var ) { |
431
|
|
|
if ( isset( $this->query_vars[ $query_var ] ) ) { |
432
|
|
|
return $this->query_vars[ $query_var ]; |
433
|
|
|
} |
434
|
|
|
|
435
|
|
|
return null; |
436
|
|
|
} |
437
|
|
|
|
438
|
|
|
/** |
439
|
|
|
* Set query variable. |
440
|
|
|
* |
441
|
|
|
* @since 1.0.19 |
442
|
|
|
* |
443
|
|
|
* @param string $query_var Query variable key. |
444
|
|
|
* @param mixed $value Query variable value. |
445
|
|
|
*/ |
446
|
|
|
public function set( $query_var, $value ) { |
447
|
|
|
$this->query_vars[ $query_var ] = $value; |
448
|
|
|
} |
449
|
|
|
|
450
|
|
|
/** |
451
|
|
|
* Return the list of customers. |
452
|
|
|
* |
453
|
|
|
* @since 1.0.19 |
454
|
|
|
* |
455
|
|
|
* @return GetPaid_Customer[]|array Found customers. |
456
|
|
|
*/ |
457
|
|
|
public function get_results() { |
458
|
|
|
return $this->results; |
459
|
|
|
} |
460
|
|
|
|
461
|
|
|
/** |
462
|
|
|
* Return the total number of customers for the current query. |
463
|
|
|
* |
464
|
|
|
* @since 1.0.19 |
465
|
|
|
* |
466
|
|
|
* @return int Number of total customers. |
467
|
|
|
*/ |
468
|
|
|
public function get_total() { |
469
|
|
|
return $this->total_customers; |
470
|
|
|
} |
471
|
|
|
|
472
|
|
|
/** |
473
|
|
|
* Parse and sanitize 'orderby' keys passed to the customers query. |
474
|
|
|
* |
475
|
|
|
* @since 1.0.19 |
476
|
|
|
* |
477
|
|
|
* @param string $orderby Alias for the field to order by. |
478
|
|
|
* @param string $table The current table. |
479
|
|
|
* @return string Value to use in the ORDER clause, if `$orderby` is valid. |
480
|
|
|
*/ |
481
|
|
|
protected function parse_orderby( $orderby, $table ) { |
482
|
|
|
|
483
|
|
|
$_orderby = ''; |
484
|
|
|
if ( in_array( $orderby, array_keys( GetPaid_Customer_Data_Store::get_database_fields() ), true ) ) { |
485
|
|
|
$_orderby = "$table.`$orderby`"; |
486
|
|
|
} elseif ( 'id' === strtolower( $orderby ) ) { |
487
|
|
|
$_orderby = "$table.id"; |
488
|
|
|
} elseif ( 'include' === $orderby && ! empty( $this->query_vars['include'] ) ) { |
489
|
|
|
$include = wp_parse_id_list( $this->query_vars['include'] ); |
490
|
|
|
$include_sql = implode( ',', $include ); |
491
|
|
|
$_orderby = "FIELD( $table.id, $include_sql )"; |
492
|
|
|
} |
493
|
|
|
|
494
|
|
|
return $_orderby; |
495
|
|
|
} |
496
|
|
|
|
497
|
|
|
/** |
498
|
|
|
* Parse an 'order' query variable and cast it to ASC or DESC as necessary. |
499
|
|
|
* |
500
|
|
|
* @since 1.0.19 |
501
|
|
|
* |
502
|
|
|
* @param string $order The 'order' query variable. |
503
|
|
|
* @return string The sanitized 'order' query variable. |
504
|
|
|
*/ |
505
|
|
|
protected function parse_order( $order ) { |
506
|
|
|
if ( ! is_string( $order ) || empty( $order ) ) { |
|
|
|
|
507
|
|
|
return 'DESC'; |
508
|
|
|
} |
509
|
|
|
|
510
|
|
|
if ( 'ASC' === strtoupper( $order ) ) { |
511
|
|
|
return 'ASC'; |
512
|
|
|
} else { |
513
|
|
|
return 'DESC'; |
514
|
|
|
} |
515
|
|
|
} |
516
|
|
|
|
517
|
|
|
} |
518
|
|
|
|
$args
can contain request data and is used in variable name context(s) leading to a potential security vulnerability.2 paths for user data to reach this point
$_GET,
and Data is passed throughrawurlencode_deep()
, and Data is passed throughwpinv_clean()
, andwpinv_clean(rawurlencode_deep($_GET[$field]))
is assigned to$query
in includes/admin/class-wpinv-customers-table.php on line 239$_GET,
and Data is passed throughrawurlencode_deep()
, and Data is passed throughwpinv_clean()
, andwpinv_clean(rawurlencode_deep($_GET[$field]))
is assigned to$query
in includes/admin/class-wpinv-customers-table.php on line 239
getpaid_get_customers()
is calledin includes/admin/class-wpinv-customers-table.php on line 256
$args
in includes/user-functions.php on line 20
in includes/user-functions.php on line 33
$query
in includes/class-getpaid-customers-query.php on line 100
in includes/class-getpaid-customers-query.php on line 102
$query
in includes/class-getpaid-customers-query.php on line 148
in includes/class-getpaid-customers-query.php on line 153
$args
in includes/class-getpaid-customers-query.php on line 115
$_GET,
and Data is passed throughrawurlencode_deep()
, and Data is passed throughwpinv_clean()
, andwpinv_clean(rawurlencode_deep($_GET[$field]))
is assigned to$query
in includes/admin/class-wpinv-customers-table.php on line 232$_GET,
and Data is passed throughrawurlencode_deep()
, and Data is passed throughwpinv_clean()
, andwpinv_clean(rawurlencode_deep($_GET[$field]))
is assigned to$query
in includes/admin/class-wpinv-customers-table.php on line 232
getpaid_get_customers()
is calledin includes/admin/class-wpinv-customers-table.php on line 256
$args
in includes/user-functions.php on line 20
in includes/user-functions.php on line 33
$query
in includes/class-getpaid-customers-query.php on line 100
in includes/class-getpaid-customers-query.php on line 102
$query
in includes/class-getpaid-customers-query.php on line 148
in includes/class-getpaid-customers-query.php on line 153
$args
in includes/class-getpaid-customers-query.php on line 115
Used in variable context
wp_parse_args()
is calledin includes/class-getpaid-customers-query.php on line 137
$args
in wordpress/wp-includes/functions.php on line 4821
wp_parse_str()
is calledin wordpress/wp-includes/functions.php on line 4827
$input_string
in wordpress/wp-includes/formatting.php on line 5148
parse_str()
is calledin wordpress/wp-includes/formatting.php on line 5149
General Strategies to prevent injection
In general, it is advisable to prevent any user-data to reach this point. This can be done by white-listing certain values:
For numeric data, we recommend to explicitly cast the data: