Completed
Push — master ( 906179...917cbb )
by Jeroen De
149:06 queued 84:07
created

routes.php$0 ➔ getPhysicalAddressFromRequest()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 10
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 10
c 0
b 0
f 0
rs 9.4285
cc 1
eloc 7
nc 1
nop 1
1
<?php
2
3
/**
4
 * These variables need to be in scope when this file is included:
5
 *
6
 * @var \Silex\Application $app
7
 * @var \WMDE\Fundraising\Frontend\Factories\FunFunFactory $ffFactory
8
 */
9
10
declare( strict_types = 1 );
11
12
use Silex\Application;
13
use Symfony\Component\HttpFoundation\Request;
14
use Symfony\Component\HttpFoundation\Response;
15
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
16
use Symfony\Component\HttpKernel\HttpKernelInterface;
17
use WMDE\Euro\Euro;
18
use WMDE\Fundraising\Frontend\App\RouteHandlers\AddDonationHandler;
19
use WMDE\Fundraising\Frontend\App\RouteHandlers\AddSubscriptionHandler;
20
use WMDE\Fundraising\Frontend\App\RouteHandlers\ApplyForMembershipHandler;
21
use WMDE\Fundraising\Frontend\App\RouteHandlers\PayPalNotificationHandler;
22
use WMDE\Fundraising\Frontend\App\RouteHandlers\SofortNotificationHandler;
23
use WMDE\Fundraising\Frontend\App\RouteHandlers\PayPalNotificationHandlerForMembershipFee;
24
use WMDE\Fundraising\Frontend\App\RouteHandlers\RouteRedirectionHandler;
25
use WMDE\Fundraising\Frontend\App\RouteHandlers\ShowDonationConfirmationHandler;
26
use WMDE\Fundraising\Frontend\App\RouteHandlers\ValidateAddressHandler;
27
use WMDE\Fundraising\Frontend\DonationContext\Domain\Model\DonationTrackingInfo;
28
use WMDE\Fundraising\Frontend\DonationContext\Domain\Model\Donor;
29
use WMDE\Fundraising\Frontend\DonationContext\Domain\Model\DonorAddress;
30
use WMDE\Fundraising\Frontend\DonationContext\Domain\Model\DonorName;
31
use WMDE\Fundraising\Frontend\DonationContext\UseCases\AddComment\AddCommentRequest;
32
use WMDE\Fundraising\Frontend\DonationContext\UseCases\CancelDonation\CancelDonationRequest;
33
use WMDE\Fundraising\Frontend\DonationContext\UseCases\CreditCardPaymentNotification\CreditCardNotificationResponse;
34
use WMDE\Fundraising\Frontend\DonationContext\UseCases\CreditCardPaymentNotification\CreditCardPaymentHandlerException;
35
use WMDE\Fundraising\Frontend\DonationContext\UseCases\CreditCardPaymentNotification\CreditCardPaymentNotificationRequest;
36
use WMDE\Fundraising\Frontend\DonationContext\UseCases\ListComments\CommentListingRequest;
37
use WMDE\Fundraising\Frontend\Factories\FunFunFactory;
38
use WMDE\Fundraising\Frontend\Infrastructure\AmountParser;
39
use WMDE\Fundraising\Frontend\Infrastructure\Cache\AuthorizedCachePurger;
40
use WMDE\Fundraising\Frontend\MembershipContext\UseCases\CancelMembershipApplication\CancellationRequest;
41
use WMDE\Fundraising\Frontend\MembershipContext\UseCases\ShowMembershipApplicationConfirmation\ShowMembershipAppConfirmationRequest;
42
use WMDE\Fundraising\Frontend\PaymentContext\Domain\Model\Iban;
43
use WMDE\Fundraising\Frontend\PaymentContext\UseCases\GenerateIban\GenerateIbanRequest;
44
use WMDE\Fundraising\Frontend\Presentation\ContentPage\ContentNotFoundException;
45
use WMDE\Fundraising\Frontend\Presentation\ContentPage\PageNotFoundException;
46
use WMDE\Fundraising\Frontend\UseCases\GetInTouch\GetInTouchRequest;
47
use WMDE\Fundraising\Frontend\Validation\MembershipFeeValidator;
48
49
$app->post(
50
	'validate-email',
51
	function( Request $request ) use ( $app, $ffFactory ) {
52
		$validationResult = $ffFactory->getEmailValidator()->validate( $request->request->get( 'email', '' ) );
53
		return $app->json( [ 'status' => $validationResult->isSuccessful() ? 'OK' : 'ERR' ] );
54
	}
55
);
56
57
$app->post(
58
	'validate-payment-data',
59
	function( Request $request ) use ( $app, $ffFactory ) {
60
61
		$amount = (float) $ffFactory->newDecimalNumberFormatter()->parse( $request->get( 'amount', '0' ) );
62
		$validator = $ffFactory->newPaymentDataValidator();
63
		$validationResult = $validator->validate( $amount, (string) $request->get( 'paymentType', '' ) );
64
65
		if ( $validationResult->isSuccessful() ) {
66
			return $app->json( [ 'status' => 'OK' ] );
67
		} else {
68
			$errors = [];
69
			foreach( $validationResult->getViolations() as $violation ) {
70
				$errors[ $violation->getSource() ] = $ffFactory->getTranslator()->trans( $violation->getMessageIdentifier() );
71
			}
72
			return $app->json( [ 'status' => 'ERR', 'messages' => $errors ] );
73
		}
74
	}
75
);
76
77
$app->post(
78
	'validate-address', // Validates donor information. This route is named badly.
79
	function( Request $request ) use ( $app, $ffFactory ) {
80
		return ( new ValidateAddressHandler( $ffFactory, $app ) )->handle( $request );
81
	}
82
);
83
84
$app->post(
85
	'validate-fee',
86
	function( Request $httpRequest ) use ( $app, $ffFactory ) {
87
		$validator = new MembershipFeeValidator();
88
		$result = $validator->validate(
89
			str_replace( ',', '.', $httpRequest->request->get( 'amount', '' ) ),
90
			(int) $httpRequest->request->get( 'paymentIntervalInMonths', '0' ),
91
			$httpRequest->request->get( 'addressType', '' )
92
		);
93
94
		if ( $result->isSuccessful() ) {
95
			return $app->json( [ 'status' => 'OK' ] );
96
		} else {
97
			$errors = $result->getViolations();
98
			return $app->json( [ 'status' => 'ERR', 'messages' => $errors ] );
99
		}
100
	}
101
);
102
103
$app->get(
104
	'list-comments.json',
105
	function( Request $request ) use ( $app, $ffFactory ) {
106
		$response = $app->json(
107
			$ffFactory->newCommentListJsonPresenter()->present(
108
				$ffFactory->newListCommentsUseCase()->listComments(
109
					new CommentListingRequest(
110
						(int)$request->query->get( 'n', '10' ),
111
						(int)$request->query->get( 'page', '1' )
112
					)
113
				)
114
			)
115
		);
116
117
		if ( $request->query->get( 'f' ) ) {
118
			$response->setCallback( $request->query->get( 'f' ) );
119
		}
120
121
		return $response;
122
	}
123
);
124
125
$app->get(
126
	'list-comments.rss',
127
	function() use ( $app, $ffFactory ) {
128
		$rss = $ffFactory->newCommentListRssPresenter()->present(
129
			$ffFactory->newListCommentsUseCase()->listComments(
130
				new CommentListingRequest( 100, CommentListingRequest::FIRST_PAGE )
131
			)
132
		);
133
134
		return new Response(
135
			$rss,
136
			200,
137
			[
138
				'Content-Type' => 'text/xml; charset=utf-8',
139
				'X-Moz-Is-Feed' => '1'
140
			]
141
		);
142
	}
143
)->bind( 'list-comments.rss' );
144
145
$app->get(
146
	'list-comments.html',
147
	function( Request $request ) use ( $app, $ffFactory ) {
148
		return new Response(
149
			$ffFactory->newCommentListHtmlPresenter()->present(
150
				$ffFactory->newListCommentsUseCase()->listComments(
151
					new CommentListingRequest(
152
						10,
153
						(int)$request->query->get( 'page', '1' )
154
					)
155
				),
156
				(int)$request->query->get( 'page', '1' )
157
			)
158
		);
159
	}
160
)->bind( 'list-comments.html' );
161
162
$app->get(
163
	'page/{pageName}',
164
	function( $pageName ) use ( $ffFactory ) {
165
		$pageSelector = $ffFactory->getContentPagePageSelector();
166
167
		try {
168
			$pageId = $pageSelector->getPageId( $pageName );
169
		} catch ( PageNotFoundException $exception ) {
170
			throw new NotFoundHttpException( "Page page name '$pageName' not found." );
171
		}
172
173
		try {
174
			return $ffFactory->getLayoutTemplate( 'Display_Page_Layout.twig' )->render( [
175
				'page_id' => $pageId
176
			] );
177
		} catch ( Twig_Error_Runtime $exception ) {
178
			if ($exception->getPrevious() instanceof ContentNotFoundException) {
179
				throw new NotFoundHttpException( "Content for page id '$pageId' not found." );
180
			}
181
182
			throw $exception;
183
		}
184
	}
185
)
186
->bind( 'page' );
187
188
// Form for this is provided by route page/Subscription_Form
189
$app->match(
190
	'contact/subscribe',
191
	function( Application $app, Request $request ) use ( $ffFactory ) {
192
		return ( new AddSubscriptionHandler( $ffFactory, $app ) )
193
			->handle( $request );
194
	}
195
)
196
->method( 'GET|POST' )
197
->bind( 'subscribe' );
198
199
$app->get( 'contact/confirm-subscription/{confirmationCode}', function ( $confirmationCode ) use ( $ffFactory ) {
200
	$useCase = $ffFactory->newConfirmSubscriptionUseCase();
201
	$response = $useCase->confirmSubscription( $confirmationCode );
202
	return $ffFactory->newConfirmSubscriptionHtmlPresenter()->present( $response );
203
} )
204
->assert( 'confirmationCode', '^[0-9a-f]+$' )
205
->bind( 'confirm-subscription' );
206
207
$app->get(
208
	'check-iban',
209
	function( Request $request ) use ( $app, $ffFactory ) {
210
		$useCase = $ffFactory->newCheckIbanUseCase();
211
		$checkIbanResponse = $useCase->checkIban( new Iban( $request->query->get( 'iban', '' ) ) );
212
		return $app->json( $ffFactory->newIbanPresenter()->present( $checkIbanResponse ) );
213
	}
214
);
215
216
$app->get(
217
	'generate-iban',
218
	function( Request $request ) use ( $app, $ffFactory ) {
219
		$generateIbanRequest = new GenerateIbanRequest(
220
			$request->query->get( 'accountNumber', '' ),
221
			$request->query->get( 'bankCode', '' )
222
		);
223
224
		$generateIbanResponse = $ffFactory->newGenerateIbanUseCase()->generateIban( $generateIbanRequest );
225
		return $app->json( $ffFactory->newIbanPresenter()->present( $generateIbanResponse ) );
226
	}
227
);
228
229
$app->post(
230
	'add-comment',
231
	function( Request $request ) use ( $app, $ffFactory ) {
232
		$addCommentRequest = new AddCommentRequest();
233
		$addCommentRequest->setCommentText( trim( $request->request->get( 'kommentar', '' ) ) );
234
		$addCommentRequest->setIsPublic( $request->request->get( 'public', '0' ) === '1' );
235
		$addCommentRequest->setAuthorDisplayName( trim( $request->request->get( 'eintrag', '' ) ) );
236
		$addCommentRequest->setDonationId( (int)$request->request->get( 'sid', '' ) );
237
		$addCommentRequest->freeze()->assertNoNullFields();
238
239
		$updateToken = $request->request->get( 'utoken', '' );
240
241
		if ( $updateToken === '' ) {
242
			return $app->json( [
243
				'status' => 'ERR',
244
				'message' => $ffFactory->getTranslator()->trans( 'comment_failure_access_denied' ),
245
			] );
246
		}
247
248
		$response = $ffFactory->newAddCommentUseCase( $updateToken )->addComment( $addCommentRequest );
249
250
		if ( $response->isSuccessful() ) {
251
			return $app->json( [
252
				'status' => 'OK',
253
				'message' => $ffFactory->getTranslator()->trans( $response->getSuccessMessage() ),
254
			] );
255
		}
256
257
		return $app->json( [
258
			'status' => 'ERR',
259
			'message' => $ffFactory->getTranslator()->trans( $response->getErrorMessage() ),
260
		] );
261
	}
262
);
263
264
$app->post(
265
	'contact/get-in-touch',
266
	function( Request $request ) use ( $app, $ffFactory ) {
267
		$contactFormRequest = new GetInTouchRequest(
268
			$request->get( 'firstname', '' ),
269
			$request->get( 'lastname', '' ),
270
			$request->get( 'email', '' ),
271
			$request->get( 'subject', '' ),
272
			$request->get( 'messageBody', '' )
273
		);
274
275
		$contactFormResponse = $ffFactory->newGetInTouchUseCase()->processContactRequest( $contactFormRequest );
276
		if ( $contactFormResponse->isSuccessful() ) {
277
			return $app->redirect( $app['url_generator']->generate( 'page', [ 'pageName' => 'Kontakt_Bestaetigung' ] ) );
278
		}
279
280
		return $ffFactory->newGetInTouchHtmlPresenter()->present( $contactFormResponse, $request->request->all() );
281
	}
282
);
283
284
$app->get(
285
	'contact/get-in-touch',
286
	function() use ( $app, $ffFactory ) {
287
		return $ffFactory->getLayoutTemplate( 'contact_form.html.twig' )->render( [ ] );
288
	}
289
)->bind('contact');
290
291
$app->post(
292
	'donation/cancel',
293
	function( Request $request ) use ( $app, $ffFactory ) {
294
		$cancellationRequest = new CancelDonationRequest(
295
			(int)$request->request->get( 'sid', '' )
296
		);
297
298
		$responseModel = $ffFactory->newCancelDonationUseCase( $request->request->get( 'utoken', '' ) )
299
			->cancelDonation( $cancellationRequest );
300
301
		$httpResponse = new Response( $ffFactory->newCancelDonationHtmlPresenter()->present( $responseModel ) );
302
		if ( $responseModel->cancellationSucceeded() ) {
303
			$httpResponse->headers->clearCookie( 'donation_timestamp' );
304
		}
305
306
		return $httpResponse;
307
	}
308
);
309
310
$app->post(
311
	'donation/add',
312
	function( Application $app, Request $request ) use ( $ffFactory ) {
313
		return ( new AddDonationHandler( $ffFactory, $app ) )
314
			->handle( $request );
315
	}
316
);
317
318
// Show a donation form with pre-filled payment values, e.g. when coming from a banner
319
$app->get( 'donation/new', function ( Request $request ) use ( $ffFactory ) {
320
	try {
321
		$amount = Euro::newFromFloat( ( new AmountParser( 'en_EN' ) )->parseAsFloat(
322
			$request->get( 'betrag_auswahl', $request->get( 'amountGiven', '' ) ) )
323
		);
324
	} catch ( \InvalidArgumentException $ex ) {
325
		$amount = Euro::newFromCents( 0 );
326
	}
327
	$validationResult = $ffFactory->newPaymentDataValidator()->validate( $amount, (string) $request->get( 'zahlweise', '' ) );
328
329
	$trackingInfo = new DonationTrackingInfo();
330
	$trackingInfo->setTotalImpressionCount( intval( $request->get( 'impCount' ) ) );
331
	$trackingInfo->setSingleBannerImpressionCount( intval( $request->get( 'bImpCount' ) ) );
332
333
	// TODO: don't we want to use newDonationFormViolationPresenter when !$validationResult->isSuccessful()?
334
335
	return new Response(
336
		$ffFactory->newDonationFormPresenter()->present(
337
			$amount,
338
			$request->get( 'zahlweise', '' ),
339
			intval( $request->get( 'periode', 0 ) ),
340
			$validationResult->isSuccessful(),
341
			$trackingInfo,
342
			$request->get( 'addressType', 'person' )
343
		)
344
	);
345
} )->method( 'POST|GET' );
346
347
$app->post(
348
	'apply-for-membership',
349
	function( Application $app, Request $httpRequest ) use ( $ffFactory ) {
350
		return ( new ApplyForMembershipHandler( $ffFactory, $app ) )->handle( $httpRequest );
351
	}
352
);
353
354
$app->get(
355
	'apply-for-membership',
356
	function( Request $request ) use ( $ffFactory ) {
357
		$params = [];
358
359
		if ( $request->query->get('type' ) === 'sustaining' ) {
360
			$params['showMembershipTypeOption'] = false ;
361
		}
362
363
		return $ffFactory->getMembershipApplicationFormTemplate()->render( $params );
364
	}
365
);
366
367
$app->get(
368
	'show-membership-confirmation',
369
	function( Request $request ) use ( $ffFactory ) {
370
		$confirmationRequest = new ShowMembershipAppConfirmationRequest( (int)$request->query->get( 'id', 0 ) );
371
372
		return $ffFactory->newMembershipApplicationConfirmationHtmlPresenter()->present(
373
			$ffFactory->newMembershipApplicationConfirmationUseCase( $request->query->get( 'accessToken', '' ) )
374
				->showConfirmation( $confirmationRequest )
375
		);
376
	}
377
)->bind( 'show-membership-confirmation' );
378
379
$app->get(
380
	'cancel-membership-application',
381
	function( Request $request ) use ( $ffFactory ) {
382
		$cancellationRequest = new CancellationRequest(
383
			(int)$request->query->get( 'id', '' )
384
		);
385
386
		return $ffFactory->newCancelMembershipApplicationHtmlPresenter()->present(
387
			$ffFactory->newCancelMembershipApplicationUseCase( $request->query->get( 'updateToken', '' ) )
388
				->cancelApplication( $cancellationRequest )
389
		);
390
	}
391
);
392
393
$app->match(
394
	'show-donation-confirmation',
395
	function( Application $app, Request $request ) use ( $ffFactory ) {
396
		return ( new ShowDonationConfirmationHandler( $ffFactory ) )->handle(
397
			$request,
398
			$app['session']->get( 'piwikTracking', [] )
399
		);
400
	}
401
)->bind( 'show-donation-confirmation' )
402
->method( 'GET|POST' );
403
404
$app->post(
405
	'handle-paypal-payment-notification',
406
	function ( Request $request ) use ( $ffFactory ) {
407
		return ( new PayPalNotificationHandler( $ffFactory ) )->handle( $request );
408
	}
409
);
410
411
$app->post(
412
	'sofort-payment-notification',
413
	function ( Request $request ) use ( $ffFactory ) {
414
		return ( new SofortNotificationHandler( $ffFactory ) )->handle( $request );
415
	}
416
);
417
418
$app->get(
419
	'handle-creditcard-payment-notification',
420
	function ( Request $request ) use ( $ffFactory ) {
421
		try {
422
			$ffFactory->newCreditCardNotificationUseCase( $request->query->get( 'utoken', '' ) )
423
				->handleNotification(
424
					( new CreditCardPaymentNotificationRequest() )
425
						->setTransactionId( $request->query->get( 'transactionId', '' ) )
426
						->setDonationId( (int)$request->query->get( 'donation_id', '' ) )
427
						->setAmount( Euro::newFromCents( (int)$request->query->get( 'amount' ) ) )
428
						->setCustomerId( $request->query->get( 'customerId', '' ) )
429
						->setSessionId( $request->query->get( 'sessionId', '' ) )
430
						->setAuthId( $request->query->get(  'auth', '' ) )
431
						->setTitle( $request->query->get( 'title', '' ) )
432
						->setCountry( $request->query->get( 'country', '' ) )
433
						->setCurrency( $request->query->get( 'currency', '' ) )
434
				);
435
436
			$response = CreditCardNotificationResponse::newSuccessResponse(
437
				(int)$request->query->get( 'donation_id', '' ),
438
				$request->query->get( 'token', '' )
439
 			);
440
		} catch ( CreditCardPaymentHandlerException $e ) {
441
			$response = CreditCardNotificationResponse::newFailureResponse( $e->getMessage() );
442
		}
443
444
		return new Response( $ffFactory->newCreditCardNotificationPresenter()->present( $response ) );
445
	}
446
);
447
448
$app->get(
449
	'donation-accepted',
450
	function( Request $request ) use ( $app, $ffFactory ) {
451
452
		$eventHandler = $ffFactory->newDonationAcceptedEventHandler( $request->query->get( 'update_token', '' ) );
453
		$result = $eventHandler->onDonationAccepted( (int)$request->query->get( 'donation_id', '' ) );
454
455
		return $app->json(
456
			$result === null ? [ 'status' => 'OK' ] : [ 'status' => 'ERR', 'message' => $result ]
457
		);
458
	}
459
);
460
461
$app->post(
462
	'handle-paypal-membership-fee-payments',
463
	function ( Request $request ) use ( $ffFactory ) {
464
		return ( new PayPalNotificationHandlerForMembershipFee( $ffFactory ) )->handle( $request->request );
465
	}
466
);
467
468
$app->get( '/', function ( Application $app, Request $request ) {
469
	$app['session']->set( 'piwikTracking', array_filter(
470
			[
471
				'paymentType' => $request->get( 'zahlweise', '' ),
472
				'paymentAmount' => $request->get( 'betrag', '' ),
473
				'paymentInterval' => $request->get( 'periode', '' )
474
			],
475
			function ( string $value ) {
476
				return $value !== '' && strlen( $value ) < 20;
477
			} )
478
	);
479
480
	return $app->handle(
481
		Request::create(
482
			'/donation/new',
483
			'GET',
484
			$request->query->all(),
485
			$request->cookies->all(),
486
			[],
487
			$request->server->all()
488
		),
489
		HttpKernelInterface::SUB_REQUEST
490
	);
491
} )->bind( '/' );
492
493
// TODO Figure out how to rewrite with Nginx
494
// See https://serverfault.com/questions/805881/nginx-populate-request-uri-with-rewritten-url
495
$app->post(
496
	'/spenden/paypal_handler.php',
497
	function ( Request $request ) use ( $ffFactory ) {
498
		return ( new PayPalNotificationHandler( $ffFactory ) )->handle( $request );
499
	}
500
);
501
502
// redirect display page requests from old URLs
503
$app->get( '/spenden/{page}', function( Application $app, Request $request, string $page ) {
504
	// Poor man's rewrite until someone has figured out how to do this with Nginx without breaking REQUEST_URI
505
	// See https://serverfault.com/questions/805881/nginx-populate-request-uri-with-rewritten-url
506
	switch ( $page ) {
507
		case 'Mitgliedschaft':
508
			return ( new RouteRedirectionHandler( $app, $request->getQueryString() ) )->handle( '/page/Membership_Application' );
509
		default:
510
			return ( new RouteRedirectionHandler( $app, $request->getQueryString() ) )->handle( '/page/' . $page );
511
	}
512
} )->assert( 'page', '[a-zA-Z_\-\s\x7f-\xff]+' );
513
514
// redirect different formats of comment lists
515
$app->get( '/spenden/{outputFormat}.php', function( Application $app, Request $request, string $outputFormat ) {
516
	return ( new RouteRedirectionHandler( $app, $request->getQueryString() ) )->handle(
517
		'/list-comments.' . ( $outputFormat === 'list' ? 'html' : $outputFormat )
518
	);
519
} )->assert( 'outputFormat', 'list|rss|json' );
520
521
// redirect all other calls to default route
522
$app->get( '/spenden{page}', function( Application $app, Request $request ) {
523
	return ( new RouteRedirectionHandler( $app, $request->getQueryString() ) )->handle( '/' );
524
} )->assert( 'page', '/?([a-z]+\.php)?' );
525
526
$app->get( '/purge-cache', function( Request $request ) use ( $ffFactory ) {
527
	$response = $ffFactory->newAuthorizedCachePurger()->purgeCache( $request->query->get( 'secret', '' ) );
528
529
	return new Response(
530
		[
531
			AuthorizedCachePurger::RESULT_SUCCESS => 'SUCCESS',
532
			AuthorizedCachePurger::RESULT_ERROR => 'ERROR',
533
			AuthorizedCachePurger::RESULT_ACCESS_DENIED=> 'ACCESS DENIED'
534
		][$response]
535
	);
536
} );
537
538
$app->get( 'status', function() {
539
	return 'Status: OK (Online)';
540
} );
541
542
return $app;
543