Completed
Pull Request — master (#594)
by Jeroen De
12:09
created

AddDonationUseCase::newDonationFromRequest()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 10
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 10
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 8
nc 1
nop 1
1
<?php
2
3
declare( strict_types = 1 );
4
5
namespace WMDE\Fundraising\Frontend\DonatingContext\UseCases\AddDonation;
6
7
use WMDE\Fundraising\Frontend\Domain\Model\PersonName;
8
use WMDE\Fundraising\Frontend\Domain\Model\PhysicalAddress;
9
use WMDE\Fundraising\Frontend\DonatingContext\Authorization\DonationTokenFetcher;
10
use WMDE\Fundraising\Frontend\DonatingContext\Domain\Model\Donation;
11
use WMDE\Fundraising\Frontend\DonatingContext\Domain\Model\DonationPayment;
12
use WMDE\Fundraising\Frontend\DonatingContext\Domain\Model\DonationTrackingInfo;
13
use WMDE\Fundraising\Frontend\DonatingContext\Domain\Model\Donor;
14
use WMDE\Fundraising\Frontend\DonatingContext\Domain\Repositories\DonationRepository;
15
use WMDE\Fundraising\Frontend\DonatingContext\Infrastructure\DonationConfirmationMailer;
16
use WMDE\Fundraising\Frontend\PaymentContext\Domain\Model\BankTransferPayment;
17
use WMDE\Fundraising\Frontend\PaymentContext\Domain\Model\DirectDebitPayment;
18
use WMDE\Fundraising\Frontend\PaymentContext\Domain\Model\PaymentMethod;
19
use WMDE\Fundraising\Frontend\PaymentContext\Domain\Model\PaymentType;
20
use WMDE\Fundraising\Frontend\PaymentContext\Domain\Model\PaymentWithoutAssociatedData;
21
use WMDE\Fundraising\Frontend\PaymentContext\Domain\Model\PayPalData;
22
use WMDE\Fundraising\Frontend\PaymentContext\Domain\Model\PayPalPayment;
23
use WMDE\Fundraising\Frontend\PaymentContext\Domain\TransferCodeGenerator;
24
25
/**
26
 * @license GNU GPL v2+
27
 * @author Kai Nissen < [email protected] >
28
 * @author Jeroen De Dauw < [email protected] >
29
 */
30
class AddDonationUseCase {
31
32
	private $donationRepository;
33
	private $donationValidator;
34
	private $policyValidator;
35
	private $referrerGeneralizer;
36
	private $mailer;
37
	private $transferCodeGenerator;
38
	private $tokenFetcher;
39
40
	public function __construct( DonationRepository $donationRepository, AddDonationValidator $donationValidator,
41
								 AddDonationPolicyValidator $policyValidator, ReferrerGeneralizer $referrerGeneralizer,
42
								 DonationConfirmationMailer $mailer, TransferCodeGenerator $transferCodeGenerator,
43
								 DonationTokenFetcher $tokenFetcher ) {
44
		$this->donationRepository = $donationRepository;
45
		$this->donationValidator = $donationValidator;
46
		$this->policyValidator = $policyValidator;
47
		$this->referrerGeneralizer = $referrerGeneralizer;
48
		$this->mailer = $mailer;
49
		$this->transferCodeGenerator = $transferCodeGenerator;
50
51
		$this->tokenFetcher = $tokenFetcher;
52
	}
53
54
	public function addDonation( AddDonationRequest $donationRequest ): AddDonationResponse {
55
		$validationResult = $this->donationValidator->validate( $donationRequest );
56
57
		if ( $validationResult->hasViolations() ) {
58
			return AddDonationResponse::newFailureResponse( $validationResult->getViolations() );
59
		}
60
61
		$donation = $this->newDonationFromRequest( $donationRequest );
62
63
		if ( $this->policyValidator->needsModeration( $donationRequest ) ) {
64
			$donation->markForModeration();
65
		}
66
67
		// TODO: handle exceptions
68
		$this->donationRepository->storeDonation( $donation );
69
70
		// TODO: handle exceptions
71
		$tokens = $this->tokenFetcher->getTokens( $donation->getId() );
72
73
		$this->sendDonationConfirmationEmail( $donation );
74
75
		return AddDonationResponse::newSuccessResponse(
76
			$donation,
77
			$tokens->getUpdateToken(),
78
			$tokens->getAccessToken()
79
		);
80
	}
81
82
	private function newDonationFromRequest( AddDonationRequest $donationRequest ): Donation {
83
		return new Donation(
84
			null,
85
			$this->getInitialDonationStatus( $donationRequest->getPaymentType() ),
86
			$this->getPersonalInfoFromRequest( $donationRequest ),
87
			$this->getPaymentFromRequest( $donationRequest ),
88
			$donationRequest->getOptIn() === '1',
89
			$this->newTrackingInfoFromRequest( $donationRequest )
90
		);
91
	}
92
93
	private function getPersonalInfoFromRequest( AddDonationRequest $request ) {
94
		if ( $request->donorIsAnonymous() ) {
95
			return null;
96
		}
97
		return new Donor(
98
			$this->getNameFromRequest( $request ),
99
			$this->getPhysicalAddressFromRequest( $request ),
100
			$request->getDonorEmailAddress()
101
		);
102
	}
103
104
	private function getPhysicalAddressFromRequest( AddDonationRequest $request ): PhysicalAddress {
105
		$address = new PhysicalAddress();
106
107
		$address->setStreetAddress( $request->getDonorStreetAddress() );
108
		$address->setPostalCode( $request->getDonorPostalCode() );
109
		$address->setCity( $request->getDonorCity() );
110
		$address->setCountryCode( $request->getDonorCountryCode() );
111
112
		return $address->freeze()->assertNoNullFields();
113
	}
114
115
	private function getNameFromRequest( AddDonationRequest $request ): PersonName {
116
		$name = $request->donorIsCompany() ? PersonName::newCompanyName() : PersonName::newPrivatePersonName();
117
118
		$name->setSalutation( $request->getDonorSalutation() );
119
		$name->setTitle( $request->getDonorTitle() );
120
		$name->setCompanyName( $request->getDonorCompany() );
121
		$name->setFirstName( $request->getDonorFirstName() );
122
		$name->setLastName( $request->getDonorLastName() );
123
124
		return $name->freeze()->assertNoNullFields();
125
	}
126
127
	private function getInitialDonationStatus( string $paymentType ): string {
128
		if ( $paymentType === PaymentType::DIRECT_DEBIT ) {
129
			return Donation::STATUS_NEW;
130
		}
131
132
		if ( $paymentType === PaymentType::BANK_TRANSFER ) {
133
			return Donation::STATUS_PROMISE;
134
		}
135
136
		return Donation::STATUS_EXTERNAL_INCOMPLETE;
137
	}
138
139
	private function getPaymentFromRequest( AddDonationRequest $donationRequest ): DonationPayment {
140
		return new DonationPayment(
141
			$donationRequest->getAmount(),
142
			$donationRequest->getInterval(),
143
			$this->getPaymentMethodFromRequest( $donationRequest )
144
		);
145
	}
146
147
	private function getPaymentMethodFromRequest( AddDonationRequest $donationRequest ): PaymentMethod {
148
		if ( $donationRequest->getPaymentType() === PaymentType::BANK_TRANSFER ) {
149
			return new BankTransferPayment( $this->transferCodeGenerator->generateTransferCode() );
150
		}
151
152
		if ( $donationRequest->getPaymentType() === PaymentType::DIRECT_DEBIT ) {
153
			return new DirectDebitPayment( $donationRequest->getBankData() );
0 ignored issues
show
Bug introduced by
It seems like $donationRequest->getBankData() can be null; however, __construct() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
154
		}
155
156
		if ( $donationRequest->getPaymentType() === PaymentType::PAYPAL ) {
157
			return new PayPalPayment( new PayPalData() );
158
		}
159
160
		return new PaymentWithoutAssociatedData( $donationRequest->getPaymentType() );
161
	}
162
163
	private function newTrackingInfoFromRequest( AddDonationRequest $request ): DonationTrackingInfo {
164
		$trackingInfo = new DonationTrackingInfo();
165
166
		$trackingInfo->setTracking( $request->getTracking() );
167
		$trackingInfo->setSource( $this->referrerGeneralizer->generalize( $request->getSource() ) );
168
		$trackingInfo->setTotalImpressionCount( $request->getTotalImpressionCount() );
169
		$trackingInfo->setSingleBannerImpressionCount( $request->getSingleBannerImpressionCount() );
170
		$trackingInfo->setColor( $request->getColor() );
171
		$trackingInfo->setSkin( $request->getSkin() );
172
		$trackingInfo->setLayout( $request->getLayout() );
173
174
		return $trackingInfo->freeze()->assertNoNullFields();
175
	}
176
177
	/**
178
	 * @param Donation $donation
179
	 *
180
	 * @throws \RuntimeException
181
	 * TODO: handle exception
182
	 */
183
	private function sendDonationConfirmationEmail( Donation $donation ) {
184
		if ( $donation->getDonor() !== null && !$donation->hasExternalPayment() ) {
185
			$this->mailer->sendConfirmationMailFor( $donation );
186
		}
187
	}
188
}