core::__construct()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 20
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 9
c 0
b 0
f 0
nc 1
nop 9
dl 0
loc 20
rs 9.9666

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\actions;
12
13
use phpbb\config\config;
14
use phpbb\event\dispatcher_interface;
15
use phpbb\language\language;
16
use phpbb\path_helper;
17
use phpbb\user;
18
19
class core
20
{
21
	public $notification;
22
23
	protected $config;
24
	protected $dispatcher;
25
	protected $language;
26
	protected $php_ext;
27
	protected $transaction_data;
28
	protected $transaction_entity;
29
	protected $transaction_operator;
30
	protected $user;
31
32
	private $donor_is_member = false;
33
	private $ipn_suffix;
34
	private $is_ipn_test = false;
35
	private $payer_data = [];
36
	private $root_path;
37
38
	/**
39
	 * Constructor
40
	 *
41
	 * @param config                              $config                    Config object
42
	 * @param language                            $language                  Language user object
43
	 * @param \skouat\ppde\notification\core      $notification              PPDE Notification object
44
	 * @param path_helper                         $path_helper               Path helpers object
45
	 * @param \skouat\ppde\entity\transactions    $ppde_entity_transaction   Transaction entity object
46
	 * @param \skouat\ppde\operators\transactions $ppde_operator_transaction Transaction operator object
47
	 * @param dispatcher_interface                $dispatcher                Dispatcher object
48
	 * @param user                                $user                      User object
49
	 * @param string                              $php_ext                   phpEx
50
	 *
51
	 * @access public
52
	 */
53
	public function __construct(
54
		config $config,
55
		language $language,
56
		\skouat\ppde\notification\core $notification,
57
		path_helper $path_helper,
58
		\skouat\ppde\entity\transactions $ppde_entity_transaction,
59
		\skouat\ppde\operators\transactions $ppde_operator_transaction,
60
		dispatcher_interface $dispatcher,
61
		user $user,
62
		string $php_ext)
63
	{
64
		$this->config = $config;
65
		$this->dispatcher = $dispatcher;
66
		$this->language = $language;
67
		$this->notification = $notification;
68
		$this->transaction_entity = $ppde_entity_transaction;
69
		$this->transaction_operator = $ppde_operator_transaction;
70
		$this->php_ext = $php_ext;
71
		$this->root_path = $path_helper->get_phpbb_root_path();
72
		$this->user = $user;
73
	}
74
75
	/**
76
	 * Sets properties related to ipn tests
77
	 *
78
	 * @param bool $ipn_test
79
	 *
80
	 * @return void
81
	 * @access public
82
	 */
83
	public function set_ipn_test_properties(bool $ipn_test): void
84
	{
85
		$this->set_ipn_test($ipn_test);
86
		$this->set_ipn_suffix();
87
	}
88
89
	/**
90
	 * Sets the property $this->is_ipn_test
91
	 *
92
	 * @param bool $ipn_test
93
	 *
94
	 * @return void
95
	 * @access private
96
	 */
97
	private function set_ipn_test($ipn_test): void
98
	{
99
		$this->is_ipn_test = (bool) $ipn_test;
100
	}
101
102
	/**
103
	 * Sets the property $this->ipn_suffix
104
	 *
105
	 * @return void
106
	 * @access private
107
	 */
108
	private function set_ipn_suffix(): void
109
	{
110
		$this->ipn_suffix = $this->is_ipn_test ? '_ipn' : '';
111
	}
112
113
	/**
114
	 * Gets the property $this->ipn_suffix
115
	 *
116
	 * @return string
117
	 * @access private
118
	 */
119
	public function get_ipn_suffix(): string
120
	{
121
		return $this->get_ipn_test() ? $this->ipn_suffix : '';
122
	}
123
124
	/**
125
	 * @return boolean
126
	 * @access private
127
	 */
128
	public function get_ipn_test(): bool
129
	{
130
		return $this->is_ipn_test;
131
	}
132
133
	/**
134
	 * Checks if the donor is a member then gets payer_data values
135
	 *
136
	 * @return void
137
	 * @access public
138
	 */
139
140
	public function is_donor_is_member(): void
141
	{
142
		if ($this->is_donor_anonymous())
143
		{
144
			$this->donor_is_member = $this->check_donor_status_based_on_email($this->transaction_data['payer_email']);
145
146
		}
147
		else
148
		{
149
			$this->donor_is_member = $this->check_donors_status('user', $this->transaction_data['user_id']);
150
		}
151
	}
152
153
	/**
154
	 * @return boolean
155
	 */
156
	public function get_donor_is_member(): bool
157
	{
158
		return $this->donor_is_member;
159
	}
160
161
	/**
162
	 * Determine if the donor is anonymous.
163
	 *
164
	 * @return bool True if the donor is anonymous, false otherwise.
165
	 */
166
	private function is_donor_anonymous(): bool
167
	{
168
		return (int) $this->transaction_data['user_id'] === ANONYMOUS || !$this->check_donors_status('user', $this->transaction_data['user_id']);
169
	}
170
171
	/**
172
	 * Gets donor informations (user id, username, amount donated) and returns if exists
173
	 *
174
	 * @param string     $type Allowed value : 'user' or 'email'
175
	 * @param string|int $args If $type is set to 'user', $args must be a user id.
176
	 *                         If $type is set to 'email', $args must be an email address
177
	 *
178
	 * @return bool
179
	 * @access private
180
	 */
181
	private function check_donors_status($type, $args): bool
182
	{
183
		$this->payer_data = $this->transaction_operator->query_donor_user_data($type, $args);
184
185
		return (bool) count($this->payer_data);
186
	}
187
188
	/**
189
	 * Checks the donor status based on email.
190
	 *
191
	 * @param string $email The email of the donor.
192
	 * @return bool Returns true if the status of the donor is active, false otherwise.
193
	 */
194
	private function check_donor_status_based_on_email($email): bool
195
	{
196
		return !empty($email) && !empty($this->check_donors_status('email', $email));
197
	}
198
199
	/**
200
	 * @return array
201
	 */
202
	public function get_payer_data(): array
203
	{
204
		return (count($this->payer_data) != 0) ? $this->payer_data : [];
205
	}
206
207
	/**
208
	 * Log the transaction to the database
209
	 *
210
	 * @param array $data Transaction data array
211
	 *
212
	 * @return void
213
	 * @access public
214
	 */
215
	public function log_to_db($data): void
216
	{
217
		$this->set_transaction_data($data);
218
		$this->validate_and_set_transaction_data();
219
		$this->transaction_entity->add_edit_data();
220
	}
221
222
	/**
223
	 * Set Transaction Data array
224
	 *
225
	 * @param array $transaction_data Array of the donation transaction.
226
	 *
227
	 * @return void
228
	 * @access public
229
	 */
230
	public function set_transaction_data(array $transaction_data): void
231
	{
232
		$this->transaction_data = $this->merge_transaction_data($transaction_data);
233
	}
234
235
	/**
236
	 * Merge transaction data if existing transaction data is not empty, else return passed transaction data
237
	 *
238
	 * @param array $transaction_data Array of the donation transaction.
239
	 *
240
	 * @return array Merged or original transaction data
241
	 * @access private
242
	 */
243
	private function merge_transaction_data(array $transaction_data): array
244
	{
245
		return !empty($this->transaction_data)
246
			? array_merge($this->transaction_data, $transaction_data)
247
			: $transaction_data;
248
	}
249
250
	private function validate_and_set_transaction_data(): void
251
	{
252
		// Handle user_id data
253
		$this->extract_user_id();
254
		$this->validate_user_id();
255
256
		// Set username in extra_data property in $entity
257
		$user_ary = $this->transaction_operator->query_donor_user_data('user', $this->transaction_data['user_id']);
258
		$this->transaction_entity->set_username($user_ary['username']);
259
260
		// Set 'net_amount' in $this->transaction_data
261
		$this->transaction_data['net_amount'] = $this->net_amount(
262
			$this->transaction_data['mc_gross'],
263
			$this->transaction_data['mc_fee']
264
		);
265
266
		$data = $this->transaction_operator->build_transaction_data_ary($this->transaction_data);
267
268
		// Load data in the entity
269
		$this->transaction_entity->set_entity_data($data);
270
		$this->transaction_entity->set_id($this->transaction_entity->transaction_exists());
271
	}
272
273
	/**
274
	 * Retrieve user_id from custom args
275
	 *
276
	 * @return void
277
	 * @access private
278
	 */
279
	private function extract_user_id(): void
280
	{
281
		$this->transaction_data['user_id'] = (int) explode('_', substr($this->transaction_data['custom'], 4), -1)[0];
282
	}
283
284
	/**
285
	 * Avoid the user_id to be set to 0
286
	 *
287
	 * @return void
288
	 * @access private
289
	 */
290
	private function validate_user_id(): void
291
	{
292
		if (empty($this->transaction_data['user_id']) || !is_numeric($this->transaction_data['user_id']))
293
		{
294
			$this->transaction_data['user_id'] = ANONYMOUS;
295
		}
296
	}
297
298
	/**
299
	 * Returns the net amount of a donation
300
	 *
301
	 * @param float  $amount
302
	 * @param float  $fee
303
	 * @param string $dec_point
304
	 * @param string $thousands_sep
305
	 *
306
	 * @return string
307
	 * @access public
308
	 */
309
	public function net_amount($amount, $fee, $dec_point = '.', $thousands_sep = ''): string
310
	{
311
		return number_format((float) $amount - (float) $fee, 2, $dec_point, $thousands_sep);
312
	}
313
314
	/**
315
	 * Check we are in the ACP
316
	 *
317
	 * @return bool
318
	 * @access public
319
	 */
320
	public function is_in_admin(): bool
321
	{
322
		return defined('IN_ADMIN') && isset($this->user->data['session_admin']) && $this->user->data['session_admin'];
323
	}
324
325
	/**
326
	 * Perform actions for validated transaction
327
	 *
328
	 * @param bool $is_member
329
	 */
330
	public function do_transactions_actions($is_member): void
331
	{
332
		$this->update_overview_stats();
333
		$this->update_raised_amount();
334
335
		if ($is_member)
336
		{
337
			$this->update_donor_stats();
338
			$this->donors_group_user_add();
339
			$this->notification->notify_donor_donation_received();
340
		}
341
	}
342
343
	/**
344
	 * Updates the Overview module statistics
345
	 *
346
	 * @return void
347
	 * @access public
348
	 */
349
	public function update_overview_stats(): void
350
	{
351
		$this->config->set('ppde_anonymous_donors_count' . $this->ipn_suffix, $this->get_count_result('ppde_anonymous_donors_count' . $this->ipn_suffix));
352
		$this->config->set('ppde_known_donors_count' . $this->ipn_suffix, $this->get_count_result('ppde_known_donors_count' . $this->ipn_suffix));
353
		$this->config->set('ppde_transactions_count' . $this->ipn_suffix, $this->get_count_result('ppde_transactions_count' . $this->ipn_suffix));
354
	}
355
356
	/**
357
	 * Returns count result for updating stats
358
	 *
359
	 * @param string $config_name
360
	 *
361
	 * @return int
362
	 * @access private
363
	 */
364
	private function get_count_result($config_name): int
365
	{
366
		if (!$this->config->offsetExists($config_name))
367
		{
368
			trigger_error($this->language->lang('EXCEPTION_INVALID_CONFIG_NAME', $config_name), E_USER_WARNING);
369
		}
370
371
		return $this->transaction_operator->sql_query_count_result($config_name, $this->is_ipn_test);
372
	}
373
374
	/**
375
	 * Updates the amount of donation raised
376
	 *
377
	 * @return void
378
	 * @access public
379
	 */
380
	public function update_raised_amount(): void
381
	{
382
		$net_amount = (float) $this->net_amount($this->transaction_data['mc_gross'], $this->transaction_data['mc_fee']);
383
384
		if (!empty($this->transaction_data['settle_amount']))
385
		{
386
			$net_amount = $this->transaction_data['settle_amount'];
387
		}
388
389
		$this->config->set('ppde_raised' . $this->ipn_suffix, (float) $this->config['ppde_raised' . $this->ipn_suffix] + $net_amount);
390
	}
391
392
	/**
393
	 * Updates donor member stats
394
	 *
395
	 * @return void
396
	 * @access public
397
	 */
398
	public function update_donor_stats(): void
399
	{
400
		if ($this->donor_is_member)
401
		{
402
			$this->update_user_stats((int) $this->payer_data['user_id'], (float) $this->payer_data['user_ppde_donated_amount'] + (float) $this->transaction_data['mc_gross']);
403
		}
404
	}
405
406
	/**
407
	 * @param int   $user_id
408
	 * @param float $amount
409
	 */
410
	public function update_user_stats(int $user_id, float $amount): void
411
	{
412
		if (!$user_id)
413
		{
414
			trigger_error($this->language->lang('EXCEPTION_INVALID_USER_ID', $user_id), E_USER_WARNING);
415
		}
416
417
		$this->transaction_operator->sql_update_user_stats($user_id, $amount);
418
	}
419
420
	/**
421
	 * Add donor to the donors group
422
	 *
423
	 * @return void
424
	 * @access public
425
	 */
426
	public function donors_group_user_add(): void
427
	{
428
		// We add the user to the donors group
429
		$can_use_autogroup = $this->can_use_autogroup();
430
		$group_id = (int) $this->config['ppde_ipn_group_id'];
431
		$payer_id = (int) $this->payer_data['user_id'];
432
		$payer_username = $this->payer_data['username'];
433
		$default_group = $this->config['ppde_ipn_group_as_default'];
434
		$payer_donated_amount = $this->payer_data['user_ppde_donated_amount'];
435
436
		/**
437
		 * Event to modify data before a user is added to the donors group
438
		 *
439
		 * @event skouat.ppde.donors_group_user_add_before
440
		 * @var bool    can_use_autogroup      Whether or not to add the user to the group
441
		 * @var int     group_id               The ID of the group to which the user will be added
442
		 * @var int     payer_id               The ID of the user who will we added to the group
443
		 * @var string  payer_username         The user name
444
		 * @var bool    default_group          Whether or not the group should be made default for the user
445
		 * @var float   payer_donated_amount   The user donated amount
446
		 * @since 1.0.3
447
		 * @changed 2.1.2 Added var $payer_donated_amount
448
		 */
449
		$vars = [
450
			'can_use_autogroup',
451
			'group_id',
452
			'payer_id',
453
			'payer_username',
454
			'default_group',
455
			'payer_donated_amount',
456
		];
457
		extract($this->dispatcher->trigger_event('skouat.ppde.donors_group_user_add_before', compact($vars)));
458
459
		if ($can_use_autogroup)
460
		{
461
			if (!function_exists('group_user_add'))
462
			{
463
				include($this->root_path . 'includes/functions_user.' . $this->php_ext);
464
			}
465
466
			// Adds the user to the donors group and set as default.
467
			group_user_add($group_id, [$payer_id], [$payer_username], get_group_name($group_id), $default_group);
468
		}
469
	}
470
471
	/**
472
	 * Checks if all required settings are meet for adding the donor to the group of donors
473
	 *
474
	 * @return bool
475
	 * @access private
476
	 */
477
	private function can_use_autogroup(): bool
478
	{
479
		return
480
			$this->autogroup_is_enabled() &&
481
			$this->donor_is_member &&
482
			$this->payment_status_is_completed() &&
483
			$this->minimum_donation_raised();
484
	}
485
486
	/**
487
	 * Checks if Autogroup could be used
488
	 *
489
	 * @return bool
490
	 * @access private
491
	 */
492
	private function autogroup_is_enabled(): bool
493
	{
494
		return $this->config['ppde_ipn_enable'] && $this->config['ppde_ipn_autogroup_enable'];
495
	}
496
497
	/**
498
	 * Checks if payment_status is completed
499
	 *
500
	 * @return bool
501
	 * @access public
502
	 */
503
	public function payment_status_is_completed(): bool
504
	{
505
		return $this->transaction_data['payment_status'] === 'Completed';
506
	}
507
508
	/**
509
	 * Checks if member's donation is upper or equal to the minimum defined
510
	 *
511
	 * @return bool
512
	 * @access public
513
	 */
514
	public function minimum_donation_raised(): bool
515
	{
516
		// Updates payer_data info before checking values
517
		$this->check_donors_status('user', $this->payer_data['user_id']);
518
519
		return (float) $this->payer_data['user_ppde_donated_amount'] >= (float) $this->config['ppde_ipn_min_before_group'];
520
	}
521
}
522