Passed
Branch 3.2.x (99ec7e)
by Mario
04:20
created

core   F

Complexity

Total Complexity 68

Size/Duplication

Total Lines 679
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
eloc 126
dl 0
loc 679
rs 2.96
c 0
b 0
f 0
wmc 68

39 Methods

Rating   Name   Duplication   Size   Complexity  
A check_post_data_content() 0 3 2
A set_post_data_func() 0 12 2
A update_user_stats() 0 8 2
A log_to_db() 0 25 1
A set_post_data_strtotime() 0 3 2
A autogroup_is_enabled() 0 3 2
A check_post_data_ascii() 0 7 2
A donors_group_user_add() 0 38 3
A extract_item_number_data() 0 3 1
A set_transaction_data() 0 9 2
A set_post_data_length() 0 3 1
A update_donor_stats() 0 5 2
A can_use_autogroup() 0 7 4
A set_ipn_test() 0 3 2
A is_donor_is_member() 0 26 4
A get_suffix_ipn() 0 3 2
A minimum_donation_raised() 0 3 2
A check_donors_status() 0 5 1
A validate_user_id() 0 5 3
A get_ipn_test() 0 3 2
A update_raised_amount() 0 3 1
A set_suffix_ipn() 0 3 2
A get_count_result() 0 8 2
A set_post_data_lowercase() 0 3 2
A check_post_data_length() 0 3 1
A set_ipn_test_properties() 0 4 1
A get_donor_is_member() 0 3 2
A net_amount() 0 3 1
A get_payer_data() 0 3 2
A payment_status_is_completed() 0 3 1
A update_overview_stats() 0 5 1
A __construct() 0 12 1
A check_post_data_empty() 0 3 2
A compare_eq() 0 3 1
A compare() 0 8 2
A compare_gt() 0 3 1
A compare_lt() 0 3 1
A compare_gte() 0 3 1
A compare_lte() 0 3 1

How to fix   Complexity   

Complex Class

Complex classes like core often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use core, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 *
4
 * PayPal Donation extension for the phpBB Forum Software package.
5
 *
6
 * @copyright (c) 2018 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
