Completed
Push — master ( 9b85c2...3f27cb )
by Mario
02:45
created

transactions::generate_sql_keyword()   B

Complexity

Conditions 3
Paths 2

Size

Total Lines 27
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 1
Metric Value
c 2
b 0
f 1
dl 0
loc 27
rs 8.8571
cc 3
eloc 12
nc 2
nop 2
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 Symfony\Component\DependencyInjection\ContainerInterface;
14
15
class transactions
16
{
17
	protected $container;
18
	protected $db;
19
	protected $ppde_transactions_log_table;
20
21
	/**
22
	 * Constructor
23
	 *
24
	 * @param ContainerInterface                $container                   Service container interface
25
	 * @param \phpbb\db\driver\driver_interface $db                          Database connection
26
	 * @param string                            $ppde_transactions_log_table Table name
27
	 *
28
	 * @access public
29
	 */
30
	public function __construct(ContainerInterface $container, \phpbb\db\driver\driver_interface $db, $ppde_transactions_log_table)
31
	{
32
		$this->container = $container;
33
		$this->db = $db;
34
		$this->ppde_transactions_log_table = $ppde_transactions_log_table;
35
	}
36
37
	/**
38
	 * SQL Query to return Transaction log data table
39
	 *
40
	 * @param $transaction_id
41
	 *
42
	 * @return string
43
	 * @access public
44
	 */
45
	public function build_sql_data($transaction_id = 0)
46
	{
47
		// Build main sql request
48
		$sql_ary = array(
49
			'SELECT'    => '*, u.username',
50
			'FROM'      => array($this->ppde_transactions_log_table => 'txn'),
51
			'LEFT_JOIN' => array(
52
				array(
53
					'FROM' => array(USERS_TABLE => 'u'),
54
					'ON'   => 'u.user_id = txn.user_id',
55
				),
56
			),
57
			'ORDER_BY'  => 'txn.transaction_id',
58
		);
59
60
		// Use WHERE clause when $currency_id is different from 0
61
		if ((int) $transaction_id)
62
		{
63
			$sql_ary['WHERE'] = 'txn.transaction_id = ' . (int) $transaction_id;
64
		}
65
66
		// Return all transactions entities
67
		return $this->db->sql_build_query('SELECT', $sql_ary);
68
	}
69
70
	/**
71
	 * Returns the SQL Query for generation the donors list
72
	 *
73
	 * @param int    $max_txn_id Identifier of the transaction logged in the DB
74
	 * @param string $order_by
75
	 *
76
	 * @return array
77
	 * @access public
78
	 */
79
	public function get_sql_donorlist_ary($max_txn_id = 0, $order_by = '')
80
	{
81
		// Build main sql request
82
		$donorlist_sql_ary = array(
83
			'SELECT'    => 'txn.*, MAX(txn.transaction_id) AS max_txn_id, SUM(txn.mc_gross) AS amount, u.username, u.user_colour',
84
			'FROM'      => array($this->ppde_transactions_log_table => 'txn'),
85
			'LEFT_JOIN' => array(
86
				array(
87
					'FROM' => array(USERS_TABLE => 'u'),
88
					'ON'   => 'u.user_id = txn.user_id',
89
				),
90
			),
91
			'WHERE'     => 'txn.user_id <> ' . ANONYMOUS . "
92
							AND txn.payment_status = 'Completed'
93
							AND txn.test_ipn = 0",
94
			'GROUP_BY'  => 'txn.user_id',
95
			'ORDER_BY'  => 'txn.transaction_id DESC',
96
		);
97
98
		if ($order_by)
99
		{
100
			$donorlist_sql_ary['ORDER_BY'] = $order_by;
101
		}
102
103
		if ($max_txn_id)
104
		{
105
			$donorlist_sql_ary['WHERE'] = 'txn.transaction_id = ' . $max_txn_id;
106
			unset($donorlist_sql_ary['GROUP_BY'], $donorlist_sql_ary['ORDER_BY']);
107
		}
108
109
		// Return all transactions entities
110
		return $donorlist_sql_ary;
111
	}
112
113
	/**
114
	 * SQL Query to return donors list details
115
	 *
116
	 * @param array $sql_donorlist_ary
117
	 *
118
	 * @return string
119
	 * @access public
120
	 */
121
	public function build_sql_donorlist_data($sql_donorlist_ary)
122
	{
123
		// Return all transactions entities
124
		return $this->db->sql_build_query('SELECT', $sql_donorlist_ary);
125
	}
126
127
	/**
128
	 * Returns total entries of selected field
129
	 *
130
	 * @param array  $count_sql_ary
131
	 * @param string $selected_field
132
	 *
133
	 * @return int
134
	 * @access public
135
	 */
136
	public function query_sql_count($count_sql_ary, $selected_field)
137
	{
138
		$count_sql_ary['SELECT'] = 'COUNT(' . $selected_field . ') AS total_entries';
139
140
		if (array_key_exists('GROUP_BY', $count_sql_ary))
141
		{
142
			$count_sql_ary['SELECT'] = 'COUNT(DISTINCT ' . $count_sql_ary['GROUP_BY'] . ') AS total_entries';
143
		}
144
		unset($count_sql_ary['ORDER_BY'], $count_sql_ary['GROUP_BY']);
145
146
		$sql = $this->db->sql_build_query('SELECT', $count_sql_ary);
147
		$this->db->sql_query($sql);
148
149
		return (int) $this->db->sql_fetchfield('total_entries');
150
	}
151
152
	/**
153
	 * Returns the SQL Query for displaying simple transactions details
154
	 *
155
	 * @param string  $keywords
156
	 * @param string  $sort_by
157
	 * @param integer $log_time
158
	 *
159
	 * @return array
1 ignored issue
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use array<string,string|array<*,string>>.

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
160
	 * @access public
161
	 */
162
	public function get_logs_sql_ary($keywords, $sort_by, $log_time)
163
	{
164
		$sql_keywords = '';
165
		if (!empty($keywords))
166
		{
167
			// Get the SQL condition for our keywords
168
			$sql_keywords = $this->generate_sql_keyword($keywords);
169
		}
170
171
		$get_logs_sql_ary = array(
172
			'SELECT'   => 'txn.transaction_id, txn.txn_id, txn.test_ipn, txn.confirmed, txn.payment_date, txn.payment_status, txn.user_id, u.username, u.user_colour',
173
			'FROM'     => array(
174
				$this->ppde_transactions_log_table => 'txn',
175
				USERS_TABLE                        => 'u',
176
			),
177
			'WHERE'    => 'txn.user_id = u.user_id ' . $sql_keywords,
178
			'ORDER_BY' => $sort_by,
179
		);
180
181
		if ($log_time)
182
		{
183
			$get_logs_sql_ary['WHERE'] = 'txn.payment_date >= ' . (int) $log_time . '
184
					AND ' . $get_logs_sql_ary['WHERE'];
185
		}
186
187
		return $get_logs_sql_ary;
188
	}
189
190
	/**
191
	 * Generates a sql condition for the specified keywords
192
	 *
193
	 * @param string $keywords           The keywords the user specified to search for
194
	 * @param string $statement_operator The operator used to prefix the statement ('AND' by default)
195
	 *
196
	 * @return string Returns the SQL condition searching for the keywords
197
	 * @access private
198
	 */
199
	private function generate_sql_keyword($keywords, $statement_operator = 'AND')
200
	{
201
		// Use no preg_quote for $keywords because this would lead to sole
202
		// backslashes being added. We also use an OR connection here for
203
		// spaces and the | string. Currently, regex is not supported for
204
		// searching (but may come later).
205
		$keywords = preg_split('#[\s|]+#u', utf8_strtolower($keywords), 0, PREG_SPLIT_NO_EMPTY);
206
		$sql_keywords = '';
207
208
		if (!empty($keywords))
209
		{
210
			$keywords_pattern = array();
211
212
			// Build pattern and keywords...
213
			for ($i = 0, $num_keywords = sizeof($keywords); $i < $num_keywords; $i++)
214
			{
215
				$keywords_pattern[] = preg_quote($keywords[$i], '#');
216
				$keywords[$i] = $this->db->sql_like_expression($this->db->get_any_char() . $keywords[$i] . $this->db->get_any_char());
217
			}
218
219
			$sql_keywords = ' ' . $statement_operator . ' (';
220
			$sql_lower = $this->db->sql_lower_text('txn.txn_id');
221
			$sql_keywords .= ' ' . $sql_lower . ' ' . implode(' OR ' . $sql_lower . ' ', $keywords) . ')';
222
		}
223
224
		return $sql_keywords;
225
	}
226
227
	/**
228
	 * Returns user information based on the ID of the donor or they email
229
	 *
230
	 * @param string $type
231
	 * @param int    $arg
232
	 *
233
	 * @return array|bool
234
	 * @access public
235
	 */
236
	public function query_donor_user_data($type = 'user', $arg = 1)
237
	{
238
239
		switch ($type)
240
		{
241
			case 'user':
242
				$sql_where = ' WHERE user_id = ' . (int) $arg;
243
				break;
244
			case 'email':
245
				$sql_where = ' WHERE user_email_hash = ' . crc32(strtolower($arg)) . strlen($arg);
246
				break;
247
			default:
248
				$sql_where = '';
249
		}
250
251
		$sql = 'SELECT user_id, username
252
			FROM ' . USERS_TABLE .
253
			$sql_where;
254
		$result = $this->db->sql_query($sql);
255
256
		return $this->db->sql_fetchrow($result);
257
	}
258
259
	/**
260
	 * Returns simple details of all PayPal transactions logged in the database
261
	 *
262
	 * @param array $get_logs_sql_ary
263
	 * @param array $url_ary
264
	 * @param int   $limit
265
	 * @param int   $last_page_offset
266
	 *
267
	 * @return array $log
268
	 * @access public
269
	 */
270
	public function build_log_ary($get_logs_sql_ary, $url_ary, $limit = 0, $last_page_offset = 0)
271
	{
272
		$sql = $this->db->sql_build_query('SELECT', $get_logs_sql_ary);
273
		$result = $this->db->sql_query_limit($sql, $limit, $last_page_offset);
274
275
		$i = 0;
276
		$log = array();
277
278
		while ($row = $this->db->sql_fetchrow($result))
279
		{
280
			$log[$i] = array(
281
				'transaction_id' => $row['transaction_id'],
282
				'txn_id'         => $this->build_transaction_url($row['transaction_id'], $row['txn_id'], $url_ary['txn_url'], $row['confirmed']),
283
				'test_ipn'       => $row['test_ipn'],
284
				'confirmed'      => $row['confirmed'],
285
				'payment_status' => $row['payment_status'],
286
				'payment_date'   => $row['payment_date'],
287
288
				'username_full'  => get_username_string('full', $row['user_id'], $row['username'], $row['user_colour'], false, $url_ary['profile_url']),
289
			);
290
291
			$i++;
292
		}
293
294
		return $log;
295
	}
296
297
	/**
298
	 * Build transaction url for placing into templates.
299
	 *
300
	 * @param int    $id         The users transaction id
301
	 * @param string $txn_id     The txn number id
302
	 * @param string $custom_url optional parameter to specify a profile url. The transaction id get appended to this
303
	 *                           url as &amp;id={id}
304
	 * @param bool   $colour
305
	 *
306
	 * @return string A string consisting of what is wanted.
307
	 * @access private
308
	 */
309
	private function build_transaction_url($id, $txn_id, $custom_url = '', $colour = false)
310
	{
311
		static $_profile_cache;
312
313
		// We cache some common variables we need within this function
314
		if (empty($_profile_cache))
315
		{
316
			$_profile_cache['tpl_nourl'] = '{TRANSACTION}';
317
			$_profile_cache['tpl_url'] = '<a href="{TXN_URL}">{TRANSACTION}</a>';
318
			$_profile_cache['tpl_url_colour'] = '<a href="{TXN_URL}" style="{TXN_COLOUR};">{TRANSACTION}</a>';
319
		}
320
321
		// Build correct transaction url
322
		$txn_url = '';
323
		if ($txn_id)
324
		{
325
			$txn_url = ($custom_url !== '') ? $custom_url . '&amp;action=view&amp;id=' . $id : $txn_id;
326
		}
327
328
		// Return
329
330
		if (!$txn_url)
331
		{
332
			return str_replace('{TRANSACTION}', $txn_id, $_profile_cache['tpl_nourl']);
333
		}
334
335
		return str_replace(array('{TXN_URL}', '{TXN_COLOUR}', '{TRANSACTION}'), array($txn_url, '#FF0000', $txn_id), (!$colour) ? $_profile_cache['tpl_url'] : $_profile_cache['tpl_url_colour']);
336
	}
337
338
	/**
339
	 * Returns SQL WHERE clause for all marked items
340
	 *
341
	 * @param $marked
342
	 *
343
	 * @return string
344
	 * @access public
345
	 */
346
	public function build_marked_where_sql($marked)
347
	{
348
		$sql_in = array();
349
		foreach ($marked as $mark)
350
		{
351
			$sql_in[] = $mark;
352
		}
353
354
		return ' WHERE ' . $this->db->sql_in_set('transaction_id', $sql_in);
355
	}
356
357
	/**
358
	 * Build SQL query for updating stats
359
	 *
360
	 * @param string $type
361
	 * @param bool   $test_ipn
362
	 *
363
	 * @return string
364
	 * @access public
365
	 */
366
	public function sql_build_update_stats($type, $test_ipn)
367
	{
368
		switch ($type)
369
		{
370
			case 'ppde_transactions_count':
371
			case 'ppde_transactions_count_ipn':
372
				$sql_ary = $this->sql_select_stats_main('txn_id');
373
				$sql_ary['WHERE'] = "confirmed = 1 AND payment_status = 'Completed' AND txn.test_ipn = " . (int) $test_ipn;
374
				break;
375
			case 'ppde_known_donors_count':
376
			case 'ppde_known_donors_count_ipn':
377
				$sql_ary = $this->sql_select_stats_main('payer_id');
378
				$sql_ary{'LEFT_JOIN'} = array(
379
					array(
380
						'FROM' => array(USERS_TABLE => 'u'),
381
						'ON'   => 'txn.user_id = u.user_id',
382
					),
383
				);
384
				$sql_ary['WHERE'] = '(u.user_type = ' . USER_NORMAL . ' OR u.user_type = ' . USER_FOUNDER . ') AND txn.test_ipn = ' . (int) $test_ipn;
385
				break;
386
			case 'ppde_anonymous_donors_count':
387
			case 'ppde_anonymous_donors_count_ipn':
388
				$sql_ary = $this->sql_select_stats_main('payer_id');
389
				$sql_ary['WHERE'] = 'txn.user_id = ' . ANONYMOUS . ' AND txn.test_ipn = ' . (int) $test_ipn;
390
				break;
391
			default:
392
				$sql_ary = $this->sql_select_stats_main('txn_id');
393
		}
394
395
		return $this->db->sql_build_query('SELECT', $sql_ary);
396
	}
397
398
	/**
399
	 * Make body of SQL query for stats calculation.
400
	 *
401
	 * @param string $field_name Name of the field
402
	 *
403
	 * @return array
404
	 * @access private
405
	 */
406
	private function sql_select_stats_main($field_name)
407
	{
408
		return array(
409
			'SELECT' => 'COUNT(DISTINCT txn.' . $field_name . ') AS count_result',
410
			'FROM'   => array($this->ppde_transactions_log_table => 'txn'),
411
		);
412
	}
413
}
414