Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
186 / 186
100.00% covered (success)
100.00%
4 / 4
CRAP
100.00% covered (success)
100.00%
1 / 1
PlatformFeaturesBootstrapProvider
100.00% covered (success)
100.00%
185 / 185
100.00% covered (success)
100.00%
4 / 4
4
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 initializeWebmail
100.00% covered (success)
100.00%
68 / 68
100.00% covered (success)
100.00%
1 / 1
1
 initializeMaps
100.00% covered (success)
100.00%
47 / 47
100.00% covered (success)
100.00%
1 / 1
1
 initializePdf
100.00% covered (success)
100.00%
69 / 69
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3declare(strict_types=1);
4
5/** @license For full copyright and license information, please see the LICENSE.md file. */
6
7namespace App\Core\Bootstrap\Provider;
8
9defined('AMMONLY_APP') || exit('Direct script access is forbidden.');
10
11use App\Core\Bootstrap\Configurator\SecurityAndTemplateConfigurator;
12use App\Core\Engine\Application\Security\PermissionContextFactory;
13use App\Core\Engine\Application\Service\UniversalCrudService;
14use App\Core\Engine\Infrastructure\Repository\SqlRecordCoOwnerRepository;
15use App\Core\Security\Encryption\AesGcmEncryptionService;
16use App\Core\Template\Application\Service\TemplateCompilerService;
17use App\Core\Template\Application\Service\TemplateVariableResolver;
18use App\Modules\Mail\Application\Service\MailHtmlSanitizer;
19use App\Modules\Mail\Application\Service\EmailContextAssociationService;
20use App\Modules\Mail\Application\Service\MailDateFormatService;
21use App\Modules\Mail\Application\Service\MailTrackingService;
22use App\Modules\Mail\Application\Service\WebmailAuthService;
23use App\Modules\Mail\Application\Service\WebmailFolderService;
24use App\Modules\Mail\Application\Service\WebmailMessageService;
25use App\Modules\Mail\Application\Service\WebmailSenderService;
26use App\Modules\Mail\Application\Service\WebmailSyncService;
27use App\Modules\Mail\Infrastructure\Protocol\MailProtocolDriverRegistry;
28use App\Modules\Mail\Infrastructure\Repository\SqlMailRepository;
29use App\Modules\Mail\Presentation\Api\WebmailApiController;
30use App\Modules\Mail\Presentation\Api\WebmailEventsApiController;
31use App\Modules\Mail\Presentation\Htmx\WebmailHtmxController;
32use App\Modules\Mail\Presentation\Web\MailTemplateWebController;
33use App\Modules\Mail\Presentation\Web\MailTrackingWebController;
34use App\Modules\Mail\Presentation\Web\WebmailWebController;
35use App\Modules\Map\Application\Service\IpGeolocationService;
36use App\Modules\Map\Application\Service\MapGeocodingService;
37use App\Modules\Map\Application\Service\MapRoutingService;
38use App\Modules\Map\Infrastructure\Client\AmmonlyMapApiClient;
39use App\Modules\Map\Infrastructure\GeoIp\MaxMindMmdbReader;
40use App\Modules\Map\Infrastructure\Provider\AmmonlyLocalMapProvider;
41use App\Modules\Map\Infrastructure\Provider\MapTilerMapProvider;
42use App\Modules\Map\Infrastructure\Provider\SmartMapLoadBalancer;
43use App\Modules\Map\Presentation\Api\MapApiController;
44use App\Modules\Map\Presentation\Htmx\MapHtmxController;
45use App\Modules\Map\Presentation\Web\MapWebController;
46use App\Modules\Pdf\Application\Service\PdfGeneratorService;
47use App\Modules\Pdf\Application\Service\PdfGeneratorServiceInterface;
48use App\Modules\Pdf\Domain\Repository\PdfTemplateRepositoryInterface;
49use App\Modules\Pdf\Infrastructure\Driver\MpdfRendererDriver;
50use App\Modules\Pdf\Infrastructure\Repository\SqlPdfTemplateRepository;
51use App\Modules\Pdf\Infrastructure\Repository\SqlPdfTemplateVersionRepository;
52use App\Modules\Pdf\Presentation\Api\PdfApiController;
53use App\Modules\Pdf\Presentation\Htmx\PdfHtmxController;
54use App\Modules\Pdf\Presentation\Htmx\PdfQueueHtmxController;
55use App\Modules\Pdf\Presentation\Htmx\PdfSignatureHtmxController;
56use App\Modules\Pdf\Presentation\Web\DocumentVerificationWebController;
57use App\Modules\Pdf\Presentation\Web\PdfWebController;
58use App\Modules\User\Infrastructure\Repository\SqlUserRepository;
59use App\Shared\Infrastructure\Config\InstallerConfigLoader;
60use Nyholm\Psr7\Factory\Psr17Factory;
61use PDO;
62use Yiisoft\Cache\CacheInterface;
63use Yiisoft\Session\SessionInterface;
64use Yiisoft\User\CurrentUser;
65
66/**
67 * Bootstrap provider encapsulating instantiations of Webmail, Maps, and PDF subsystems.
68 */
69final readonly class PlatformFeaturesBootstrapProvider
70{
71    public function __construct(
72        private Psr17Factory $psr17Factory,
73        private CurrentUser $currentUser,
74        private SessionInterface $session,
75        private SqlUserRepository $userRepository
76    ) {
77    }
78
79    /**
80     * Initializes Webmail subsystem.
81     *
82     * @return array{
83     *     apis: array<string, object>,
84     *     webmail_web: WebmailWebController,
85     *     webmail_htmx: WebmailHtmxController
86     * }
87     */
88    public function initializeWebmail(
89        ?PDO $pdo,
90        SecurityAndTemplateConfigurator $sec,
91        CacheInterface $cache,
92        ?SqlMailRepository $sqlMailRepo = null,
93        ?PdfGeneratorServiceInterface $pdfGenerator = null,
94        ?PdfTemplateRepositoryInterface $pdfTemplateRepo = null
95    ): array {
96        $sqlMailRepo ??= new SqlMailRepository($pdo);
97        $coOwnersRepo = new SqlRecordCoOwnerRepository($pdo);
98        $enc = new AesGcmEncryptionService();
99        $registry = new MailProtocolDriverRegistry();
100        $sanitizer = new MailHtmlSanitizer();
101
102        $webmailAuth = new WebmailAuthService($pdo, $sqlMailRepo, $coOwnersRepo, $enc, $registry);
103        $webmailFolder = new WebmailFolderService($pdo, $sqlMailRepo, $webmailAuth, $enc, $registry, $cache);
104        $dateFormatService = new MailDateFormatService();
105        $webmailMessage = new WebmailMessageService(
106            $sqlMailRepo,
107            $coOwnersRepo,
108            $enc,
109            $registry,
110            $sanitizer,
111            $dateFormatService,
112            $this->userRepository,
113            $cache
114        );
115        $webmailSender = new WebmailSenderService($sqlMailRepo, $coOwnersRepo, $enc, $registry);
116
117        $webmailWebController = new WebmailWebController(
118            $sec->twig,
119            $this->currentUser,
120            $this->psr17Factory,
121            $webmailAuth,
122            $sqlMailRepo
123        );
124
125        $associationService = new EmailContextAssociationService($pdo, $webmailMessage);
126        $webmailHtmxController = new WebmailHtmxController(
127            $sec->twig,
128            $this->currentUser,
129            $this->psr17Factory,
130            $webmailAuth,
131            $webmailFolder,
132            $webmailMessage,
133            $webmailSender,
134            $sqlMailRepo,
135            null,
136            $associationService,
137            null,
138            null,
139            null,
140            $pdfGenerator,
141            $pdfTemplateRepo,
142            $pdo
143        );
144
145        $webmailSync = new WebmailSyncService($pdo, $sqlMailRepo, $enc, $registry);
146        $webmailApi = new WebmailApiController(
147            $this->psr17Factory,
148            $this->currentUser,
149            $webmailAuth,
150            $webmailFolder,
151            $webmailMessage,
152            $webmailSender,
153            $webmailSync
154        );
155        $webmailEventsApi = new WebmailEventsApiController(
156            $this->psr17Factory,
157            $this->currentUser,
158            $webmailAuth
159        );
160
161        return [
162            'apis' => [
163                'webmail'        => $webmailApi,
164                'webmail_events' => $webmailEventsApi,
165            ],
166            'webmail_web'  => $webmailWebController,
167            'webmail_htmx' => $webmailHtmxController,
168        ];
169    }
170
171    /**
172     * Initializes Maps subsystem.
173     *
174     * @return array{
175     *     apis: array<string, object>,
176     *     map_web: MapWebController,
177     *     map_htmx: MapHtmxController
178     * }
179     */
180    public function initializeMaps(
181        ?PDO $pdo,
182        SecurityAndTemplateConfigurator $sec
183    ): array {
184        $installerConfig = InstallerConfigLoader::load();
185        $mapUrl = (string) ($installerConfig['maps']['api_url'] ?? $_ENV['AMMONLY_MAP_API_URL']
186            ?? 'https://map.ammonly.com');
187        $mapKey = (string) ($installerConfig['maps']['api_key'] ?? $_ENV['AMMONLY_MAP_API_KEY'] ?? '');
188        $maptilerKey = (string) ($installerConfig['maps']['maptiler_key'] ?? $_ENV['MAPTILER_API_KEY']
189            ?? MapTilerMapProvider::DEFAULT_KEY);
190        $geoipDbPath = (string) ($installerConfig['maps']['geoip_db_path']
191            ?? dirname(__DIR__, 4) . '/resources/geoip/GeoLite2-City.mmdb');
192
193        $mapClient = new AmmonlyMapApiClient($mapUrl, $mapKey);
194        $mmdbReader = new MaxMindMmdbReader($geoipDbPath);
195        $ipGeoService = new IpGeolocationService($pdo, $mmdbReader);
196        $smartLoadBalancer = new SmartMapLoadBalancer([
197            new AmmonlyLocalMapProvider($mapClient),
198            new MapTilerMapProvider($maptilerKey),
199        ]);
200
201        $geocodingService = new MapGeocodingService($mapClient);
202        $routingService = new MapRoutingService($mapClient);
203        $mapWebController = new MapWebController(
204            $sec->twig,
205            $this->currentUser,
206            $this->psr17Factory,
207            $mapClient,
208            $smartLoadBalancer
209        );
210        $mapHtmxController = new MapHtmxController(
211            $sec->twig,
212            $this->psr17Factory,
213            $mapClient,
214            $pdo,
215            $ipGeoService,
216            $smartLoadBalancer
217        );
218        $mapApiController = new MapApiController(
219            $this->psr17Factory,
220            $geocodingService,
221            $routingService,
222            $pdo,
223            $ipGeoService,
224            $smartLoadBalancer
225        );
226
227        return [
228            'apis' => [
229                'maps' => $mapApiController,
230            ],
231            'map_web'  => $mapWebController,
232            'map_htmx' => $mapHtmxController,
233        ];
234    }
235
236    /**
237     * Initializes PDF & Document Templates subsystem.
238     *
239     * @return array{
240     *     apis: array<string, object>,
241     *     pdf_htmx: PdfHtmxController,
242     *     pdf_web: PdfWebController,
243     *     doc_verification: DocumentVerificationWebController,
244     *     pdf_signature_htmx: PdfSignatureHtmxController,
245     *     pdf_queue_htmx: PdfQueueHtmxController,
246     *     mail_tracking_web: MailTrackingWebController,
247     *     mail_template_web: MailTemplateWebController
248     * }
249     */
250    public function initializePdf(
251        ?PDO $pdo,
252        SecurityAndTemplateConfigurator $sec,
253        UniversalCrudService $crudService
254    ): array {
255        $pdfRepo = new SqlPdfTemplateRepository($pdo);
256        $versionRepo = new SqlPdfTemplateVersionRepository($pdo, $pdfRepo);
257        $resolver = new TemplateVariableResolver($pdo);
258        $compiler = new TemplateCompilerService();
259        $driver = new MpdfRendererDriver();
260        $generator = new PdfGeneratorService($pdfRepo, $resolver, $compiler, $driver, $pdo);
261
262        $pdfApiController = new PdfApiController(
263            $this->psr17Factory,
264            $pdfRepo,
265            $generator,
266            $resolver,
267            $compiler,
268            $versionRepo
269        );
270        $pdfHtmxController = new PdfHtmxController(
271            $sec->twig,
272            $this->psr17Factory,
273            $pdfRepo,
274            $generator
275        );
276        $pdfWebController = new PdfWebController(
277            $this->psr17Factory,
278            $generator,
279            $sec->twig,
280            $pdfRepo,
281            $pdo,
282            $crudService,
283            new PermissionContextFactory($this->session)
284        );
285        $docVerificationController = new DocumentVerificationWebController(
286            $this->psr17Factory,
287            $sec->twig,
288            $pdo
289        );
290        $pdfSignatureHtmxController = new PdfSignatureHtmxController(
291            $sec->twig,
292            $this->psr17Factory,
293            $pdo
294        );
295        $pdfQueueHtmxController = new PdfQueueHtmxController(
296            $sec->twig,
297            $this->psr17Factory,
298            $pdo
299        );
300        $mailTrackingService = new MailTrackingService($pdo);
301        $mailTrackingWebController = new MailTrackingWebController(
302            $this->psr17Factory,
303            $mailTrackingService
304        );
305        $mailTemplateWebController = new MailTemplateWebController(
306            $this->psr17Factory,
307            $sec->twig,
308            null,
309            $pdo
310        );
311
312        return [
313            'apis' => [
314                'pdf' => $pdfApiController,
315            ],
316            'pdf_htmx'           => $pdfHtmxController,
317            'pdf_web'            => $pdfWebController,
318            'doc_verification'   => $docVerificationController,
319            'pdf_signature_htmx' => $pdfSignatureHtmxController,
320            'pdf_queue_htmx'     => $pdfQueueHtmxController,
321            'mail_tracking_web'  => $mailTrackingWebController,
322            'mail_template_web'  => $mailTemplateWebController,
323            'generator'          => $generator,
324            'template_repo'      => $pdfRepo,
325        ];
326    }
327}