Completed
Push — master ( 996d66...c95bf7 )
by Jeroen De
58:45
created

AddDonationHandler::newBankDataFromIban()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 3
c 0
b 0
f 0
rs 10
cc 1
eloc 2
nc 1
nop 1
1
<?php
2
3
declare( strict_types = 1 );
4
5
namespace WMDE\Fundraising\Frontend\App\RouteHandlers;
6
7
use Silex\Application;
8
use Symfony\Component\HttpFoundation\Request;
9
use Symfony\Component\HttpFoundation\Response;
10
use WMDE\Euro\Euro;
11
use WMDE\Fundraising\Frontend\DonationContext\UseCases\AddDonation\AddDonationRequest;
12
use WMDE\Fundraising\Frontend\DonationContext\UseCases\AddDonation\AddDonationResponse;
13
use WMDE\Fundraising\Frontend\Factories\FunFunFactory;
14
use WMDE\Fundraising\Frontend\Infrastructure\AmountParser;
15
use WMDE\Fundraising\Frontend\PaymentContext\Domain\Model\BankData;
16
use WMDE\Fundraising\Frontend\PaymentContext\Domain\Model\Iban;
17
use WMDE\Fundraising\Frontend\PaymentContext\Domain\Model\PaymentType;
18
19
/**
20
 * @license GNU GPL v2+
21
 * @author Kai Nissen < [email protected] >
22
 * @author Jeroen De Dauw < [email protected] >
23
 */
