Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
92.31% covered (success)
92.31%
36 / 39
57.14% covered (warning)
57.14%
4 / 7
CRAP
0.00% covered (danger)
0.00%
0 / 1
AppointmentConfirmService
92.31% covered (success)
92.31%
36 / 39
57.14% covered (warning)
57.14%
4 / 7
22.22
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 processConfirm
93.33% covered (success)
93.33%
14 / 15
0.00% covered (danger)
0.00%
0 / 1
7.01
 extractClientData
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
6
 validateClientData
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getReservedProcess
88.89% covered (warning)
88.89%
8 / 9
0.00% covered (danger)
0.00%
0 / 1
3.01
 confirmProcess
80.00% covered (warning)
80.00%
4 / 5
0.00% covered (danger)
0.00%
0 / 1
3.07
 sendConfirmationEmail
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3declare(strict_types=1);
4
5namespace BO\Zmscitizenapi\Services\Appointment;
6
7use BO\Zmscitizenapi\Models\AuthenticatedUser;
8use BO\Zmscitizenapi\Models\ThinnedProcess;
9use BO\Zmscitizenapi\Services\Captcha\CaptchaService;
10use BO\Zmscitizenapi\Services\Core\ValidationService;
11use BO\Zmscitizenapi\Services\Core\ZmsApiFacadeService;
12use BO\Zmscitizenapi\Services\Core\MapperService;
13
14class AppointmentConfirmService
15{
16    private CaptchaService $captchaService;
17
18    public function __construct()
19    {
20        $this->captchaService = new CaptchaService();
21    }
22
23    public function processConfirm(array $body, ?AuthenticatedUser $authenticatedUser): ThinnedProcess|array
24    {
25        $clientData = $this->extractClientData($body);
26        $errors = $this->validateClientData($clientData);
27        if (!empty($errors['errors'])) {
28            return $errors;
29        }
30
31        $reservedProcess = $this->getReservedProcess($clientData->processId, $clientData->authKey, $authenticatedUser);
32        if (is_array($reservedProcess) && !empty($reservedProcess['errors'])) {
33            return $reservedProcess;
34        }
35
36        // Todo: check if the email template confirmed exists for the scope before submitting and sending
37        $result = $this->confirmProcess($reservedProcess);
38        if (is_array($result) && !empty($result['errors'])) {
39            return $result;
40        }
41
42        $token = $this->captchaService->generateToken();
43        $result->setCaptchaToken($token);
44
45        if ($result->status === 'confirmed') {
46            $this->sendConfirmationEmail($result);
47        }
48
49        return $result;
50    }
51
52
53    private function extractClientData(array $body): object
54    {
55        return (object) [
56            'processId' => isset($body['processId']) && is_numeric($body['processId'])
57                ? (int) $body['processId']
58                : null,
59            'authKey' => isset($body['authKey']) && is_string($body['authKey']) && trim($body['authKey']) !== ''
60                ? htmlspecialchars(trim($body['authKey']), ENT_QUOTES, 'UTF-8')
61                : null
62        ];
63    }
64
65    private function validateClientData(object $data): array
66    {
67        return ValidationService::validateGetProcessById($data->processId, $data->authKey);
68    }
69
70    private function getReservedProcess(int $processId, ?string $authKey, ?AuthenticatedUser $user): ThinnedProcess|array
71    {
72        $process = ZmsApiFacadeService::getProcessById($processId, $authKey, $user);
73        $notFound = ValidationService::validateGetProcessNotFound($process);
74        if (!empty($notFound['errors'])) {
75            return $notFound;
76        }
77
78        $thinned = MapperService::processToThinnedProcess($process);
79        $confirmErrors = ValidationService::validateAppointmentConfirm($thinned, $process->getExternalUserId());
80        if ($confirmErrors['errors'] !== []) {
81            return $confirmErrors;
82        }
83
84        return $thinned;
85    }
86
87    private function confirmProcess(ThinnedProcess $process): ThinnedProcess|array
88    {
89        $processEntity = MapperService::thinnedProcessToProcess($process);
90        $result = ZmsApiFacadeService::confirmAppointment($processEntity);
91        if (is_array($result) && !empty($result['errors'])) {
92            return $result;
93        }
94
95        return MapperService::processToThinnedProcess($result);
96    }
97
98    private function sendConfirmationEmail(ThinnedProcess $process): void
99    {
100        $processEntity = MapperService::thinnedProcessToProcess($process);
101        ZmsApiFacadeService::sendConfirmationEmail($processEntity);
102    }
103}