Completed
Push — master ( 4b187e...d8fefd )
by Jeroen De
04:05
created

newMembershipApplicationConfirmationUseCase()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 6
rs 9.4285
c 0
b 0
f 0
cc 1
eloc 4
nc 1
nop 1
1
<?php
2
3
declare( strict_types = 1 );
4
5
namespace WMDE\Fundraising\Frontend\Factories;
6
7
use Doctrine\DBAL\Connection;
8
use Doctrine\DBAL\DriverManager;
9
use Doctrine\ORM\EntityManager;
10
use GuzzleHttp\Client;
11
use GuzzleHttp\ClientInterface;
12
use GuzzleHttp\Handler\CurlHandler;
13
use GuzzleHttp\HandlerStack;
14
use Mediawiki\Api\ApiUser;
15
use Mediawiki\Api\Guzzle\MiddlewareFactory;
16
use Mediawiki\Api\MediawikiApi;
17
use Monolog\Formatter\JsonFormatter;
18
use Monolog\Formatter\LineFormatter;
19
use Monolog\Handler\BufferHandler;
20
use Monolog\Handler\StreamHandler;
21
use Monolog\Logger;
22
use NumberFormatter;
23
use Psr\Log\LoggerInterface;
24
use Swift_MailTransport;
25
use Swift_NullTransport;
26
use Symfony\Component\Translation\TranslatorInterface;
27
use TNvpServiceDispatcher;
28
use Twig_Environment;
29
use Twig_Extensions_Extension_Intl;
30
use WMDE\Fundraising\Frontend\DataAccess\ApiBasedPageRetriever;
31
use WMDE\Fundraising\Frontend\DataAccess\DoctrineCommentFinder;
32
use WMDE\Fundraising\Frontend\DataAccess\DoctrineDonationAuthorizer;
33
use WMDE\Fundraising\Frontend\DataAccess\DoctrineDonationEventLogger;
34
use WMDE\Fundraising\Frontend\DataAccess\DoctrineDonationPrePersistSubscriber;
35
use WMDE\Fundraising\Frontend\DataAccess\DoctrineDonationRepository;
36
use WMDE\Fundraising\Frontend\DataAccess\DoctrineDonationTokenFetcher;
37
use WMDE\Fundraising\Frontend\DataAccess\DoctrineMembershipApplicationAuthorizer;
38
use WMDE\Fundraising\Frontend\DataAccess\DoctrineMembershipApplicationPrePersistSubscriber;
39
use WMDE\Fundraising\Frontend\DataAccess\DoctrineMembershipApplicationRepository;
40
use WMDE\Fundraising\Frontend\DataAccess\DoctrineMembershipApplicationTokenFetcher;
41
use WMDE\Fundraising\Frontend\DataAccess\DoctrineMembershipApplicationTracker;
42
use WMDE\Fundraising\Frontend\DataAccess\DoctrineSubscriptionRepository;
43
use WMDE\Fundraising\Frontend\DataAccess\InternetDomainNameValidator;
44
use WMDE\Fundraising\Frontend\DataAccess\McpCreditCardService;
45
use WMDE\Fundraising\Frontend\DataAccess\UniqueTransferCodeGenerator;
46
use WMDE\Fundraising\Frontend\Domain\BankDataConverter;
47
use WMDE\Fundraising\Frontend\Domain\CommentFinder;
48
use WMDE\Fundraising\Frontend\Domain\Model\EmailAddress;
49
use WMDE\Fundraising\Frontend\Domain\Model\PaymentType;
50
use WMDE\Fundraising\Frontend\Domain\ReferrerGeneralizer;
51
use WMDE\Fundraising\Frontend\Domain\Repositories\DonationRepository;
52
use WMDE\Fundraising\Frontend\Domain\Repositories\MembershipApplicationRepository;
53
use WMDE\Fundraising\Frontend\Domain\Repositories\SubscriptionRepository;
54
use WMDE\Fundraising\Frontend\Domain\SimpleTransferCodeGenerator;
55
use WMDE\Fundraising\Frontend\Domain\TransferCodeGenerator;
56
use WMDE\Fundraising\Frontend\Infrastructure\BestEffortDonationEventLogger;
57
use WMDE\Fundraising\Frontend\Infrastructure\CreditCardService;
58
use WMDE\Fundraising\Frontend\Infrastructure\DonationAuthorizer;
59
use WMDE\Fundraising\Frontend\Infrastructure\DonationConfirmationMailer;
60
use WMDE\Fundraising\Frontend\Infrastructure\DonationEventLogger;
61
use WMDE\Fundraising\Frontend\Infrastructure\DonationTokenFetcher;
62
use WMDE\Fundraising\Frontend\Infrastructure\Honorifics;
63
use WMDE\Fundraising\Frontend\Infrastructure\LoggingMailer;
64
use WMDE\Fundraising\Frontend\Infrastructure\LoggingPaymentNotificationVerifier;
65
use WMDE\Fundraising\Frontend\Infrastructure\MembershipApplicationAuthorizer;
66
use WMDE\Fundraising\Frontend\Infrastructure\MembershipApplicationTokenFetcher;
67
use WMDE\Fundraising\Frontend\Infrastructure\MembershipApplicationTracker;
68
use WMDE\Fundraising\Frontend\Infrastructure\Messenger;
69
use WMDE\Fundraising\Frontend\Infrastructure\PageRetriever;
70
use WMDE\Fundraising\Frontend\Infrastructure\PaymentNotificationVerifier;
71
use WMDE\Fundraising\Frontend\Infrastructure\PayPalPaymentNotificationVerifier;
72
use WMDE\Fundraising\Frontend\Infrastructure\RandomTokenGenerator;
73
use WMDE\Fundraising\Frontend\Infrastructure\Repositories\LoggingCommentFinder;
74
use WMDE\Fundraising\Frontend\Infrastructure\Repositories\LoggingDonationRepository;
75
use WMDE\Fundraising\Frontend\Infrastructure\Repositories\LoggingMembershipApplicationRepository;
76
use WMDE\Fundraising\Frontend\Infrastructure\Repositories\LoggingSubscriptionRepository;
77
use WMDE\Fundraising\Frontend\Infrastructure\TemplateBasedMailer;
78
use WMDE\Fundraising\Frontend\Infrastructure\TokenGenerator;
79
use WMDE\Fundraising\Frontend\Presentation\AmountFormatter;
80
use WMDE\Fundraising\Frontend\Presentation\Content\PageContentModifier;
81
use WMDE\Fundraising\Frontend\Presentation\Content\WikiContentProvider;
82
use WMDE\Fundraising\Frontend\Presentation\CreditCardUrlConfig;
83
use WMDE\Fundraising\Frontend\Presentation\CreditCardUrlGenerator;
84
use WMDE\Fundraising\Frontend\Presentation\DonationConfirmationPageSelector;
85
use WMDE\Fundraising\Frontend\Presentation\GreetingGenerator;
86
use WMDE\Fundraising\Frontend\Presentation\PayPalUrlConfig;
87
use WMDE\Fundraising\Frontend\Presentation\PayPalUrlGenerator;
88
use WMDE\Fundraising\Frontend\Presentation\Presenters\AddSubscriptionHtmlPresenter;
89
use WMDE\Fundraising\Frontend\Presentation\Presenters\AddSubscriptionJsonPresenter;
90
use WMDE\Fundraising\Frontend\Presentation\Presenters\CancelDonationHtmlPresenter;
91
use WMDE\Fundraising\Frontend\Presentation\Presenters\CancelMembershipApplicationHtmlPresenter;
92
use WMDE\Fundraising\Frontend\Presentation\Presenters\CommentListHtmlPresenter;
93
use WMDE\Fundraising\Frontend\Presentation\Presenters\CommentListJsonPresenter;
94
use WMDE\Fundraising\Frontend\Presentation\Presenters\CommentListRssPresenter;
95
use WMDE\Fundraising\Frontend\Presentation\Presenters\ConfirmSubscriptionHtmlPresenter;
96
use WMDE\Fundraising\Frontend\Presentation\Presenters\CreditCardNotificationPresenter;
97
use WMDE\Fundraising\Frontend\Presentation\Presenters\CreditCardPaymentHtmlPresenter;
98
use WMDE\Fundraising\Frontend\Presentation\Presenters\DisplayPagePresenter;
99
use WMDE\Fundraising\Frontend\Presentation\Presenters\DonationConfirmationHtmlPresenter;
100
use WMDE\Fundraising\Frontend\Presentation\Presenters\DonationFormViolationPresenter;
101
use WMDE\Fundraising\Frontend\Presentation\Presenters\GetInTouchHtmlPresenter;
102
use WMDE\Fundraising\Frontend\Presentation\Presenters\IbanPresenter;
103
use WMDE\Fundraising\Frontend\Presentation\Presenters\InternalErrorHtmlPresenter;
104
use WMDE\Fundraising\Frontend\Presentation\Presenters\MembershipApplicationConfirmationHtmlPresenter;
105
use WMDE\Fundraising\Frontend\Presentation\Presenters\MembershipFormViolationPresenter;
106
use WMDE\Fundraising\Frontend\Presentation\TwigTemplate;
107
use WMDE\Fundraising\Frontend\UseCases\AddComment\AddCommentUseCase;
108
use WMDE\Fundraising\Frontend\UseCases\AddDonation\AddDonationUseCase;
109
use WMDE\Fundraising\Frontend\UseCases\AddSubscription\AddSubscriptionUseCase;
110
use WMDE\Fundraising\Frontend\UseCases\ApplyForMembership\ApplyForMembershipUseCase;
111
use WMDE\Fundraising\Frontend\UseCases\ApplyForMembership\MembershipApplicationValidator;
112
use WMDE\Fundraising\Frontend\UseCases\CancelDonation\CancelDonationUseCase;
113
use WMDE\Fundraising\Frontend\UseCases\CancelMembershipApplication\CancelMembershipApplicationUseCase;
114
use WMDE\Fundraising\Frontend\UseCases\CheckIban\CheckIbanUseCase;
115
use WMDE\Fundraising\Frontend\UseCases\ConfirmSubscription\ConfirmSubscriptionUseCase;
116
use WMDE\Fundraising\Frontend\UseCases\CreditCardPaymentNotification\CreditCardNotificationResponse;
117
use WMDE\Fundraising\Frontend\UseCases\CreditCardPaymentNotification\CreditCardNotificationUseCase;
118
use WMDE\Fundraising\Frontend\UseCases\DisplayPage\DisplayPageUseCase;
119
use WMDE\Fundraising\Frontend\UseCases\GenerateIban\GenerateIbanUseCase;
120
use WMDE\Fundraising\Frontend\UseCases\GetInTouch\GetInTouchUseCase;
121
use WMDE\Fundraising\Frontend\UseCases\HandlePayPalPaymentNotification\HandlePayPalPaymentNotificationUseCase;
122
use WMDE\Fundraising\Frontend\UseCases\ListComments\ListCommentsUseCase;
123
use WMDE\Fundraising\Frontend\UseCases\ShowDonationConfirmation\ShowDonationConfirmationUseCase;
124
use WMDE\Fundraising\Frontend\UseCases\ShowMembershipApplicationConfirmation\ShowMembershipApplicationConfirmationUseCase;
125
use WMDE\Fundraising\Frontend\Validation\AllowedValuesValidator;
126
use WMDE\Fundraising\Frontend\Validation\AmountPolicyValidator;
127
use WMDE\Fundraising\Frontend\Validation\AmountValidator;
128
use WMDE\Fundraising\Frontend\Validation\BankDataValidator;
129
use WMDE\Fundraising\Frontend\Validation\DonationValidator;
130
use WMDE\Fundraising\Frontend\Validation\EmailValidator;
131
use WMDE\Fundraising\Frontend\Validation\GetInTouchValidator;
132
use WMDE\Fundraising\Frontend\Validation\IbanValidator;
133
use WMDE\Fundraising\Frontend\Validation\MembershipFeeValidator;
134
use WMDE\Fundraising\Frontend\Validation\PersonalInfoValidator;
135
use WMDE\Fundraising\Frontend\Validation\PersonNameValidator;
136
use WMDE\Fundraising\Frontend\Validation\PhysicalAddressValidator;
137
use WMDE\Fundraising\Frontend\Validation\SubscriptionDuplicateValidator;
138
use WMDE\Fundraising\Frontend\Validation\SubscriptionValidator;
139
use WMDE\Fundraising\Frontend\Validation\TemplateNameValidator;
140
use WMDE\Fundraising\Frontend\Validation\TextPolicyValidator;
141
use WMDE\Fundraising\Store\Factory as StoreFactory;
142
use WMDE\Fundraising\Store\Installer;
143
144
/**
145
 * @licence GNU GPL v2+
146
 */
