transactions_controller::__construct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 37
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 17
nc 1
nop 17
dl 0
loc 37
rs 9.7
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-2024 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 skouat\ppde\actions\core;
21
use skouat\ppde\actions\currency;
22
use skouat\ppde\exception\transaction_exception;
23
use skouat\ppde\helpers\transaction_template_helper;
24
use skouat\ppde\helpers\transaction_validator_helper;
25
use skouat\ppde\operators\transactions;
26
use Symfony\Component\DependencyInjection\ContainerInterface;
27
28
/**
29
 * @property array              args               Array of args for hidden fields
30
 * @property config             config             Config object
31
 * @property ContainerInterface container          Service container interface
32
 * @property string             id_prefix_name     Prefix name for identifier in the URL
33
 * @property string             lang_key_prefix    Prefix for the messages thrown by exceptions
34
 * @property language           language           Language user object
35
 * @property log                log                The phpBB log system
36
 * @property request            request            Request object
37
 * @property template           template           Template object
38
 * @property string             u_action           Action URL
39
 * @property user               user               User object
40
 */
41
class transactions_controller extends admin_main
42
{
43
	protected $transactions_operator;
44
	protected $auth;
45
	protected $entry_count;
46
	protected $last_page_offset;
47
	protected $php_ext;
48
	protected $phpbb_admin_path;
49
	protected $phpbb_root_path;
50
	protected $ppde_actions;
51
	protected $ppde_actions_currency;
52
	protected $transactions_entity;
53
	protected $template_helper;
54
	protected $transaction_validator;
55
56
	/**
57
	 * Constructor
58
	 *
59
	 * @param auth                             $auth                       Authentication object
60
	 * @param config                           $config                     Config object
61
	 * @param ContainerInterface               $container                  Service container interface
62
	 * @param language                         $language                   Language user object
63
	 * @param log                              $log                        The phpBB log system
64
	 * @param core                             $ppde_actions               PPDE actions object
65
	 * @param currency                         $ppde_actions_currency      PPDE currency actions object
66
	 * @param \skouat\ppde\entity\transactions $ppde_entity_transactions   Entity object
67
	 * @param transactions                     $ppde_operator_transactions Operator object
68
	 * @param request                          $request                    Request object
69
	 * @param template                         $template                   Template object
70
	 * @param user                             $user                       User object
71
	 * @param string                           $adm_relative_path          phpBB admin relative path
72
	 * @param string                           $phpbb_root_path            phpBB root path
73
	 * @param string                           $php_ext                    phpEx
74
	 */
75
	public function __construct(
76
		auth $auth,
77
		config $config,
78
		ContainerInterface $container,
79
		language $language,
80
		log $log,
81
		core $ppde_actions,
82
		currency $ppde_actions_currency,
83
		\skouat\ppde\entity\transactions $ppde_entity_transactions,
84
		transactions $ppde_operator_transactions,
85
		request $request,
86
		template $template,
87
		user $user,
88
		transaction_template_helper $template_helper,
89
		transaction_validator_helper $transaction_validator,
90
		string $adm_relative_path,
91
		string $phpbb_root_path,
92
		string $php_ext
93
	)
94
	{
95
		$this->auth = $auth;
96
		$this->config = $config;
97
		$this->container = $container;
98
		$this->language = $language;
99
		$this->log = $log;
100
		$this->ppde_actions = $ppde_actions;
101
		$this->ppde_actions_currency = $ppde_actions_currency;
102
		$this->request = $request;
103
		$this->template = $template;
104
		$this->transactions_entity = $ppde_entity_transactions;
105
		$this->transactions_operator = $ppde_operator_transactions;
106
		$this->user = $user;
107
		$this->template_helper = $template_helper;
108
		$this->transaction_validator = $transaction_validator;
109
		$this->phpbb_admin_path = $phpbb_root_path . $adm_relative_path;
110
		$this->phpbb_root_path = $phpbb_root_path;
111
		$this->php_ext = $php_ext;
112
	}
113
114
	/**
115
	 * {@inheritdoc}
116
	 */
117
	protected function display(): void
118
	{
119
		// Sorting and pagination setup
120
		$sort_by_text = $this->get_sort_by_text_options();
121
		$sort_by_sql = $this->transactions_operator->get_sort_options();
122
		$sort_key = $this->request->variable('sk', 't');
123
		$sort_dir = $this->request->variable('sd', 'd');
124
		$start = $this->request->variable('start', 0);
125
		$limit = (int) $this->config['topics_per_page'];
126
127
		// Filtering setup
128
		$limit_days = $this->get_limit_day_options();
129
		$selected_days = $this->request->variable('st', 0);
130
		$keywords = $this->request->variable('keywords', '', true);
131
132
		// Generate sorting and filtering selects
133
		$s_limit_days = $s_sort_key = $s_sort_dir = $u_sort_param = '';
134
		gen_sort_selects($limit_days, $sort_by_text, $selected_days, $sort_key, $sort_dir, $s_limit_days, $s_sort_key, $s_sort_dir, $u_sort_param);
135
136
		// Prepare SQL conditions
137
		$sql_sort = $sort_by_sql[$sort_key] . ' ' . (($sort_dir === 'd') ? 'DESC' : 'ASC');
138
139
		// Fetch log data
140
		$log_data = [];
141
		$log_count = 0;
142
		$log_time = $this->calculate_timestamp($selected_days);
143
		$this->view_txn_log($log_data, $log_count, $limit, $start, $log_time, $sql_sort, $keywords);
144
145
		// Generate pagination
146
		$this->generate_pagination($log_count, $limit, $start, $u_sort_param, $keywords);
147
148
		// Assign template variables
149
		$this->assign_template_vars($s_limit_days, $s_sort_key, $s_sort_dir, $u_sort_param, $keywords, $start);
150
151
		// Assign log entries to template
152
		$this->assign_log_entries_to_template($log_data);
153
	}
154
155
	/**
156
	 * Get sort by text options for transactions
157
	 *
158
	 * @return array An associative array of sort options and their corresponding language strings
159
	 */
160
	private function get_sort_by_text_options(): array
161
	{
162
		return [
163
			'txn'      => $this->language->lang('PPDE_DT_SORT_TXN_ID'),
164
			'u'        => $this->language->lang('PPDE_DT_SORT_DONORS'),
165
			'ipn'      => $this->language->lang('PPDE_DT_SORT_IPN_STATUS'),
166
			'ipn_test' => $this->language->lang('PPDE_DT_SORT_IPN_TYPE'),
167
			'ps'       => $this->language->lang('PPDE_DT_SORT_PAYMENT_STATUS'),
168
			't'        => $this->language->lang('SORT_DATE'),
169
		];
170
	}
171
172
	/**
173
	 * Get limit day options for filtering
174
	 *
175
	 * @return array An associative array of day limits and their corresponding language strings
176
	 */
177
	private function get_limit_day_options(): array
178
	{
179
		return [
180
			0   => $this->language->lang('ALL_ENTRIES'),
181
			1   => $this->language->lang('1_DAY'),
182
			7   => $this->language->lang('7_DAYS'),
183
			14  => $this->language->lang('2_WEEKS'),
184
			30  => $this->language->lang('1_MONTH'),
185
			90  => $this->language->lang('3_MONTHS'),
186
			180 => $this->language->lang('6_MONTHS'),
187
			365 => $this->language->lang('1_YEAR'),
188
		];
189
	}
190
191
	/**
192
	 * Calculate the timestamp for filtering transactions based on the selected number of days
193
	 *
194
	 * @param int $selected_days Number of days to look back for transactions
195
	 * @return int The calculated timestamp, or 0 if no day limit is set
196
	 */
197
	private function calculate_timestamp(int $selected_days): int
198
	{
199
		return $selected_days > 0 ? time() - ($selected_days * self::SECONDS_IN_A_DAY) : 0;
200
	}
201
202
	/**
203
	 * View transaction log
204
	 *
205
	 * @param array  &$log       The result array with the logs
206
	 * @param int    &$log_count If $log_count is set to false, we will skip counting all entries in the database
207
	 *                           Otherwise an integer with the number of total matching entries is returned
208
	 * @param int     $limit     Limit the number of entries that are returned
209
	 * @param int     $offset    Offset when fetching the log entries, e.g. when paginating
210
	 * @param int     $log_time  Timestamp to filter logs
211
	 * @param string  $sort_by   SQL order option, e.g. 'l.log_time DESC'
212
	 * @param string  $keywords  Will only return log entries that have the keywords in log_operation or log_data
213
	 * @return void
214
	 */
215
	private function view_txn_log(array &$log, &$log_count, int $limit = 0, int $offset = 0, int $log_time = 0, string $sort_by = 'txn.payment_date DESC', string $keywords = ''): void
216
	{
217
		$count_logs = ($log_count !== false);
218
219
		$log = $this->get_logs($count_logs, $limit, $offset, $log_time, $sort_by, $keywords);
220
		$log_count = $this->get_log_count();
221
	}
222
223
	/**
224
	 * Get logs based on specified parameters
225
	 *
226
	 * @param bool   $count_logs Whether to count the total number of logs
227
	 * @param int    $limit      Maximum number of logs to retrieve
228
	 * @param int    $offset     Starting point for retrieving logs
229
	 * @param int    $log_time   Timestamp to filter logs
230
	 * @param string $sort_by    SQL ORDER BY clause
231
	 * @param string $keywords   Keywords to filter logs
232
	 * @return array Array of log entries
233
	 */
234
	private function get_logs(bool $count_logs = true, int $limit = 0, int $offset = 0, int $log_time = 0, string $sort_by = 'txn.payment_date DESC', string $keywords = ''): array
235
	{
236
		$this->entry_count = 0;
237
		$this->last_page_offset = $offset;
238
		$url_ary = [];
239
240
		if ($this->phpbb_admin_path && $this->ppde_actions->is_in_admin())
241
		{
242
			$url_ary['profile_url'] = append_sid($this->phpbb_admin_path . 'index.' . $this->php_ext, 'i=users&amp;mode=overview');
243
			$url_ary['txn_url'] = append_sid($this->phpbb_admin_path . 'index.' . $this->php_ext, 'i=-skouat-ppde-acp-ppde_module&amp;mode=transactions');
244
		}
245
		else
246
		{
247
			$url_ary['profile_url'] = append_sid($this->phpbb_root_path . 'memberlist.' . $this->php_ext, 'mode=viewprofile');
248
			$url_ary['txn_url'] = '';
249
		}
250
251
		$get_logs_sql_ary = $this->transactions_operator->get_logs_sql_ary($keywords, $sort_by, $log_time);
252
253
		if ($count_logs)
254
		{
255
			$this->entry_count = $this->transactions_operator->query_sql_count($get_logs_sql_ary, 'txn.transaction_id');
256
257
			if ($this->entry_count === 0)
258
			{
259
				// Save the queries, because there are no logs to display
260
				$this->last_page_offset = 0;
261
262
				return [];
263
			}
264
265
			// Return the user to the last page that is valid
266
			while ($this->last_page_offset >= $this->entry_count)
267
			{
268
				$this->last_page_offset = max(0, $this->last_page_offset - $limit);
269
			}
270
		}
271
272
		return $this->transactions_operator->build_log_entries($get_logs_sql_ary, $url_ary, $limit, $this->last_page_offset);
273
	}
274
275
	/**
276
	 * Get the total count of log entries
277
	 *
278
	 * @return int The total number of log entries
279
	 */
280
	public function get_log_count(): int
281
	{
282
		return (int) $this->entry_count ?: 0;
283
	}
284
285
	/**
286
	 * Generate pagination for transaction list
287
	 *
288
	 * @param int    $log_count    Total number of log entries
289
	 * @param int    $limit        Number of entries per page
290
	 * @param int    $start        Starting offset for the current page
291
	 * @param string $u_sort_param URL parameters for sorting
292
	 * @param string $keywords     Search keywords
293
	 */
294
	private function generate_pagination(int $log_count, int $limit, int $start, string $u_sort_param, string $keywords): void
295
	{
296
		$pagination = $this->container->get('pagination');
297
		$base_url = $this->u_action . '&amp;' . $u_sort_param . $this->get_keywords_param($keywords);
298
		$pagination->generate_template_pagination($base_url, 'pagination', 'start', $log_count, $limit, $start);
299
	}
300
301
	/**
302
	 * Get keywords parameter for URL
303
	 *
304
	 * @param string $keywords Search keywords
305
	 * @return string URL-encoded keywords parameter
306
	 */
307
	private function get_keywords_param(string $keywords): string
308
	{
309
		return !empty($keywords) ? '&amp;keywords=' . urlencode(htmlspecialchars_decode($keywords)) : '';
310
	}
311
312
	/**
313
	 * Assign common template variables
314
	 *
315
	 * @param string $s_limit_days
316
	 * @param string $s_sort_key
317
	 * @param string $s_sort_dir
318
	 * @param string $u_sort_param
319
	 * @param string $keywords
320
	 * @param int    $start
321
	 */
322
	private function assign_template_vars(string $s_limit_days, string $s_sort_key, string $s_sort_dir, string $u_sort_param, string $keywords, int $start): void
323
	{
324
		$this->template->assign_vars([
325
			'S_CLEARLOGS'  => $this->auth->acl_get('a_ppde_manage'),
326
			'S_KEYWORDS'   => $keywords,
327
			'S_LIMIT_DAYS' => $s_limit_days,
328
			'S_SORT_KEY'   => $s_sort_key,
329
			'S_SORT_DIR'   => $s_sort_dir,
330
			'U_ACTION'     => $this->u_action . '&amp;' . $u_sort_param . $this->get_keywords_param($keywords) . '&amp;start=' . $start,
331
		]);
332
	}
333
334
	/**
335
	 * Assign log entries to template
336
	 *
337
	 * @param array $log_data Array of log entries
338
	 */
339
	private function assign_log_entries_to_template(array $log_data): void
340
	{
341
		foreach ($log_data as $row)
342
		{
343
			$this->template->assign_block_vars('log', [
344
				'CONFIRMED'        => ($row['confirmed']) ? $this->language->lang('PPDE_DT_VERIFIED') : $this->language->lang('PPDE_DT_UNVERIFIED'),
345
				'DATE'             => $this->user->format_date($row['payment_date']),
346
				'ID'               => $row['transaction_id'],
347
				'PAYMENT_STATUS'   => $this->language->lang(['PPDE_DT_PAYMENT_STATUS_VALUES', strtolower($row['payment_status'])]),
348
				'TXN_ID'           => $row['txn_id'],
349
				'USERNAME'         => $row['username_full'],
350
				'S_CONFIRMED'      => (bool) $row['confirmed'],
351
				'S_PAYMENT_STATUS' => strtolower($row['payment_status']) === 'completed',
352
				'S_TXN_ERRORS'     => !empty($row['txn_errors']),
353
				'S_TEST_IPN'       => (bool) $row['test_ipn'],
354
			]);
355
		}
356
	}
357
358
	/**
359
	 * Set hidden fields for the transaction form
360
	 *
361
	 * @param string $id     Module id
362
	 * @param string $mode   Module category
363
	 * @param string $action Action name
364
	 */
365
	public function set_hidden_fields($id, $mode, $action): void
366
	{
367
		$this->args['action'] = $action;
368
		$this->args['hidden_fields'] = [
369
			'start'     => $this->request->variable('start', 0),
370
			'delall'    => $this->request->variable('delall', false, false, \phpbb\request\request_interface::POST),
371
			'delmarked' => $this->request->variable('delmarked', false, false, \phpbb\request\request_interface::POST),
372
			'i'         => $id,
373
			'mark'      => $this->request->variable('mark', [0]),
374
			'mode'      => $mode,
375
			'st'        => $this->request->variable('st', 0),
376
			'sk'        => $this->request->variable('sk', 't'),
377
			'sd'        => $this->request->variable('sd', 'd'),
378
		];
379
380
		// Prepare args depending on actions
381
		if (($this->args['hidden_fields']['delall'] || ($this->args['hidden_fields']['delmarked'] && count($this->args['hidden_fields']['mark']))) && $this->auth->acl_get('a_ppde_manage'))
0 ignored issues
show
introduced by
Consider adding parentheses for clarity. Current Interpretation: ($this->args['hidden_fie...cl_get('a_ppde_manage'), Probably Intended Meaning: $this->args['hidden_fiel...l_get('a_ppde_manage'))
Loading history...
382
		{
383
			$this->args['action'] = 'delete';
384
		}
385
		else if ($this->request->is_set('approve'))
386
		{
387
			$this->args['action'] = 'approve';
388
			$this->args['hidden_fields'] = array_merge($this->args['hidden_fields'], [
389
				'approve'             => true,
390
				'id'                  => $this->request->variable('id', 0),
391
				'txn_errors_approved' => $this->request->variable('txn_errors_approved', 0),
392
			]);
393
		}
394
		else if ($this->request->is_set('add'))
395
		{
396
			$this->args['action'] = 'add';
397
		}
398
		else if ($this->request->is_set_post('change'))
399
		{
400
			$this->args['action'] = 'change';
401
		}
402
	}
403
404
	/**
405
	 * Get hidden fields for the transaction form
406
	 *
407
	 * @return array
408
	 */
409
	protected function get_hidden_fields(): array
410
	{
411
		return array_merge(
412
			['i'                           => $this->args['hidden_fields']['i'],
413
			 'mode'                        => $this->args['hidden_fields']['mode'],
414
			 'action'                      => $this->args['action'],
415
			 $this->id_prefix_name . '_id' => $this->args[$this->id_prefix_name . '_id']],
416
			$this->args['hidden_fields']);
417
	}
418
419
	/**
420
	 * {@inheritdoc}
421
	 */
422
	public function change(): void
423
	{
424
		$username = $this->request->variable('username', '', true);
425
		$donor_id = $this->request->variable('donor_id', 0);
426
		$transaction_id = $this->request->variable('id', 0);
427
428
		try
429
		{
430
			$user_id = $this->transaction_validator->validate_user_id($username, $donor_id);
431
			$this->update_transaction($transaction_id, $user_id);
432
			$this->log_action('DT_UPDATED');
433
		}
434
		catch (transaction_exception $e)
435
		{
436
			$this->output_errors($e->get_errors());
437
		}
438
	}
439
440
	/**
441
	 * Update transaction with new user ID
442
	 *
443
	 * @param int $transaction_id
444
	 * @param int $user_id
445
	 * @throws transaction_exception
446
	 */
447
	private function update_transaction(int $transaction_id, int $user_id): void
448
	{
449
		$this->transactions_entity->load($transaction_id);
450
451
		if (!$this->transactions_entity->data_exists($this->transactions_entity->build_sql_data_exists()))
452
		{
453
			throw new transaction_exception([$this->language->lang('PPDE_DT_NO_TRANSACTION')]);
454
		}
455
456
		$this->transactions_entity->set_user_id($user_id)->add_edit_data();
457
	}
458
459
	/**
460
	 * Log the action in the admin log
461
	 *
462
	 * @param string $action_type
463
	 */
464
	private function log_action(string $action_type): void
465
	{
466
		$this->log->add('admin', $this->user->data['user_id'], $this->user->ip, 'LOG_PPDE_' . $action_type);
467
		trigger_error($this->language->lang('PPDE_' . $action_type) . adm_back_link($this->u_action));
468
	}
469
470
	/**
471
	 * {@inheritdoc}
472
	 */
473
	protected function add(): void
474
	{
475
		$transaction_data = $this->request_transaction_vars();
476
477
		if ($this->is_form_submitted())
478
		{
479
			try
480
			{
481
				$this->process_transaction($transaction_data);
482
				$this->log_action('MT_ADDED');
483
			}
484
			catch (transaction_exception $e)
485
			{
486
				$this->prepare_add_template($e->get_errors(), $transaction_data);
487
				return;
488
			}
489
		}
490
491
		$this->prepare_add_template([], $transaction_data);
492
	}
493
494
	/**
495
	 * Request transaction variables from the form
496
	 *
497
	 * @return array
498
	 */
499
	private function request_transaction_vars(): array
500
	{
501
		return [
502
			'MT_ANONYMOUS'          => $this->request->is_set('u'),
503
			'MT_USERNAME'           => $this->request->variable('username', '', true),
504
			'MT_FIRST_NAME'         => $this->request->variable('first_name', '', true),
505
			'MT_LAST_NAME'          => $this->request->variable('last_name', '', true),
506
			'MT_PAYER_EMAIL'        => $this->request->variable('payer_email', '', true),
507
			'MT_RESIDENCE_COUNTRY'  => $this->request->variable('residence_country', ''),
508
			'MT_MC_GROSS'           => $this->request->variable('mc_gross', 0.0),
509
			'MT_MC_CURRENCY'        => $this->request->variable('mc_currency', ''),
510
			'MT_MC_FEE'             => $this->request->variable('mc_fee', 0.0),
511
			'MT_PAYMENT_DATE_YEAR'  => $this->request->variable('payment_date_year', (int) $this->user->format_date(time(), 'Y')),
512
			'MT_PAYMENT_DATE_MONTH' => $this->request->variable('payment_date_month', (int) $this->user->format_date(time(), 'n')),
513
			'MT_PAYMENT_DATE_DAY'   => $this->request->variable('payment_date_day', (int) $this->user->format_date(time(), 'j')),
514
			'MT_PAYMENT_TIME'       => $this->request->variable('payment_time', $this->user->format_date(time(), 'H:i:s')),
515
			'MT_MEMO'               => $this->request->variable('memo', '', true),
516
		];
517
	}
518
519
	/**
520
	 * Process a transaction with the given transaction data and handle any errors that occur
521
	 *
522
	 * @param array $transaction_data The data for the transaction
523
	 * @throws transaction_exception
524
	 */
525
	private function process_transaction(array $transaction_data): void
526
	{
527
		$data_ary = $this->build_data_ary($transaction_data);
528
		$this->ppde_actions->log_to_db($data_ary);
529
530
		$this->ppde_actions->set_transaction_data($transaction_data);
531
		$this->ppde_actions->is_donor_is_member();
532
533
		$this->ppde_actions->do_transactions_actions(
534
			$this->ppde_actions->get_donor_is_member() && !$transaction_data['MT_ANONYMOUS']
535
		);
536
	}
537
538
	/**
539
	 * Prepare data array before sending it to $this->entity
540
	 *
541
	 * @param array $transaction_data
542
	 * @return array
543
	 * @throws transaction_exception
544
	 */
545
	private function build_data_ary(array $transaction_data): array
546
	{
547
		$errors = [];
548
549
		try
550
		{
551
			$user_id = $this->transaction_validator->validate_user_id($transaction_data['MT_USERNAME']);
552
		}
553
		catch (transaction_exception $e)
554
		{
555
			$errors = array_merge($errors, $e->get_errors());
556
		}
557
558
		try
559
		{
560
			$payment_date_time = $this->transaction_validator->validate_payment_date_time($transaction_data);
561
		}
562
		catch (transaction_exception $e)
563
		{
564
			$errors = array_merge($errors, $e->get_errors());
565
		}
566
567
		try
568
		{
569
			$this->transaction_validator->validate_transaction_amounts($transaction_data);
570
		}
571
		catch (transaction_exception $e)
572
		{
573
			$errors = array_merge($errors, $e->get_errors());
574
		}
575
576
		if (!empty($errors))
577
		{
578
			throw new transaction_exception($errors);
579
		}
580
581
		return [
582
			'business'          => $this->config['ppde_account_id'],
583
			'confirmed'         => true,
584
			'custom'            => implode('_', ['uid', $user_id, time()]),
585
			'exchange_rate'     => '',
586
			'first_name'        => $transaction_data['MT_FIRST_NAME'],
587
			'item_name'         => '',
588
			'item_number'       => implode('_', ['uid', $user_id, time()]),
589
			'last_name'         => $transaction_data['MT_LAST_NAME'],
590
			'mc_currency'       => $transaction_data['MT_MC_CURRENCY'],
591
			'mc_gross'          => $transaction_data['MT_MC_GROSS'],
592
			'mc_fee'            => $transaction_data['MT_MC_FEE'],
593
			'net_amount'        => 0.0, // This value is calculated in core_actions:log_to_db()
594
			'parent_txn_id'     => '',
595
			'payer_email'       => $transaction_data['MT_PAYER_EMAIL'],
596
			'payer_id'          => '',
597
			'payer_status'      => '',
598
			'payment_date'      => $payment_date_time,
599
			'payment_status'    => 'Completed',
600
			'payment_type'      => '',
601
			'memo'              => $transaction_data['MT_MEMO'],
602
			'receiver_id'       => '',
603
			'receiver_email'    => '',
604
			'residence_country' => strtoupper($transaction_data['MT_RESIDENCE_COUNTRY']),
605
			'settle_amount'     => 0.0,
606
			'settle_currency'   => '',
607
			'test_ipn'          => false,
608
			'txn_errors'        => '',
609
			'txn_id'            => 'PPDE' . gen_rand_string(13),
610
			'txn_type'          => 'ppde_manual_donation',
611
			'user_id'           => $user_id,
612
		];
613
	}
614
615
	/**
616
	 * Prepare and assign template variables for adding a new transaction
617
	 *
618
	 * @param array $errors           Array of error messages
619
	 * @param array $transaction_data Transaction data to be displayed in the form
620
	 */
621
	private function prepare_add_template(array $errors, array $transaction_data): void
622
	{
623
		$this->ppde_actions_currency->build_currency_select_menu((int) $this->config['ppde_default_currency']);
624
		$this->s_error_assign_template_vars($errors);
625
		$this->template->assign_vars($transaction_data);
626
		$this->template->assign_vars([
627
			'U_ACTION'             => $this->u_action,
628
			'U_BACK'               => $this->u_action,
629
			'S_ADD'                => true,
630
			'ANONYMOUS_USER_ID'    => ANONYMOUS,
631
			'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'),
632
			'PAYMENT_TIME_FORMATS' => $this->get_payment_time_examples(),
633
		]);
634
	}
635
636
	/**
637
	 * Returns a list of valid times that the user can provide in the manual transaction form
638
	 *
639
	 * @return array Array of strings representing the current time, each in a different format
640
	 */
641
	private function get_payment_time_examples(): array
642
	{
643
		$formats = [
644
			'H:i:s',
645
			'G:i',
646
			'h:i:s a',
647
			'g:i A',
648
		];
649
650
		$examples = [];
651
652
		foreach ($formats as $format)
653
		{
654
			$examples[] = $this->user->format_date(time(), $format);
655
		}
656
657
		return $examples;
658
	}
659
660
	/**
661
	 * Output errors
662
	 *
663
	 * @param array $errors
664
	 */
665
	private function output_errors(array $errors): void
666
	{
667
		trigger_error(implode('<br>', $errors) . adm_back_link($this->u_action), E_USER_WARNING);
668
	}
669
670
	/**
671
	 * Approve a transaction
672
	 */
673
	protected function approve(): void
674
	{
675
		$transaction_id = (int) $this->args['hidden_fields']['id'];
676
		$txn_approved = empty($this->args['hidden_fields']['txn_errors_approved']);
677
678
		// Update DB record
679
		$this->transactions_entity->load($transaction_id);
680
		$this->transactions_entity->set_txn_errors_approved($txn_approved);
681
		$this->transactions_entity->save(false);
682
683
		// Prepare transaction settings before doing actions
684
		$transaction_data = $this->transactions_entity->get_data($this->transactions_operator->build_sql_data($transaction_id));
685
		$this->ppde_actions->set_transaction_data($transaction_data[0]);
686
		$this->ppde_actions->set_ipn_test_properties($this->transactions_entity->get_test_ipn());
687
		$this->ppde_actions->is_donor_is_member();
688
689
		if ($txn_approved)
690
		{
691
			$this->ppde_actions->do_transactions_actions(!$this->ppde_actions->get_ipn_test() && $this->ppde_actions->get_donor_is_member());
692
		}
693
694
		$this->log->add('admin', $this->user->data['user_id'], $this->user->ip, 'LOG_' . $this->lang_key_prefix . '_UPDATED', time());
695
	}
696
697
	/**
698
	 * View transaction details
699
	 */
700
	protected function view(): void
701
	{
702
		// Request Identifier of the transaction
703
		$transaction_id = (int) $this->request->variable('id', 0);
704
705
		// Add additional fields to the table schema needed by entity->import()
706
		$additional_table_schema = [
707
			'item_username'    => ['name' => 'username', 'type' => 'string'],
708
			'item_user_colour' => ['name' => 'user_colour', 'type' => 'string'],
709
		];
710
711
		// Grab transaction data
712
		$data_ary = $this->transactions_entity->get_data($this->transactions_operator->build_sql_data($transaction_id), $additional_table_schema);
713
714
		array_map([$this, 'action_assign_template_vars'], $data_ary);
715
716
		$this->template->assign_vars([
717
			'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'),
718
			'U_ACTION'        => $this->u_action,
719
			'U_BACK'          => $this->u_action,
720
			'S_VIEW'          => true,
721
		]);
722
	}
