Passed
Push — 3.2.x ( ff823b...891047 )
by Mario
07:26
created

transactions::sql_last_donation_ary()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 4
c 0
b 0
f 0
nc 1
nop 1
dl 0
loc 7
rs 10
1
<?php
2
/**
3
 *
4
 * PayPal Donation extension for the phpBB Forum Software package.
5
 *
6
 * @copyright (c) 2015 Skouat
7
 * @license GNU General Public License, version 2 (GPL-2.0)
8
 *
9
 */
10
11
namespace skouat\ppde\operators;
12
13
use phpbb\db\driver\driver_interface;
14
15
class transactions
16
{
17
	protected $container;
18
	protected $db;
19
	protected $ppde_transactions_log_table;
20
21
	/**
22
	 * Constructor
23
	 *
24
	 * @param driver_interface   $db                          Database connection
25
	 * @param string             $ppde_transactions_log_table Table name
26
	 *
27
	 * @access public
28
	 */
29
	public function __construct(driver_interface $db, $ppde_transactions_log_table)
30
	{
31
		$this->db = $db;
32
		$this->ppde_transactions_log_table = $ppde_transactions_log_table;
33
	}
34
35
	/**
36
	 * SQL Query to return Transaction log data table
37
	 *
38
	 * @param $transaction_id
39
	 *
40
	 * @return string
41
	 * @access public
42
	 */
43
	public function build_sql_data($transaction_id = 0)
44
	{
45
		// Build main sql request
46
		$sql_ary = array(
47
			'SELECT'    => 'txn.*, u.username, u.user_colour',
48
			'FROM'      => array($this->ppde_transactions_log_table => 'txn'),
49
			'LEFT_JOIN' => array(
50
				array(
51
					'FROM' => array(USERS_TABLE => 'u'),
52
					'ON'   => 'u.user_id = txn.user_id',
53
				),
54
			),
55
			'ORDER_BY'  => 'txn.transaction_id',
56
		);
57
58
		// Use WHERE clause when $currency_id is different from 0
59
		if ((int) $transaction_id)
60
		{
61
			$sql_ary['WHERE'] = 'txn.transaction_id = ' . (int) $transaction_id;
62
		}
63
64
		// Return all transactions entities
65
		return $this->db->sql_build_query('SELECT', $sql_ary);
66
	}
67
68
	/**
69
	 * SQL Query to count how many donated
70
	 *
71
	 * @param bool   $detailed
72
	 * @param string $order_by
73
	 *
74
	 * @return array
75
	 * @access public
76
	 */
77
	public function sql_donorlist_ary($detailed = false, $order_by = '')
78
	{
79
		// Build sql request
80
		$sql_donorslist_ary = array(
81
			'SELECT'   => 'txn.user_id',
82
			'FROM'     => array($this->ppde_transactions_log_table => 'txn'),
83
			'WHERE'    => 'txn.user_id <> ' . ANONYMOUS . "
84
							AND txn.payment_status = 'Completed'
85
							AND txn.test_ipn = 0",
86
			'GROUP_BY' => 'txn.user_id',
87
		);
88
89
		if ($order_by)
90
		{
91
			$sql_donorslist_ary['ORDER_BY'] = $order_by;
92
		}
93
94
		if ($detailed)
95
		{
96
			$sql_donorslist_ary['SELECT'] = 'txn.user_id, MAX(txn.transaction_id) AS max_txn_id, SUM(txn.mc_gross) AS amount, MAX(u.username)';
97
			$sql_donorslist_ary['LEFT_JOIN'] = array(
98
				array(
99
					'FROM' => array(USERS_TABLE => 'u'),
100
					'ON'   => 'u.user_id = txn.user_id',
101
				));
102
		}
103
104
		return $sql_donorslist_ary;
105
	}
106
107
	/**
108
	 * SQL Query to return information of the last donation of the donor
109
	 *
110
	 * @param $transaction_id
111
	 *
112
	 * @return array
113
	 * @access public
114
	 */
115
	public function sql_last_donation_ary($transaction_id)
116
	{
117
		// Build sql request
118
		return array(
119
			'SELECT' => 'txn.payment_date, txn.mc_gross',
120
			'FROM'   => array($this->ppde_transactions_log_table => 'txn'),
121
			'WHERE'  => 'txn.transaction_id = ' . (int) $transaction_id,
122
		);
123
	}
124
125
	/**
126
	 * Build SQL Query to return the donors list
127
	 *
128
	 * @param array $sql_donorlist_ary
129
	 *
130
	 * @return string
131
	 * @access public
132
	 */
133
	public function build_sql_donorlist_data($sql_donorlist_ary)
134
	{
135
		// Return all transactions entities
136
		return $this->db->sql_build_query('SELECT', $sql_donorlist_ary);
137
	}
138
139
	/**
140
	 * Returns total entries of selected field
141
	 *
142
	 * @param array  $count_sql_ary
143
	 * @param string $selected_field
144
	 *
145
	 * @return int
146
	 * @access public
147
	 */
148
	public function query_sql_count($count_sql_ary, $selected_field)
149
	{
150
		$count_sql_ary['SELECT'] = 'COUNT(' . $selected_field . ') AS total_entries';
151
152
		if (array_key_exists('GROUP_BY', $count_sql_ary))
153
		{
154
			$count_sql_ary['SELECT'] = 'COUNT(DISTINCT ' . $count_sql_ary['GROUP_BY'] . ') AS total_entries';
155
		}
156
		unset($count_sql_ary['ORDER_BY'], $count_sql_ary['GROUP_BY']);
157
158
		$sql = $this->db->sql_build_query('SELECT', $count_sql_ary);
159
		$result = $this->db->sql_query($sql);
160
		$field = (int) $this->db->sql_fetchfield('total_entries');
161
		$this->db->sql_freeresult($result);
162
163
		return $field;
164
	}
165
166
	/**
167
	 * Returns the SQL Query for displaying simple transactions details
168
	 *
169
	 * @param string $keywords
170
	 * @param string $sort_by
171
	 * @param int    $log_time
172
	 *
173
	 * @return array
174
	 * @access public
175
	 */
176
	public function get_logs_sql_ary($keywords, $sort_by, $log_time)
177
	{
178
		$sql_keywords = '';
179
		if (!empty($keywords))
180
		{
181
			// Get the SQL condition for our keywords
182
			$sql_keywords = $this->generate_sql_keyword($keywords);
183
		}
184
185
		$get_logs_sql_ary = array(
186
			'SELECT'   => 'txn.transaction_id, txn.txn_id, txn.test_ipn, txn.confirmed, txn.txn_errors, txn.payment_date, txn.payment_status, txn.user_id, u.username, u.user_colour',
187
			'FROM'     => array(
188
				$this->ppde_transactions_log_table => 'txn',
189
				USERS_TABLE                        => 'u',
190
			),
191
			'WHERE'    => 'txn.user_id = u.user_id ' . $sql_keywords,
192
			'ORDER_BY' => $sort_by,
193
		);
194
195
		if ($log_time)
196
		{
197
			$get_logs_sql_ary['WHERE'] = 'txn.payment_date >= ' . (int) $log_time . '
198
					AND ' . $get_logs_sql_ary['WHERE'];
199
		}
200
201
		return $get_logs_sql_ary;
202
	}
203
204
	/**
205
	 * Generates a sql condition for the specified keywords
206
	 *
207
	 * @param string $keywords           The keywords the user specified to search for
208
	 * @param string $statement_operator The operator used to prefix the statement ('AND' by default)
209
	 *
210
	 * @return string Returns the SQL condition searching for the keywords
211
	 * @access private
212
	 */
213
	private function generate_sql_keyword($keywords, $statement_operator = 'AND')
214
	{
215
		// Use no preg_quote for $keywords because this would lead to sole
216
		// backslashes being added. We also use an OR connection here for
217
		// spaces and the | string. Currently, regex is not supported for
218
		// searching (but may come later).
219
		$keywords = preg_split('#[\s|]+#u', utf8_strtolower($keywords), 0, PREG_SPLIT_NO_EMPTY);
0 ignored issues
show
Bug introduced by
The function utf8_strtolower was not found. Maybe you did not declare it correctly or list all dependencies? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

219
		$keywords = preg_split('#[\s|]+#u', /** @scrutinizer ignore-call */ utf8_strtolower($keywords), 0, PREG_SPLIT_NO_EMPTY);
Loading history...
220
		$sql_keywords = '';
221
222
		if (!empty($keywords))
223
		{
224
			// Build pattern and keywords...
225
			for ($i = 0, $num_keywords = count($keywords); $i < $num_keywords; $i++)
226
			{
227
				$keywords[$i] = $this->db->sql_like_expression($this->db->get_any_char() . $keywords[$i] . $this->db->get_any_char());
228
			}
229
230
			$sql_keywords = ' ' . $statement_operator . ' (';
231
			$sql_lower = $this->db->sql_lower_text('txn.txn_id');
232
			$sql_keywords .= ' ' . $sql_lower . ' ' . implode(' OR ' . $sql_lower . ' ', $keywords) . ')';
233
		}
234
235
		return $sql_keywords;
236
	}
237
238
	/**
239
	 * Returns user information based on the donor ID or email
240
	 *
241
	 * @param string     $type
242
	 * @param int|string $arg
243
	 *
244
	 * @return array|bool
245
	 * @access public
246
	 */
247
	public function query_donor_user_data($type = 'user', $arg = 1)
248
	{
249
250
		switch ($type)
251
		{
252
			case 'user':
253
				$sql_where = ' WHERE user_id = ' . (int) $arg;
254
			break;
255
			case 'username':
256
				$sql_where = " WHERE username_clean = '" . $this->db->sql_escape(utf8_clean_string($arg)) . "'";
257
			break;
258
			case 'email':
259
				$sql_where = " WHERE user_email_hash = '" . $this->db->sql_escape(phpbb_email_hash($arg)) . "'";
260
			break;
261
			default:
262
				$sql_where = '';
263
		}
264
265
		$sql = 'SELECT user_id, username, user_ppde_donated_amount
266
			FROM ' . USERS_TABLE .
267
			$sql_where;
268
		$result = $this->db->sql_query($sql);
269
		$row = $this->db->sql_fetchrow($result);
270
		$this->db->sql_freeresult($result);
271
272
		return $row;
273
	}
274
275
	/**
276
	 * Returns simple details of all PayPal transactions logged in the database
277
	 *
278
	 * @param array $get_logs_sql_ary
279
	 * @param array $url_ary
280
	 * @param int   $limit
281
	 * @param int   $last_page_offset
282
	 *
283
	 * @return array $log
284
	 * @access public
285
	 */
286
	public function build_log_ary($get_logs_sql_ary, $url_ary, $limit = 0, $last_page_offset = 0)
287
	{
288
		$sql = $this->db->sql_build_query('SELECT', $get_logs_sql_ary);
289
		$result = $this->db->sql_query_limit($sql, $limit, $last_page_offset);
290
291
		$log = array();
292
293
		while ($row = $this->db->sql_fetchrow($result))
294
		{
295
			$log[] = array(
296
				'confirmed'      => $row['confirmed'],
297
				'payment_date'   => $row['payment_date'],
298
				'payment_status' => $row['payment_status'],
299
				'test_ipn'       => $row['test_ipn'],
300
				'transaction_id' => $row['transaction_id'],
301
				'txn_errors'     => $row['txn_errors'],
302
				'txn_id'         => $this->build_transaction_url($row['transaction_id'], $row['txn_id'], $url_ary['txn_url'], $row['confirmed']),
303
				'username_full'  => get_username_string('full', $row['user_id'], $row['username'], $row['user_colour'], false, $url_ary['profile_url']),
0 ignored issues
show
Bug introduced by
false of type false is incompatible with the type string expected by parameter $guest_username of get_username_string(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

303
				'username_full'  => get_username_string('full', $row['user_id'], $row['username'], $row['user_colour'], /** @scrutinizer ignore-type */ false, $url_ary['profile_url']),
Loading history...
304
			);
305
		}
306
307
		$this->db->sql_freeresult($result);
308
309
		return $log;
310
	}
311
312
	/**
313
	 * Build transaction url for placing into templates.
314
	 *
315
	 * @param int    $id         The users transaction id
316
	 * @param string $txn_id     The txn number id
317
	 * @param string $custom_url optional parameter to specify a profile url. The transaction id get appended to this
318
	 *                           url as &amp;id={id}
319
	 * @param bool   $colour     If false the color #FF0000 will be applied on the URL.
320
	 *
321
	 * @return string A string consisting of what is wanted.
322
	 * @access private
323
	 */
324
	private function build_transaction_url($id, $txn_id, $custom_url = '', $colour = false)
325
	{
326
		static $_profile_cache;
327
328
		// We cache some common variables we need within this function
329
		if (empty($_profile_cache))
330
		{
331
			$_profile_cache['tpl_nourl'] = '{{ TRANSACTION }}';
332
			$_profile_cache['tpl_url'] = '<a href="{{ TXN_URL }}">{{ TRANSACTION }}</a>';
333
			$_profile_cache['tpl_url_colour'] = '<a href="{{ TXN_URL }}" style="{{ TXN_COLOUR }}">{{ TRANSACTION }}</a>';
334
		}
335
336
		// Build correct transaction url
337
		$txn_url = '';
338
		if ($txn_id)
339
		{
340
			$txn_url = ($custom_url !== '') ? $custom_url . '&amp;action=view&amp;id=' . $id : $txn_id;
341
		}
342
343
		// Return
344
345
		if (!$txn_url)
346
		{
347
			return str_replace('{{ TRANSACTION }}', $txn_id, $_profile_cache['tpl_nourl']);
348
		}
349
350
		return str_replace(array('{{ TXN_URL }}', '{{ TXN_COLOUR }}', '{{ TRANSACTION }}'), array($txn_url, 'color: #FF0000;', $txn_id), (!$colour) ? $_profile_cache['tpl_url_colour'] : $_profile_cache['tpl_url']);
351
	}
352
353
	/**
354
	 * Returns SQL WHERE clause for all marked items
355
	 *
356
	 * @param $marked
357
	 *
358
	 * @return string
359
	 * @access public
360
	 */
361
	public function build_marked_where_sql($marked)
362
	{
363
		$sql_in = array();
364
		foreach ($marked as $mark)
365
		{
366
			$sql_in[] = $mark;
367
		}
368
369
		return ' WHERE ' . $this->db->sql_in_set('transaction_id', $sql_in);
370
	}
371
372
	/**
373
	 * Returns the count result for updating stats
374
	 *
375
	 * @param string $type
376
	 * @param bool   $test_ipn
377
	 *
378
	 * @return int
379
	 * @access public
380
	 */
381
	public function sql_query_count_result($type, $test_ipn)
382
	{
383
		switch ($type)
384
		{
385
			case 'ppde_transactions_count':
386
			case 'ppde_transactions_count_ipn':
387
				$sql_ary = $this->sql_select_stats_main('txn_id');
388
				$sql_ary['WHERE'] = "confirmed = 1 AND payment_status = 'Completed' AND txn.test_ipn = " . (int) $test_ipn;
389
			break;
390
			case 'ppde_known_donors_count':
391
			case 'ppde_known_donors_count_ipn':
392
				$sql_ary = $this->sql_select_stats_main('payer_id');
393
				$sql_ary['LEFT_JOIN'] = array(
394
					array(
395
						'FROM' => array(USERS_TABLE => 'u'),
396
						'ON'   => 'txn.user_id = u.user_id',
397
					),
398
				);
399
				$sql_ary['WHERE'] = '(u.user_type = ' . USER_NORMAL . ' OR u.user_type = ' . USER_FOUNDER . ') AND txn.test_ipn = ' . (int) $test_ipn;
400
			break;
401
			case 'ppde_anonymous_donors_count':
402
			case 'ppde_anonymous_donors_count_ipn':
403
				$sql_ary = $this->sql_select_stats_main('payer_id');
404
				$sql_ary['WHERE'] = 'txn.user_id = ' . ANONYMOUS . ' AND txn.test_ipn = ' . (int) $test_ipn;
405
			break;
406
			default:
407
				$sql_ary = $this->sql_select_stats_main('txn_id');
408
		}
409
410
		$result = $this->db->sql_query($this->db->sql_build_query('SELECT', $sql_ary));
411
		$count = (int) $this->db->sql_fetchfield('count_result');
412
		$this->db->sql_freeresult($result);
413
414
		return $count;
415
	}
416
417
	/**
418
	 * Make body of SQL query for stats calculation.
419
	 *
420
	 * @param string $field_name Name of the field
421
	 *
422
	 * @return array
423
	 * @access private
424
	 */
425
	private function sql_select_stats_main($field_name)
426
	{
427
		return array(
428
			'SELECT' => 'COUNT(DISTINCT txn.' . $field_name . ') AS count_result',
429
			'FROM'   => array($this->ppde_transactions_log_table => 'txn'),
430
		);
431
	}
432
433
	/**
434
	 * Updates the user donated amount
435
	 *
436
	 * @param int    $user_id
437
	 * @param string $value
438
	 *
439
	 * @return void
440
	 * @access public
441
	 */
442
	public function sql_update_user_stats($user_id, $value)
443
	{
444
		$sql = 'UPDATE ' . USERS_TABLE . '
445
			SET user_ppde_donated_amount = ' . (float) $value . '
446
			WHERE user_id = ' . (int) $user_id;
447
		$this->db->sql_query($sql);
448
	}
449
450
	/**
451
	 * Prepare data array() before send it to $entity
452
	 *
453
	 * @param array $data
454
	 *
455
	 * @return array
456
	 * @access public
457
	 */
458
	public function build_data_ary($data)
459
	{
460
		return array(
461
			'business'          => $data['business'],
462
			'confirmed'         => (bool) $data['confirmed'],
463
			'exchange_rate'     => $data['exchange_rate'],
464
			'first_name'        => $data['first_name'],
465
			'item_name'         => $data['item_name'],
466
			'item_number'       => $data['item_number'],
467
			'last_name'         => $data['last_name'],
468
			'mc_currency'       => $data['mc_currency'],
469
			'mc_gross'          => floatval($data['mc_gross']),
470
			'mc_fee'            => floatval($data['mc_fee']),
471
			'net_amount'        => floatval($data['net_amount']),
472
			'parent_txn_id'     => $data['parent_txn_id'],
473
			'payer_email'       => $data['payer_email'],
474
			'payer_id'          => $data['payer_id'],
475
			'payer_status'      => $data['payer_status'],
476
			'payment_date'      => $data['payment_date'],
477
			'payment_status'    => $data['payment_status'],
478
			'payment_type'      => $data['payment_type'],
479
			'memo'              => $data['memo'],
480
			'receiver_id'       => $data['receiver_id'],
481
			'receiver_email'    => $data['receiver_email'],
482
			'residence_country' => $data['residence_country'],
483
			'settle_amount'     => floatval($data['settle_amount']),
484
			'settle_currency'   => $data['settle_currency'],
485
			'test_ipn'          => (bool) $data['test_ipn'],
486
			'txn_errors'        => $data['txn_errors'],
487
			'txn_id'            => $data['txn_id'],
488
			'txn_type'          => $data['txn_type'],
489
			'user_id'           => (int) $data['user_id'],
490
		);
491
	}
492
}
493