18
class core
19
{
20
	const ASCII_RANGE = '1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
21
22
	/** @var array */
23
	private static $operators_table = array(
24
		'<'  => 'compare_lt',
25
		'<=' => 'compare_lte',
26
		'==' => 'compare_eq',
27
		'>=' => 'compare_gte',
28
		'>'  => 'compare_gt',
29
	);
30
31
	/**
32
	 * Services properties declaration
33
	 */
34
	public $notification;
35
	protected $config;
36
	protected $dispatcher;
37
	protected $language;
38
	protected $path_helper;
39
	protected $php_ext;
40
	protected $ppde_entity_transaction;
41
	protected $ppde_operator_transaction;
42
	protected $transaction_data;
43
44
	/**
45
	 * @var boolean
46
	 */
47
	private $donor_is_member = false;
48
	/**
49
	 * @var boolean
50
	 */
51
	private $is_ipn_test = false;
52
	/**
53
	 * @var array
54
	 */
55
	private $payer_data;
56
	/**
57
	 * phpBB root path
58
	 *
59
	 * @var string
60
	 */
61
	private $root_path;
62
	/**
63
	 * @var string
64
	 */
65
	private $suffix_ipn;
66
67
	/**
68
	 * Constructor
69
	 *
70
	 * @param config                              $config                    Config object
71
	 * @param language                            $language                  Language user object
72
	 * @param \skouat\ppde\notification\core      $notification              PPDE Notification object
73
	 * @param path_helper                         $path_helper               Path helper object
74
	 * @param \skouat\ppde\entity\transactions    $ppde_entity_transaction   Transaction entity object
75
	 * @param \skouat\ppde\operators\transactions $ppde_operator_transaction Transaction operator object
76
	 * @param dispatcher_interface                $dispatcher                Dispatcher object
77
	 * @param string                              $php_ext                   phpEx
78
	 *
79
	 * @access public
80
	 */
81
	public function __construct(config $config, language $language, \skouat\ppde\notification\core $notification, path_helper $path_helper, \skouat\ppde\entity\transactions $ppde_entity_transaction, \skouat\ppde\operators\transactions $ppde_operator_transaction, dispatcher_interface $dispatcher, $php_ext)
82
	{
83
		$this->config = $config;
84
		$this->dispatcher = $dispatcher;
85
		$this->language = $language;
86
		$this->notification = $notification;
87
		$this->path_helper = $path_helper;
88
		$this->ppde_entity_transaction = $ppde_entity_transaction;
89
		$this->ppde_operator_transaction = $ppde_operator_transaction;
90
		$this->php_ext = $php_ext;
91
92
		$this->root_path = $this->path_helper->get_phpbb_root_path();
93
	}
94
95
	/**
96
	 * Sets properties related to ipn tests
97
	 *
98
	 * @param bool $ipn_test
99
	 *
100
	 * @return void
101
	 * @access public
102
	 */
103
	public function set_ipn_test_properties($ipn_test)
104
	{
105
		$this->set_ipn_test($ipn_test);
106
		$this->set_suffix_ipn($this->is_ipn_test);
107
	}
108
109
	/**
110
	 * Sets the property $this->is_ipn_test
111
	 *
112
	 * @param bool $ipn_test
113
	 *
114
	 * @return void
115
	 * @access private
116
	 */
117
	private function set_ipn_test($ipn_test)
118
	{
119
		$this->is_ipn_test = $ipn_test ? (bool) $ipn_test : false;
120
	}
121
122
	/**
123
	 * Sets the property $this->suffix_ipn
124
	 *
125
	 * @param bool $is_ipn_test
126
	 *
127
	 * @return void
128
	 * @access private
129
	 */
130
	private function set_suffix_ipn($is_ipn_test)
131
	{
132
		$this->suffix_ipn = $is_ipn_test ? '_ipn' : '';
133
	}
134
135
	/**
136
	 * @return string
137
	 */
138
	public function get_suffix_ipn()
139
	{
140
		return ($this->get_ipn_test()) ? $this->suffix_ipn : '';
141
	}
142
143
	/**
144
	 * @return boolean
145
	 */
146
	public function get_ipn_test()
147
	{
148
		return ($this->is_ipn_test) ? (bool) $this->is_ipn_test : false;
149
	}
150
151
	/**
152
	 * Updates the amount of donation raised
153
	 *
154
	 * @return void
155
	 * @access public
156
	 */
157
	public function update_raised_amount()
158
	{
159
		$this->config->set('ppde_raised' . $this->suffix_ipn, (float) $this->config['ppde_raised' . $this->suffix_ipn] + (float) $this->net_amount($this->transaction_data['mc_gross'], $this->transaction_data['mc_fee']), true);
160
	}
161
162
	/**
163
	 * Returns the net amount of a donation
164
	 *
165
	 * @param float  $amount
166
	 * @param float  $fee
167
	 * @param string $dec_point
168
	 * @param string $thousands_sep
169
	 *
170
	 * @return string
171
	 * @access public
172
	 */
173
	public function net_amount($amount, $fee, $dec_point = '.', $thousands_sep = '')
174
	{
175
		return number_format((float) $amount - (float) $fee, 2, $dec_point, $thousands_sep);
176
	}
177
178
	/**
179
	 * Updates the Overview module statistics
180
	 *
181
	 * @return void
182
	 * @access public
183
	 */
184
	public function update_overview_stats()
185
	{
186
		$this->config->set('ppde_anonymous_donors_count' . $this->suffix_ipn, $this->get_count_result('ppde_anonymous_donors_count' . $this->suffix_ipn));
187
		$this->config->set('ppde_known_donors_count' . $this->suffix_ipn, $this->get_count_result('ppde_known_donors_count' . $this->suffix_ipn), true);
188
		$this->config->set('ppde_transactions_count' . $this->suffix_ipn, $this->get_count_result('ppde_transactions_count' . $this->suffix_ipn), true);
189
	}
190
191
	/**
192
	 * Returns count result for updating stats
193
	 *
194
	 * @param string $config_name
195
	 *
196
	 * @return int
197
	 * @access private
198
	 */
199
	private function get_count_result($config_name)
200
	{
201
		if (!$this->config->offsetExists($config_name))
202
		{
203
			trigger_error($this->language->lang('EXCEPTION_INVALID_CONFIG_NAME', $config_name), E_USER_WARNING);
204
		}
205
206
		return $this->ppde_operator_transaction->sql_query_count_result($config_name, $this->is_ipn_test);
207
	}
208
209
	/**
210
	 * Checks if the donor is a member then gets payer_data values
211
	 *
212
	 * @return void
213
	 * @access public
214
	 */
215
216
	public function is_donor_is_member()
217
	{
218
		$anonymous_user = false;
219
220
		// If the user_id is not anonymous
221
		if ($this->transaction_data['user_id'] != ANONYMOUS)
222
		{
223
			$this->donor_is_member = $this->check_donors_status('user', $this->transaction_data['user_id']);
224
225
			if (!$this->donor_is_member)
226
			{
227
				// No results, therefore the user is anonymous...
228
				$anonymous_user = true;
229
			}
230
		}
231
		else
232
		{
233
			// The user is anonymous by default
234
			$anonymous_user = true;
235
		}
236
237
		if ($anonymous_user)
238
		{
239
			// If the user is anonymous, check their PayPal email address with all known email hashes
240
			// to determine if the user exists in the database with that email
241
			$this->donor_is_member = $this->check_donors_status('email', $this->transaction_data['payer_email']);
242
		}
243
	}
244
245
	/**
246
	 * @return boolean
247
	 */
248
	public function get_donor_is_member()
249
	{
250
		return ($this->donor_is_member) ? (bool) $this->donor_is_member : false;
251
	}
252
253
	/**
254
	 * Gets donor informations (user id, username, amount donated) and returns if exists
255
	 *
256
	 * @param string     $type Allowed value : 'user' or 'email'
257
	 * @param string|int $args If $type is set to 'user', $args must be a user id.
258
	 *                         If $type is set to 'email', $args must be an email address
259
	 *
260
	 * @return bool
261
	 * @access private
262
	 */
263
	private function check_donors_status($type, $args)
264
	{
265
		$this->payer_data = $this->ppde_operator_transaction->query_donor_user_data($type, $args);
266
267
		return (bool) count($this->payer_data);
0 ignored issues
show
Bug introduced by
It seems like $this->payer_data can also be of type boolean; however, parameter $var of count() does only seem to accept Countable|array, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

267
		return (bool) count(/** @scrutinizer ignore-type */ $this->payer_data);
Loading history...
268
	}
269
270
	/**
271
	 * @return array
272
	 */
273
	public function get_payer_data()
274
	{
275
		return (count($this->payer_data) != 0) ? $this->payer_data : array();
276
	}
277
278
	/**
279
	 * Updates donor member stats
280
	 *
281
	 * @return void
282
	 * @access public
283
	 */
284
	public function update_donor_stats()
285
	{
286
		if ($this->donor_is_member)
287
		{
288
			$this->update_user_stats((int) $this->payer_data['user_id'], (float) $this->payer_data['user_ppde_donated_amount'] + (float) $this->net_amount($this->transaction_data['mc_gross'], $this->transaction_data['mc_fee']));
289
		}
290
	}
291
292
	/**
293
	 * @param int   $user_id
294
	 * @param float $amount
295
	 */
296
	public function update_user_stats($user_id, $amount)
297
	{
298
		if (!$user_id)
299
		{
300
			trigger_error($this->language->lang('EXCEPTION_INVALID_USER_ID', $user_id), E_USER_WARNING);
301
		}
302
303
		$this->ppde_operator_transaction->sql_update_user_stats($user_id, $amount);
304
	}
305
306
	/**
307
	 * Add donor to the donors group
308
	 *
309
	 * @return void
310
	 * @access public
311
	 */
312
	public function donors_group_user_add()
313
	{
314
		// We add the user to the donors group
315
		$can_use_autogroup = $this->can_use_autogroup();
316
		$group_id = (int) $this->config['ppde_ipn_group_id'];
317
		$payer_id = (int) $this->payer_data['user_id'];
318
		$payer_username = $this->payer_data['username'];
319
		$default_group = $this->config['ppde_ipn_group_as_default'];
320
321
		/**
322
		 * Event to modify data before a user is added to the donors group
323
		 *
324
		 * @event skouat.ppde.donors_group_user_add_before
325
		 * @var bool    can_use_autogroup   Whether or not to add the user to the group
326
		 * @var int     group_id            The ID of the group to which the user will be added
327
		 * @var int     payer_id            The ID of the user who will we added to the group
328
		 * @var string  payer_username      The user name
329
		 * @var bool    default_group       Whether or not the group should be made default for the user
330
		 * @since 1.0.3
331
		 */
332
		$vars = array(
333
			'can_use_autogroup',
334
			'group_id',
335
			'payer_id',
336
			'payer_username',
337
			'default_group',
338
		);
339
		extract($this->dispatcher->trigger_event('skouat.ppde.donors_group_user_add_before', compact($vars)));
340
341
		if ($can_use_autogroup)
342
		{
343
			if (!function_exists('group_user_add'))
344
			{
345
				include($this->root_path . 'includes/functions_user.' . $this->php_ext);
346
			}
347
348
			// Adds the user to the donors group and set as default.
349
			group_user_add($group_id, array($payer_id), array($payer_username), get_group_name($group_id), $default_group);
350
		}
351
	}
352
353
	/**
354
	 * Checks if all required settings are meet for adding the donor to the group of donors
355
	 *
356
	 * @return bool
357
	 * @access private
358
	 */
359
	private function can_use_autogroup()
360
	{
361
		return
362
			$this->autogroup_is_enabled() &&
363
			$this->donor_is_member &&
364
			$this->payment_status_is_completed() &&
365
			$this->minimum_donation_raised();
366
	}
367
368
	/**
369
	 * Checks if Autogroup could be used
370
	 *
371
	 * @return bool
372
	 * @access private
373
	 */
374
	private function autogroup_is_enabled()
375
	{
376
		return $this->config['ppde_ipn_enable'] && $this->config['ppde_ipn_autogroup_enable'];
377
	}
378
379
	/**
380
	 * Checks if payment_status is completed
381
	 *
382
	 * @return bool
383
	 * @access public
384
	 */
385
	public function payment_status_is_completed()
386
	{
387
		return $this->transaction_data['payment_status'] === 'Completed';
388
	}
389
390
	/**
391
	 * Checks if member's donation is upper or equal to the minimum defined
392
	 *
393
	 * @return bool
394
	 * @access public
395
	 */
396
	public function minimum_donation_raised()
397
	{
398
		return (float) $this->payer_data['user_ppde_donated_amount'] >= (float) $this->config['ppde_ipn_min_before_group'] ? true : false;
399
	}
400
401
	/**
402
	 * Log the transaction to the database
403
	 *
404
	 * @param array $data Transaction data array
405
	 *
406
	 * @access public
407
	 */
408
	public function log_to_db($data)
409
	{
410
		// Set the property $this->transaction_data
411
		$this->set_transaction_data($data);
412
413
		// The item number contains the user_id
414
		$this->extract_item_number_data();
415
		$this->validate_user_id();
416
417
		// Set username in extra_data property in $entity
418
		$user_ary = $this->ppde_operator_transaction->query_donor_user_data('user', $this->transaction_data['user_id']);
419
		$this->ppde_entity_transaction->set_username($user_ary['username']);
420
421
		// Set 'net_amount' in $this->transaction_data
422
		$this->transaction_data['net_amount'] = $this->net_amount($this->transaction_data['mc_gross'], $this->transaction_data['mc_fee']);
423
424
		// List the data to be thrown into the database
425
		$data = $this->ppde_operator_transaction->build_data_ary($this->transaction_data);
426
427
		// Load data in the entity
428
		$this->ppde_entity_transaction->set_entity_data($data);
429
		$this->ppde_entity_transaction->set_id($this->ppde_entity_transaction->transaction_exists());
430
431
		// Add or edit transaction data
432
		$this->ppde_entity_transaction->add_edit_data();
433
	}
434
435
	/**
436
	 * Set Transaction Data array
437
	 *
438
	 * @param array $transaction_data Array of the donation transaction.
439
	 *
440
	 * @return void
441
	 * @access public
442
	 */
443
	public function set_transaction_data($transaction_data)
444
	{
445
		if (!empty($this->transaction_data))
446
		{
447
			array_merge($this->transaction_data, $transaction_data);
448
		}
449
		else
450
		{
451
			$this->transaction_data = $transaction_data;
452
		}
453
	}
454
455
	/**
456
	 * Retrieve user_id from item_number args
457
	 *
458
	 * @return void
459
	 * @access private
460
	 */
461
	private function extract_item_number_data()
462
	{
463
		list($this->transaction_data['user_id']) = explode('_', substr($this->transaction_data['item_number'], 4), -1);
464
	}
465
466
	/**
467
	 * Avoid the user_id to be set to 0
468
	 *
469
	 * @return void
470
	 * @access private
471
	 */
472
	private function validate_user_id()
473
	{
474
		if (empty($this->transaction_data['user_id']) || !is_numeric($this->transaction_data['user_id']))
475
		{
476
			$this->transaction_data['user_id'] = ANONYMOUS;
477
		}
478
	}
479
480
	/**
481
	 * Check requirements for data value.
482
	 *
483
	 * @param array $data_ary
484
	 *
485
	 * @access public
486
	 * @return mixed
487
	 */
488
	public function set_post_data_func($data_ary)
489
	{
490
		$value = $data_ary['value'];
491
492
		foreach ($data_ary['force_settings'] as $control_point => $params)
493
		{
494
			// Calling the set_post_data_function
495
			$value = call_user_func_array(array($this, 'set_post_data_' . $control_point), array($data_ary['value'], $params));
496
		}
497
		unset($data_ary, $control_point, $params);
498
499
		return $value;
500
	}
501
502
	/**
503
	 * Check Post data length.
504
	 * Called by $this->check_post_data() method
505
	 *
506
	 * @param string $value
507
	 * @param array  $statement
508
	 *
509
	 * @return bool
510
	 * @access public
511
	 */
512
	public function check_post_data_length($value, $statement)
513
	{
514
		return $this->compare(strlen($value), $statement['value'], $statement['operator']);
515
	}
516
517
	/**
518
	 * Check if parsed value contains only ASCII chars.
519
	 * Return false if it contains non ASCII chars.
520
	 *
521
	 * @param $value
522
	 *
523
	 * @return bool
524
	 * @access public
525
	 */
526
	public function check_post_data_ascii($value)
527
	{
528
		// We ensure that the value contains only ASCII chars...
529
		$pos = strspn($value, self::ASCII_RANGE);
530
		$len = strlen($value);
531
532
		return $pos != $len ? false : true;
533
	}
534
535
	/**
536
	 * Check Post data content based on an array list.
537
	 * Called by $this->check_post_data() method
538
	 *
539
	 * @param string $value
540
	 * @param array  $content_ary
541
	 *
542
	 * @return bool
543
	 * @access public
544
	 */
545
	public function check_post_data_content($value, $content_ary)
546
	{
547
		return in_array($value, $content_ary) ? true : false;
548
	}
549
550
	/**
551
	 * Check if Post data is empty.
552
	 * Called by $this->check_post_data() method
553
	 *
554
	 * @param string $value
555
	 *
556
	 * @return bool
557
	 * @access public
558
	 */
559
	public function check_post_data_empty($value)
560
	{
561
		return empty($value) ? false : true;
562
	}
563
564
	/**
565
	 * Set Post data length.
566
	 * Called by $this->set_post_data() method
567
	 *
568
	 * @param string  $value
569
	 * @param integer $length
570
	 *
571
	 * @return string
572
	 * @access public
573
	 */
574
	public function set_post_data_length($value, $length)
575
	{
576
		return substr($value, 0, (int) $length);
577
	}
578
579
	/**
580
	 * Set Post data to lowercase.
581
	 * Called by $this->set_post_data() method
582
	 *
583
	 * @param string $value
584
	 * @param bool   $force
585
	 *
586
	 * @return string
587
	 * @access public
588
	 */
589
	public function set_post_data_lowercase($value, $force = false)
590
	{
591
		return $force ? strtolower($value) : $value;
592
	}
593
594
	/**
595
	 * Set Post data to date/time format.
596
	 * Called by $this->set_post_data() method
597
	 *
598
	 * @param string $value
599
	 * @param bool   $force
600
	 *
601
	 * @return string
602
	 * @access public
603
	 */
604
	public function set_post_data_strtotime($value, $force = false)
605
	{
606
		return $force ? strtotime($value) : $value;
607
	}
608
609
	/**
610
	 * Compare two value
611
	 *
612
	 * @param int    $value1
613
	 * @param int    $value2
614
	 * @param string $operator
615
	 *
616
	 * @return bool
617
	 * @access public
618
	 */
619
	public function compare($value1, $value2, $operator)
620
	{
621
		if (array_key_exists($operator, self::$operators_table))
622
		{
623
			return call_user_func_array(array($this, self::$operators_table[$operator]), array($value1, $value2));
624
		}
625
626
		return false;
627
	}
628
629
	/**
630
	 * Method called by $this->compare
631
	 *
632
	 * @param $a
633
	 * @param $b
634
	 *
635
	 * @return bool
636
	 * @access private
637
	 */
638
	private function compare_lt($a, $b)
639
	{
640
		return $a < $b;
641
	}
642
643
	/**
644
	 * Method called by $this->compare
645
	 *
646
	 * @param $a
647
	 * @param $b
648
	 *
649
	 * @return bool
650
	 * @access private
651
	 */
652
	private function compare_lte($a, $b)
653
	{
654
		return $a <= $b;
655
	}
656
657
	/**
658
	 * Method called by $this->compare
659
	 *
660
	 * @param $a
661
	 * @param $b
662
	 *
663
	 * @return bool
664
	 * @access private
665
	 */
666
	private function compare_eq($a, $b)
667
	{
668
		return $a == $b;
669
	}
670
671
	/**
672
	 * Method called by $this->compare
673
	 *
674
	 * @param $a
675
	 * @param $b
676
	 *
677
	 * @return bool
678
	 * @access private
679
	 */
680
	private function compare_gte($a, $b)
681
	{
682
		return $a >= $b;
683
	}
684
685
	/**
686
	 * Method called by $this->compare
687
	 *
688
	 * @param $a
689
	 * @param $b
690
	 *
691
	 * @return bool
692
	 * @access private
693
	 */
694
	private function compare_gt($a, $b)
695
	{
696
		return $a > $b;
697
	}
698
}
699