723
724
	/**
725
	 * Delete transaction(s)
726
	 */
727
	protected function delete(): void
728
	{
729
		$where_sql = '';
730
731
		if ($this->args['hidden_fields']['delmarked'] && count($this->args['hidden_fields']['mark']))
732
		{
733
			$where_sql = $this->transactions_operator->build_marked_where_sql($this->args['hidden_fields']['mark']);
734
		}
735
736
		if ($where_sql || $this->args['hidden_fields']['delall'])
737
		{
738
			$this->transactions_entity->delete(0, '', $where_sql, $this->args['hidden_fields']['delall']);
739
			$this->ppde_actions->set_ipn_test_properties(true);
740
			$this->ppde_actions->update_overview_stats();
741
			$this->ppde_actions->set_ipn_test_properties(false);
742
			$this->ppde_actions->update_overview_stats();
743
			$this->log->add('admin', $this->user->data['user_id'], $this->user->ip, 'LOG_' . $this->lang_key_prefix . '_PURGED', time());
744
		}
745
	}
746
747
	/**
748
	 * Assign action template variables
749
	 *
750
	 * @param array $data Transaction data
751
	 */
752
	protected function action_assign_template_vars(array $data): void
753
	{
754
		$this->template_helper->assign_hidden_fields($data);
755
		$this->template_helper->assign_currency_data($data);
756
		$this->template_helper->assign_user_data($data);
757
		$this->template_helper->assign_transaction_details($data);
758
		$this->template_helper->assign_payment_details($data);
759
		$this->template_helper->assign_error_data($data);
760
	}
761
}
762