Passed
Push — main ( b7b8b7...5de84d )
by Gabriel
51s queued 15s
created

AddressChange::hasBeenUsed()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 2
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

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