Passed
Push — develop-3.3.x ( 2b4c5a...83f4a3 )
by Mario
02:46
created

transactions_controller::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 41
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 21
c 0
b 0
f 0
nc 1
nop 17
dl 0
loc 41
rs 9.584

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