Passed
Push — master ( 6fe09a...7e8f13 )
by
unknown
11:28
created

AddressChange   A

Complexity

Total Complexity 26

Size/Duplication

Total Lines 144
Duplicated Lines 0 %

Test Coverage

Coverage 80.88%

Importance

Changes 1
Bugs 0 Features 0
Metric Value
wmc 26
eloc 63
dl 0
loc 144
ccs 55
cts 68
cp 0.8088
rs 10
c 1
b 0
f 0

18 Methods

Rating   Name   Duplication   Size   Complexity  
A getId() 0 2 1
A getCurrentIdentifier() 0 2 1
A markAsExported() 0 5 2
A resetExportState() 0 2 1
A isModified() 0 2 1
A isExported() 0 2 1
A isPersonalAddress() 0 2 1
A __construct() 0 18 5
A getExportState() 0 10 3
A markAsModified() 0 6 1
A isOptedIntoDonationReceipt() 0 2 1
A optOutOfDonationReceipt() 0 3 1
A getPreviousIdentifier() 0 2 1
A getExternalIdType() 0 2 1
A isCompanyAddress() 0 2 1
A getAddress() 0 2 1
A getExternalId() 0 2 1
A performAddressChange() 0 6 2
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
17
	public const ADDRESS_TYPE_PERSON = 'person';
18
	public const ADDRESS_TYPE_COMPANY = 'company';
19
20
	public const EXTERNAL_ID_TYPE_DONATION = 'donation';
21
	public const EXTERNAL_ID_TYPE_MEMBERSHIP = 'membership';
22
23
	public const EXPORT_STATE_NO_DATA = 'NO_DATA';
24
	public const EXPORT_STATE_USED_NOT_EXPORTED = 'USED_NOT_EXPORTED';
25
	public const EXPORT_STATE_USED_EXPORTED = 'USED_EXPORTED';
26
27
	/**
28
	 * @var int|null
29
	 * @phpstan-ignore-next-line
30
	 */
31
	private ?int $id;
32
33
	private AddressChangeId $identifier;
34
35
	private AddressChangeId $previousIdentifier;
36
37
	private ?Address $address;
38
39
	private string $addressType;
40
41
	private bool $donationReceipt;
42
43
	private int $externalId;
44
45
	private string $externalIdType;
46
47
	private ?\DateTimeInterface $exportDate;
48
49
	private \DateTimeInterface $createdAt;
50
51
	private \DateTimeInterface $modifiedAt;
52
53 14
	public function __construct( string $addressType, string $externalIdType, int $externalId, AddressChangeId $identifier,
54
			?Address $address = null, ?\DateTime $createdAt = null ) {
55 14
		$this->addressType = $addressType;
56 14
		$this->identifier = $identifier;
57 14
		$this->previousIdentifier = $identifier;
58 14
		$this->address = $address;
59 14
		if ( $addressType !== self::ADDRESS_TYPE_PERSON && $addressType !== self::ADDRESS_TYPE_COMPANY ) {
60 1
			throw new \InvalidArgumentException( 'Invalid address type' );
61
		}
62 13
		if ( $externalIdType !== self::EXTERNAL_ID_TYPE_DONATION && $externalIdType !== self::EXTERNAL_ID_TYPE_MEMBERSHIP ) {
63 1
			throw new \InvalidArgumentException( 'Invalid external reference type' );
64
		}
65 12
		$this->exportDate = null;
66 12
		$this->createdAt = $createdAt ?? new \DateTime();
67 12
		$this->modifiedAt = clone $this->createdAt;
68 12
		$this->donationReceipt = true;
69 12
		$this->externalId = $externalId;
70 12
		$this->externalIdType = $externalIdType;
71 12
	}
72
73 5
	public function performAddressChange( Address $address, AddressChangeId $newIdentifier ): void {
74 5
		if ( $this->address !== null ) {
75
			throw new LogicException( 'Cannot perform address change for instances that already have an address.' );
76
		}
77 5
		$this->address = $address;
78 5
		$this->markAsModified( $newIdentifier );
79 5
	}
80
81 1
	public function optOutOfDonationReceipt( AddressChangeId $newIdentifier ): void {
82 1
		$this->donationReceipt = false;
83 1
		$this->markAsModified( $newIdentifier );
84 1
	}
85
86 6
	public function getCurrentIdentifier(): AddressChangeId {
87 6
		return $this->identifier;
88
	}
89
90 2
	public function getPreviousIdentifier(): ?AddressChangeId {
91 2
		return $this->previousIdentifier;
92
	}
93
94 1
	public function getAddress(): ?Address {
95 1
		return $this->address;
96
	}
97
98
	public function isPersonalAddress(): bool {
99
		return $this->addressType === self::ADDRESS_TYPE_PERSON;
100
	}
101
102
	public function isCompanyAddress(): bool {
103
		return $this->addressType === self::ADDRESS_TYPE_COMPANY;
104
	}
105
106
	public function isOptedIntoDonationReceipt(): bool {
107
		return $this->donationReceipt;
108
	}
109
110 5
	public function markAsExported(): void {
111 5
		if ( $this->isExported() ) {
112 1
			throw new LogicException( 'Address changes can only be exported once.' );
113
		}
114 5
		$this->exportDate = new \DateTime();
115 5
	}
116
117 6
	private function resetExportState(): void {
118 6
		$this->exportDate = null;
119 6
	}
120
121 6
	public function isExported(): bool {
122 6
		return $this->exportDate !== null;
123
	}
124
125 4
	public function isModified(): bool {
126 4
		return $this->createdAt < $this->modifiedAt;
127
	}
128
129 6
	private function markAsModified( AddressChangeId $newIdentifier ): void {
130 6
		$this->previousIdentifier = $this->getCurrentIdentifier();
131 6
		$this->identifier = $newIdentifier;
132
133 6
		$this->modifiedAt = new \DateTime();
134 6
		$this->resetExportState();
135 6
	}
136
137
	public function getId(): ?int {
138
		return $this->id;
139
	}
140
141
	public function getExternalId(): int {
142
		return $this->externalId;
143
	}
144
145
	public function getExternalIdType(): string {
146
		return $this->externalIdType;
147
	}
148
149 3
	public function getExportState(): string {
150 3
		if ( !$this->address ) {
151 1
			return self::EXPORT_STATE_NO_DATA;
152
		}
153
154 2
		if ( $this->exportDate ) {
155 1
			return self::EXPORT_STATE_USED_EXPORTED;
156
		}
157
158 1
		return self::EXPORT_STATE_USED_NOT_EXPORTED;
159
	}
160
}
161