Completed
Pull Request — develop-3.2.x (#45)
by Mario
01:50
created

admin_transactions_controller   B

Complexity

Total Complexity 47

Size/Duplication

Total Lines 425
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 4

Importance

Changes 2
Bugs 0 Features 0
Metric Value
wmc 47
c 2
b 0
f 0
lcom 1
cbo 4
dl 0
loc 425
rs 8.439

14 Methods

Rating   Name   Duplication   Size   Complexity  
D display_transactions() 0 110 17
A update_stats() 0 7 1
A set_ipn_test_properties() 0 5 1
A set_ipn_test() 0 4 2
A set_suffix_ipn() 0 4 2
B do_action() 0 53 6
A view_txn_log() 0 9 1
A get_ipn_test() 0 4 2
A get_suffix_ipn() 0 4 2
A __construct() 0 23 1
A sql_query_update_stats() 0 11 2
B get_logs() 0 41 6
A get_log_count() 0 4 2
A get_valid_offset() 0 4 2

How to fix   Complexity   

Complex Class

Complex classes like admin_transactions_controller often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use admin_transactions_controller, and based on these observations, apply Extract Interface, too.

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