Completed
Branch develop-3.3.x-refactor_modules (cfd1e1)
by Mario
03:51
created

transactions_controller::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 44
Code Lines 23

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 23
nc 1
nop 18
dl 0
loc 44
rs 9.552
c 0
b 0
f 0

How to fix   Many Parameters   

Many Parameters

Methods with many parameters are not only hard to understand, but their parameters also often become inconsistent when you need more, or different data.

There are several approaches to avoid long parameter lists:

1
<?php
2
/**
3
 *
4
 * PayPal Donation extension for the phpBB Forum Software package.
5
 *
6
 * @copyright (c) 2015-2020 Skouat
7
 * @license GNU General Public License, version 2 (GPL-2.0)
8
 *
9
 */
10
11
namespace skouat\ppde\controller\admin;
12
13
use phpbb\auth\auth;
14
use phpbb\config\config;
15
use phpbb\language\language;
16
use phpbb\log\log;
17
use phpbb\request\request;
18
use phpbb\template\template;
19
use phpbb\user;
20
use phpbb\user_loader;
21
use skouat\ppde\actions\core;
22
use skouat\ppde\actions\currency;
23
use skouat\ppde\exception\transaction_exception;
24
use skouat\ppde\operators\transactions;
25
use Symfony\Component\DependencyInjection\ContainerInterface;
26
27
/**
28
 * @property array              args               Array of args for hidden fiels
29
 * @property config             config             Config object
30
 * @property ContainerInterface container          Service container interface
31
 * @property string             id_prefix_name     Prefix name for identifier in the URL
32
 * @property string             lang_key_prefix    Prefix for the messages thrown by exceptions
33
 * @property language           language           Language user object
34
 * @property log                log                The phpBB log system.
35
 * @property string             module_name        Name of the module currently used
36
 * @property request            request            Request object.
37
 * @property bool               submit             State of submit $_POST variable
38
 * @property template           template           Template object
39
 * @property string             u_action           Action URL
40
 * @property user               user               User object.
41
 * @property user_loader        user_loader        User loader object
42
 */
