Passed
Push — main ( c73e00...0a00da )
by
unknown
15:13 queued 14s
created

AddressChange   A

Complexity

Total Complexity 24

Size/Duplication

Total Lines 128
Duplicated Lines 0 %

Test Coverage

Coverage 76.35%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 24
eloc 49
c 1
b 0
f 0
dl 0
loc 128
ccs 42
cts 55
cp 0.7635
rs 10

18 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 16 3
A getId() 0 2 1
A getCurrentIdentifier() 0 2 1
A getExportState() 0 10 3
A markAsExported() 0 5 2
A markAsModified() 0 6 1
A resetExportState() 0 2 1
A isOptedIntoDonationReceipt() 0 2 1
A optOutOfDonationReceipt() 0 3 1
A getPreviousIdentifier() 0 2 1
A getExternalIdType() 0 2 1
A isModified() 0 2 1
A isCompanyAddress() 0 2 1
A getAddress() 0 2 1
A getExternalId() 0 2 1
A isExported() 0 2 1
A performAddressChange() 0 6 2
A isPersonalAddress() 0 2 1
1
<?php
2
3
declare( strict_types = 1 );
4
5
namespace WMDE\Fundraising\AddressChangeContext\Domain\Model;
6
7
use LogicException;
8
9
/**
10
 * An Address change record with a UUID identifier for accessing it, an optional address (if the user preformed an
11
 * address change) and a reference to the originating record (donation or membership).
12
 *
13
 * The recommended way to construct this class is through the AddressChangeBuilder
14
 */
15
class AddressChange {
16
	public const EXTERNAL_ID_TYPE_DONATION = 'donation';
17
	public const EXTERNAL_ID_TYPE_MEMBERSHIP = 'membership';
18
19
	public const EXPORT_STATE_NO_DATA = 'NO_DATA';
20
	public const EXPORT_STATE_USED_NOT_EXPORTED = 'USED_NOT_EXPORTED';
21
	public const EXPORT_STATE_USED_EXPORTED = 'USED_EXPORTED';
22
23
	/**
24
	 * @var int|null
25
	 * @phpstan-ignore-next-line
26
	 */
27
	private ?int $id;
28
29
	private AddressChangeId $previousIdentifier;
30
31
	private bool $donationReceipt;
32
33
	private ?\DateTimeInterface $exportDate;
34
35
	private \DateTimeInterface $createdAt;
36
37
	private \DateTimeInterface $modifiedAt;
38
39 13
	public function __construct(
40
		private readonly AddressType $addressType,
41
		private readonly string $externalIdType,
42
		private readonly int $externalId,
43
		private AddressChangeId $identifier,
44
		private ?Address $address = null,
45
		?\DateTime $createdAt = null
46
	) {
47 13
		$this->previousIdentifier = $identifier;
48 13
		if ( $externalIdType !== self::EXTERNAL_ID_TYPE_DONATION && $externalIdType !== self::EXTERNAL_ID_TYPE_MEMBERSHIP ) {
49 1
			throw new \InvalidArgumentException( 'Invalid external reference type' );
50
		}
51 12
		$this->exportDate = null;
52 12
		$this->createdAt = $createdAt ?? new \DateTime();
53 12
		$this->modifiedAt = clone $this->createdAt;
54 12
		$this->donationReceipt = true;
55
	}
56
57 5
	public function performAddressChange( Address $address, AddressChangeId $newIdentifier ): void {
58 5
		if ( $this->address !== null ) {
59
			throw new LogicException( 'Cannot perform address change for instances that already have an address.' );
60
		}
61 5
		$this->address = $address;
62 5
		$this->markAsModified( $newIdentifier );
63
	}
64
65 1
	public function optOutOfDonationReceipt( AddressChangeId $newIdentifier ): void {
66 1
		$this->donationReceipt = false;
67 1
		$this->markAsModified( $newIdentifier );
68
	}
69
70 6
	public function getCurrentIdentifier(): AddressChangeId {
71 6
		return $this->identifier;
72
	}
73
74 2
	public function getPreviousIdentifier(): ?AddressChangeId {
75 2
		return $this->previousIdentifier;
76
	}
77
78 1
	public function getAddress(): ?Address {
79 1
		return $this->address;
80
	}
81
82
	public function isPersonalAddress(): bool {
83
		return $this->addressType === AddressType::Person;
84
	}
85
86
	public function isCompanyAddress(): bool {
87
		return $this->addressType === AddressType::Company;
88
	}
89
90
	public function isOptedIntoDonationReceipt(): bool {
91
		return $this->donationReceipt;
92
	}
93
94 5
	public function markAsExported(): void {
95 5
		if ( $this->isExported() ) {
96 1
			throw new LogicException( 'Address changes can only be exported once.' );
97
		}
98 5
		$this->exportDate = new \DateTime();
99
	}
100
101 6
	private function resetExportState(): void {
102 6
		$this->exportDate = null;
103
	}
104
105 6
	public function isExported(): bool {
106 6
		return $this->exportDate !== null;
107
	}
108
109 4
	public function isModified(): bool {
110 4
		return $this->createdAt < $this->modifiedAt;
111
	}
112
113 6
	private function markAsModified( AddressChangeId $newIdentifier ): void {
114 6
		$this->previousIdentifier = $this->getCurrentIdentifier();
115 6
		$this->identifier = $newIdentifier;
116
117 6
		$this->modifiedAt = new \DateTime();
118 6
		$this->resetExportState();
119
	}
120
121
	public function getId(): ?int {
122
		return $this->id;
123
	}
124
125
	public function getExternalId(): int {
126
		return $this->externalId;
127
	}
128
129
	public function getExternalIdType(): string {
130
		return $this->externalIdType;
131
	}
132
133 3
	public function getExportState(): string {
134 3
		if ( !$this->address ) {
135 1
			return self::EXPORT_STATE_NO_DATA;
136
		}
137
138 2
		if ( $this->exportDate ) {
139 1
			return self::EXPORT_STATE_USED_EXPORTED;
140
		}
141
142 1
		return self::EXPORT_STATE_USED_NOT_EXPORTED;
143
	}
144
}
145