24
class AddDonationHandler {
25
26
	private $ffFactory;
27
	private $app;
28
29
	public function __construct( FunFunFactory $ffFactory, Application $app ) {
30
		$this->ffFactory = $ffFactory;
31
		$this->app = $app;
32
	}
33
34
	public function handle( Request $request ): Response {
35
		if ( !$this->isSubmissionAllowed( $request ) ) {
36
			return new Response( $this->ffFactory->newSystemMessageResponse( 'donation_rejected_limit' ) );
37
		}
38
39
		$addDonationRequest = $this->createDonationRequest( $request );
40
		$responseModel = $this->ffFactory->newAddDonationUseCase()->addDonation( $addDonationRequest );
41
42
		if ( !$responseModel->isSuccessful() ) {
43
			return new Response( $this->ffFactory->newDonationFormViolationPresenter()->present( $responseModel->getValidationErrors(), $addDonationRequest ) );
44
		}
45
46
		return $this->newHttpResponse( $responseModel );
47
	}
48
49
	private function newHttpResponse( AddDonationResponse $responseModel ): Response {
50
		switch( $responseModel->getDonation()->getPaymentType() ) {
51
			case PaymentType::DIRECT_DEBIT:
52
			case PaymentType::BANK_TRANSFER:
53
				$httpResponse = $this->app->redirect(
54
					$this->app['url_generator']->generate(
55
						'show-donation-confirmation',
56
						[
57
							'id' => $responseModel->getDonation()->getId(),
58
							'accessToken' => $responseModel->getAccessToken()
59
						]
60
					),
61
					Response::HTTP_SEE_OTHER
62
				);
63
64
				break;
65
			case PaymentType::PAYPAL:
66
				$httpResponse = $this->app->redirect(
67
					$this->ffFactory->newPayPalUrlGeneratorForDonations()->generateUrl(
68
						$responseModel->getDonation()->getId(),
69
						$responseModel->getDonation()->getAmount(),
70
						$responseModel->getDonation()->getPaymentIntervalInMonths(),
71
						$responseModel->getUpdateToken(),
72
						$responseModel->getAccessToken()
73
					)
74
				);
75
				break;
76
			case PaymentType::CREDIT_CARD:
77
				$httpResponse = new Response(
78
					$this->ffFactory->newCreditCardPaymentHtmlPresenter()->present( $responseModel )
79
				);
80
				break;
81
			default:
82
				throw new \LogicException( 'This code should not be reached' );
83
		}
84
		return $httpResponse;
85
	}
86
87
	private function createDonationRequest( Request $request ): AddDonationRequest {
88
		$donationRequest = new AddDonationRequest();
89
90
		$donationRequest->setAmount( $this->getEuroAmountFromString( $request->get( 'betrag', '' ) ) );
91
92
		$donationRequest->setPaymentType( $request->get( 'zahlweise', '' ) );
93
		$donationRequest->setInterval( intval( $request->get( 'periode', 0 ) ) );
94
95
		$donationRequest->setDonorType( $request->get( 'addressType', '' ) );
96
		$donationRequest->setDonorSalutation( $request->get( 'salutation', '' ) );
97
		$donationRequest->setDonorTitle( $request->get( 'title', '' ) );
98
		$donationRequest->setDonorCompany( $request->get( 'companyName', '' ) );
99
		$donationRequest->setDonorFirstName( $request->get( 'firstName', '' ) );
100
		$donationRequest->setDonorLastName( $request->get( 'lastName', '' ) );
101
		$donationRequest->setDonorStreetAddress( $request->get( 'street', '' ) );
102
		$donationRequest->setDonorPostalCode( $request->get( 'postcode', '' ) );
103
		$donationRequest->setDonorCity( $request->get( 'city', '' ) );
104
		$donationRequest->setDonorCountryCode( $request->get( 'country', '' ) );
105
		$donationRequest->setDonorEmailAddress( $request->get( 'email', '' ) );
106
107
		if ( $request->get( 'zahlweise', '' ) === PaymentType::DIRECT_DEBIT ) {
108
			$donationRequest->setBankData( $this->getBankDataFromRequest( $request ) );
109
		}
110
111
		$donationRequest->setTracking( $request->attributes->get( 'trackingCode' ) );
112
		$donationRequest->setOptIn( $request->get( 'info', '' ) );
113
		$donationRequest->setSource( $request->attributes->get( 'trackingSource' ) );
114
		$donationRequest->setTotalImpressionCount( intval( $request->get( 'impCount', 0 ) ) );
115
		$donationRequest->setSingleBannerImpressionCount( intval( $request->get( 'bImpCount', 0 ) ) );
116
117
		return $donationRequest;
118
	}
119
120
	private function getBankDataFromRequest( Request $request ): BankData {
121
		$bankData = new BankData();
122
		$bankData->setIban( new Iban( $request->get( 'iban', '' ) ) )
123
			->setBic( $request->get( 'bic', '' ) )
124
			->setAccount( $request->get( 'konto', '' ) )
125
			->setBankCode( $request->get( 'blz', '' ) )
126
			->setBankName( $request->get( 'bankname', '' ) );
127
128
		if ( $bankData->hasIban() && !$bankData->hasCompleteLegacyBankData() ) {
129
			$bankData = $this->newBankDataFromIban( $bankData->getIban() );
130
		}
131
		if ( $bankData->hasCompleteLegacyBankData() && !$bankData->hasIban() ) {
132
			$bankData = $this->newBankDataFromAccountAndBankCode( $bankData->getAccount(), $bankData->getBankCode() );
133
		}
134
135
		return $bankData->freeze()->assertNoNullFields();
136
	}
137
138
	private function newBankDataFromIban( Iban $iban ): BankData {
139
		return $this->ffFactory->newBankDataConverter()->getBankDataFromIban( $iban );
140
	}
141
142
	private function newBankDataFromAccountAndBankCode( string $account, string $bankCode ): BankData {
143
		return $this->ffFactory->newBankDataConverter()->getBankDataFromAccountData( $account, $bankCode );
144
	}
145
146
	private function getEuroAmountFromString( string $amount ): Euro {
147
		$locale = 'de_DE'; // TODO: make this configurable for multilanguage support
148
		try {
149
			return Euro::newFromFloat( ( new AmountParser( $locale ) )->parseAsFloat( $amount ) );
150
		} catch ( \InvalidArgumentException $ex ) {
151
			return Euro::newFromCents( 0 );
152
		}
153
154
	}
155
156
	private function isSubmissionAllowed( Request $request ) {
157
		$lastSubmission = $request->cookies->get( ShowDonationConfirmationHandler::SUBMISSION_COOKIE_NAME, '' );
158
		if ( $lastSubmission === '' ) {
159
			return true;
160
		}
161
162
		$minNextTimestamp = \DateTime::createFromFormat( ShowDonationConfirmationHandler::TIMESTAMP_FORMAT, $lastSubmission )
163
			->add( new \DateInterval( $this->ffFactory->getDonationTimeframeLimit() ) );
164
		if ( $minNextTimestamp > new \DateTime() ) {
165
			return false;
166
		}
167
168
		return true;
169
	}
170
171
}