147
class FunFunFactory {
148
149
	private $config;
150
151
	/**
152
	 * @var \Pimple
153
	 */
154
	private $pimple;
155
	private $tokenGenerator;
156
	private $addDoctrineSubscribers = true;
157
158
	public function __construct( array $config ) {
159
		$this->config = $config;
160
		$this->pimple = $this->newPimple();
161
	}
162
163
	private function newPimple(): \Pimple {
164
		$pimple = new \Pimple();
165
166
		$pimple['dbal_connection'] = $pimple->share( function() {
167
			return DriverManager::getConnection( $this->config['db'] );
168
		} );
169
170
		$pimple['entity_manager'] = $pimple->share( function() {
171
			$entityManager = ( new StoreFactory( $this->getConnection() ) )->getEntityManager();
172
			if ( $this->addDoctrineSubscribers ) {
173
				$entityManager->getEventManager()->addEventSubscriber( $this->newDoctrineDonationPrePersistSubscriber() );
174
				$entityManager->getEventManager()->addEventSubscriber( $this->newDoctrineMembershipApplicationPrePersistSubscriber() );
175
			}
176
177
			return $entityManager;
178
		} );
179
180
		$pimple['subscription_repository'] = $pimple->share( function() {
181
			return new LoggingSubscriptionRepository(
182
				new DoctrineSubscriptionRepository( $this->getEntityManager() ),
183
				$this->getLogger()
184
			);
185
		} );
186
187
		$pimple['donation_repository'] = $pimple->share( function() {
188
			return new LoggingDonationRepository(
189
				new DoctrineDonationRepository( $this->getEntityManager() ),
190
				$this->getLogger()
191
			);
192
		} );
193
194
		$pimple['membership_application_repository'] = $pimple->share( function() {
195
			return new LoggingMembershipApplicationRepository(
196
				new DoctrineMembershipApplicationRepository( $this->getEntityManager() ),
197
				$this->getLogger()
198
			);
199
		} );
200
201
		$pimple['comment_repository'] = $pimple->share( function() {
202
			return new LoggingCommentFinder(
203
				new DoctrineCommentFinder( $this->getEntityManager() ),
204
				$this->getLogger()
205
			);
206
		} );
207
208
		$pimple['mail_validator'] = $pimple->share( function() {
209
			return new EmailValidator( new InternetDomainNameValidator() );
210
		} );
211
212
		$pimple['subscription_validator'] = $pimple->share( function() {
213
			return new SubscriptionValidator(
214
				$this->getEmailValidator(),
215
				$this->getTextPolicyValidator( 'fields' ),
216
				$this->newSubscriptionDuplicateValidator(),
217
				$this->newHonorificValidator()
218
			);
219
		} );
220
221
		$pimple['template_name_validator'] = $pimple->share( function() {
222
			return new TemplateNameValidator( $this->getTwig() );
223
		} );
224
225
		$pimple['contact_validator'] = $pimple->share( function() {
226
			return new GetInTouchValidator( $this->getEmailValidator() );
227
		} );
228
229
		$pimple['greeting_generator'] = $pimple->share( function() {
230
			return new GreetingGenerator();
231
		} );
232
233
		$pimple['mw_api'] = $pimple->share( function() {
234
			return new MediawikiApi(
235
				$this->config['cms-wiki-api-url'],
236
				$this->getGuzzleClient()
237
			);
238
		} );
239
240
		$pimple['guzzle_client'] = $pimple->share( function() {
241
			$middlewareFactory = new MiddlewareFactory();
242
			$middlewareFactory->setLogger( $this->getLogger() );
243
244
			$handlerStack = HandlerStack::create( new CurlHandler() );
245
			$handlerStack->push( $middlewareFactory->retry() );
246
247
			return new Client( [
248
				'cookies' => true,
249
				'handler' => $handlerStack,
250
				'headers' => [ 'User-Agent' => 'WMDE Fundraising Frontend' ],
251
			] );
252
		} );
253
254
		$pimple['translator'] = $pimple->share( function() {
255
			$translationFactory = new TranslationFactory();
256
			$loaders = [
257
				'json' => $translationFactory->newJsonLoader()
258
			];
259
			$locale = $this->config['locale'];
260
			$translator = $translationFactory->create( $loaders, $locale );
261
			$translator->addResource( 'json', __DIR__ . '/../../app/translations/messages.' . $locale . '.json', $locale );
262
			$translator->addResource(
263
				'json',
264
				__DIR__ . '/../../app/translations/paymentTypes.' . $locale . '.json',
265
				$locale,
266
				'paymentTypes'
267
			);
268
			$translator->addResource(
269
				'json',
270
				__DIR__ . '/../../app/translations/paymentIntervals.' . $locale . '.json',
271
				$locale,
272
				'paymentIntervals'
273
			);
274
			$translator->addResource( 'json', __DIR__ . '/../../app/translations/validations.' . $locale . '.json', $locale,
275
				'validations' );
276
			return $translator;
277
		} );
278
279
		// In the future, this could be locale-specific or filled from a DB table
280
		$pimple['honorifics'] = $pimple->share( function() {
281
			return new Honorifics( [
282
				'' => 'Kein Titel',
283
				'Dr.' => 'Dr.',
284
				'Prof.' => 'Prof.',
285
				'Prof. Dr.' => 'Prof. Dr.'
286
			] );
287
		} );
288
289
		$pimple['twig_factory'] = $pimple->share( function () {
290
			return new TwigFactory( $this->config['twig'] );
291
		} );
292
293
		$pimple['twig'] = $pimple->share( function() {
294
			$twigFactory = $this->getTwigFactory();
295
			$loaders = array_filter( [
296
				$twigFactory->newFileSystemLoader(),
297
				$twigFactory->newArrayLoader(), // This is just a fallback for testing
298
				$twigFactory->newWikiPageLoader( $this->newWikiContentProvider() ),
299
			] );
300
			$extensions = [
301
				$twigFactory->newTranslationExtension( $this->getTranslator() ),
302
				new Twig_Extensions_Extension_Intl()
303
			];
304
			return $twigFactory->create( $loaders, $extensions );
305
		} );
306
307
		$pimple['logger'] = $pimple->share( function() {
308
			$logger = new Logger( 'WMDE Fundraising Frontend logger' );
309
310
			$streamHandler = new StreamHandler( $this->newLoggerPath( ( new \DateTime() )->format( 'Y-m-d\TH:i:s\Z' ) ) );
311
			$bufferHandler = new BufferHandler( $streamHandler, 500, Logger::DEBUG, true, true );
312
			$streamHandler->setFormatter( new LineFormatter( "%message%\n" ) );
313
			$logger->pushHandler( $bufferHandler );
314
315
			$errorHandler = new StreamHandler( $this->newLoggerPath( 'error' ), Logger::ERROR );
316
			$errorHandler->setFormatter( new JsonFormatter() );
317
			$logger->pushHandler( $errorHandler );
318
319
			return $logger;
320
		} );
321
322
		$pimple['messenger'] = $pimple->share( function() {
323
			return new Messenger(
324
				new Swift_MailTransport(),
325
				$this->getOperatorAddress(),
326
				$this->config['operator-displayname']
327
			);
328
		} );
329
330
		$pimple['confirmation-page-selector'] = $pimple->share( function() {
331
			return new DonationConfirmationPageSelector( $this->config['confirmation-pages'] );
332
		} );
333
334
		$pimple['paypal-payment-notification-verifier'] = $pimple->share( function() {
335
			return new LoggingPaymentNotificationVerifier(
336
				new PayPalPaymentNotificationVerifier(
337
					new Client(),
338
					$this->config['paypal']
339
				),
340
				$this->getLogger()
341
			);
342
		} );
343
344
		$pimple['credit-card-api-service'] = $pimple->share( function() {
345
			return new McpCreditCardService(
346
				new TNvpServiceDispatcher(
347
					'IMcpCreditcardService_v1_5',
348
					'https://sipg.micropayment.de/public/creditcard/v1.5/nvp/'
349
				),
350
				$this->config['creditcard']['access-key'],
351
				$this->config['creditcard']['testmode']
352
			);
353
		} );
354
355
		return $pimple;
356
	}
357
358
	public function getConnection(): Connection {
359
		return $this->pimple['dbal_connection'];
360
	}
361
362
	public function getEntityManager(): EntityManager {
363
		return $this->pimple['entity_manager'];
364
	}
365
366
	private function newDonationEventLogger(): DonationEventLogger {
367
		return new BestEffortDonationEventLogger(
368
			new DoctrineDonationEventLogger( $this->getEntityManager() ),
369
			$this->getLogger()
370
		);
371
	}
372
373
	public function newInstaller(): Installer {
374
		return ( new StoreFactory( $this->getConnection() ) )->newInstaller();
375
	}
376
377
	public function newListCommentsUseCase(): ListCommentsUseCase {
378
		return new ListCommentsUseCase( $this->getCommentFinder() );
379
	}
380
381
	public function newCommentListJsonPresenter(): CommentListJsonPresenter {
382
		return new CommentListJsonPresenter();
383
	}
384
385
	public function newCommentListRssPresenter(): CommentListRssPresenter {
386
		return new CommentListRssPresenter( new TwigTemplate(
387
			$this->getTwig(),
388
			'CommentList.rss.twig'
389
		) );
390
	}
391
392
	public function newCommentListHtmlPresenter(): CommentListHtmlPresenter {
393
		return new CommentListHtmlPresenter( $this->getLayoutTemplate( 'CommentList.html.twig' ) );
394
	}
395
396
	private function getCommentFinder(): CommentFinder {
397
		return $this->pimple['comment_repository'];
398
	}
399
400
	public function getSubscriptionRepository(): SubscriptionRepository {
401
		return $this->pimple['subscription_repository'];
402
	}
403
404
	public function setSubscriptionRepository( SubscriptionRepository $subscriptionRepository ) {
405
		$this->pimple['subscription_repository'] = $subscriptionRepository;
406
	}
407
408
	private function getSubscriptionValidator(): SubscriptionValidator {
409
		return $this->pimple['subscription_validator'];
410
	}
411
412
	public function getEmailValidator(): EmailValidator {
413
		return $this->pimple['mail_validator'];
414
	}
415
416
	private function getTemplateNameValidator(): TemplateNameValidator {
417
		return $this->pimple['template_name_validator'];
418
	}
419
420
	public function newDisplayPageUseCase(): DisplayPageUseCase {
421
		return new DisplayPageUseCase(
422
			$this->getTemplateNameValidator()
423
		);
424
	}
425
426
	public function newDisplayPagePresenter(): DisplayPagePresenter {
427
		return new DisplayPagePresenter( $this->getLayoutTemplate( 'DisplayPageLayout.twig' ) );
428
	}
429
430
	public function newAddSubscriptionHTMLPresenter(): AddSubscriptionHtmlPresenter {
431
		return new AddSubscriptionHtmlPresenter( $this->getIncludeTemplate( 'Subscription_Form.twig' ), $this->getTranslator() );
432
	}
433
434
	public function newConfirmSubscriptionHtmlPresenter(): ConfirmSubscriptionHtmlPresenter {
435
		return new ConfirmSubscriptionHtmlPresenter(
436
			$this->getLayoutTemplate( 'ConfirmSubscription.html.twig' ),
437
			$this->getTranslator()
438
		);
439
	}
440
441
	public function newAddSubscriptionJSONPresenter(): AddSubscriptionJsonPresenter {
442
		return new AddSubscriptionJsonPresenter( $this->getTranslator() );
443
	}
444
445
	public function newGetInTouchHTMLPresenter(): GetInTouchHtmlPresenter {
446
		return new GetInTouchHtmlPresenter( $this->getIncludeTemplate( 'Kontaktformular.twig' ), $this->getTranslator() );
447
	}
448
449
	public function getTwig(): Twig_Environment {
450
		return $this->pimple['twig'];
451
	}
452
453
	/**
454
	 * Get a template, with the content for the layout areas filled in.
455
	 *
456
	 * @param string $templateName
457
	 * @return TwigTemplate
458
	 */
459
	private function getLayoutTemplate( string $templateName ): TwigTemplate {
460
		 return new TwigTemplate(
461
			$this->getTwig(),
462
			$templateName,
463
			$this->getDefaultTwigVariables()
464
		);
465
	}
466
467
	/**
468
	 * Get a layouted template that includes another template
469
	 *
470
	 * @param string $templateName Template to include
471
	 * @return TwigTemplate
472
	 */
473
	private function getIncludeTemplate( string $templateName ): TwigTemplate {
474
		return new TwigTemplate(
475
			$this->getTwig(),
476
			'IncludeInLayout.twig',
477
			array_merge(
478
				$this->getDefaultTwigVariables(),
479
				[ 'main_template' => $templateName]
480
			)
481
		);
482
	}
483
484
	private function getDefaultTwigVariables() {
485
		return [
486
			'basepath' => $this->config['web-basepath'],
487
			'honorifics' => $this->getHonorifics()->getList(),
488
			'header_template' => $this->config['default-layout-templates']['header'],
489
			'footer_template' => $this->config['default-layout-templates']['footer'],
490
			'no_js_notice_template' => $this->config['default-layout-templates']['no-js-notice'],
491
		];
492
	}
493
494
	private function newReferrerGeneralizer() {
495
		return new ReferrerGeneralizer(
496
			$this->config['referrer-generalization']['default'],
497
			$this->config['referrer-generalization']['domain-map']
498
		);
499
	}
500
501
	private function newPageRetriever(): PageRetriever {
502
		return new ApiBasedPageRetriever(
503
			$this->getMediaWikiApi(),
504
			new ApiUser( $this->config['cms-wiki-user'], $this->config['cms-wiki-password'] ),
505
			$this->getLogger()
506
		);
507
	}
508
509
	private function getMediaWikiApi(): MediawikiApi {
510
		return $this->pimple['mw_api'];
511
	}
512
513
	public function setMediaWikiApi( MediawikiApi $api ) {
514
		$this->pimple['mw_api'] = $api;
515
	}
516
517
	private function getGuzzleClient(): ClientInterface {
518
		return $this->pimple['guzzle_client'];
519
	}
520
521
	private function newWikiContentProvider() {
522
		return new WikiContentProvider(
523
			$this->newPageRetriever(),
524
			$this->newPageContentModifier(),
525
			$this->config['cms-wiki-title-prefix']
526
		);
527
	}
528
529
	public function getLogger(): LoggerInterface {
530
		return $this->pimple['logger'];
531
	}
532
533
	private function newLoggerPath( string $fileName ): string {
534
		return __DIR__ . '/../../var/log/' . $fileName . '.log';
535
	}
536
537
	private function newPageContentModifier(): PageContentModifier {
538
		return new PageContentModifier(
539
			$this->getLogger()
540
		);
541
	}
542
543
	public function newAddSubscriptionUseCase(): AddSubscriptionUseCase {
544
		return new AddSubscriptionUseCase(
545
			$this->getSubscriptionRepository(),
546
			$this->getSubscriptionValidator(),
547
			$this->newAddSubscriptionMailer()
548
		);
549
	}
550
551
	public function newConfirmSubscriptionUseCase(): ConfirmSubscriptionUseCase {
552
		return new ConfirmSubscriptionUseCase(
553
			$this->getSubscriptionRepository(),
554
			$this->newConfirmSubscriptionMailer()
555
		);
556
	}
557
558
	private function newAddSubscriptionMailer(): TemplateBasedMailer {
559
		return $this->newTemplateMailer(
560
			new TwigTemplate(
561
				$this->getTwig(),
562
				'Mail_Subscription_Request.twig',
563
				[
564
					'basepath' => $this->config['web-basepath'],
565
					'greeting_generator' => $this->getGreetingGenerator()
566
				]
567
			),
568
			'mail_subject_membership'
569
		);
570
	}
571
572
	private function newConfirmSubscriptionMailer(): TemplateBasedMailer {
573
		return $this->newTemplateMailer(
574
			new TwigTemplate(
575
					$this->getTwig(),
576
					'Mail_Subscription_Confirmation.twig',
577
					[ 'greeting_generator' => $this->getGreetingGenerator() ]
578
			),
579
			'mail_subject_membership'
580
		);
581
	}
582
583
	private function newTemplateMailer( TwigTemplate $template, string $messageKey ): TemplateBasedMailer {
584
		$mailer = new TemplateBasedMailer(
585
			$this->getMessenger(),
586
			$template,
587
			$this->getTranslator()->trans( $messageKey )
588
		);
589
590
		return new LoggingMailer( $mailer, $this->getLogger() );
591
	}
592
593
	public function getGreetingGenerator() {
594
		return $this->pimple['greeting_generator'];
595
	}
596
597
	public function newCheckIbanUseCase(): CheckIbanUseCase {
598
		return new CheckIbanUseCase( $this->newBankDataConverter() );
599
	}
600
601
	public function newGenerateIbanUseCase(): GenerateIbanUseCase {
602
		return new GenerateIbanUseCase( $this->newBankDataConverter() );
603
	}
604
605
	public function newIbanPresenter(): IbanPresenter {
606
		return new IbanPresenter();
607
	}
608
609
	public function newBankDataConverter() {
610
		return new BankDataConverter( $this->config['bank-data-file'] );
611
	}
612
613
	public function setSubscriptionValidator( SubscriptionValidator $subscriptionValidator ) {
614
		$this->pimple['subscription_validator'] = $subscriptionValidator;
615
	}
616
617
	public function setPageTitlePrefix( string $prefix ) {
618
		$this->config['cms-wiki-title-prefix'] = $prefix;
619
	}
620
621
	public function newGetInTouchUseCase() {
622
		return new GetInTouchUseCase(
623
			$this->getContactValidator(),
624
			$this->getMessenger(),
625
			$this->newContactConfirmationMailer()
626
		);
627
	}
628
629
	private function newContactConfirmationMailer(): TemplateBasedMailer {
630
		return $this->newTemplateMailer(
631
			new TwigTemplate( $this->getTwig(), 'KontaktMailExtern.twig' ),
632
			'mail_subject_getintouch'
633
		);
634
	}
635
636
	private function getContactValidator(): GetInTouchValidator {
637
		return $this->pimple['contact_validator'];
638
	}
639
640
	private function newSubscriptionDuplicateValidator(): SubscriptionDuplicateValidator {
641
		return new SubscriptionDuplicateValidator(
642
				$this->getSubscriptionRepository(),
643
				$this->newSubscriptionDuplicateCutoffDate()
644
		);
645
	}
646
647
	private function newSubscriptionDuplicateCutoffDate(): \DateTime {
648
		$cutoffDateTime = new \DateTime();
649
		$cutoffDateTime->sub( new \DateInterval( $this->config['subscription-interval'] ) );
650
		return $cutoffDateTime;
651
	}
652
653
	private function newHonorificValidator(): AllowedValuesValidator {
654
		return new AllowedValuesValidator( $this->getHonorifics()->getKeys() );
655
	}
656
657
	private function getHonorifics(): Honorifics {
658
		return $this->pimple['honorifics'];
659
	}
660
661
	private function newPaymentTypeValidator(): AllowedValuesValidator {
662
		return new AllowedValuesValidator( PaymentType::getPaymentTypes() );
663
	}
664
665
	private function newBankDataValidator(): BankDataValidator {
666
		return new BankDataValidator( new IbanValidator( $this->newBankDataConverter() ) );
667
	}
668
669
	private function getMessenger(): Messenger {
670
		return $this->pimple['messenger'];
671
	}
672
673
	public function setMessenger( Messenger $messenger ) {
674
		$this->pimple['messenger'] = $messenger;
675
	}
676
677
	public function setNullMessenger() {
678
		$this->setMessenger( new Messenger(
679
			Swift_NullTransport::newInstance(),
680
			$this->getOperatorAddress()
681
		) );
682
	}
683
684
	public function getOperatorAddress() {
685
		return new EmailAddress( $this->config['operator-email'] );
686
	}
687
688
	public function newInternalErrorHTMLPresenter(): InternalErrorHtmlPresenter {
689
		return new InternalErrorHtmlPresenter( $this->getIncludeTemplate( 'ErrorPage.twig' ) );
690
	}
691
692
	public function newAccessDeniedHTMLPresenter(): InternalErrorHtmlPresenter {
693
		return new InternalErrorHtmlPresenter( $this->getLayoutTemplate( 'AccessDenied.twig' ) );
694
	}
695
696
	public function getTranslator(): TranslatorInterface {
697
		return $this->pimple['translator'];
698
	}
699
700
	public function setTranslator( TranslatorInterface $translator ) {
701
		$this->pimple['translator'] = $translator;
702
	}
703
704
	private function getTwigFactory(): TwigFactory {
705
		return $this->pimple['twig_factory'];
706
	}
707
708
	private function getTextPolicyValidator( $policyName ) {
709
		$policyValidator = new TextPolicyValidator();
710
711
		$contentProvider = $this->newWikiContentProvider();
712
		$textPolicyConfig = $this->config['text-policies'][$policyName];
713
714
		// TODO: this is not the place to retrieve resources over the network
715
		$policyValidator->addBadWordsFromArray( $this->loadWordsFromWiki(
716
			$contentProvider,
717
			$textPolicyConfig['badwords'] ?? ''
718
		) );
719
		$policyValidator->addWhiteWordsFromArray( $this->loadWordsFromWiki(
720
			$contentProvider,
721
			$textPolicyConfig['whitewords'] ?? ''
722
		) );
723
724
		return $policyValidator;
725
	}
726
727
	private function loadWordsFromWiki( WikiContentProvider $contentProvider, string $pageName ): array {
728
		if ( $pageName === '' ) {
729
			return [ ];
730
		}
731
		$content = $contentProvider->getContent( $pageName, 'raw' );
732
		$words = array_map( 'trim', explode( "\n", $content ) );
733
734
		return array_filter( $words );
735
	}
736
737
	public function newCancelDonationUseCase( string $updateToken ): CancelDonationUseCase {
738
		return new CancelDonationUseCase(
739
			$this->getDonationRepository(),
740
			$this->newCancelDonationMailer(),
741
			$this->newDonationAuthorizer( $updateToken )
742
		);
743
	}
744
745
	private function newCancelDonationMailer(): TemplateBasedMailer {
746
		return $this->newTemplateMailer(
747
			new TwigTemplate(
748
				$this->getTwig(),
749
				'Mail_Donation_Cancellation_Confirmation.twig',
750
				[ 'greeting_generator' => $this->getGreetingGenerator() ]
751
			),
752
			'mail_subject_confirm_cancellation'
753
		);
754
	}
755
756
	public function newAddDonationUseCase(): AddDonationUseCase {
757
		return new AddDonationUseCase(
758
			$this->getDonationRepository(),
759
			$this->newDonationValidator(),
760
			$this->newReferrerGeneralizer(),
761
			$this->newDonationConfirmationMailer(),
762
			$this->newBankTransferCodeGenerator(),
763
			$this->newBankDataConverter(),
764
			$this->newDonationTokenFetcher()
765
		);
766
	}
767
768
	private function newBankTransferCodeGenerator(): TransferCodeGenerator {
769
		return new UniqueTransferCodeGenerator(
770
			new SimpleTransferCodeGenerator(),
771
			$this->getEntityManager()
772
		);
773
	}
774
775
	private function newDonationValidator(): DonationValidator {
776
		return new DonationValidator(
777
			$this->newAmountValidator(),
778
			new AmountPolicyValidator( 1000, 200, 300 ),
779
			$this->newPersonalInfoValidator(),
780
			$this->getTextPolicyValidator( 'fields' ),
781
			$this->newPaymentTypeValidator(),
782
			$this->newBankDataValidator()
783
		);
784
	}
785
786
	public function newPersonalInfoValidator(): PersonalInfoValidator {
787
		return new PersonalInfoValidator(
788
			new PersonNameValidator(),
789
			new PhysicalAddressValidator(),
790
			$this->getEmailValidator()
791
		);
792
	}
793
794
	private function newDonationConfirmationMailer(): DonationConfirmationMailer {
795
		return new DonationConfirmationMailer(
796
			$this->newTemplateMailer(
797
				new TwigTemplate(
798
					$this->getTwig(),
799
					'Mail_Donation_Confirmation.twig', // TODO: ongoing unification of different templates
800
					[
801
						'basepath' => $this->config['web-basepath']
802
					]
803
				),
804
				'mail_subject_confirm_donation'
805
			)
806
		);
807
	}
808
809
	public function newPayPalUrlGenerator() {
810
		return new PayPalUrlGenerator( $this->getPayPalUrlConfig() );
811
	}
812
813
	private function getPayPalUrlConfig() {
814
		return PayPalUrlConfig::newFromConfig( $this->config['paypal'] );
815
	}
816
817
	private function newCreditCardUrlGenerator() {
818
		return new CreditCardUrlGenerator( $this->newCreditCardUrlConfig() );
819
	}
820
821
	private function newCreditCardUrlConfig() {
822
		return CreditCardUrlConfig::newFromConfig( $this->config['creditcard'] );
823
	}
824
825
	public function getDonationRepository(): DonationRepository {
826
		return $this->pimple['donation_repository'];
827
	}
828
829
	public function newAmountValidator(): AmountValidator {
830
		return new AmountValidator(
831
			0.01,
832
			[
833
				PaymentType::CREDIT_CARD => 1,
834
				PaymentType::PAYPAL => 1,
835
			]
836
		);
837
	}
838
839
	private function newAmountFormatter(): AmountFormatter {
840
		return new AmountFormatter( $this->config['locale'] );
841
	}
842
843
	public function newDecimalNumberFormatter(): NumberFormatter {
844
		return new NumberFormatter( $this->config['locale'], NumberFormatter::DECIMAL );
845
	}
846
847
	public function newAddCommentUseCase( string $updateToken ): AddCommentUseCase {
848
		return new AddCommentUseCase(
849
			$this->getDonationRepository(),
850
			$this->newDonationAuthorizer( $updateToken ),
851
			$this->getTextPolicyValidator( 'comment' )
852
		);
853
	}
854
855
	private function newDonationAuthorizer( string $updateToken = null, string $accessToken = null ): DonationAuthorizer {
856
		return new DoctrineDonationAuthorizer(
857
			$this->getEntityManager(),
858
			$updateToken,
859
			$accessToken
860
		);
861
	}
862
863
	public function getTokenGenerator(): TokenGenerator {
864
		if ( $this->tokenGenerator === null ) {
865
			$this->tokenGenerator = new RandomTokenGenerator(
866
				$this->config['token-length'],
867
				new \DateInterval( $this->config['token-validity-timestamp'] )
868
			);
869
		}
870
871
		return $this->tokenGenerator;
872
	}
873
874
	public function newDonationConfirmationPresenter() {
875
		return new DonationConfirmationHtmlPresenter(
876
			$this->getIncludeTemplate( 'DonationConfirmation.twig' )
877
		);
878
	}
879
880
	public function newCreditCardPaymentHtmlPresenter() {
881
		return new CreditCardPaymentHtmlPresenter(
882
			$this->getIncludeTemplate( 'CreditCardPaymentIframe.twig' ),
883
			$this->getTranslator(),
884
			$this->newCreditCardUrlGenerator()
885
		);
886
	}
887
888
	public function newCancelDonationHtmlPresenter() {
889
		return new CancelDonationHtmlPresenter(
890
			$this->getIncludeTemplate( 'Donation_Cancellation_Confirmation.twig' )
891
		);
892
	}
893
894
	public function newApplyForMembershipUseCase(): ApplyForMembershipUseCase {
895
		return new ApplyForMembershipUseCase(
896
			$this->getMembershipApplicationRepository(),
897
			$this->newMembershipApplicationTokenFetcher(),
898
			$this->newApplyForMembershipMailer(),
899
			$this->newMembershipApplicationValidator(),
900
			$this->newMembershipApplicationTracker()
901
		);
902
	}
903
904
	private function newApplyForMembershipMailer(): TemplateBasedMailer {
905
		return $this->newTemplateMailer(
906
			new TwigTemplate(
907
				$this->getTwig(),
908
				'Mail_Membership_Application_Confirmation.twig',
909
				[ 'greeting_generator' => $this->getGreetingGenerator() ]
910
			),
911
			'mail_subject_confirm_membership_application'
912
		);
913
	}
914
915
	private function newMembershipApplicationValidator(): MembershipApplicationValidator {
916
		return new MembershipApplicationValidator(
917
			new MembershipFeeValidator(),
918
			$this->newBankDataValidator(),
919
			$this->getEmailValidator()
920
		);
921
	}
922
923
	private function newMembershipApplicationTracker(): MembershipApplicationTracker {
924
		return new DoctrineMembershipApplicationTracker( $this->getEntityManager() );
925
	}
926
927
	public function newCancelMembershipApplicationUseCase( string $updateToken ): CancelMembershipApplicationUseCase {
928
		return new CancelMembershipApplicationUseCase(
929
			$this->newMembershipApplicationAuthorizer( $updateToken ),
930
			$this->getMembershipApplicationRepository(),
931
			$this->newCancelMembershipApplicationMailer()
932
		);
933
	}
934
935
	private function newMembershipApplicationAuthorizer(
936
		string $updateToken = null, string $accessToken = null ): MembershipApplicationAuthorizer {
937
938
		return new DoctrineMembershipApplicationAuthorizer(
939
			$this->getEntityManager(),
940
			$updateToken,
941
			$accessToken
942
		);
943
	}
944
945
	public function getMembershipApplicationRepository(): MembershipApplicationRepository {
946
		return $this->pimple['membership_application_repository'];
947
	}
948
949
	private function newCancelMembershipApplicationMailer(): TemplateBasedMailer {
950
		return $this->newTemplateMailer(
951
			new TwigTemplate(
952
				$this->getTwig(),
953
				'Mail_Membership_Application_Cancellation_Confirmation.twig',
954
				[ 'greeting_generator' => $this->getGreetingGenerator() ]
955
			),
956
			'mail_subject_confirm_membership_application_cancellation'
957
		);
958
	}
959
960
	public function newMembershipApplicationConfirmationUseCase( string $accessToken ) {
961
		return new ShowMembershipApplicationConfirmationUseCase(
962
			$this->newMembershipApplicationAuthorizer( null, $accessToken ), $this->getMembershipApplicationRepository(),
963
			$this->newMembershipApplicationTokenFetcher()
964
		);
965
	}
966
967
	public function newShowDonationConfirmationUseCase( string $accessToken ): ShowDonationConfirmationUseCase {
968
		return new ShowDonationConfirmationUseCase(
969
			$this->newDonationAuthorizer( null, $accessToken ),
970
			$this->getDonationRepository()
971
		);
972
	}
973
974
	public function setDonationConfirmationPageSelector( DonationConfirmationPageSelector $selector ) {
975
		$this->pimple['confirmation-page-selector'] = $selector;
976
	}
977
978
	public function getDonationConfirmationPageSelector() {
979
		return $this->pimple['confirmation-page-selector'];
980
	}
981
982
	public function newDonationFormViolationPresenter() {
983
		$template = $this->getLayoutTemplate( 'DisplayPageLayout.twig' );
984
		// TODO make this dependent on the 'form' value from the HTTP POST request
985
		// (we need different form pages for A/B testing)
986
		$template->context['main_template'] = 'DonationForm.twig';
0 ignored issues
show
Bug introduced by
The property context does not seem to exist in WMDE\Fundraising\Fronten...esentation\TwigTemplate.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
987
		return new DonationFormViolationPresenter( $template, $this->newAmountFormatter() );
988
	}
989
990
	public function newHandlePayPalPaymentNotificationUseCase( string $updateToken ) {
991
		return new HandlePayPalPaymentNotificationUseCase(
992
			$this->getDonationRepository(),
993
			$this->newDonationAuthorizer( $updateToken ),
994
			$this->newDonationConfirmationMailer(),
995
			$this->getLogger(),
996
			$this->newDonationEventLogger()
997
		);
998
	}
999
1000
	public function getPayPalPaymentNotificationVerifier(): PaymentNotificationVerifier {
1001
		return $this->pimple['paypal-payment-notification-verifier'];
1002
	}
1003
1004
	public function setPayPalPaymentNotificationVerifier( PaymentNotificationVerifier $verifier ) {
1005
		$this->pimple['paypal-payment-notification-verifier'] = $verifier;
1006
	}
1007
1008
	public function newCreditCardNotificationUseCase( string $updateToken ) {
1009
		return new CreditCardNotificationUseCase(
1010
			$this->getDonationRepository(),
1011
			$this->newDonationAuthorizer( $updateToken ),
1012
			$this->getCreditCardService(),
1013
			$this->newDonationConfirmationMailer(),
1014
			$this->getLogger(),
1015
			$this->newDonationEventLogger()
1016
		);
1017
	}
1018
1019
	public function newCancelMembershipApplicationHtmlPresenter() {
1020
		return new CancelMembershipApplicationHtmlPresenter(
1021
			$this->getIncludeTemplate( 'Membership_Application_Cancellation_Confirmation.twig' )
1022
		);
1023
	}
1024
1025
	public function newMembershipApplicationConfirmationHtmlPresenter() {
1026
		return new MembershipApplicationConfirmationHtmlPresenter(
1027
			$this->getIncludeTemplate( 'MembershipApplicationConfirmation.twig' )
1028
		);
1029
	}
1030
1031
	public function newMembershipFormViolationPresenter() {
1032
		return new MembershipFormViolationPresenter(
1033
			$this->getIncludeTemplate( 'MembershipApplication.twig' )
1034
		);
1035
	}
1036
1037
	public function setCreditCardService( CreditCardService $ccService ) {
1038
		$this->pimple['credit-card-api-service'] = $ccService;
1039
	}
1040
1041
	public function getCreditCardService(): CreditCardService {
1042
		return $this->pimple['credit-card-api-service'];
1043
	}
1044
1045
	public function newCreditCardNotificationPresenter(): CreditCardNotificationPresenter {
1046
		return new CreditCardNotificationPresenter(
1047
			new TwigTemplate(
1048
				$this->getTwig(),
1049
				'CreditCardPaymentNotification.twig',
1050
				[ 'returnUrl' => $this->config['creditcard']['return-url'] ]
1051
			)
1052
		);
1053
	}
1054
1055
	private function newDoctrineDonationPrePersistSubscriber(): DoctrineDonationPrePersistSubscriber {
1056
		$tokenGenerator = $this->getTokenGenerator();
1057
		return new DoctrineDonationPrePersistSubscriber(
1058
			$tokenGenerator,
1059
			$tokenGenerator
1060
		);
1061
	}
1062
1063
	private function newDoctrineMembershipApplicationPrePersistSubscriber(): DoctrineMembershipApplicationPrePersistSubscriber {
1064
		$tokenGenerator = $this->getTokenGenerator();
1065
		return new DoctrineMembershipApplicationPrePersistSubscriber(
1066
			$tokenGenerator,
1067
			$tokenGenerator
1068
		);
1069
	}
1070
1071
	public function setTokenGenerator( TokenGenerator $tokenGenerator ) {
1072
		$this->tokenGenerator = $tokenGenerator;
1073
	}
1074
1075
	public function disableDoctrineSubscribers() {
1076
		$this->addDoctrineSubscribers = false;
1077
	}
1078
1079
	private function newDonationTokenFetcher(): DonationTokenFetcher {
1080
		return new DoctrineDonationTokenFetcher(
1081
			$this->getEntityManager()
1082
		);
1083
	}
1084
1085
	private function newMembershipApplicationTokenFetcher(): MembershipApplicationTokenFetcher {
1086
		return new DoctrineMembershipApplicationTokenFetcher(
1087
			$this->getEntityManager()
1088
		);
1089
	}
1090
1091
}
1092