Test Setup Failed
Push — issue/3917 ( 5fcf3b...6ce93d )
by Ravinder
08:41
created

Give_Donation_Stats::get_donation_statics()   B

Complexity

Conditions 6
Paths 15

Size

Total Lines 78

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
nc 15
nop 1
dl 0
loc 78
rs 7.8577
c 0
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * Earnings / Sales Stats
4
 *
5
 * @package     Give
6
 * @subpackage  Classes/Stats
7
 * @copyright   Copyright (c) 2018, GiveWP
8
 * @license     https://opensource.org/licenses/gpl-license GNU Public License
9
 * @since       2.4.1
10
 */
11
12
// Exit if accessed directly.
13
if ( ! defined( 'ABSPATH' ) ) {
14
	exit;
15
}
16
17
/**
18
 * Give_Donation_Stats Class
19
 *
20
 * This class is for retrieving stats for earnings and sales.
21
 *
22
 * Stats can be retrieved for date ranges and pre-defined periods.
23
 *
24
 * @since 2.4.1
25
 */
26
class Give_Donation_Stats extends Give_Stats {
27
	/**
28
	 * Give_Donation_Stats constructor.
29
	 *
30
	 * @param array $query
31
	 */
32
	public function __construct( array $query = array() ) {
33
		// Add additional default query params
34
		$this->query_var_defaults = array_merge( array(
35
			'status'     => array( 'publish' ),
36
			'give_forms' => array(),
37
			'gateways'   => array(),
38
		), $this->query_var_defaults );
39
40
		parent::__construct( $query );
41
	}
42
43
	/**
44
	 * Retrieve sale stats
45
	 *
46
	 * @since  2.4.1
47
	 * @access public
48
	 *
49
	 * @param array $query
50
	 *
51
	 * @return stdClass
52
	 */
53
	public function get_sales( $query = array() ) {
54
		// Add table and column name to query_vars to assist with date query generation.
55
		$this->query_vars['table']  = $this->get_db()->posts;
56
		$this->query_vars['column'] = $this->query_vars['inner_join_at'] = 'ID';
57
58
		// Run pre-query checks and maybe generate SQL.
59
		$this->pre_query( $query );
60
61
		$allowed_functions = array( 'COUNT', 'AVG' );
62
63
		$is_relative = true === $this->query_vars['relative'];
64
65
		$function = isset( $this->query_vars['function'] ) && in_array( $this->query_vars['function'], $allowed_functions, true )
66
			? "{$this->query_vars['function']}({$this->query_vars['table']}.{$this->query_vars['column']})"
67
			: "COUNT({$this->query_vars['table']}.{$this->query_vars['column']})";
68
69
		if ( $is_relative ) {
70
			$sql = "SELECT IFNULL(COUNT({$this->query_vars['table']}.{$this->query_vars['column']}), 0) AS sales, IFNULL(relative, 0) AS relative
71
					FROM {$this->query_vars['table']}
72
					CROSS JOIN (
73
						SELECT IFNULL(COUNT({$this->query_vars['table']}.{$this->query_vars['column']}), 0) AS relative
74
						FROM {$this->query_vars['table']}
75
						{$this->query_vars['inner_join_sql']}
76
						WHERE 1=1
77
						{$this->query_vars['where_sql']}
78
						{$this->query_vars['relative_date_sql']}
79
					) o
80
					WHERE 1=1
81
					{$this->query_vars['where_sql']}
82
					{$this->query_vars['date_sql']}
83
					";
84
		} else {
85
			$sql = "SELECT IFNULL({$function}, 0) AS sales
86
					FROM {$this->query_vars['table']}
87
					{$this->query_vars['inner_join_sql']}
88
					WHERE 1=1
89
					{$this->query_vars['where_sql']}
90
					{$this->query_vars['date_sql']}
91
					";
92
		}
93
94
		$result = $this->get_db()->get_row( $sql );
95
96
		if ( is_null( $result ) ) {
97
			$result        = new stdClass();
98
			$result->sales = $result->relative = 0;
99
		}
100
101
		if ( $is_relative ) {
102
			$result->growth = $this->get_growth( $result->sales, $result->relative );
103
		}
104
105
		// Reset query vars.
106
		$this->reset_query();
107
108
		return $result;
109
	}
110
111
112
	/**
113
	 * Retrieve earning stats
114
	 *
115
	 * @since  2.4.1
116
	 * @access public
117
	 *
118
	 * @param array $query
119
	 *
120
	 * @return stdClass
121
	 */
122
	public function get_earnings( $query = array() ) {
123
		// Add table and column name to query_vars to assist with date query generation.
124
		$this->query_vars['table']         = $this->get_db()->donationmeta;
125
		$this->query_vars['column']        = 'meta_value';
126
127
		// Run pre-query checks and maybe generate SQL.
128
		$this->pre_query( $query );
129
130
		$allowed_functions = array( 'SUM', 'AVG' );
131
132
		$is_relative = true === $this->query_vars['relative'];
133
134
		$function = isset( $this->query_vars['function'] ) && in_array( $this->query_vars['function'], $allowed_functions, true )
135
			? "{$this->query_vars['function']}({$this->query_vars['table']}.{$this->query_vars['column']})"
136
			: "SUM({$this->query_vars['table']}.{$this->query_vars['column']})";
137
138
		if ( $is_relative ) {
139
			$sql = "SELECT IFNULL({$function}, 0) AS total, IFNULL(relative, 0) AS relative
140
					FROM {$this->query_vars['table']}
141
					CROSS JOIN (
142
						SELECT IFNULL($function, 0) AS relative
143
						FROM {$this->query_vars['table']}
144
						INNER JOIN {$this->get_db()->posts} on {$this->get_db()->posts}.ID = {$this->query_vars['table']}.{$this->query_vars['inner_join_at']}
145
						{$this->query_vars['inner_join_sql']}
146
						WHERE 1=1
147
						{$this->query_vars['where_sql']}
148
						{$this->query_vars['relative_date_sql']}
149
						AND {$this->query_vars['table']}.meta_key='_give_payment_total'
150
					) o
151
					INNER JOIN {$this->get_db()->posts} on {$this->get_db()->posts}.ID = {$this->query_vars['table']}.{$this->query_vars['inner_join_at']}
152
					{$this->query_vars['inner_join_sql']}
153
					WHERE 1=1
154
					{$this->query_vars['where_sql']}
155
					{$this->query_vars['date_sql']}
156
					AND {$this->query_vars['table']}.meta_key='_give_payment_total'
157
					";
158
		} else {
159
			$sql = "SELECT IFNULL({$function}, 0) AS total
160
					FROM {$this->query_vars['table']}
161
					INNER JOIN {$this->get_db()->posts} on {$this->get_db()->posts}.ID = {$this->query_vars['table']}.{$this->query_vars['inner_join_at']}
162
					{$this->query_vars['inner_join_sql']}
163
					WHERE 1=1
164
					{$this->query_vars['where_sql']}
165
					{$this->query_vars['date_sql']}
166
					AND {$this->query_vars['table']}.meta_key='_give_payment_total'
167
					";
168
		}
169
170
		$result = $this->get_db()->get_row( $sql );
171
172
		if ( is_null( $result ) ) {
173
			$result        = new stdClass();
174
			$result->total = $result->relative = $result->growth = 0;
175
		}
176
177
		if ( $is_relative ) {
178
			$result->growth = $this->get_growth( $result->total, $result->relative );
179
		}
180
181
		// Reset query vars.
182
		$this->reset_query();
183
184
		return $result;
185
	}
186
187
	/**
188
	 * Get donation earning and sales information
189
	 *
190
	 * @since  2.4.1
191
	 * @access public
192
	 *
193
	 * @param array $query
194
	 *
195
	 * @return stdClass
196
	 */
197
	public function get_donation_statistics( $query = array() ) {
198
		$day_by_day = true;
199
200
		$this->query_vars['table']  = $this->get_db()->posts;
201
		$this->query_vars['column'] = 'post_date_gmt';
202
203
		$column = "{$this->query_vars['table']}.{$this->query_vars['column']}";
204
205
		$sql_clauses = array(
206
			'select'  => "YEAR({$column}) AS year, MONTH({$column}) AS month, DAY({$column}) AS day",
207
			'groupby' => "YEAR({$column}), MONTH({$column}), DAY({$column})",
208
			'orderby' => "YEAR({$column}), MONTH({$column}), DAY({$column})",
209
		);
210
0 ignored issues
show
Coding Style introduced by
Functions must not contain multiple empty lines in a row; found 2 empty lines
Loading history...
211
212
		$this->pre_query( $query );
213
214
		$sql = "SELECT COUNT(ID) AS sales, SUM(m1.meta_value) AS earnings, {$sql_clauses['select']}
215
					FROM {$this->query_vars['table']}
216
					INNER JOIN {$this->get_db()->donationmeta} as m1 on m1.donation_id={$this->query_vars['table']}.{$this->query_vars['inner_join_at']}
217
					{$this->query_vars['where_sql']}
218
					AND m1.meta_key='_give_payment_total'
219
					{$this->query_vars['date_sql']}
220
                    GROUP BY {$sql_clauses['groupby']}
221
                    ORDER BY {$sql_clauses['orderby']} ASC";
222
223
		$results = $this->get_db()->get_results( $sql );
224
225
		$sales    = array();
226
		$earnings = array();
227
		$dates = array(
228
			'start' => $this->query_vars['start_date'],
229
			'end' => $this->query_vars['end_date']
230
		);
231
232
		// Initialise all arrays with timestamps and set values to 0.
233
		while ( strtotime( $dates['start']->copy()->format( 'mysql' ) ) <= strtotime( $dates['end']->copy()->format( 'mysql' ) ) ) {
234
			$day = ( true === $day_by_day )
235
				? $dates['start']->day
236
				: 1;
237
238
			$timestamp = Give_Date::create( $dates['start']->year, $dates['start']->month, $day, 0, 0, 0, $this->date->getWpTimezone() )->timestamp;
239
240
			$sales[ $timestamp ]['x']    = $earnings[ $timestamp ]['x'] = $timestamp * 1000;
241
			$sales[ $timestamp ]['y']    = 0;
242
			$earnings[ $timestamp ]['y'] = 0.00;
243
244
			$dates['start'] = ( true === $day_by_day )
245
				? $dates['start']->addDays( 1 )
246
				: $dates['start']->addMonth( 1 );
247
		}
248
249
		foreach ( $results as $result ) {
250
			$day = ( true === $day_by_day )
251
				? $result->day
252
				: 1;
253
254
			$timestamp = Give_Date::create( $result->year, $result->month, $day, 0, 0, 0, $this->date->getWpTimezone() )->timestamp;
255
256
			$sales[ $timestamp ]['y']  = $result->sales;
257
			$earnings[ $timestamp ]['y'] = floatval( $result->earnings );
258
		}
259
260
		$sales    = array_values( $sales );
261
		$earnings = array_values( $earnings );
262
263
		$results = new stdClass();
264
265
		$results->sales    = $sales;
266
		$results->earnings = $earnings;
267
268
		// Set query_vars in result
269
		$results->query_vars = $this->query_vars;
270
271
		$this->reset_query();
272
273
		return $results;
274
	}
275
276
	/**
277
	 * Get the best selling forms
278
	 *
279
	 * @since  2.4.1
280
	 * @access public
281
	 *
282
	 * @param array $query Array of query arguments
283
	 *
284
	 * @return string
285
	 */
286
	public function get_busiest_day( $query = array() ) {
287
		// Add table and column name to query_vars to assist with date query generation.
288
		$this->query_vars['table']  = $this->get_db()->posts;
289
		$this->query_vars['column'] = 'post_date';
290
291
		$this->pre_query( $query );
292
293
		$sql = "SELECT DAYOFWEEK({$this->query_vars['column']}) AS day, COUNT(ID) as total
294
				FROM {$this->query_vars['table']}
295
				{$this->query_vars['inner_join_sql']}
296
				WHERE 1=1
297
				{$this->query_vars['where_sql'] }
298
				{$this->query_vars['date_sql'] }
299
				GROUP BY day
300
				ORDER BY day DESC
301
				LIMIT 1";
302
303
		$result = $this->get_db()->get_row( $sql );
304
305
		$day = is_null( $result )
306
			? ''
307
			: Give_Date::getDays()[ $result->day - 1 ];
308
309
		$this->reset_query();
310
311
		return $day;
312
	}
313
314
	/**
315
	 * Get the best selling forms
316
	 * @todo   : make this function dynamic with new api
317
	 *
318
	 * @since  2.4.1
319
	 * @access public
320
	 * @global wpdb $wpdb
321
	 *
322
	 * @param       $number int The number of results to retrieve with the default set to 10.
323
	 *
324
	 * @return array       Best selling forms
325
	 */
326
	public function get_best_selling( $number = 10 ) {
327
		$meta_table = __give_v20_bc_table_details( 'form' );
328
329
		$give_forms = $this->get_db()->get_results(
330
			$this->get_db()->prepare(
331
				"SELECT {$meta_table['column']['id']} as form_id, max(meta_value) as sales
332
				FROM {$meta_table['name']} WHERE meta_key='_give_form_sales' AND meta_value > 0
333
				GROUP BY meta_value+0
334
				DESC LIMIT %d;", $number
335
			) );
0 ignored issues
show
Coding Style introduced by
This line of the multi-line function call does not seem to be indented correctly. Expected 8 spaces, but found 12.
Loading history...
336
337
		return $give_forms;
338
	}
339
340
	/**
341
	 * Get most valuable cause
342
	 *
343
	 * @since  2.4.1
344
	 * @access public
345
	 *
346
	 * @param array $query
347
	 *
348
	 * @return int
349
	 */
350
	public function get_most_valuable_cause( $query = array() ) {
351
		$donation_col_name = Give()->payment_meta->get_meta_type() . '_id';
352
353
		// Add table and column name to query_vars to assist with date query generation.
354
		$this->query_vars['table']  = $this->get_db()->donationmeta;
355
		$this->query_vars['column'] = 'meta_value';
356
357
		$this->pre_query( $query );
358
359
		$sql = "SELECT {$this->query_vars['table']}.{$this->query_vars['column']} as form, COUNT({$this->query_vars['table']}.{$donation_col_name}) as total_donation
360
			FROM {$this->query_vars['table']}
361
			INNER JOIN {$this->get_db()->posts} ON {$this->query_vars['table']}.{$donation_col_name}={$this->get_db()->posts}.ID
362
			{$this->query_vars['inner_join_sql']}
363
			WHERE 1=1
364
			{$this->query_vars['where_sql']}
365
			{$this->query_vars['date_sql']}
366
			AND {$this->query_vars['table']}.meta_key='_give_payment_form_id'
367
			GROUP BY form
368
			ORDER BY total_donation DESC
369
			LIMIT 1
370
			";
371
372
		$result = $this->get_db()->get_row( $sql );
373
374
		$form = is_null( $result ) ? 0 : $result->form;
375
376
		return absint( $form );
377
	}
378
379
	/**
380
	 * Calculate number of refunded donations.
381
	 *
382
	 * @since 2.4.1
383
	 * @acess public
384
	 *
385
	 * @param array $query
386
	 *
387
	 * @return stdClass
388
	 */
389 View Code Duplication
	public function get_refund_count( $query = array() ) {
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...
390
		$query['status'] = isset( $query['status'] )
391
			? $query['status']
392
			: array( 'refunded' );
393
394
		return $this->get_sales( $query );
395
	}
396
397
	/**
398
	 * Calculate amount of refunded donations.
399
	 *
400
	 * @since 2.4.1
401
	 * @acess public
402
	 *
403
	 * @param array $query
404
	 *
405
	 * @return stdClass
406
	 */
407 View Code Duplication
	public function get_refund( $query = array() ) {
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...
408
		$query['status'] = isset( $query['status'] )
409
			? $query['status']
410
			: array( 'refunded' );
411
412
		return $this->get_earnings( $query );
413
	}
414
415
	/**
416
	 *  Set meta query
417
	 *
418
	 * @since  2.4.1
419
	 * @access public
420
	 *
421
	 * @param string $query_key
422
	 * @param string $meta_key
423
	 *
424
	 */
425
	private function set_meta_sql( $query_key, $meta_key ) {
426
		// Bailout.
427
		if ( empty( $this->query_vars[ $query_key ] ) ) {
428
			return;
429
		}
430
431
		$donation_col_name              = Give()->payment_meta->get_meta_type() . '_id';
432
		$this->query_vars[ $query_key ] = (array) $this->query_vars[ $query_key ];
433
434
		$alias = "m{$this->get_counter( $this->get_db()->donationmeta )}";
435
		$data  = implode( '\',\'', $this->query_vars[ $query_key ] );
436
437
		$this->query_vars['inner_join_sql'][] = "INNER JOIN {$this->get_db()->donationmeta} as {$alias} on {$alias}.{$donation_col_name}={$this->query_vars['table']}.{$this->query_vars['inner_join_at']}";
438
439
		$this->query_vars['where_sql'][] = " AND {$alias}.meta_key='{$meta_key}'";
440
		$this->query_vars['where_sql'][] = " AND {$alias}.meta_value IN ('{$data}')";
441
0 ignored issues
show
Coding Style introduced by
Functions must not contain multiple empty lines in a row; found 2 empty lines
Loading history...
442
443
		// Set counter.
444
		$this->set_counter( $this->get_db()->donationmeta );
445
	}
446
447
	/**
448
	 * Pre process query
449
	 *
450
	 * @since  2.4.1
451
	 * @access protected
452
	 *
453
	 * @param array $query
454
	 */
455
	protected function pre_query( $query = array() ) {
456
		parent::pre_query( $query );
457
458
		$this->query_vars['function'] = strtoupper( $this->query_vars['function'] );
459
460
		$sql_types = array( 'relative_date_sql', 'date_sql', 'inner_join_sql', 'where_sql' );
461
462
		// Set empty sql collection string to array
463
		foreach ( $sql_types as $sql_type ) {
464
			$this->query_vars[$sql_type] = array_filter( (array) $this->query_vars['where_sql'] );
0 ignored issues
show
introduced by
Array keys should be surrounded by spaces unless they contain a string or an integer.
Loading history...
465
		}
466
467
		// Where sql.
468
		if ( ! empty( $this->query_vars['status'] ) ) {
469
			if ( 'any' !== $this->query_vars['status'] ) {
470
				$this->query_vars['status'] = array_map( 'sanitize_text_field', $this->query_vars['status'] );
471
472
				$placeholders = implode( ', ', array_fill( 0, count( $this->query_vars['status'] ), '%s' ) );
473
474
				$this->query_vars['where_sql'][] = $this->get_db()->prepare( "AND {$this->get_db()->posts}.post_status IN ({$placeholders})", $this->query_vars['status'] );
475
			}
476
		}
477
		$this->query_vars['where_sql'][] = $this->get_db()->prepare( "AND {$this->get_db()->posts}.post_type=%s", 'give_payment' );
478
479
		// Date sql.
480 View Code Duplication
		if ( $this->query_vars["start_date"] ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
Coding Style Comprehensibility introduced by
The string literal start_date 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...
481
			$this->query_vars['date_sql'][] = "AND {$this->get_db()->posts}.post_date>='{$this->query_vars["start_date"]->format('mysql')}'";
482
		}
483
484 View Code Duplication
		if ( $this->query_vars["end_date"] ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
Coding Style Comprehensibility introduced by
The string literal end_date 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...
485
			$this->query_vars['date_sql'][] = "AND {$this->get_db()->posts}.post_date<='{$this->query_vars["end_date"]->format('mysql')}'";
486
		}
487
488
		// Relative date query.
489
		if ( $this->query_vars['range'] ) {
490 View Code Duplication
			if ( $this->query_vars["relative_start_date"] ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
Coding Style Comprehensibility introduced by
The string literal relative_start_date 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...
491
				$this->query_vars['relative_date_sql'][] = "AND {$this->get_db()->posts}.post_date>='{$this->query_vars["relative_start_date"]->format('mysql')}'";
492
			}
493
494 View Code Duplication
			if ( $this->query_vars["relative_end_date"] ) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across 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...
Coding Style Comprehensibility introduced by
The string literal relative_end_date 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...
495
				$this->query_vars['relative_date_sql'][] = "AND {$this->get_db()->posts}.post_date<='{$this->query_vars["relative_end_date"]->format('mysql')}'";
496
			}
497
		}
498
499
		// Add sql for specific donation form.
500
		$this->set_meta_sql( 'give_forms', '_give_payment_form_id' );
501
502
		// Add sql for specific donation payment gateways.
503
		$this->set_meta_sql( 'gateways', '_give_payment_gateway' );
504
505
		// Create sql query string
506
		foreach ( $sql_types as $sql_type ) {
507
			$this->query_vars[ $sql_type ] = is_array( $this->query_vars[ $sql_type ] )
508
				? implode( ' ', $this->query_vars[ $sql_type ] )
509
				: $this->query_vars[ $sql_type ];
510
		}
511
	}
512
513
}
514
515
// @todo: compatibility with recurring, fee recovery and currency switcher
516
// @todo: currency formatting compatibility for earnings and other
517
// @todo  review donation earning growth logic
518
// @todo: develop logic to sent raw and formatted value
519
// @todo: review number decimal format
520
// @todo: document stat query params
521
// @todo: think about table backward compatibility for paymentmeta
522
// @todo: think about custom dates
523
524