Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
88.68% covered (warning)
88.68%
47 / 53
66.67% covered (warning)
66.67%
4 / 6
CRAP
0.00% covered (danger)
0.00%
0 / 1
AppointmentUpdateService
88.68% covered (warning)
88.68%
47 / 53
66.67% covered (warning)
66.67%
4 / 6
34.58
0.00% covered (danger)
0.00%
0 / 1
 processUpdate
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
2
 validateClientData
80.00% covered (warning)
80.00%
16 / 20
0.00% covered (danger)
0.00%
0 / 1
6.29
 extractClientData
100.00% covered (success)
100.00%
11 / 11
100.00% covered (success)
100.00%
1 / 1
16
 getReservedProcess
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 updateProcessWithClientData
100.00% covered (success)
100.00%
8 / 8
100.00% covered (success)
100.00%
1 / 1
3
 saveProcessUpdate
71.43% covered (warning)
71.43%
5 / 7
0.00% covered (danger)
0.00%
0 / 1
5.58
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\Core\ValidationService;
10use BO\Zmscitizenapi\Services\Core\ZmsApiFacadeService;
11use BO\Zmscitizenapi\Services\Core\MapperService;
12use BO\Zmsentities\Helper\ProcessPlainText;
13
14class AppointmentUpdateService
15{
16    public function processUpdate(array $body, ?AuthenticatedUser $authenticatedUser): ThinnedProcess|array
17    {
18        $clientData = $this->extractClientData($body);
19
20        $validated = $this->validateClientData($clientData, $authenticatedUser);
21        if (!$validated instanceof ThinnedProcess) {
22            return $validated;
23        }
24
25        $updatedProcess = $this->updateProcessWithClientData($validated, $clientData);
26        return $this->saveProcessUpdate($updatedProcess, $authenticatedUser);
27    }
28
29    /**
30     * @return ThinnedProcess|array{errors: array}
31     */
32    private function validateClientData(object $data, ?AuthenticatedUser $authenticatedUser): ThinnedProcess|array
33    {
34        $authErrors = ValidationService::validateGetProcessById($data->processId, $data->authKey);
35        if ($authErrors['errors'] !== []) {
36            return ['errors' => $authErrors['errors']];
37        }
38
39        $reservedProcess = $this->getReservedProcess($data->processId, $data->authKey, $authenticatedUser);
40        if (!$reservedProcess instanceof ThinnedProcess) {
41            $errors = array_key_exists('errors', $reservedProcess) && is_array($reservedProcess['errors'])
42                ? $reservedProcess['errors']
43                : [];
44            return ['errors' => $errors];
45        }
46
47        $fieldErrors = ValidationService::validateAppointmentUpdateFields(
48            $data->familyName,
49            $data->email,
50            $data->telephone,
51            $data->customTextfield,
52            $data->customTextfield2,
53            $reservedProcess->scope ?? null
54        );
55        if ($fieldErrors['errors'] !== []) {
56            return ['errors' => $fieldErrors['errors']];
57        }
58
59        return $reservedProcess;
60    }
61
62    private function extractClientData(array $body): object
63    {
64        return (object) [
65            'processId' => isset($body['processId']) && is_numeric($body['processId'])
66                ? (int) $body['processId']
67                : null,
68            'authKey' => isset($body['authKey']) && is_string($body['authKey']) && trim($body['authKey']) !== ''
69                ? htmlspecialchars(trim($body['authKey']), ENT_QUOTES, 'UTF-8')
70                : null,
71            'familyName' => isset($body['familyName']) && is_string($body['familyName']) ? (string) $body['familyName'] : null,
72            'email' => isset($body['email']) && is_string($body['email']) ? (string) $body['email'] : null,
73            'telephone' => isset($body['telephone']) && is_string($body['telephone']) ? (string) $body['telephone'] : null,
74            'customTextfield' => isset($body['customTextfield']) && is_string($body['customTextfield']) ? (string) $body['customTextfield'] : null,
75            'customTextfield2' => isset($body['customTextfield2']) && is_string($body['customTextfield2']) ? (string) $body['customTextfield2'] : null,
76        ];
77    }
78
79    private function getReservedProcess(int $processId, ?string $authKey, ?AuthenticatedUser $user): ThinnedProcess|array
80    {
81        return ZmsApiFacadeService::getThinnedProcessById($processId, $authKey, $user);
82    }
83
84    private function updateProcessWithClientData(ThinnedProcess $process, object $data): ThinnedProcess
85    {
86        $process->familyName = $data->familyName ?? $process->familyName ?? null;
87        $process->email = $data->email ?? $process->email ?? null;
88        $process->telephone = $data->telephone ?? $process->telephone ?? null;
89        if ($data->customTextfield !== null) {
90            $process->customTextfield = ProcessPlainText::normalize($data->customTextfield);
91        }
92        if ($data->customTextfield2 !== null) {
93            $process->customTextfield2 = ProcessPlainText::normalize($data->customTextfield2);
94        }
95        return $process;
96    }
97
98    private function saveProcessUpdate(ThinnedProcess $process, ?AuthenticatedUser $authenticatedUser): ThinnedProcess|array
99    {
100        $processEntity = MapperService::thinnedProcessToProcess($process);
101        if (!is_null($authenticatedUser) && is_null($processEntity->getExternalUserId())) {
102            $processEntity->setExternalUserId($authenticatedUser->getExternalUserId());
103        }
104        $result = ZmsApiFacadeService::updateClientData($processEntity);
105        if (is_array($result) && !empty($result['errors'])) {
106            return $result;
107        }
108
109        return MapperService::processToThinnedProcess($result);
110    }
111}