Completed
Pull Request — master (#10)
by Gabriel
60:20
created

AddressChange::resetExportState()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
nc 1
nop 0
dl 0
loc 2
rs 10
c 0
b 0
f 0
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
	/**
24
	 * @var int|null
25
	 */
26
	private $id;
27
28
	private $identifier;
29
30
	private $previousIdentifier;
31
32
	private $address;
33
34
	private $addressType;
35
36
	private $donationReceipt;
37
38
	private $externalId;
39
40
	private $externalIdType;
41
42
	/**
43
	 * @var \DateTimeInterface|null
44
	 */
45
	private $exportDate;
46
47
	/**
48
	 * @var \DateTimeInterface|null
49
	 */
50
	private $createdAt;
51
52
	private $modifiedAt;
53
54
	public function __construct( string $addressType, string $externalIdType, int $externalId, AddressChangeId $identifier,
55
			?Address $address = null, ?\DateTime $createdAt = null ) {
56
		$this->addressType = $addressType;
57
		$this->identifier = $identifier;
58
		$this->previousIdentifier = $identifier;
59
		$this->address = $address;
60
		if ( $addressType !== self::ADDRESS_TYPE_PERSON && $addressType !== self::ADDRESS_TYPE_COMPANY ) {
61
			throw new \InvalidArgumentException( 'Invalid address type' );
62
		}
63
		if( $externalIdType !== self::EXTERNAL_ID_TYPE_DONATION && $externalIdType !== self::EXTERNAL_ID_TYPE_MEMBERSHIP ) {
64
			throw new \InvalidArgumentException( 'Invalid external reference type' );
65
		}
66
		$this->createdAt = $createdAt ?? new \DateTime();
67
		$this->modifiedAt = clone( $this->createdAt );
68
		$this->donationReceipt = true;
69
		$this->externalId = $externalId;
70
		$this->externalIdType = $externalIdType;
71
	}
72
73
	public function performAddressChange( Address $address, AddressChangeId $newIdentifier ): void {
74
		if ( $this->address !== null ) {
75
			throw new LogicException( 'Cannot perform address change for instances that already have an address.' );
76
		}
77
		$this->address = $address;
78
		$this->markAsModified( $newIdentifier );
79
	}
80
81
	public function optOutOfDonationReceipt( AddressChangeId $newIdentifier ): void {
82
		$this->donationReceipt = false;
83
		$this->markAsModified( $newIdentifier );
84
	}
85
86
	public function getCurrentIdentifier(): AddressChangeId {
87
		return $this->identifier;
88
	}
89
90
	public function getPreviousIdentifier(): ?AddressChangeId {
91
		return $this->previousIdentifier;
92
	}
93
94
	public function getAddress(): ?Address {
95
		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
	public function markAsExported(): void {
111
		if ( $this->isExported() ) {
112
			throw new LogicException( 'Address changes can only be exported once.' );
113
		}
114
		$this->exportDate = new \DateTime();
115
	}
116
117
	private function resetExportState(): void {
118
		$this->exportDate = null;
119
	}
120
121
	public function isExported(): bool {
122
		return $this->exportDate !== null;
123
	}
124
125
	public function isModified(): bool {
126
		return $this->createdAt < $this->modifiedAt;
127
	}
128
129
	private function markAsModified( AddressChangeId $newIdentifier ): void {
130
		$this->previousIdentifier = $this->getCurrentIdentifier();
131
		$this->identifier = $newIdentifier;
132
133
		$this->modifiedAt = new \DateTime();
134
		$this->resetExportState();
135
	}
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