Passed
Push — develop-3.3.x ( c85e2c...2b4c5a )
by Mario
02:35
created

validate_transaction_amounts()   A

Complexity

Conditions 5
Paths 16

Size

Total Lines 22
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 5
eloc 9
c 1
b 0
f 0
nc 16
nop 1
dl 0
loc 22
rs 9.6111
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\includes;
12
13
use phpbb\language\language;
14
use phpbb\user;
15
use skouat\ppde\exception\transaction_exception;
16
17
class transaction_validator
18
{
19
	/** @var language */
20
	protected $language;
21
22
	/** @var user */
23
	protected $user;
24
25
	/** @var \phpbb\user_loader */
26
	protected $user_loader;
27
28
	/**
29
	 * Constructor
30
	 *
31
	 * @param language           $language
32
	 * @param user               $user
33
	 * @param \phpbb\user_loader $user_loader
34
	 */
35
	public function __construct(language $language, user $user, \phpbb\user_loader $user_loader)
36
	{
37
		$this->language = $language;
38
		$this->user = $user;
39
		$this->user_loader = $user_loader;
40
	}
41
42
	/**
43
	 * Validate and return the user ID
44
	 *
45
	 * @param string $username
46
	 * @param int    $donor_id
47
	 * @return int
48
	 * @throws transaction_exception
49
	 */
50
	public function validate_user_id(string $username, int $donor_id = 0): int
51
	{
52
		if (empty($username) && ($donor_id === ANONYMOUS || $this->request->is_set('u')))
0 ignored issues
show
Bug Best Practice introduced by
The property request does not exist on skouat\ppde\includes\transaction_validator. Did you maybe forget to declare it?
Loading history...
53
		{
54
			return ANONYMOUS;
55
		}
56
57
		$user_id = ($username !== '') ? $this->user_loader->load_user_by_username($username) : $donor_id;
58
59
		if ($user_id <= ANONYMOUS)
60
		{
61
			throw new transaction_exception([$this->language->lang('PPDE_MT_DONOR_NOT_FOUND')]);
62
		}
63
64
		return $user_id;
65
	}
66
67
	/**
68
	 * Validate payment date and time
69
	 *
70
	 * @param array $transaction_data
71
	 * @return int
72
	 * @throws transaction_exception
73
	 */
74
	public function validate_payment_date_time(array $transaction_data): int
75
	{
76
		$payment_date = implode('-', [
77
			$transaction_data['MT_PAYMENT_DATE_YEAR'],
78
			$transaction_data['MT_PAYMENT_DATE_MONTH'],
79
			$transaction_data['MT_PAYMENT_DATE_DAY'],
80
		]);
81
82
		$payment_time = $transaction_data['MT_PAYMENT_TIME'];
83
		$date_time_string = $payment_date . ' ' . $payment_time;
84
85
		$payment_date_time = $this->parse_date_time($date_time_string);
86
87
		if ($payment_date_time === false)
88
		{
89
			throw new transaction_exception([$this->language->lang('PPDE_MT_PAYMENT_DATE_ERROR', $date_time_string)]);
90
		}
91
92
		if ($payment_date_time > time())
93
		{
94
			throw new transaction_exception([$this->language->lang('PPDE_MT_PAYMENT_DATE_FUTURE', $this->user->format_date($payment_date_time))]);
95
		}
96
97
		$this->validate_time($payment_time);
98
99
		return $payment_date_time;
100
	}
101
102
	/**
103
	 * Parse date and time string
104
	 *
105
	 * @param string $date_time_string
106
	 * @return int|false
107
	 */
108
	private function parse_date_time($date_time_string)
109
	{
110
		$formats = ['Y-m-d H:i:s', 'Y-m-d G:i', 'Y-m-d h:i:s a', 'Y-m-d g:i A'];
111
112
		foreach ($formats as $format)
113
		{
114
			$parsed = \DateTime::createFromFormat($format, $date_time_string);
115
			if ($parsed !== false)
116
			{
117
				return $parsed->getTimestamp();
118
			}
119
		}
120
121
		return false;
122
	}
123
124
	/**
125
	 * Validate time format
126
	 *
127
	 * @param string $payment_time
128
	 * @throws transaction_exception
129
	 */
130
	private function validate_time(string $payment_time): void
131
	{
132
		$time_parts = explode(':', $payment_time);
133
		if (count($time_parts) < 2 || count($time_parts) > 3)
134
		{
135
			throw new transaction_exception([$this->language->lang('PPDE_MT_PAYMENT_TIME_ERROR', $payment_time)]);
136
		}
137
138
		$hours = (int) $time_parts[0];
139
		$minutes = (int) $time_parts[1];
140
		$seconds = isset($time_parts[2]) ? (int) $time_parts[2] : 0;
141
142
		if ($hours >= 24 || $minutes >= 60 || $seconds >= 60)
143
		{
144
			throw new transaction_exception([$this->language->lang('PPDE_MT_PAYMENT_TIME_ERROR', $payment_time)]);
145
		}
146
	}
147
148
	/**
149
	 * Validate transaction amounts
150
	 *
151
	 * @param array $transaction_data
152
	 * @throws transaction_exception
153
	 */
154
	public function validate_transaction_amounts(array $transaction_data): void
155
	{
156
		$errors = [];
157
158
		if ($transaction_data['MT_MC_GROSS'] <= 0)
159
		{
160
			$errors[] = $this->language->lang('PPDE_MT_MC_GROSS_TOO_LOW');
161
		}
162
163
		if ($transaction_data['MT_MC_FEE'] < 0)
164
		{
165
			$errors[] = $this->language->lang('PPDE_MT_MC_FEE_NEGATIVE');
166
		}
167
168
		if ($transaction_data['MT_MC_FEE'] >= $transaction_data['MT_MC_GROSS'])
169
		{
170
			$errors[] = $this->language->lang('PPDE_MT_MC_FEE_TOO_HIGH');
171
		}
172
173
		if (!empty($errors))
174
		{
175
			throw new transaction_exception($errors);
176
		}
177
	}
178
}
179