Passed
Push — master ( e32ade...233249 )
by Jeroen De
03:39
created

Donation   C

Complexity

Total Complexity 71

Size/Duplication

Total Lines 731
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 1

Test Coverage

Coverage 20.69%

Importance

Changes 0
Metric Value
wmc 71
lcom 2
cbo 1
dl 0
loc 731
ccs 36
cts 174
cp 0.2069
rs 5
c 0
b 0
f 0

57 Methods

Rating   Name   Duplication   Size   Complexity  
A setDonorFullName() 0 5 1
A getDonorFullName() 0 3 1
A setDonorCity() 0 5 1
A getDonorCity() 0 3 1
A setDonorEmail() 0 5 1
A getDonorEmail() 0 3 1
A setDonorOptsIntoNewsletter() 0 5 1
A getDonorOptsIntoNewsletter() 0 3 1
A setDonationReceipt() 0 5 1
A getDonationReceipt() 0 3 1
A setPublicRecord() 0 5 1
A getPublicRecord() 0 3 1
A setAmount() 0 5 1
A getAmount() 0 3 1
A setPaymentIntervalInMonths() 0 5 1
A getPaymentIntervalInMonths() 0 3 1
A setPaymentType() 0 5 1
A getPaymentType() 0 3 1
A setComment() 0 5 1
A getComment() 0 3 1
A setBankTransferCode() 0 5 1
A getBankTransferCode() 0 3 1
A setSource() 0 5 1
A getSource() 0 3 1
A setRemoteAddr() 0 5 1
A getRemoteAddr() 0 3 1
A setHash() 0 5 1
A getHash() 0 3 1
A setIsPublic() 0 5 1
A getIsPublic() 0 3 1
A setCreationTime() 0 5 1
A getCreationTime() 0 3 1
A setDeletionTime() 0 5 1
A getDeletionTime() 0 3 1
A setDtExp() 0 5 1
A getDtExp() 0 3 1
A setStatus() 0 5 1
A getStatus() 0 3 1
A setDtGruen() 0 5 1
A getDtGruen() 0 3 1
A setDtBackup() 0 5 1
A getDtBackup() 0 3 1
A getId() 0 3 1
A getPayment() 0 3 1
A setPayment() 0 3 1
A setId() 0 3 1
A getUExpiry() 0 3 1
A uTokenIsExpired() 0 3 1
A validateToken() 0 9 1
C getEntryType() 0 22 8
A setData() 0 5 1
A getData() 0 3 1
A getDecodedData() 0 9 3
A encodeAndSetData() 0 3 1
A getDataObject() 0 11 4
A setDataObject() 0 18 3
A modifyDataObject() 0 5 1

How to fix   Complexity   

Complex Class

Complex classes like Donation 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. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

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 Donation, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
declare( strict_types = 1 );
4
5
namespace WMDE\Fundraising\Entities;
6
7
use Doctrine\ORM\Mapping as ORM;
8
use Gedmo\Mapping\Annotation as Gedmo;
9
use WMDE\Fundraising\Store\DonationData;
10
11
/**
12
 * @since 2.0
13
 *
14
 * @ORM\Table(
15
 *     name="spenden",
16
 *	 indexes={
17
 *	 		@ORM\Index(name="d_email", columns={"email"}, flags={"fulltext"}),
18
 *		  	@ORM\Index(name="d_name", columns={"name"}, flags={"fulltext"}),
19
 *	 		@ORM\Index(name="d_ort", columns={"ort"}, flags={"fulltext"}),
20
 *	 		@ORM\Index(name="d_dt_new", columns={"dt_new", "is_public"}),
21
 *	 		@ORM\Index(name="d_zahlweise", columns={"zahlweise", "dt_new"}),
22
 *	 		@ORM\Index(name="d_dt_gruen", columns={"dt_gruen", "dt_del"}),
23
 *	 		@ORM\Index(name="d_ueb_code", columns={"ueb_code"}),
24
 *	 		@ORM\Index(name="d_dt_backup", columns={"dt_backup"}),
25
 *	 		@ORM\Index(name="d_status", columns={"status", "dt_new"}),
26
 *	 		@ORM\Index(name="d_comment_list", columns={"is_public", "dt_del"})
27
 *	 }
28
 *  )
29
 * @ORM\Entity
30
 */
