Issues (4296)

Security Analysis    not enabled

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

includes/payments/class-payment-stats.php (22 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/**
3
 * Earnings / Sales Stats
4
 *
5
 * @package     Give
6
 * @subpackage  Classes/Stats
7
 * @copyright   Copyright (c) 2016, WordImpress
8
 * @license     https://opensource.org/licenses/gpl-license GNU Public License
9
 * @since       1.0
10
 */
11
12
// Exit if accessed directly.
13
if ( ! defined( 'ABSPATH' ) ) {
14
	exit;
15
}
16
17
/**
18
 * Give_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 1.0
25
 */
26
class Give_Payment_Stats extends Give_Stats {
27
28
	/**
29
	 * Retrieve sale stats
30
	 *
31
	 * @since  1.0
32
	 * @access public
33
	 *
34
	 * @param  $form_id    int          The donation form to retrieve stats for. If false, gets stats for all forms
35
	 * @param  $start_date string|bool  The starting date for which we'd like to filter our sale stats. If false, we'll use the default start date of `this_month`
36
	 * @param  $end_date   string|bool  The end date for which we'd like to filter our sale stats. If false, we'll use the default end date of `this_month`
37
	 * @param  $status     string|array The sale status(es) to count. Only valid when retrieving global stats
38
	 *
39
	 * @return float|int                Total amount of donations based on the passed arguments.
40
	 */
41
	public function get_sales( $form_id = 0, $start_date = false, $end_date = false, $status = 'publish' ) {
0 ignored issues
show
The parameter $status is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
42 2
43
		$this->setup_dates( $start_date, $end_date );
0 ignored issues
show
$start_date is of type boolean, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
44 2
45
		// Make sure start date is valid
46
		if ( is_wp_error( $this->start_date ) ) {
47 2
			return $this->start_date;
48
		}
49
50
		// Make sure end date is valid
51
		if ( is_wp_error( $this->end_date ) ) {
52 2
			return $this->end_date;
53
		}
54
55
		$args = array(
56 2
			'status'     => 'publish',
57
			'start_date' => $this->start_date,
58
			'end_date'   => $this->end_date,
59 2
			'fields'     => 'ids',
60
			'number'     => - 1,
61 2
			'output'     => ''
62
		);
63
64
		if ( ! empty( $form_id ) ) {
65
			$args['give_forms'] = $form_id;
66
		}
67 2
68
		/* @var Give_Payments_Query $payments */
69
		$payments = new Give_Payments_Query( $args );
70 2
		$payments = $payments->get_payments();
71
72 2
		return count( $payments );
73
	}
74
75
76
	/**
77
	 * Retrieve earning stats
78
	 *
79
	 * @since  1.0
80
	 * @access public
81
	 *
82
	 * @param  $form_id     int         The donation form to retrieve stats for. If false, gets stats for all forms.
83
	 * @param  $start_date  string|bool The starting date for which we'd like to filter our donation earnings stats. If false, method will use the default start date of `this_month`.
84
	 * @param  $end_date    string|bool The end date for which we'd like to filter the donations stats. If false, method will use the default end date of `this_month`.
85
	 * @param  $gateway_id  string|bool The gateway to get earnings for such as 'paypal' or 'stripe'.
86
	 *
87 2
	 * @return float|int                Total amount of donations based on the passed arguments.
88
	 */
89
	public function get_earnings( $form_id = 0, $start_date = false, $end_date = false, $gateway_id = false ) {
90
		global $wpdb;
91
		$this->setup_dates( $start_date, $end_date );
0 ignored issues
show
$start_date is of type boolean, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
92
93
		// Make sure start date is valid
94
		if ( is_wp_error( $this->start_date ) ) {
95
			return $this->start_date;
96
		}
97
98
		// Make sure end date is valid
99
		if ( is_wp_error( $this->end_date ) ) {
100
			return $this->end_date;
101
		}
102
103
		$args = array(
104
			'status'     => 'publish',
105 2
			'give_forms' => $form_id,
106
			'start_date' => $this->start_date,
107 2
			'end_date'   => $this->end_date,
108
			'fields'     => 'ids',
109 2
			'number'     => - 1,
110
			'output'     => '',
111
		);
112 2
0 ignored issues
show
Functions must not contain multiple empty lines in a row; found 2 empty lines
Loading history...
113
114
		// Filter by Gateway ID meta_key
115
		if ( $gateway_id ) {
116
			$args['meta_query'][] = array(
117 2
				'key'   => '_give_payment_gateway',
118
				'value' => $gateway_id,
119
			);
120
		}
121 2
122
		// Filter by Gateway ID meta_key
123 2
		if ( $form_id ) {
124
			$args['meta_query'][] = array(
125
				'key'   => '_give_payment_form_id',
126
				'value' => $form_id,
127 2
			);
128 2
		}
129 2
130 2 View Code Duplication
		if ( ! empty( $args['meta_query'] ) && 1 < count( $args['meta_query'] ) ) {
0 ignored issues
show
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...
131 2
			$args['meta_query']['relation'] = 'AND';
132 2
		}
133 2
134
		$args = apply_filters( 'give_stats_earnings_args', $args );
135 2
		$key  = Give_Cache::get_key( 'give_stats', $args );
136 2
137
		// Set transient for faster stats.
138 2
		$earnings = Give_Cache::get( $key );
139
140
		if ( false === $earnings ) {
141 2
142
			$this->timestamp = false;
0 ignored issues
show
Documentation Bug introduced by
The property $timestamp was declared of type string, but false is of type false. Maybe add a type cast?

This check looks for assignments to scalar types that may be of the wrong type.

To ensure the code behaves as expected, it may be a good idea to add an explicit type cast.

$answer = 42;

$correct = false;

$correct = (bool) $answer;
Loading history...
143
			$payments        = new Give_Payments_Query( $args );
144
			$payments        = $payments->get_payments();
145
			$earnings        = 0;
146 2
147 2
			if ( ! empty( $payments ) ) {
148 2
				$donation_id_col = Give()->payment_meta->get_meta_type() . '_id';
149
				$query = "SELECT {$donation_id_col} as id, meta_value as total
150 2
					FROM {$wpdb->donationmeta}
151 2
					WHERE meta_key='_give_payment_total'
152 2
					AND {$donation_id_col} IN ('". implode( '\',\'', $payments ) ."')";
153 2
154 2
				$payments = $wpdb->get_results($query, ARRAY_A);
0 ignored issues
show
Usage of a direct database call is discouraged.
Loading history...
Usage of a direct database call without caching is prohibited. Use wp_cache_get / wp_cache_set.
Loading history...
Expected 1 spaces after opening bracket; 0 found
Loading history...
Expected 1 spaces before closing bracket; 0 found
Loading history...
155 2
156 2 View Code Duplication
				if( ! empty( $payments ) ) {
0 ignored issues
show
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...
Space after opening control structure is required
Loading history...
No space before opening parenthesis is prohibited
Loading history...
157
					foreach ( $payments as $payment ) {
158 2
						$currency_code = give_get_payment_currency_code( $payment['id'] );
159 2
160
						/**
161 2
						 * Filter the donation amount
162
						 * Note: this filter documented in payments/functions.php:give_donation_amount()
163
						 *
164
						 * @since 2.1
165
						 */
166
						$formatted_amount = apply_filters(
167
							'give_donation_amount',
168
							give_format_amount(  $payment['total'], array( 'donation_id' =>  $payment['id'] ) ),
0 ignored issues
show
Expected 1 spaces after opening bracket; 2 found
Loading history...
Expected 1 space after "=>"; 2 found
Loading history...
169
							$payment['total'],
170
							$payment['id'],
171
							array( 'type' => 'stats', 'currency'=> false, 'amount' => false )
0 ignored issues
show
Expected 1 space before "=>"; 0 found
Loading history...
172
						);
173
174
						$earnings += (float) give_maybe_sanitize_amount( $formatted_amount, array( 'currency' => $currency_code  ) );
175
					}
176
				}
0 ignored issues
show
Blank line found after control structure
Loading history...
177
178
			}
179
180
			// Cache the results for one hour.
181
			Give_Cache::set( $key, give_sanitize_amount_for_db( $earnings ), 60 * 60 );
182
		}
183
184
		/**
185
		 * Filter the earnings.
186
		 *
187
		 * @since 1.8.17
188
		 *
189
		 * @param  float       $earnings   Earning amount.
190
		 * @param  int         $form_id    Donation Form ID.
191
		 * @param  string|bool $start_date Earning start date.
192
		 * @param  string|bool $end_date   Earning end date.
193
		 * @param  string|bool $gateway_id Payment gateway id.
194
		 */
195
		$earnings = apply_filters( 'give_get_earnings', $earnings, $form_id, $start_date, $end_date, $gateway_id );
196
197
		//return earnings
198
		return round( $earnings, give_get_price_decimals( $form_id ) );
199
200
	}
201
202
	/**
203
	 * Retrieve earning stat transient key
204
	 *
205 2
	 * @since  1.0
206
	 * @access public
207
	 *
208 2
	 * @param  $form_id     int         The donation form to retrieve stats for. If false, gets stats for all forms
209
	 * @param  $start_date  string|bool The starting date for which we'd like to filter our donation earnings stats. If false, we'll use the default start date of `this_month`
210
	 * @param  $end_date    string|bool The end date for which we'd like to filter our sale stats. If false, we'll use the default end date of `this_month`
211
	 * @param  $gateway_id  string|bool The gateway to get earnings for such as 'paypal' or 'stripe'
212
	 *
213
	 * @return float|int                Total amount of donations based on the passed arguments.
214
	 */
215
	public function get_earnings_cache_key( $form_id = 0, $start_date = false, $end_date = false, $gateway_id = false ) {
216
217
		$this->setup_dates( $start_date, $end_date );
0 ignored issues
show
$start_date is of type boolean, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
218
219
		// Make sure start date is valid
220
		if ( is_wp_error( $this->start_date ) ) {
221
			return $this->start_date;
222 1
		}
223
224 1
		// Make sure end date is valid
225
		if ( is_wp_error( $this->end_date ) ) {
226 1
			return $this->end_date;
227
		}
228 1
229
		$args = array(
230 1
			'status'     => 'publish',
231 1
			'give_forms' => $form_id,
232
			'start_date' => $this->start_date,
233 1
			'end_date'   => $this->end_date,
234
			'fields'     => 'ids',
235
			'number'     => - 1,
236
		);
237
0 ignored issues
show
Functions must not contain multiple empty lines in a row; found 2 empty lines
Loading history...
238
239
		// Filter by Gateway ID meta_key
240
		if ( $gateway_id ) {
241
			$args['meta_query'][] = array(
242
				'key'   => '_give_payment_gateway',
243
				'value' => $gateway_id,
244
			);
245
		}
246
247
		// Filter by Gateway ID meta_key
248
		if ( $form_id ) {
249
			$args['meta_query'][] = array(
250
				'key'   => '_give_payment_form_id',
251
				'value' => $form_id,
252
			);
253
		}
254
255 View Code Duplication
		if ( ! empty( $args['meta_query'] ) && 1 < count( $args['meta_query'] ) ) {
0 ignored issues
show
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...
256
			$args['meta_query']['relation'] = 'AND';
257
		}
258
259
		$args = apply_filters( 'give_stats_earnings_args', $args );
260
		$key  = Give_Cache::get_key( 'give_stats', $args );
261
262
		//return earnings
263
		return $key;
264
265
	}
266
267
	/**
268
	 * Get the best selling forms
269
	 *
270
	 * @since  1.0
271
	 * @access public
272
	 * @global wpdb $wpdb
273
	 *
274
	 * @param       $number int The number of results to retrieve with the default set to 10.
275
	 *
276
	 * @return array       Best selling forms
277
	 */
278
	public function get_best_selling( $number = 10 ) {
279
		global $wpdb;
280
281
		$meta_table = __give_v20_bc_table_details( 'form' );
282
283
		$give_forms = $wpdb->get_results( $wpdb->prepare(
0 ignored issues
show
Usage of a direct database call is discouraged.
Loading history...
Usage of a direct database call without caching is prohibited. Use wp_cache_get / wp_cache_set.
Loading history...
284
			"SELECT {$meta_table['column']['id']} as form_id, max(meta_value) as sales
285
				FROM {$meta_table['name']} WHERE meta_key='_give_form_sales' AND meta_value > 0
286
				GROUP BY meta_value+0
287
				DESC LIMIT %d;", $number
288
		) );
289
290
		return $give_forms;
291
	}
292
293
}
294