Passed
Pull Request — develop-3.2.x (#79)
by Mario
05:01
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
use Symfony\Component\DependencyInjection\ContainerInterface;
15
16
class transactions
17
{
18
	protected $container;
19
	protected $db;
20
	protected $ppde_transactions_log_table;
21
22
	/**
23
	 * Constructor
24
	 *
25
	 * @param ContainerInterface $container                   Service container interface
26
	 * @param driver_interface   $db                          Database connection
27
	 * @param string             $ppde_transactions_log_table Table name
28
	 *
29
	 * @access public
30
	 */
31
	public function __construct(ContainerInterface $container, driver_interface $db, $ppde_transactions_log_table)
32
	{
33
		$this->container = $container;
34
		$this->db = $db;
35
		$this->ppde_transactions_log_table = $ppde_transactions_log_table;
36
	}
37
38
	/**
39
	 * SQL Query to return Transaction log data table
40
	 *
41
	 * @param $transaction_id
42
	 *
43
	 * @return string
44
	 * @access public
45
	 */
46
	public function build_sql_data($transaction_id = 0)
47
	{
48
		// Build main sql request
49
		$sql_ary = array(
50
			'SELECT'    => '*, u.username, u.user_colour',
51
			'FROM'      => array($this->ppde_transactions_log_table => 'txn'),
52
			'LEFT_JOIN' => array(
53
				array(
54
					'FROM' => array(USERS_TABLE => 'u'),
55
					'ON'   => 'u.user_id = txn.user_id',
56
				),
57
			),
58
			'ORDER_BY'  => 'txn.transaction_id',
59
		);
60
61
		// Use WHERE clause when $currency_id is different from 0
62
		if ((int) $transaction_id)
63
		{
64
			$sql_ary['WHERE'] = 'txn.transaction_id = ' . (int) $transaction_id;
65
		}
66
67
		// Return all transactions entities
68
		return $this->db->sql_build_query('SELECT', $sql_ary);
69
	}
70
71
	/**
72
	 * SQL Query to count how many donated
73
	 *
74
	 * @param bool $detailed
75
	 *
76
	 * @return array
77
	 * @access public
78
	 */
79
	public function sql_donorlist_ary($detailed = false)
80
	{
81
		// Build sql request
82
		$sql_donorslist_ary = array(
83
			'SELECT'   => 'txn.user_id',
84
			'FROM'     => array($this->ppde_transactions_log_table => 'txn'),
85
			'WHERE'    => 'txn.user_id <> ' . ANONYMOUS . "
86
							AND txn.payment_status = 'Completed'
87
							AND txn.test_ipn = 0",
88
			'GROUP_BY' => 'txn.user_id',
89
		);
90
91
		if ($detailed)
92
		{
93
			$sql_donorslist_ary['SELECT'] = 'txn.user_id, MAX(txn.transaction_id) AS max_txn_id, SUM(txn.mc_gross) AS amount';
94
		}
95
96
		return $sql_donorslist_ary;
97
	}
98
99
	/**
100
	 * SQL Query to return information of the last donation of the donor
101
	 *
102
	 * @param $transaction_id
103
	 *
104
	 * @return array
105
	 * @access public
106
	 */
107
	public function sql_last_donation_ary($transaction_id)
108
	{
109
		// Build sql request
110
		return array(
111
			'SELECT' => 'txn.payment_date, txn.mc_gross',
112
			'FROM'   => array($this->ppde_transactions_log_table => 'txn'),
113
			'WHERE'  => 'txn.transaction_id = ' . (int) $transaction_id,
114
		);
115
	}
116
117
	/**
118
	 * Build SQL Query to return the donors list
119
	 *
120
	 * @param array $sql_donorlist_ary
121
	 *
122
	 * @return string
123
	 * @access public
124
	 */
125
	public function build_sql_donorlist_data($sql_donorlist_ary)
126
	{
127
		// Return all transactions entities
128
		return $this->db->sql_build_query('SELECT', $sql_donorlist_ary);
129
	}
130
131
	/**
132
	 * Returns total entries of selected field
133
	 *
134
	 * @param array  $count_sql_ary
135
	 * @param string $selected_field
136
	 *
137
	 * @return int
138
	 * @access public
139
	 */
140
	public function query_sql_count($count_sql_ary, $selected_field)
141
	{
142
		$count_sql_ary['SELECT'] = 'COUNT(' . $selected_field . ') AS total_entries';
143
144
		if (array_key_exists('GROUP_BY', $count_sql_ary))
145
		{
146
			$count_sql_ary['SELECT'] = 'COUNT(DISTINCT ' . $count_sql_ary['GROUP_BY'] . ') AS total_entries';
147
		}
148
		unset($count_sql_ary['ORDER_BY'], $count_sql_ary['GROUP_BY']);
149
150
		$sql = $this->db->sql_build_query('SELECT', $count_sql_ary);
151
		$result = $this->db->sql_query($sql);
152
		$field = (int) $this->db->sql_fetchfield('total_entries');
153
		$this->db->sql_freeresult($result);
154
155
		return $field;
156
	}
157
158
	/**
159
	 * Returns the SQL Query for displaying simple transactions details
160
	 *
161
	 * @param string $keywords
162
	 * @param string $sort_by
163
	 * @param int    $log_time
164
	 *
165
	 * @return array
166
	 * @access public
167
	 */
168
	public function get_logs_sql_ary($keywords, $sort_by, $log_time)
169
	{
170
		$sql_keywords = '';
171
		if (!empty($keywords))
172
		{
173
			// Get the SQL condition for our keywords
174
			$sql_keywords = $this->generate_sql_keyword($keywords);
175
		}
176
177
		$get_logs_sql_ary = array(
178
			'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',
179
			'FROM'     => array(
180
				$this->ppde_transactions_log_table => 'txn',
181
				USERS_TABLE                        => 'u',
182
			),
183
			'WHERE'    => 'txn.user_id = u.user_id ' . $sql_keywords,
184
			'ORDER_BY' => $sort_by,
185
		);
186
187
		if ($log_time)
188
		{
189
			$get_logs_sql_ary['WHERE'] = 'txn.payment_date >= ' . (int) $log_time . '
190
					AND ' . $get_logs_sql_ary['WHERE'];
191
		}
192
193
		return $get_logs_sql_ary;
194
	}
195
196
	/**
197
	 * Generates a sql condition for the specified keywords
198
	 *
199
	 * @param string $keywords           The keywords the user specified to search for
200
	 * @param string $statement_operator The operator used to prefix the statement ('AND' by default)
201
	 *
202
	 * @return string Returns the SQL condition searching for the keywords
203
	 * @access private
204
	 */
205
	private function generate_sql_keyword($keywords, $statement_operator = 'AND')
206
	{
207
		// Use no preg_quote for $keywords because this would lead to sole
208
		// backslashes being added. We also use an OR connection here for
209
		// spaces and the | string. Currently, regex is not supported for
210
		// searching (but may come later).
211
		$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

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

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