Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
92.05% covered (success)
92.05%
81 / 88
0.00% covered (danger)
0.00%
0 / 3
CRAP
0.00% covered (danger)
0.00%
0 / 1
MailTemplatesCopy
92.05% covered (success)
92.05%
81 / 88
0.00% covered (danger)
0.00%
0 / 3
22.24
0.00% covered (danger)
0.00%
0 / 1
 readResponse
95.59% covered (success)
95.59%
65 / 68
0.00% covered (danger)
0.00%
0 / 1
12
 readPositiveInt
81.82% covered (warning)
81.82%
9 / 11
0.00% covered (danger)
0.00%
0 / 1
6.22
 readTargetScopeIds
77.78% covered (warning)
77.78%
7 / 9
0.00% covered (danger)
0.00%
0 / 1
4.18
1<?php
2
3namespace BO\Zmsbackend\Mail\Api;
4
5use BO\Mellon\Validator;
6use BO\Slim\Render;
7use BO\Zmsbackend\Helper\User;
8use BO\Zmsbackend\Mail\Exception\MailTemplateCopyInvalidInput;
9use BO\Zmsbackend\Mail\Service\MailTemplates;
10use BO\Zmsbackend\Scope\Exception\ScopeNotFound;
11use BO\Zmsbackend\Scope\Service\Scope;
12use BO\Zmsentities\Useraccount\EntityAccess;
13use Psr\Http\Message\RequestInterface;
14use Psr\Http\Message\ResponseInterface;
15
16class MailTemplatesCopy extends \BO\Zmsbackend\Api\BaseController
17{
18    /**
19     * @return ResponseInterface
20     */
21    #[\Override]
22    public function readResponse(
23        RequestInterface $request,
24        ResponseInterface $response,
25        array $args
26    ): ResponseInterface {
27        $userAccess = new User($request, 2);
28        $userAccess->checkPermissions('mailtemplates');
29
30        $input = Validator::input()->isJson()->getValue();
31
32        if (!is_array($input)) {
33            throw new MailTemplateCopyInvalidInput();
34        }
35
36        $sourceScopeId = $this->readPositiveInt(
37            $input['sourceScopeId'] ?? null
38        );
39        $sourceTemplateId = $this->readPositiveInt(
40            $input['sourceTemplateId'] ?? null
41        );
42        $targetScopeIds = $this->readTargetScopeIds(
43            $input['targetScopeIds'] ?? null
44        );
45
46        if (
47            $sourceScopeId === null
48            || $sourceTemplateId === null
49            || $targetScopeIds === null
50            || count($targetScopeIds) === 0
51            || in_array($sourceScopeId, $targetScopeIds, true)
52        ) {
53            throw new MailTemplateCopyInvalidInput();
54        }
55
56        $scopeIds = array_values(
57            array_unique(
58                array_merge([$sourceScopeId], $targetScopeIds)
59            )
60        );
61
62        $scopeReader = new Scope();
63
64        $scopeList = $scopeReader->readEntitiesByIds(
65            $scopeIds,
66            1
67        );
68
69        if (count($scopeList) !== count($scopeIds)) {
70            throw new ScopeNotFound();
71        }
72
73        /*
74         * Neben der fachlichen Berechtigung wird geprüft, ob der Benutzer
75         * auf jeden Quell- und Zielstandort zugreifen darf.
76         */
77        foreach ($scopeList as $scope) {
78            $userAccess->checkPermissions(
79                new EntityAccess($scope)
80            );
81        }
82
83        $sourceScope = $scopeList[$sourceScopeId];
84        $sourceProviderId = (string) $sourceScope->getProviderId();
85
86        $targetProviderIds = [];
87
88        foreach ($targetScopeIds as $targetScopeId) {
89            $targetScope = $scopeList[$targetScopeId];
90            $targetProviderId = (string) $targetScope->getProviderId();
91
92            /*
93             * Mail-Templates sind technisch einem Provider zugeordnet.
94             * Ein Standort mit demselben Provider wie die Quelle darf daher
95             * nicht als Ziel verwendet werden.
96             */
97            if ($targetProviderId === $sourceProviderId) {
98                throw new MailTemplateCopyInvalidInput();
99            }
100
101            $targetProviderIds[] = $targetProviderId;
102        }
103
104        $targetProviderIds = array_values(
105            array_unique($targetProviderIds)
106        );
107
108        if (count($targetProviderIds) === 0) {
109            throw new MailTemplateCopyInvalidInput();
110        }
111
112        $template = (new MailTemplates())
113            ->copyCustomizationToProviders(
114                $sourceTemplateId,
115                $sourceProviderId,
116                $targetProviderIds
117            );
118
119        $message = \BO\Zmsbackend\Api\Response\Message::create($request);
120        $message->data = $template;
121
122        $response = Render::withLastModified(
123            $response,
124            time(),
125            '0'
126        );
127
128        return Render::withJson(
129            $response,
130            $message,
131            $message->getStatuscode()
132        );
133    }
134
135    private function readPositiveInt(mixed $value): ?int
136    {
137        if (
138            (!is_int($value) && !is_string($value))
139            || is_bool($value)
140        ) {
141            return null;
142        }
143
144        $validatedValue = filter_var(
145            $value,
146            FILTER_VALIDATE_INT
147        );
148
149        if (
150            $validatedValue === false
151            || $validatedValue < 1
152        ) {
153            return null;
154        }
155
156        return (int) $validatedValue;
157    }
158
159    private function readTargetScopeIds(mixed $value): ?array
160    {
161        if (!is_array($value)) {
162            return null;
163        }
164
165        $scopeIds = [];
166
167        foreach ($value as $scopeId) {
168            $validatedScopeId = $this->readPositiveInt($scopeId);
169
170            if ($validatedScopeId === null) {
171                return null;
172            }
173
174            $scopeIds[] = $validatedScopeId;
175        }
176
177        return array_values(array_unique($scopeIds));
178    }
179}