Completed
Pull Request — develop (#34)
by Mario
03:14
created

admin_transactions_controller::set_suffix_ipn()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 4
rs 10
cc 2
eloc 2
nc 2
nop 0
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\controller;
12
13
use Symfony\Component\DependencyInjection\ContainerInterface;
14
15
/**
16
 * @property ContainerInterface       container         The phpBB log system
17
 * @property string                   id_prefix_name    Prefix name for identifier in the URL
18
 * @property string                   lang_key_prefix   Prefix for the messages thrown by exceptions
19
 * @property \phpbb\log\log           log               The phpBB log system.
20
 * @property string                   module_name       Name of the module currently used
21
 * @property \phpbb\request\request   request           Request object.
22
 * @property bool                     submit            State of submit $_POST variable
23
 * @property \phpbb\template\template template          Template object
24
 * @property string                   u_action          Action URL
25
 * @property \phpbb\user              user              User object.
26
 */
27
class admin_transactions_controller extends admin_main
28
{
29
	public $ppde_operator;
30
	protected $adm_relative_path;
31
	protected $auth;
32
	protected $db;
33
	protected $config;
34
	protected $entry_count;
35
	protected $last_page_offset;
36
	protected $php_ext;
37
	protected $phpbb_admin_path;
38
	protected $phpbb_root_path;
39
	protected $table_ppde_transactions;
40
	private $is_ipn_test = false;
41
	private $suffix_ipn;
42
43
	/**
44
	 * Constructor
45
	 *
46
	 * @param \phpbb\auth\auth                    $auth                       Authentication object
47
	 * @param \phpbb\db\driver\driver_interface   $db                         Database object
48
	 * @param \phpbb\config\config                $config                     Config object
49
	 * @param ContainerInterface                  $container
50
	 * @param \phpbb\log\log                      $log                        The phpBB log system
51
	 * @param \skouat\ppde\operators\transactions $ppde_operator_transactions Operator object
52
	 * @param \phpbb\request\request              $request                    Request object
53
	 * @param \phpbb\template\template            $template                   Template object
54
	 * @param \phpbb\user                         $user                       User object.
55
	 * @param string                              $adm_relative_path          phpBB admin relative path
56
	 * @param string                              $phpbb_root_path            phpBB root path
57
	 * @param string                              $php_ext                    phpEx
58
	 * @param string                              $table_ppde_transactions    Name of the table used to store data
59
	 *
60
	 * @access public
61
	 */
62
	public function __construct(\phpbb\auth\auth $auth, \phpbb\db\driver\driver_interface $db, \phpbb\config\config $config, ContainerInterface $container, \phpbb\log\log $log, \skouat\ppde\operators\transactions $ppde_operator_transactions, \phpbb\request\request $request, \phpbb\template\template $template, \phpbb\user $user, $adm_relative_path, $phpbb_root_path, $php_ext, $table_ppde_transactions)
63
	{
64
		$this->auth = $auth;
65
		$this->db = $db;
66
		$this->config = $config;
67
		$this->container = $container;
68
		$this->log = $log;
69
		$this->ppde_operator = $ppde_operator_transactions;
70
		$this->request = $request;
71
		$this->template = $template;
72
		$this->user = $user;
73
		$this->adm_relative_path = $adm_relative_path;
74
		$this->phpbb_admin_path = $phpbb_root_path . $adm_relative_path;
75
		$this->phpbb_root_path = $phpbb_root_path;
76
		$this->php_ext = $php_ext;
77
		$this->table_ppde_transactions = $table_ppde_transactions;
78
		parent::__construct(
79
			'transactions',
80
			'PPDE_DT',
81
			'transaction'
82
		);
83
	}
84
85
	/**
86
	 * Display the transactions list
87
	 *
88
	 * @param string $id     Module id
89
	 * @param string $mode   Module categorie
90
	 * @param string $action Action name
91
	 *
92
	 * @return null
93
	 * @access public
94
	 */
95
	public function display_transactions($id, $mode, $action)
96
	{
97
		// Set up general vars
98
		$start = $this->request->variable('start', 0);
99
		$deletemark = $this->request->is_set('delmarked');
100
		$deleteall = $this->request->is_set('delall');
101
		$marked = $this->request->variable('mark', array(0));
102
		// Sort keys
103
		$sort_days = $this->request->variable('st', 0);
104
		$sort_key = $this->request->variable('sk', 't');
105
		$sort_dir = $this->request->variable('sd', 'd');
106
107
		// Initiate an entity
108
		/** @type \skouat\ppde\entity\transactions $entity */
109
		$entity = $this->get_container_entity();
110
111
		// Delete entries if requested and able
112
		if (($deletemark || $deleteall) && $this->auth->acl_get('a_ppde_manage'))
113
		{
114
			if (confirm_box(true))
115
			{
116
				$where_sql = '';
117
118
				if ($deletemark && sizeof($marked))
119
				{
120
					$where_sql = $this->ppde_operator->build_marked_where_sql($marked);
121
				}
122
123
				if ($where_sql || $deleteall)
124
				{
125
					$entity->delete(0, '', $where_sql);
126
					$this->update_stats();
127
					$this->update_stats(true);
128
					$this->log->add('admin', $this->user->data['user_id'], $this->user->ip, 'LOG_' . $this->lang_key_prefix . '_PURGED', time());
129
				}
130
			}
131
			else
132
			{
133
				confirm_box(false, $this->user->lang['CONFIRM_OPERATION'], build_hidden_fields(array(
134
						'start'     => $start,
135
						'delmarked' => $deletemark,
136
						'delall'    => $deleteall,
137
						'mark'      => $marked,
138
						'st'        => $sort_days,
139
						'sk'        => $sort_key,
140
						'sd'        => $sort_dir,
141
						'i'         => $id,
142
						'mode'      => $mode,
143
						'action'    => $action))
144
				);
145
			}
146
		}
147
148
		$this->do_action($action);
149
150
		if (!$action)
151
		{
152
			/** @type \phpbb\pagination $pagination */
153
			$pagination = $this->container->get('pagination');
154
155
			// Sorting
156
			$limit_days = array(0 => $this->user->lang['ALL_ENTRIES'], 1 => $this->user->lang['1_DAY'], 7 => $this->user->lang['7_DAYS'], 14 => $this->user->lang['2_WEEKS'], 30 => $this->user->lang['1_MONTH'], 90 => $this->user->lang['3_MONTHS'], 180 => $this->user->lang['6_MONTHS'], 365 => $this->user->lang['1_YEAR']);
157
			$sort_by_text = array('txn' => $this->user->lang['PPDE_DT_SORT_TXN_ID'], 'u' => $this->user->lang['PPDE_DT_SORT_DONORS'], 'ipn' => $this->user->lang['PPDE_DT_SORT_IPN_STATUS'], 'ipn_test' => $this->user->lang['PPDE_DT_SORT_IPN_TYPE'], 'ps' => $this->user->lang['PPDE_DT_SORT_PAYMENT_STATUS'], 't' => $this->user->lang['SORT_DATE']);
158
			$sort_by_sql = array('txn' => 'txn.txn_id', 'u' => 'u.username_clean', 'ipn' => 'txn.confirmed', 'ipn_test' => 'txn.test_ipn', 'ps' => 'txn.payment_status', 't' => 'txn.payment_date');
159
160
			$s_limit_days = $s_sort_key = $s_sort_dir = $u_sort_param = '';
161
			gen_sort_selects($limit_days, $sort_by_text, $sort_days, $sort_key, $sort_dir, $s_limit_days, $s_sort_key, $s_sort_dir, $u_sort_param);
162
163
			// Define where and sort sql for use in displaying transactions
164
			$sql_where = ($sort_days) ? (time() - ($sort_days * 86400)) : 0;
165
			$sql_sort = $sort_by_sql[$sort_key] . ' ' . (($sort_dir == 'd') ? 'DESC' : 'ASC');
166
167
			$keywords = utf8_normalize_nfc($this->request->variable('keywords', '', true));
168
			$keywords_param = !empty($keywords) ? '&amp;keywords=' . urlencode(htmlspecialchars_decode($keywords)) : '';
169
170
			// Grab log data
171
			$log_data = array();
172
			$log_count = 0;
173
174
			$this->view_txn_log($log_data, $log_count, $this->config['topics_per_page'], $start, $sql_where, $sql_sort, $keywords);
175
176
			$base_url = $this->u_action . '&amp;' . $u_sort_param . $keywords_param;
177
			$pagination->generate_template_pagination($base_url, 'pagination', 'start', $log_count, $this->config['topics_per_page'], $start);
178
179
			$this->template->assign_vars(array(
180
				'S_CLEARLOGS'  => $this->auth->acl_get('a_ppde_manage'),
181
				'S_KEYWORDS'   => $keywords,
182
				'S_LIMIT_DAYS' => $s_limit_days,
183
				'S_SORT_KEY'   => $s_sort_key,
184
				'S_SORT_DIR'   => $s_sort_dir,
185
				'S_TXN'        => $mode,
186
				'U_ACTION'     => $this->u_action . '&amp;' . $u_sort_param . $keywords_param . '&amp;start=' . $start,
187
			));
188
189
			foreach ($log_data as $row)
190
			{
191
				// Initiate vars to retrieve the 'payment_status' translation from the language key
192
				$payment_status_ary = $this->user->lang['PPDE_DT_PAYMENT_STATUS_VALUES'];
193
				$payment_status_name = strtolower($row['payment_status']);
194
195
				$this->template->assign_block_vars('log', array(
196
					'TNX_ID'           => $row['txn_id'],
197
					'USERNAME'         => $row['username_full'],
198
					'DATE'             => $this->user->format_date($row['payment_date']),
199
					'ID'               => $row['transaction_id'],
200
					'S_TEST_IPN'       => $row['test_ipn'],
201
					'CONFIRMED'        => ($row['confirmed']) ? $this->user->lang['PPDE_DT_VERIFIED'] : $this->user->lang['PPDE_DT_UNVERIFIED'],
202
					'PAYMENT_STATUS'   => $payment_status_ary[$payment_status_name],
203
					'S_CONFIRMED'      => ($row['confirmed']) ? false : true,
204
					'S_PAYMENT_STATUS' => ($payment_status_name === 'completed') ? false : true,
205
				));
206
				unset($payment_status_name);
207
			}
208
		}
209
	}
210
211
212
	/**
213
	 * @param bool $ipn_stats
214
	 */
215
	public function update_stats($ipn_stats = false)
216
	{
217
		$this->set_ipn_test_properties($ipn_stats);
218
		$this->config->set('ppde_known_donors_count' . $this->suffix_ipn, $this->sql_query_update_stats('ppde_known_donors_count' . $this->suffix_ipn), true);
219
		$this->config->set('ppde_anonymous_donors_count' . $this->suffix_ipn, $this->sql_query_update_stats('ppde_anonymous_donors_count' . $this->suffix_ipn));
220
		$this->config->set('ppde_transactions_count' . $this->suffix_ipn, $this->sql_query_update_stats('ppde_transactions_count' . $this->suffix_ipn), true);
221
	}
222
223
	/**
224
	 * Sets properties related to ipn tests
225
	 *
226
	 * @param bool $ipn_stats
227
	 *
228
	 * @return null
229
	 * @access public
230
	 */
231
	public function set_ipn_test_properties($ipn_stats)
232
	{
233
		$this->set_ipn_test($ipn_stats);
234
		$this->set_suffix_ipn();
235
	}
236
237
	/**
238
	 * Sets the property $this->is_ipn_test
239
	 *
240
	 * @param $ipn_test
241
	 *
242
	 * @return null
243
	 * @access private
244
	 */
245
	private function set_ipn_test($ipn_test)
246
	{
247
		$this->is_ipn_test = $ipn_test ? (bool) $ipn_test : false;
248
	}
249
250
	/**
251
	 * Sets the property $this->suffix_ipn
252
	 *
253
	 * @return null
254
	 * @access private
255
	 */
256
	private function set_suffix_ipn()
257
	{
258
		$this->suffix_ipn = $this->is_ipn_test ? '_ipn' : '';
259
	}
260
261
	/**
262
	 * Returns count result for updating stats
263
	 *
264
	 * @param string $config_name
265
	 *
266
	 * @return int
267
	 * @access private
268
	 */
269
	private function sql_query_update_stats($config_name)
270
	{
271
		if (!$this->config->offsetExists($config_name))
272
		{
273
			trigger_error($this->user->lang('EXCEPTION_INVALID_CONFIG_NAME', $config_name), E_USER_WARNING);
274
		}
275
276
		$this->db->sql_query($this->make_stats_sql_update($config_name));
277
278
		return (int) $this->db->sql_fetchfield('count_result');
279
	}
280
281
	/**
282
	 * Build SQL query for updating stats
283
	 *
284
	 * @param string $type
285
	 *
286
	 * @return string
287
	 * @access private
288
	 */
289
	private function make_stats_sql_update($type)
290
	{
291
		switch ($type)
292
		{
293
			case 'ppde_transactions_count':
294
			case 'ppde_transactions_count_ipn':
295
				$sql = $this->make_stats_sql_select('txn_id');
296
				$sql .= " WHERE confirmed = 1 AND payment_status = 'Completed' AND txn.test_ipn = " . (int) $this->is_ipn_test;
297
298
				return $sql;
299
			case 'ppde_known_donors_count':
300
			case 'ppde_known_donors_count_ipn':
301
				$sql = $this->make_stats_sql_select('payer_id');
302
				$sql .= ' LEFT JOIN ' . USERS_TABLE . ' u
303
				 					ON txn.user_id = u.user_id
304
								WHERE (u.user_type = ' . USER_NORMAL . ' OR u.user_type = ' . USER_FOUNDER . ") AND txn.test_ipn = " . (int) $this->is_ipn_test;
0 ignored issues
show
Coding Style Comprehensibility introduced by
The string literal ) AND txn.test_ipn = 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...
305
306
				return $sql;
307
			case 'ppde_anonymous_donors_count':
308
			case 'ppde_anonymous_donors_count_ipn':
309
				$sql = $this->make_stats_sql_select('payer_id');
310
				$sql .= ' WHERE txn.user_id = ' . ANONYMOUS . ' AND txn.test_ipn = ' . (int) $this->is_ipn_test;
311
312
				return $sql;
313
			default:
314
				return $this->make_stats_sql_select('txn_id');
315
		}
316
	}
317
318
	/**
319
	 * Make body of SQL query for stats calculation.
320
	 *
321
	 * @param string $field_name Name of the field
322
	 *
323
	 * @return string
324
	 * @access private
325
	 */
326
	private function make_stats_sql_select($field_name)
327
	{
328
		return 'SELECT COUNT(DISTINCT txn.' . $field_name . ') AS count_result
329
				FROM ' . $this->table_ppde_transactions . ' txn';
330
	}
331
332
	/**
333
	 * Do action regarding the value of $action
334
	 *
335
	 * @param $action
336
	 *
337
	 * @return null
338
	 * @access private
339
	 */
340
	private function do_action($action)
341
	{
342
		// Action: view
343
		if ($action == 'view')
344
		{
345
			// Request Identifier of the transaction
346
			$transaction_id = $this->request->variable('id', 0);
347
348
			// Initiate an entity
349
			/** @type \skouat\ppde\entity\currency $entity */
350
			$entity = $this->get_container_entity();
351
352
			// add field username to the table schema needed by entity->import()
353
			$additional_table_schema = array('item_username' => array('name' => 'username', 'type' => 'string'));
354
355
			// Grab transaction data
356
			$data_ary = $entity->get_data($this->ppde_operator->build_sql_data($transaction_id), $additional_table_schema);
357
358
			foreach ($data_ary as $data)
359
			{
360
				// Initiate vars to retrieve the 'payment_status' translation from the language key
361
				$payment_status_ary = $this->user->lang['PPDE_DT_PAYMENT_STATUS_VALUES'];
362
363
				$this->template->assign_vars(array(
364
					'BOARD_USERNAME' => $data['username'],
365
					'EXCHANGE_RATE'  => '1 ' . $data['mc_currency'] . ' = ' . $data['exchange_rate'] . ' ' . $data['settle_currency'],
366
					'ITEM_NAME'      => $data['item_name'],
367
					'ITEM_NUMBER'    => $data['item_number'],
368
					'MC_CURRENCY'    => $data['net_amount'] . ' ' . $data['mc_currency'],
369
					'MC_GROSS'       => $data['mc_gross'] . ' ' . $data['mc_currency'],
370
					'MC_FEE'         => '-' . $data['mc_fee'] . ' ' . $data['mc_currency'],
371
					'MC_NET'         => $data['net_amount'] . ' ' . $data['mc_currency'],
372
					'NAME'           => $data['first_name'] . ' ' . $data['last_name'],
373
					'PAYER_EMAIL'    => $data['payer_email'],
374
					'PAYER_ID'       => $data['payer_id'],
375
					'PAYER_STATUS'   => ($data['payer_status']) ? $this->user->lang['PPDE_DT_VERIFIED'] : $this->user->lang['PPDE_DT_UNVERIFIED'],
376
					'PAYMENT_DATE'   => $this->user->format_date($data['payment_date']),
377
					'PAYMENT_STATUS' => $payment_status_ary[strtolower($data['payment_status'])],
378
					'RECEIVER_EMAIL' => $data['receiver_email'],
379
					'RECEIVER_ID'    => $data['receiver_id'],
380
					'SETTLE_AMOUNT'  => $data['settle_amount'] . ' ' . $data['settle_currency'],
381
					'TXN_ID'         => $data['txn_id'],
382
383
					'L_PPDE_DT_SETTLE_AMOUNT'         => $this->user->lang('PPDE_DT_SETTLE_AMOUNT', $data['settle_currency']),
384
					'L_PPDE_DT_EXCHANGE_RATE_EXPLAIN' => $this->user->lang('PPDE_DT_EXCHANGE_RATE_EXPLAIN', $this->user->format_date($data['payment_date'])),
385
					'S_CONVERT'                       => ($data['settle_amount'] == 0 && empty($data['exchange_rate'])) ? false : true,
386
				));
387
			}
388
389
			$this->template->assign_vars(array(
390
				'U_ACTION' => $this->u_action,
391
				'U_BACK'   => $this->u_action,
392
				'S_VIEW'   => true,
393
			));
394
		}
395
	}
396
397
	/**
398
	 * View log
399
	 *
400
	 * @param array  &$log         The result array with the logs
401
	 * @param mixed  &$log_count   If $log_count is set to false, we will skip counting all entries in the
402
	 *                             database. Otherwise an integer with the number of total matching entries is returned.
403
	 * @param int    $limit        Limit the number of entries that are returned
404
	 * @param int    $offset       Offset when fetching the log entries, f.e. when paginating
405
	 * @param int    $limit_days
406
	 * @param string $sort_by      SQL order option, e.g. 'l.log_time DESC'
407
	 * @param string $keywords     Will only return log entries that have the keywords in log_operation or log_data
408
	 *
409
	 * @return int Returns the offset of the last valid page, if the specified offset was invalid
410
	 *                               (too high)
411
	 * @access private
412
	 */
413
	private function view_txn_log(&$log, &$log_count, $limit = 0, $offset = 0, $limit_days = 0, $sort_by = 'txn.payment_date DESC', $keywords = '')
414
	{
415
		$count_logs = ($log_count !== false);
416
417
		$log = $this->get_logs($count_logs, $limit, $offset, $limit_days, $sort_by, $keywords);
418
		$log_count = $this->get_log_count();
419
420
		return $this->get_valid_offset();
421
	}
422
423
	/**
424
	 * @param bool   $count_logs
425
	 * @param int    $limit
426
	 * @param int    $offset
427
	 * @param int    $log_time
428
	 * @param string $sort_by
429
	 * @param string $keywords
430
	 *
431
	 * @return array $log
432
	 * @access private
433
	 */
434
	private function get_logs($count_logs = true, $limit = 0, $offset = 0, $log_time = 0, $sort_by = 'txn.payment_date DESC', $keywords = '')
435
	{
436
		$this->entry_count = 0;
437
		$this->last_page_offset = $offset;
438
		$url_ary = array();
439
440
		if ($this->get_container_entity()->is_in_admin() && $this->phpbb_admin_path)
441
		{
442
			$url_ary['profile_url'] = append_sid($this->phpbb_admin_path . 'index.' . $this->php_ext, 'i=users&amp;mode=overview');
443
			$url_ary['txn_url'] = append_sid($this->phpbb_admin_path . 'index.' . $this->php_ext, 'i=-skouat-ppde-acp-ppde_module&amp;mode=transactions');
444
445
		}
446
		else
447
		{
448
			$url_ary['profile_url'] = append_sid($this->phpbb_root_path . 'memberlist.' . $this->php_ext, 'mode=viewprofile');
449
			$url_ary['txn_url'] = '';
450
		}
451
452
		$get_logs_sql_ary = $this->ppde_operator->get_logs_sql_ary($keywords, $sort_by, $log_time);
453
454
		if ($count_logs)
455
		{
456
			$this->entry_count = $this->ppde_operator->query_sql_count($get_logs_sql_ary, 'txn.transaction_id');
457
458
			if ($this->entry_count == 0)
459
			{
460
				// Save the queries, because there are no logs to display
461
				$this->last_page_offset = 0;
462
463
				return array();
464
			}
465
466
			// Return the user to the last page that is valid
467
			while ($this->last_page_offset >= $this->entry_count)
468
			{
469
				$this->last_page_offset = max(0, $this->last_page_offset - $limit);
470
			}
471
		}
472
473
		return $this->ppde_operator->build_log_ary($get_logs_sql_ary, $url_ary, $limit, $this->last_page_offset);
474
	}
475
476
	/**
477
	 * @return integer
478
	 */
479
	public function get_log_count()
480
	{
481
		return ($this->entry_count) ? $this->entry_count : 0;
482
	}
483
484
	/**
485
	 * @return integer
486
	 */
487
	public function get_valid_offset()
488
	{
489
		return ($this->last_page_offset) ? $this->last_page_offset : 0;
490
	}
491
492
	/**
493
	 * @return boolean
494
	 */
495
	public function get_is_ipn_test()
496
	{
497
		return ($this->is_ipn_test) ? $this->is_ipn_test : false;
498
	}
499
500
	/**
501
	 * @return string
502
	 */
503
	public function get_suffix_ipn()
504
	{
505
		return ($this->suffix_ipn) ? $this->suffix_ipn : '';
506
	}
507
}
508