31
class Donation {
32
33
	/**
34
	 * @since 2.0
35
	 */
36
	public const STATUS_NEW = 'N'; // status for direct debit
37
	public const STATUS_PROMISE = 'Z'; // status for bank transfer
38
	public const STATUS_EXTERNAL_INCOMPLETE = 'X'; // status for external payments
39
	public const STATUS_EXTERNAL_BOOKED = 'B'; // status for external payments
40
	public const STATUS_MODERATION = 'P';
41
	public const STATUS_CANCELLED = 'D';
42
43
	/**
44
	 * @var integer
45
	 *
46
	 * @ORM\Column(name="id", type="integer")
47
	 * @ORM\Id
48
	 * @ORM\GeneratedValue(strategy="IDENTITY")
49
	 */
50
	private $id;
51
52
	/**
53
	 * @var string
54
	 *
55
	 * @ORM\Column(name="status", type="string", length=1, options={"default":"N", "fixed":true}, nullable=false)
56
	 */
57
	private $status = self::STATUS_NEW;
58
59
	/**
60
	 * @var string
61
	 *
62
	 * @ORM\Column(name="name", type="string", length=250, nullable=true)
63
	 */
64
	private $donorFullName;
65
66
	/**
67
	 * @var string
68
	 *
69
	 * @ORM\Column(name="ort", type="string", length=250, nullable=true)
70
	 */
71
	private $donorCity;
72
73
	/**
74
	 * @var string
75
	 *
76
	 * @ORM\Column(name="email", type="string", length=250, nullable=true)
77
	 */
78
	private $donorEmail;
79
80
	/**
81
	 * @var boolean
82
	 *
83
	 * @ORM\Column(name="info", type="boolean", options={"default":0}, nullable=false)
84
	 */
85
	private $donorOptsIntoNewsletter = 0;
86
87
	/**
88
	 * @var boolean
89
	 *
90
	 * @ORM\Column(name="bescheinigung", type="boolean", nullable=true)
91
	 */
92
	private $donationReceipt;
93
94
	/**
95
	 * @var string
96
	 *
97
	 * @ORM\Column(name="eintrag", type="string", length=250, options={"default":""}, nullable=false)
98
	 */
99
	private $publicRecord = '';
100
101
	/**
102
	 * @var string
103
	 *
104
	 * @ORM\Column(name="betrag", type="string", length=250, nullable=true)
105
	 */
106
	private $amount;
107
108
	/**
109
	 * @var integer
110
	 *
111
	 * @ORM\Column(name="periode", type="smallint", options={"default":0}, nullable=false)
112
	 */
113
	private $paymentIntervalInMonths = 0;
114
115
	/**
116
	 * @var string
117
	 *
118
	 * @ORM\Column(name="zahlweise", type="string", length=3, options={"default":"BEZ", "fixed":true}, nullable=false)
119
	 */
120
	private $paymentType = 'BEZ';
121
122
	/**
123
	 * @var string
124
	 *
125
	 * @ORM\Column(name="kommentar", type="text", options={"default":""}, nullable=false)
126
	 */
127
	private $comment = '';
128
129
	/**
130
	 * @var string
131
	 *
132
	 * @ORM\Column(name="ueb_code", type="string", length=32, options={"default":""}, nullable=false)
133
	 */
134
	private $bankTransferCode = '';
135
136
	/**
137
	 * @var string
138
	 *
139
	 * @ORM\Column(name="data", type="text", nullable=true)
140
	 */
141
	private $data;
142
143
	/**
144
	 * @var string
145
	 *
146
	 * @ORM\Column(name="source", type="string", length=250, nullable=true)
147
	 */
148
	private $source;
149
150
	/**
151
	 * @var string
152
	 *
153
	 * @ORM\Column(name="remote_addr", type="string", length=250, options={"default":""}, nullable=false)
154
	 */
155
	private $remoteAddr = '';
156
157
	/**
158
	 * @var string
159
	 *
160
	 * @ORM\Column(name="hash", type="string", length=250, nullable=true)
161
	 */
162
	private $hash;
163
164
	/**
165
	 * @var boolean
166
	 *
167
	 * @ORM\Column(name="is_public", type="boolean", options={"default":0}, nullable=false)
168
	 */
169
	private $isPublic = 0;
170
171
	/**
172
	 * @var \DateTime
173
	 *
174
	 * @Gedmo\Timestampable(on="create")
175
	 * @ORM\Column(name="dt_new", type="datetime")
176
	 */
177
	private $creationTime;
178
179
	/**
180
	 * @var \DateTime
181
	 *
182
	 * @ORM\Column(name="dt_del", type="datetime", nullable=true)
183
	 */
184
	private $deletionTime;
185
186
	/**
187
	 * @var \DateTime
188
	 *
189
	 * @ORM\Column(name="dt_exp", type="datetime", nullable=true)
190
	 */
191
	private $dtExp;
192
193
	/**
194
	 * @var \DateTime
195
	 *
196
	 * @ORM\Column(name="dt_gruen", type="datetime", nullable=true)
197
	 */
198
	private $dtGruen;
199
200
	/**
201
	 * @var \DateTime
202
	 *
203
	 * @ORM\Column(name="dt_backup", type="datetime", nullable=true)
204
	 */
205
	private $dtBackup;
206
207
	/**
208
	 * @ORM\OneToOne(targetEntity="WMDE\Fundraising\Entities\DonationPayment", cascade={"all"}, fetch="EAGER")
209
	 */
210
	private $payment;
211
212
	/**
213
	 * @param string $donorFullName
214
	 *
215
	 * @return self
216
	 */
217
	public function setDonorFullName( $donorFullName ) {
218
		$this->donorFullName = $donorFullName;
219
220
		return $this;
221
	}
222
223
	/**
224
	 * @return string
225
	 */
226
	public function getDonorFullName() {
227
		return $this->donorFullName;
228
	}
229
230
	/**
231
	 * @param string $donorCity
232
	 *
233
	 * @return self
234
	 */
235
	public function setDonorCity( $donorCity ) {
236
		$this->donorCity = $donorCity;
237
238
		return $this;
239
	}
240
241
	/**
242
	 * @return string
243
	 */
244
	public function getDonorCity() {
245
		return $this->donorCity;
246
	}
247
248
	/**
249
	 * @param string $donorEmail
250
	 *
251
	 * @return self
252
	 */
253
	public function setDonorEmail( $donorEmail ) {
254
		$this->donorEmail = $donorEmail;
255
256
		return $this;
257
	}
258
259
	/**
260
	 * @return string
261
	 */
262
	public function getDonorEmail() {
263
		return $this->donorEmail;
264
	}
265
266
	/**
267
	 * @param boolean $donorOptsIntoNewsletter
268
	 *
269
	 * @return self
270
	 */
271
	public function setDonorOptsIntoNewsletter( $donorOptsIntoNewsletter ) {
272
		$this->donorOptsIntoNewsletter = $donorOptsIntoNewsletter;
273
274
		return $this;
275
	}
276
277
	/**
278
	 * @return boolean
279
	 */
280
	public function getDonorOptsIntoNewsletter() {
281
		return $this->donorOptsIntoNewsletter;
282
	}
283
284
	/**
285
	 * Set donation receipt state
286
	 *
287
	 * @param boolean $donationReceipt
288
	 * @return self
289
	 */
290
	public function setDonationReceipt( $donationReceipt ) {
291
		$this->donationReceipt = $donationReceipt;
292
293
		return $this;
294
	}
295
296
	/**
297
	 * Get donation receipt state
298
	 *
299
	 * @return boolean
300
	 */
301
	public function getDonationReceipt() {
302
		return $this->donationReceipt;
303
	}
304
305
	/**
306
	 * Set publicly displayed donation record
307
	 *
308
	 * @param string $publicRecord
309
	 * @return self
310
	 */
311
	public function setPublicRecord( $publicRecord ) {
312
		$this->publicRecord = $publicRecord;
313
314
		return $this;
315
	}
316
317
	/**
318
	 * Get publicly displayed donation record
319
	 *
320
	 * @return string
321
	 */
322
	public function getPublicRecord() {
323
		return $this->publicRecord;
324
	}
325
326
	/**
327
	 * @param string $amount
328
	 * @return self
329
	 */
330
	public function setAmount( $amount ) {
331
		$this->amount = $amount;
332
333
		return $this;
334
	}
335
336
	/**
337
	 * @return string
338
	 */
339
	public function getAmount() {
340
		return $this->amount;
341
	}
342
343
	/**
344
	 * @param integer $paymentIntervalInMonths
345
	 *
346
	 * @return self
347
	 */
348
	public function setPaymentIntervalInMonths( $paymentIntervalInMonths ) {
349
		$this->paymentIntervalInMonths = $paymentIntervalInMonths;
350
351
		return $this;
352
	}
353
354
	/**
355
	 * @return integer
356
	 */
357
	public function getPaymentIntervalInMonths() {
358
		return $this->paymentIntervalInMonths;
359
	}
360
361
	/**
362
	 * Set payment type short code
363
	 *
364
	 * @param string $paymentType
365
	 * @return self
366
	 */
367
	public function setPaymentType( $paymentType ) {
368
		$this->paymentType = $paymentType;
369
370
		return $this;
371
	}
372
373
	/**
374
	 * Get payment type short code
375
	 *
376
	 * @return string
377
	 */
378
	public function getPaymentType() {
379
		return $this->paymentType;
380
	}
381
382
	/**
383
	 * @param string $comment
384
	 * @return self
385
	 */
386
	public function setComment( $comment ) {
387
		$this->comment = $comment;
388
389
		return $this;
390
	}
391
392
	/**
393
	 * @return string
394
	 */
395
	public function getComment() {
396
		return $this->comment;
397
	}
398
399
	/**
400
	 * Set bank transfer reference code
401
	 *
402
	 * @param string $bankTransferCode
403
	 *
404
	 * @return self
405
	 */
406
	public function setBankTransferCode( $bankTransferCode ) {
407
		$this->bankTransferCode = $bankTransferCode;
408
409
		return $this;
410
	}
411
412
	/**
413
	 * Get bank transfer reference code
414
	 *
415
	 * @return string
416
	 */
417
	public function getBankTransferCode() {
418
		return $this->bankTransferCode;
419
	}
420
421
	/**
422
	 * @param string $source
423
	 * @return self
424
	 */
425
	public function setSource( $source ) {
426
		$this->source = $source;
427
428
		return $this;
429
	}
430
431
	/**
432
	 * @return string
433
	 */
434
	public function getSource() {
435
		return $this->source;
436
	}
437
438
	/**
439
	 * @param string $remoteAddr
440
	 * @return self
441
	 */
442
	public function setRemoteAddr( $remoteAddr ) {
443
		$this->remoteAddr = $remoteAddr;
444
445
		return $this;
446
	}
447
448
	/**
449
	 * @return string
450
	 */
451
	public function getRemoteAddr() {
452
		return $this->remoteAddr;
453
	}
454
455
	/**
456
	 * @param string $hash
457
	 * @return self
458
	 */
459
	public function setHash( $hash ) {
460
		$this->hash = $hash;
461
462
		return $this;
463
	}
464
465
	/**
466
	 * @return string
467
	 */
468
	public function getHash() {
469
		return $this->hash;
470
	}
471
472
	/**
473
	 * Sets if the donations comment should be public or private.
474
	 * @param boolean $isPublic
475
	 * @return self
476
	 */
477
	public function setIsPublic( $isPublic ) {
478
		$this->isPublic = $isPublic;
479
480
		return $this;
481
	}
482
483
	/**
484
	 * Gets if the donations comment is public or private.
485
	 * @return boolean
486
	 */
487
	public function getIsPublic() {
488
		return $this->isPublic;
489
	}
490
491
	/**
492
	 * @param \DateTime $creationTime
493
	 *
494
	 * @return self
495
	 */
496
	public function setCreationTime( $creationTime ) {
497
		$this->creationTime = $creationTime;
498
499
		return $this;
500
	}
501
502
	/**
503
	 * @return \DateTime
504
	 */
505
	public function getCreationTime() {
506
		return $this->creationTime;
507
	}
508
509
	/**
510
	 * @param \DateTime|null $deletionTime
511
	 *
512
	 * @return self
513
	 */
514
	public function setDeletionTime( $deletionTime ) {
515
		$this->deletionTime = $deletionTime;
516
517
		return $this;
518
	}
519
520
	/**
521
	 * @return \DateTime|null
522
	 */
523
	public function getDeletionTime() {
524
		return $this->deletionTime;
525
	}
526
527
	/**
528
	 * @param \DateTime $dtExp
529
	 * @return self
530
	 */
531
	public function setDtExp( $dtExp ) {
532
		$this->dtExp = $dtExp;
533
534
		return $this;
535
	}
536
537
	/**
538
	 * @return \DateTime
539
	 */
540
	public function getDtExp() {
541
		return $this->dtExp;
542
	}
543
544
	/**
545
	 * @param string $status
546
	 * @return self
547
	 */
548
	public function setStatus( $status ) {
549
		$this->status = $status;
550
551
		return $this;
552
	}
553
554
	/**
555
	 * @return string
556
	 */
557
	public function getStatus() {
558
		return $this->status;
559
	}
560
561
	/**
562
	 * @param \DateTime $dtGruen
563
	 * @return self
564
	 */
565
	public function setDtGruen( $dtGruen ) {
566
		$this->dtGruen = $dtGruen;
567
568
		return $this;
569
	}
570
571
	/**
572
	 * @return \DateTime
573
	 */
574
	public function getDtGruen() {
575
		return $this->dtGruen;
576
	}
577
578
	/**
579
	 * @param \DateTime $dtBackup
580
	 * @return self
581
	 */
582
	public function setDtBackup( $dtBackup ) {
583
		$this->dtBackup = $dtBackup;
584
585
		return $this;
586
	}
587
588
	/**
589
	 * @return \DateTime
590
	 */
591
	public function getDtBackup() {
592
		return $this->dtBackup;
593
	}
594
595
	/**
596
	 * @return integer|null
597
	 */
598 3
	public function getId() {
599 3
		return $this->id;
600
	}
601
602
	public function getPayment(): ?DonationPayment {
603
		return $this->payment;
604
	}
605
606
	public function setPayment( DonationPayment $payment ) {
607
		$this->payment = $payment;
608
	}
609
610
611
	/**
612
	 * @since 2.0
613
	 *
614
	 * @param integer|null $id
615
	 */
616 2
	public function setId( $id ) {
617 2
		$this->id = $id;
618 2
	}
619
620
	public function getUExpiry() {
621
		return $this->getDecodedData()[ 'uexpiry' ];
622
	}
623
624
	public function uTokenIsExpired() {
625
		return time() > strtotime( $this->getUExpiry() );
626
	}
627
628
	public function validateToken( $tokenToCheck, $serverSecret ) {
629
		$checkToken = preg_replace( '/\$.*$/', '', $tokenToCheck );
630
631
		$checkToken = $checkToken . '$' .
632
			sha1( sha1( "$checkToken+$serverSecret" ) . '|' .
633
				sha1( "{$this->id}+$serverSecret" ) . '|' .
634
				sha1( "{$this->creationTime->format( 'Y-m-d H:i:s' )}+$serverSecret" ) );
635
		return $checkToken === $tokenToCheck;
636
	}
637
638
	public function getEntryType( $mode = null ) {
639
		$data = $this->getDecodedData();
640
641
		if ( $mode === null ) {
642
			$mode = $this->publicRecord;
643
			if ( !is_int( $mode ) ) {
644
				return $this->publicRecord;
645
			}
646
		}
647
648
		if ( $mode == 1 || $mode == 2 ) {
649
			$eintrag = $this->donorFullName;
650
		} else {
651
			$eintrag = "anonym";
652
		}
653
654
		if ( ( $mode == 1 || $mode == 3 ) && !empty( $data[ "ort" ] ) ) {
655
			$eintrag .= ", " . $data[ "ort" ];
656
		}
657
658
		return $eintrag;
659
	}
660
661
	/**
662
	 * @deprecated since 2.0, use encodeAndSetData or setDataObject instead
663
	 *
664
	 * @param string $data Base 64 encoded, serialized PHP array
665
	 * @return self
666
	 */
667
	public function setData( $data ) {
668
		$this->data = $data;
669
670
		return $this;
671
	}
672
673
	/**
674
	 * @deprecated since 2.0, use @see getDecodedData or @see getDataObject instead
675
	 *
676
	 * @return string Base 64 encoded, serialized PHP array
677
	 */
678
	public function getData() {
679
		return $this->data;
680
	}
681
682
	/**
683
	 * NOTE: if possible, use @see getDataObject instead, as it provides a nicer API.
684
	 *
685
	 * @since 2.0
686
	 * @return array
687
	 */
688 8
	public function getDecodedData() {
689 8
		if ( $this->data === null ) {
690 4
			return [];
691
		}
692
693 6
		$data = unserialize( base64_decode( $this->data ) );
694
695 6
		return is_array( $data ) ? $data : [];
696
	}
697
698
	/**
699
	 * NOTE: if possible, use @see modifyDataObject instead, as it provides a nicer API.
700
	 *
701
	 * @since 2.0
702
	 * @param array $data
703
	 */
704 6
	public function encodeAndSetData( array $data ) {
705 6
		$this->data = base64_encode( serialize( $data ) );
706 6
	}
707
708
	/**
709
	 * WARNING: updates made to the return value will not be reflected in the Donation state.
710
	 * Similarly, updates to the Donation state will not propagate to the returned object.
711
	 * To update the Donation state, explicitly call @see setDataObject.
712
	 *
713
	 * @since 2.0
714
	 * @return DonationData
715
	 */
716 3
	public function getDataObject() {
717 3
		$dataArray = $this->getDecodedData();
718
719 3
		$data = new DonationData();
720
721 3
		$data->setAccessToken( array_key_exists( 'token', $dataArray ) ? $dataArray['token'] : null );
722 3
		$data->setUpdateToken( array_key_exists( 'utoken', $dataArray ) ? $dataArray['utoken'] : null );
723 3
		$data->setUpdateTokenExpiry( array_key_exists( 'uexpiry', $dataArray ) ? $dataArray['uexpiry'] : null );
724
725 3
		return $data;
726
	}
727
728
	/**
729
	 * @since 2.0
730
	 * @param DonationData $data
731
	 */
732 4
	public function setDataObject( DonationData $data ) {
733 4
		$dataArray = array_merge(
734 4
			$this->getDecodedData(),
735
			[
736 4
				'token' => $data->getAccessToken(),
737 4
				'utoken' => $data->getUpdateToken(),
738 4
				'uexpiry' => $data->getUpdateTokenExpiry(),
739
			]
740
		);
741
742 4
		foreach ( [ 'token', 'utoken', 'uexpiry' ] as $keyName ) {
743 4
			if ( is_null( $dataArray[$keyName] ) ) {
744 4
				unset( $dataArray[$keyName] );
745
			}
746
		}
747
748 4
		$this->encodeAndSetData( $dataArray );
749 4
	}
750
751
	/**
752
	 * @since 2.0
753
	 * @param callable $modificationFunction Takes a modifiable DonationData parameter
754
	 */
755 1
	public function modifyDataObject( callable $modificationFunction ) {
756 1
		$dataObject = $this->getDataObject();
757 1
		$modificationFunction( $dataObject );
758 1
		$this->setDataObject( $dataObject );
759 1
	}
760
761
}
762