43
class transactions_controller extends admin_main
44
{
45
	public $ppde_operator;
46
	protected $adm_relative_path;
47
	protected $auth;
48
	protected $user_loader;
49
	protected $entry_count;
50
	protected $last_page_offset;
51
	protected $php_ext;
52
	protected $phpbb_admin_path;
53
	protected $phpbb_root_path;
54
	protected $ppde_actions;
55
	protected $ppde_actions_currency;
56
	protected $ppde_entity;
57
	protected $table_prefix;
58
	protected $table_ppde_transactions;
59
60
	/**
61
	 * Constructor
62
	 *
63
	 * @param auth                             $auth                       Authentication object
64
	 * @param config                           $config                     Config object
65
	 * @param ContainerInterface               $container                  Service container interface
66
	 * @param language                         $language                   Language user object
67
	 * @param log                              $log                        The phpBB log system
68
	 * @param core                             $ppde_actions               PPDE actions object
69
	 * @param currency                         $ppde_actions_currency      PPDE currency actions object
70
	 * @param \skouat\ppde\entity\transactions $ppde_entity_transactions   Entity object
71
	 * @param transactions                     $ppde_operator_transactions Operator object
72
	 * @param request                          $request                    Request object
73
	 * @param template                         $template                   Template object
74
	 * @param user                             $user                       User object.
75
	 * @param user_loader                      $user_loader                User loader object
76
	 * @param string                           $adm_relative_path          phpBB admin relative path
77
	 * @param string                           $phpbb_root_path            phpBB root path
78
	 * @param string                           $php_ext                    phpEx
79
	 * @param string                           $table_prefix               The table prefix
80
	 * @param string                           $table_ppde_transactions    Name of the table used to store data
81
	 *
82
	 * @access public
83
	 */
84
	public function __construct(
85
		auth $auth,
86
		config $config,
87
		ContainerInterface $container,
88
		language $language,
89
		log $log,
90
		core $ppde_actions,
91
		currency $ppde_actions_currency,
92
		\skouat\ppde\entity\transactions $ppde_entity_transactions,
93
		transactions $ppde_operator_transactions,
94
		request $request,
95
		template $template,
96
		user $user,
97
		user_loader $user_loader,
98
		$adm_relative_path,
99
		$phpbb_root_path,
100
		$php_ext,
101
		$table_prefix,
102
		$table_ppde_transactions
103
	)
104
	{
105
		$this->auth = $auth;
106
		$this->config = $config;
107
		$this->container = $container;
108
		$this->language = $language;
109
		$this->log = $log;
110
		$this->ppde_actions = $ppde_actions;
111
		$this->ppde_actions_currency = $ppde_actions_currency;
112
		$this->ppde_entity = $ppde_entity_transactions;
113
		$this->ppde_operator = $ppde_operator_transactions;
114
		$this->request = $request;
115
		$this->template = $template;
116
		$this->user = $user;
117
		$this->user_loader = $user_loader;
118
		$this->adm_relative_path = $adm_relative_path;
119
		$this->phpbb_admin_path = $phpbb_root_path . $adm_relative_path;
120
		$this->phpbb_root_path = $phpbb_root_path;
121
		$this->php_ext = $php_ext;
122
		$this->table_prefix = $table_prefix;
123
		$this->table_ppde_transactions = $table_ppde_transactions;
124
		parent::__construct(
125
			'transactions',
126
			'PPDE_DT',
127
			'transaction'
128
		);
129
	}
130
131
	/**
132
	 * Display the transactions list
133
	 *
134
	 * @return void
135
	 * @access public
136
	 */
137
	public function display()
138
	{
139
		/** @type \phpbb\pagination $pagination */
140
		$pagination = $this->container->get('pagination');
141
142
		// Sorting
143
		$limit_days = [
144
			0   => $this->language->lang('ALL_ENTRIES'),
145
			1   => $this->language->lang('1_DAY'),
146
			7   => $this->language->lang('7_DAYS'),
147
			14  => $this->language->lang('2_WEEKS'),
148
			30  => $this->language->lang('1_MONTH'),
149
			90  => $this->language->lang('3_MONTHS'),
150
			180 => $this->language->lang('6_MONTHS'),
151
			365 => $this->language->lang('1_YEAR'),
152
		];
153
		$sort_by_text = [
154
			'txn'      => $this->language->lang('PPDE_DT_SORT_TXN_ID'),
155
			'u'        => $this->language->lang('PPDE_DT_SORT_DONORS'),
156
			'ipn'      => $this->language->lang('PPDE_DT_SORT_IPN_STATUS'),
157
			'ipn_test' => $this->language->lang('PPDE_DT_SORT_IPN_TYPE'),
158
			'ps'       => $this->language->lang('PPDE_DT_SORT_PAYMENT_STATUS'),
159
			't'        => $this->language->lang('SORT_DATE'),
160
		];
161
		$sort_by_sql = [
162
			'txn'      => 'txn.txn_id',
163
			'u'        => 'u.username_clean',
164
			'ipn'      => 'txn.confirmed',
165
			'ipn_test' => 'txn.test_ipn',
166
			'ps'       => 'txn.payment_status',
167
			't'        => 'txn.payment_date',
168
		];
169
170
		$s_limit_days = $s_sort_key = $s_sort_dir = $u_sort_param = '';
171
		gen_sort_selects($limit_days, $sort_by_text, $this->args['hidden_fields']['st'], $this->args['hidden_fields']['sk'], $this->args['hidden_fields']['sd'], $s_limit_days, $s_sort_key, $s_sort_dir, $u_sort_param);
172
173
		// Define where and sort sql for use in displaying transactions
174
		$sql_where = ($this->args['hidden_fields']['st']) ? (time() - ($this->args['hidden_fields']['st'] * 86400)) : 0;
175
		$sql_sort = $sort_by_sql[$this->args['hidden_fields']['sk']] . ' ' . (($this->args['hidden_fields']['sd'] == 'd') ? 'DESC' : 'ASC');
176
177
		$keywords = $this->request->variable('keywords', '', true);
178
		$keywords_param = !empty($keywords) ? '&amp;keywords=' . urlencode(htmlspecialchars_decode($keywords)) : '';
179
180
		// Grab log data
181
		$log_data = [];
182
		$log_count = 0;
183
184
		$this->view_txn_log($log_data, $log_count, (int) $this->config['topics_per_page'], $this->args['hidden_fields']['start'], $sql_where, $sql_sort, $keywords);
185
186
		$base_url = $this->u_action . '&amp;' . $u_sort_param . $keywords_param;
187
		$pagination->generate_template_pagination($base_url, 'pagination', 'start', $log_count, (int) $this->config['topics_per_page'], $this->args['hidden_fields']['start']);
188
189
		$this->template->assign_vars([
190
			'S_CLEARLOGS'  => $this->auth->acl_get('a_ppde_manage'),
191
			'S_KEYWORDS'   => $keywords,
192
			'S_LIMIT_DAYS' => $s_limit_days,
193
			'S_SORT_KEY'   => $s_sort_key,
194
			'S_SORT_DIR'   => $s_sort_dir,
195
			'U_ACTION'     => $this->u_action . '&amp;' . $u_sort_param . $keywords_param . '&amp;start=' . $this->args['hidden_fields']['start'],
196
		]);
197
198
		array_map([$this, 'display_log_assign_template_vars'], $log_data);
199
	}
200
201
	/**
202
	 * View log
203
	 *
204
	 * @param array  &$log         The result array with the logs
205
	 * @param mixed  &$log_count   If $log_count is set to false, we will skip counting all entries in the
206
	 *                             database. Otherwise an integer with the number of total matching entries is returned.
207
	 * @param int     $limit       Limit the number of entries that are returned
208
	 * @param int     $offset      Offset when fetching the log entries, f.e. when paginating
209
	 * @param int     $limit_days
210
	 * @param string  $sort_by     SQL order option, e.g. 'l.log_time DESC'
211
	 * @param string  $keywords    Will only return log entries that have the keywords in log_operation or log_data
212
	 *
213
	 * @return int Returns the offset of the last valid page, if the specified offset was invalid (too high)
214
	 * @access private
215
	 */
216
	private function view_txn_log(&$log, &$log_count, $limit = 0, $offset = 0, $limit_days = 0, $sort_by = 'txn.payment_date DESC', $keywords = '')
217
	{
218
		$count_logs = ($log_count !== false);
219
220
		$log = $this->get_logs($count_logs, $limit, $offset, $limit_days, $sort_by, $keywords);
221
		$log_count = $this->get_log_count();
222
223
		return $this->get_valid_offset();
224
	}
225
226
	/**
227
	 * @param bool   $count_logs
228
	 * @param int    $limit
229
	 * @param int    $offset
230
	 * @param int    $log_time
231
	 * @param string $sort_by
232
	 * @param string $keywords
233
	 *
234
	 * @return array $log
235
	 * @access private
236
	 */
237
	private function get_logs($count_logs = true, $limit = 0, $offset = 0, $log_time = 0, $sort_by = 'txn.payment_date DESC', $keywords = '')
238
	{
239
		$this->entry_count = 0;
240
		$this->last_page_offset = $offset;
241
		$url_ary = [];
242
243
		if ($this->ppde_actions->is_in_admin() && $this->phpbb_admin_path)
244
		{
245
			$url_ary['profile_url'] = append_sid($this->phpbb_admin_path . 'index.' . $this->php_ext, 'i=users&amp;mode=overview');
246
			$url_ary['txn_url'] = append_sid($this->phpbb_admin_path . 'index.' . $this->php_ext, 'i=-skouat-ppde-acp-ppde_module&amp;mode=transactions');
247
248
		}
249
		else
250
		{
251
			$url_ary['profile_url'] = append_sid($this->phpbb_root_path . 'memberlist.' . $this->php_ext, 'mode=viewprofile');
252
			$url_ary['txn_url'] = '';
253
		}
254
255
		$get_logs_sql_ary = $this->ppde_operator->get_logs_sql_ary($keywords, $sort_by, $log_time);
256
257
		if ($count_logs)
258
		{
259
			$this->entry_count = $this->ppde_operator->query_sql_count($get_logs_sql_ary, 'txn.transaction_id');
260
261
			if ($this->entry_count == 0)
262
			{
263
				// Save the queries, because there are no logs to display
264
				$this->last_page_offset = 0;
265
266
				return [];
267
			}
268
269
			// Return the user to the last page that is valid
270
			while ($this->last_page_offset >= $this->entry_count)
271
			{
272
				$this->last_page_offset = max(0, $this->last_page_offset - $limit);
273
			}
274
		}
275
276
		return $this->ppde_operator->build_log_ary($get_logs_sql_ary, $url_ary, $limit, $this->last_page_offset);
277
	}
278
279
	/**
280
	 * @return integer
281
	 */
282
	public function get_log_count()
283
	{
284
		return ($this->entry_count) ? (int) $this->entry_count : 0;
285
	}
286
287
	/**
288
	 * @return integer
289
	 */
290
	public function get_valid_offset()
291
	{
292
		return ($this->last_page_offset) ? (int) $this->last_page_offset : 0;
293
	}
294
295
	/**
296
	 * Gets vars from POST then build a array of them
297
	 *
298
	 * @param string $id     Module id
299
	 * @param string $mode   Module categorie
300
	 * @param string $action Action name
301
	 *
302
	 * @return void
303
	 * @access private
304
	 */
305
	public function set_hidden_fields($id, $mode, $action)
306
	{
307
		$this->args = [
308
			'action'        => $action,
309
			'hidden_fields' => [
310
				'start'     => $this->request->variable('start', 0),
311
				'delall'    => $this->request->variable('delall', false, false, \phpbb\request\request_interface::POST),
312
				'delmarked' => $this->request->variable('delmarked', false, false, \phpbb\request\request_interface::POST),
313
				'mark'      => $this->request->variable('mark', [0]),
314
				'st'        => $this->request->variable('st', 0),
315
				'sk'        => $this->request->variable('sk', 't'),
316
				'sd'        => $this->request->variable('sd', 'd'),
317
			],
318
		];
319
320
		// Prepares args depending actions
321
		if (($this->args['hidden_fields']['delmarked'] || $this->args['hidden_fields']['delall']) && $this->auth->acl_get('a_ppde_manage'))
322
		{
323
			$this->args['action'] = 'delete';
324
			$this->args['hidden_fields'] = array_merge($this->args['hidden_fields'], [
325
				'i'    => $id,
326
				'mode' => $mode,
327
			]);
328
		}
329
		else if ($this->request->is_set('approve'))
330
		{
331
			$this->args = [
332
				'action'        => 'approve',
333
				'hidden_fields' => [
334
					'approve'             => true,
335
					'id'                  => $this->request->variable('id', 0),
336
					'txn_errors_approved' => $this->request->variable('txn_errors_approved', 0),
337
				],
338
			];
339
		}
340
		else if ($this->request->is_set('add'))
341
		{
342
			$this->args['action'] = 'add';
343
		}
344
		else if ($this->request->is_set_post('change'))
345
		{
346
			$this->args['action'] = 'change';
347
		}
348
	}
349
350
	public function change()
351
	{
352
		$username = $this->request->variable('username', '', true);
353
		$donor_id = $this->request->variable('donor_id', 0);
354
355
		try
356
		{
357
			$user_id = $this->validate_user_id($username, $donor_id);
358
		}
359
		catch (transaction_exception $e)
360
		{
361
			trigger_error(implode('<br>', $e->get_errors()) . adm_back_link($this->u_action), E_USER_WARNING);
362
		}
363
364
		// Request Identifier of the transaction
365
		$transaction_id = $this->request->variable('id', 0);
366
367
		$this->ppde_entity->load($transaction_id);
368
369
		if (!$this->ppde_entity->data_exists($this->ppde_entity->build_sql_data_exists()))
370
		{
371
			trigger_error($this->language->lang('PPDE_DT_NO_TRANSACTION') . adm_back_link($this->u_action), E_USER_WARNING);
372
		}
373
374
		$log_action = $this->ppde_entity
375
			->set_user_id($user_id)
376
			->add_edit_data()
377
		;
378
379
		$this->log->add('admin', $this->user->data['user_id'], $this->user->ip, 'LOG_' . $this->lang_key_prefix . '_' . strtoupper($log_action));
380
		trigger_error($this->language->lang($this->lang_key_prefix . '_' . strtoupper($log_action)) . adm_back_link($this->u_action));
381
	}
382
383
	/**
384
	 * Returns the intended user ID
385
	 *
386
	 * @param string $username
387
	 * @param int    $donor_id
388
	 *
389
	 * @return int
390
	 * @access private
391
	 * @throws \skouat\ppde\exception\transaction_exception
392
	 */
393
	private function validate_user_id($username, $donor_id = 0)
394
	{
395
		if (($this->request->is_set('u') || ($donor_id == 1)) && $username === '')
396
		{
397
			return ANONYMOUS;
398
		}
399
400
		$user_id = ($username !== '') ? $this->user_loader->load_user_by_username($username) : $donor_id;
401
402
		if ($user_id <= ANONYMOUS)
403
		{
404
			throw (new transaction_exception())->set_errors([$this->language->lang('PPDE_MT_DONOR_NOT_FOUND')]);
405
		}
406
407
		return $user_id;
408
	}
409
410
	public function approve()
411
	{
412
		$transaction_id = (int) $this->args['hidden_fields']['id'];
413
		$txn_approved = !empty($this->args['hidden_fields']['txn_errors_approved']) ? false : true;
414
415
		// Update DB record
416
		$this->ppde_entity->load($transaction_id);
417
		$this->ppde_entity->set_txn_errors_approved($txn_approved);
418
		$this->ppde_entity->save(false);
419
420
		// Prepare transaction settings before doing actions
421
		$transaction_data = $this->ppde_entity->get_data($this->ppde_operator->build_sql_data($transaction_id));
422
		$this->ppde_actions->set_transaction_data($transaction_data[0]);
423
		$this->ppde_actions->set_ipn_test_properties($this->ppde_entity->get_test_ipn());
424
		$this->ppde_actions->is_donor_is_member();
425
426
		if ($txn_approved)
427
		{
428
			$this->do_transactions_actions(!$this->ppde_actions->get_ipn_test() && $this->ppde_actions->get_donor_is_member());
429
		}
430
431
		$this->log->add('admin', $this->user->data['user_id'], $this->user->ip, 'LOG_' . $this->lang_key_prefix . '_UPDATED', time());
432
	}
433
434
	/**
435
	 * Does actions for validated transaction
436
	 *
437
	 * @param bool $is_member
438
	 *
439
	 * @return void
440
	 * @access private
441
	 */
442
	private function do_transactions_actions($is_member)
443
	{
444
		$this->ppde_actions->update_overview_stats();
445
		$this->ppde_actions->update_raised_amount();
446
447
		if ($is_member)
448
		{
449
			$this->ppde_actions->update_donor_stats();
450
			$this->ppde_actions->donors_group_user_add();
451
			$this->ppde_actions->notification->notify_donor_donation_received();
452
		}
453
	}
454
455
	public function add()
456
	{
457
		$errors = [];
458
459
		$transaction_data = $this->request_transaction_vars();
460
461
		if ($this->request->is_set_post('submit'))
462
		{
463
			try
464
			{
465
				$this->ppde_actions->log_to_db($this->build_data_ary($transaction_data));
466
467
				// Prepare transaction settings before doing actions
468
				$this->ppde_actions->set_transaction_data($transaction_data);
469
				$this->ppde_actions->is_donor_is_member();
470
471
				$this->do_transactions_actions($this->ppde_actions->get_donor_is_member() && !$transaction_data['MT_ANONYMOUS']);
472
473
				$this->log->add('admin', $this->user->data['user_id'], $this->user->ip, 'LOG_PPDE_MT_ADDED', time(), [$transaction_data['MT_USERNAME']]);
474
				trigger_error($this->language->lang('PPDE_MT_ADDED') . adm_back_link($this->u_action));
475
			}
476
			catch (transaction_exception $e)
477
			{
478
				$errors = $e->get_errors();
479
			}
480
		}
481
482
		$this->ppde_actions_currency->build_currency_select_menu((int) $this->config['ppde_default_currency']);
483
484
		$this->s_error_assign_template_vars($errors);
485
486
		$this->template->assign_vars($transaction_data);
487
488
		$this->template->assign_vars([
489
			'U_ACTION'             => $this->u_action,
490
			'U_BACK'               => $this->u_action,
491
			'S_ADD'                => true,
492
			'ANONYMOUS_USER_ID'    => ANONYMOUS,
493
			'U_FIND_USERNAME'      => append_sid($this->phpbb_root_path . 'memberlist.' . $this->php_ext, 'mode=searchuser&amp;form=manual_transaction&amp;field=username&amp;select_single=true'),
494
			'PAYMENT_TIME_FORMATS' => $this->get_payment_time_examples(),
495
		]);
496
	}
497
498
	/**
499
	 * Returns requested data from manual transaction form
500
	 *
501
	 * @return array
502
	 * @access private
503
	 */
504
	private function request_transaction_vars()
505
	{
506
		return [
507
			'MT_ANONYMOUS'          => $this->request->is_set('u'),
508
			'MT_USERNAME'           => $this->request->variable('username', '', true),
509
			'MT_FIRST_NAME'         => $this->request->variable('first_name', '', true),
510
			'MT_LAST_NAME'          => $this->request->variable('last_name', '', true),
511
			'MT_PAYER_EMAIL'        => $this->request->variable('payer_email', '', true),
512
			'MT_RESIDENCE_COUNTRY'  => $this->request->variable('residence_country', ''),
513
			'MT_MC_GROSS'           => $this->request->variable('mc_gross', (float) 0),
514
			'MT_MC_CURRENCY'        => $this->request->variable('mc_currency', ''),
515
			'MT_MC_FEE'             => $this->request->variable('mc_fee', (float) 0),
516
			'MT_PAYMENT_DATE_YEAR'  => $this->request->variable('payment_date_year', (int) $this->user->format_date(time(), 'Y')),
517
			'MT_PAYMENT_DATE_MONTH' => $this->request->variable('payment_date_month', (int) $this->user->format_date(time(), 'n')),
518
			'MT_PAYMENT_DATE_DAY'   => $this->request->variable('payment_date_day', (int) $this->user->format_date(time(), 'j')),
519
			'MT_PAYMENT_TIME'       => $this->request->variable('payment_time', $this->user->format_date(time(), 'H:i:s')),
520
			'MT_MEMO'               => $this->request->variable('memo', '', true),
521
		];
522
	}
523
524
	/**
525
	 * Prepare data array before send it to $this->entity
526
	 *
527
	 * @param array $transaction_data
528
	 *
529
	 * @return array
530
	 * @access private
531
	 * @throws \skouat\ppde\exception\transaction_exception
532
	 */
533
	private function build_data_ary($transaction_data)
534
	{
535
		$errors = [];
536
537
		try
538
		{
539
			$user_id = $this->validate_user_id($transaction_data['MT_USERNAME']);
540
		}
541
		catch (transaction_exception $e)
542
		{
543
			$errors = $e->get_errors();
544
		}
545
546
		$payment_date = implode('-', [
547
			$transaction_data['MT_PAYMENT_DATE_YEAR'],
548
			$transaction_data['MT_PAYMENT_DATE_MONTH'],
549
			$transaction_data['MT_PAYMENT_DATE_DAY'],
550
		]);
551
552
		$payment_date_timestamp_at_midnight = $this->user->get_timestamp_from_format('Y-m-d H:i:s', $payment_date . ' 00:00:00');
553
		$payment_time = $transaction_data['MT_PAYMENT_TIME'];
554
		$payment_time_timestamp = strtotime($payment_time);
555
556
		// Normalize payment time to start from today at midnight
557
		$payment_time_timestamp_from_midnight = $payment_time_timestamp - strtotime('00:00:00');
558
559
		$payment_date_time = $payment_date_timestamp_at_midnight + $payment_time_timestamp_from_midnight;
560
561
		$errors = array_merge($errors,
562
			$this->mc_gross_too_low($transaction_data),
563
			$this->mc_fee_negative($transaction_data),
564
			$this->mc_fee_too_high($transaction_data),
565
			$this->payment_date_timestamp_at_midnight($payment_date_timestamp_at_midnight, $payment_date),
566
			$this->payment_time_timestamp($payment_time_timestamp, $payment_date),
567
			$this->payment_date_time((string) $payment_date_time));
568
569
		if (count($errors))
570
		{
571
			throw (new transaction_exception())->set_errors($errors);
572
		}
573
574
		return [
575
			'business'          => $this->config['ppde_account_id'],
576
			'confirmed'         => true,
577
			'exchange_rate'     => '',
578
			'first_name'        => $transaction_data['MT_FIRST_NAME'],
579
			'item_name'         => '',
580
			'item_number'       => implode('_', ['uid', $user_id, time()]),
581
			'last_name'         => $transaction_data['MT_LAST_NAME'],
582
			'mc_currency'       => $transaction_data['MT_MC_CURRENCY'],
583
			'mc_gross'          => $transaction_data['MT_MC_GROSS'],
584
			'mc_fee'            => $transaction_data['MT_MC_FEE'],
585
			'net_amount'        => (float) 0, // This value is calculated in core_actions:log_to_db()
586
			'parent_txn_id'     => '',
587
			'payer_email'       => $transaction_data['MT_PAYER_EMAIL'],
588
			'payer_id'          => '',
589
			'payer_status'      => '',
590
			'payment_date'      => $payment_date_time,
591
			'payment_status'    => 'Completed',
592
			'payment_type'      => '',
593
			'memo'              => $transaction_data['MT_MEMO'],
594
			'receiver_id'       => '',
595
			'receiver_email'    => '',
596
			'residence_country' => strtoupper($transaction_data['MT_RESIDENCE_COUNTRY']),
597
			'settle_amount'     => (float) 0,
598
			'settle_currency'   => '',
599
			'test_ipn'          => false,
600
			'txn_errors'        => '',
601
			'txn_id'            => 'PPDE' . gen_rand_string(13),
602
			'txn_type'          => 'ppde_manual_donation',
603
			'user_id'           => $user_id,
604
		];
605
	}
606
607
	/**
608
	 * Tests if mc_gross is to low
609
	 *
610
	 * @param array $data
611
	 *
612
	 * @return array
613
	 * @access private
614
	 */
615
	private function mc_gross_too_low($data)
616
	{
617
		if ($data['MT_MC_GROSS'] <= 0)
618
		{
619
			return [$this->language->lang('PPDE_MT_MC_GROSS_TOO_LOW')];
620
		}
621
622
		return [];
623
	}
624
625
	/**
626
	 * Tests if mc_fee has a negative value
627
	 *
628
	 * @param array $data
629
	 *
630
	 * @return array
631
	 * @access private
632
	 */
633
	private function mc_fee_negative($data)
634
	{
635
		if ($data['MT_MC_FEE'] < 0)
636
		{
637
			return [$this->language->lang('PPDE_MT_MC_FEE_NEGATIVE')];
638
		}
639
640
		return [];
641
	}
642
643
	/**
644
	 * Tests if mc_fee is to high
645
	 *
646
	 * @param array $data
647
	 *
648
	 * @return array
649
	 * @access private
650
	 */
651
	private function mc_fee_too_high($data)
652
	{
653
		if ($data['MT_MC_FEE'] >= $data['MT_MC_GROSS'])
654
		{
655
			return [$this->language->lang('PPDE_MT_MC_FEE_TOO_HIGH')];
656
		}
657
658
		return [];
659
	}
660
661
	/**
662
	 * Tests if the date is valid
663
	 *
664
	 * @param string|false $payment_date_timestamp_at_midnight
665
	 * @param string       $payment_date
666
	 *
667
	 * @return array
668
	 * @access private
669
	 */
670
	private function payment_date_timestamp_at_midnight($payment_date_timestamp_at_midnight, $payment_date)
671
	{
672
		if ($payment_date_timestamp_at_midnight === false)
673
		{
674
			return [$this->language->lang('PPDE_MT_PAYMENT_DATE_ERROR', $payment_date)];
675
		}
676
677
		return [];
678
	}
679
680
	/**
681
	 * @param int|false $payment_time_timestamp
682
	 * @param string    $payment_date
683
	 *
684
	 * @return array
685
	 * @access private
686
	 */
687
	private function payment_time_timestamp($payment_time_timestamp, $payment_date)
688
	{
689
		if ($payment_time_timestamp === false)
690
		{
691
			return [$this->language->lang('PPDE_MT_PAYMENT_TIME_ERROR', $payment_date)];
692
		}
693
694
		return [];
695
	}
696
697
	/**
698
	 * @param string $payment_date_time
699
	 *
700
	 * @return array
701
	 * @access private
702
	 */
703
	private function payment_date_time($payment_date_time)
704
	{
705
		if ($payment_date_time > time())
706
		{
707
			return [$this->language->lang('PPDE_MT_PAYMENT_DATE_FUTURE', $this->user->format_date($payment_date_time))];
708
		}
709
710
		return [];
711
	}
712
713
	/**
714
	 * Returns a list of valid times that the user can provide in the manual transaction form
715
	 *
716
	 * @return array Array of strings representing the current time, each in a different format
717
	 * @access private
718
	 */
719
	private function get_payment_time_examples()
720
	{
721
		$formats = [
722
			'H:i:s',
723
			'G:i',
724
			'h:i:s a',
725
			'g:i A',
726
		];
727
728
		$examples = [];
729
730
		foreach ($formats as $format)
731
		{
732
			$examples[] = $this->user->format_date(time(), $format);
733
		}
734
735
		return $examples;
736
	}
737
738
	public function view()
739
	{
740
		// Request Identifier of the transaction
741
		$transaction_id = $this->request->variable('id', 0);
742
743
		// add additional fields to the table schema needed by entity->import()
744
		$additional_table_schema = [
745
			'item_username'    => ['name' => 'username', 'type' => 'string'],
746
			'item_user_colour' => ['name' => 'user_colour', 'type' => 'string'],
747
		];
748
749
		// Grab transaction data
750
		$data_ary = $this->ppde_entity->get_data($this->ppde_operator->build_sql_data($transaction_id), $additional_table_schema);
751
752
		array_map([$this, 'action_assign_template_vars'], $data_ary);
753
754
		$this->template->assign_vars([
755
			'U_FIND_USERNAME' => append_sid($this->phpbb_root_path . 'memberlist.' . $this->php_ext, 'mode=searchuser&amp;form=view_transactions&amp;field=username&amp;select_single=true'),
756
			'U_ACTION'        => $this->u_action,
757
			'U_BACK'          => $this->u_action,
758
			'S_VIEW'          => true,
759
		]);
760
	}
761
762
	public function delete()
763
	{
764
		$where_sql = '';
765
766
		if ($this->args['hidden_fields']['delmarked'] && count($this->args['hidden_fields']['mark']))
767
		{
768
			$where_sql = $this->ppde_operator->build_marked_where_sql($this->args['hidden_fields']['mark']);
769
		}
770
771
		if ($where_sql || $this->args['hidden_fields']['delall'])
772
		{
773
			$this->ppde_entity->delete(0, '', $where_sql, $this->args['hidden_fields']['delall']);
774
			$this->ppde_actions->set_ipn_test_properties(true);
775
			$this->ppde_actions->update_overview_stats();
776
			$this->ppde_actions->set_ipn_test_properties(false);
777
			$this->ppde_actions->update_overview_stats();
778
			$this->log->add('admin', $this->user->data['user_id'], $this->user->ip, 'LOG_' . $this->lang_key_prefix . '_PURGED', time());
779
		}
780
	}
781
782
	/**
783
	 * Set log output vars for display in the template
784
	 *
785
	 * @param array $row
786
	 *
787
	 * @return void
788
	 * @access protected
789
	 */
790
	protected function display_log_assign_template_vars($row)
791
	{
792
		$this->template->assign_block_vars('log', [
793
			'CONFIRMED'        => ($row['confirmed']) ? $this->language->lang('PPDE_DT_VERIFIED') : $this->language->lang('PPDE_DT_UNVERIFIED'),
794
			'DATE'             => $this->user->format_date($row['payment_date']),
795
			'ID'               => $row['transaction_id'],
796
			'PAYMENT_STATUS'   => $this->language->lang(['PPDE_DT_PAYMENT_STATUS_VALUES', strtolower($row['payment_status'])]),
797
			'TNX_ID'           => $row['txn_id'],
798
			'USERNAME'         => $row['username_full'],
799
			'S_CONFIRMED'      => (bool) $row['confirmed'],
800
			'S_PAYMENT_STATUS' => strtolower($row['payment_status']) === 'completed',
801
			'S_TXN_ERRORS'     => !empty($row['txn_errors']),
802
			'S_TEST_IPN'       => (bool) $row['test_ipn'],
803
		]);
804
	}
805
806
	/**
807
	 * Set output vars for display in the template
808
	 *
809
	 * @param array $data
810
	 *
811
	 * @return void
812
	 * @access protected
813
	 */
814
	protected function action_assign_template_vars($data)
815
	{
816
		$s_hidden_fields = build_hidden_fields([
817
			'id'                  => $data['transaction_id'],
818
			'donor_id'            => $data['user_id'],
819
			'txn_errors_approved' => $data['txn_errors_approved'],
820
		]);
821
822
		$currency_mc_data = $this->ppde_actions_currency->get_currency_data($data['mc_currency']);
823
		$currency_settle_data = $this->ppde_actions_currency->get_currency_data($data['settle_currency']);
824
825
		$this->template->assign_vars([
826
			'BOARD_USERNAME' => get_username_string('full', $data['user_id'], $data['username'], $data['user_colour'], $this->language->lang('GUEST'), append_sid($this->phpbb_admin_path . 'index.' . $this->php_ext, 'i=users&amp;mode=overview')),
827
			'EXCHANGE_RATE'  => '1 ' . $data['mc_currency'] . ' = ' . $data['exchange_rate'] . ' ' . $data['settle_currency'],
828
			'ITEM_NAME'      => $data['item_name'],
829
			'ITEM_NUMBER'    => $data['item_number'],
830
			'MC_GROSS'       => $this->ppde_actions_currency->format_currency((float) $data['mc_gross'], $currency_mc_data[0]['currency_iso_code'], $currency_mc_data[0]['currency_symbol'], (bool) $currency_mc_data[0]['currency_on_left']),
831
			'MC_FEE'         => $this->ppde_actions_currency->format_currency((float) $data['mc_fee'], $currency_mc_data[0]['currency_iso_code'], $currency_mc_data[0]['currency_symbol'], (bool) $currency_mc_data[0]['currency_on_left']),
832
			'MC_NET'         => $this->ppde_actions_currency->format_currency((float) $data['net_amount'], $currency_mc_data[0]['currency_iso_code'], $currency_mc_data[0]['currency_symbol'], (bool) $currency_mc_data[0]['currency_on_left']),
833
			'MEMO'           => $data['memo'],
834
			'NAME'           => $data['first_name'] . ' ' . $data['last_name'],
835
			'PAYER_EMAIL'    => $data['payer_email'],
836
			'PAYER_ID'       => $data['payer_id'],
837
			'PAYER_STATUS'   => $data['payer_status'] ? $this->language->lang('PPDE_DT_VERIFIED') : $this->language->lang('PPDE_DT_UNVERIFIED'),
838
			'PAYMENT_DATE'   => $this->user->format_date($data['payment_date']),
839
			'PAYMENT_STATUS' => $this->language->lang(['PPDE_DT_PAYMENT_STATUS_VALUES', strtolower($data['payment_status'])]),
840
			'RECEIVER_EMAIL' => $data['receiver_email'],
841
			'RECEIVER_ID'    => $data['receiver_id'],
842
			'SETTLE_AMOUNT'  => $this->ppde_actions_currency->format_currency((float) $data['settle_amount'], $currency_settle_data[0]['currency_iso_code'], $currency_settle_data[0]['currency_symbol'], (bool) $currency_settle_data[0]['currency_on_left']),
843
			'TXN_ID'         => $data['txn_id'],
844
845
			'L_PPDE_DT_SETTLE_AMOUNT'         => $this->language->lang('PPDE_DT_SETTLE_AMOUNT', $data['settle_currency']),
846
			'L_PPDE_DT_EXCHANGE_RATE_EXPLAIN' => $this->language->lang('PPDE_DT_EXCHANGE_RATE_EXPLAIN', $this->user->format_date($data['payment_date'])),
847
			'S_CONVERT'                       => ($data['settle_amount'] == 0 && empty($data['exchange_rate'])) ? false : true,
848
			'S_ERROR'                         => !empty($data['txn_errors']),
849
			'S_ERROR_APPROVED'                => !empty($data['txn_errors_approved']),
850
			'S_HIDDEN_FIELDS'                 => $s_hidden_fields,
851
			'ERROR_MSG'                       => (!empty($data['txn_errors'])) ? $data['txn_errors'] : '',
852
		]);
853
	}
854
}
855