PluginProbe ʕ •ᴥ•ʔ
Booking for Appointments and Events Calendar – Amelia / 2.4.8
Booking for Appointments and Events Calendar – Amelia v2.4.8
2.4.9 2.4.8 2.4.7 2.4.6 2.4.5 2.4.4 2.4.3 2.4.2 2.4.1 2.4 trunk 1.2.1 1.2.10 1.2.11 1.2.12 1.2.13 1.2.14 1.2.15 1.2.16 1.2.17 1.2.18 1.2.19 1.2.2 1.2.20 1.2.21 1.2.22 1.2.23 1.2.24 1.2.25 1.2.26 1.2.27 1.2.28 1.2.29 1.2.3 1.2.30 1.2.31 1.2.32 1.2.33 1.2.34 1.2.35 1.2.36 1.2.37 1.2.38 1.2.4 1.2.5 1.2.6 1.2.7 1.2.8 1.2.9 2.0 2.0.1 2.0.2 2.1 2.1.1 2.1.2 2.1.3 2.2 2.2.1 2.3
ameliabooking / src / Application / Commands / User / Provider / UpdateProviderCommandHandler.php
ameliabooking / src / Application / Commands / User / Provider Last commit date
AddProviderCommand.php 1 year ago AddProviderCommandHandler.php 2 months ago GetProviderCommand.php 7 years ago GetProviderCommandHandler.php 4 months ago GetProvidersCommand.php 1 year ago GetProvidersCommandHandler.php 6 months ago UpdateProviderCommand.php 1 year ago UpdateProviderCommandHandler.php 1 week ago UpdateProviderStatusCommand.php 1 year ago UpdateProviderStatusCommandHandler.php 2 weeks ago
UpdateProviderCommandHandler.php
407 lines
1 <?php
2
3 namespace AmeliaBooking\Application\Commands\User\Provider;
4
5 use AmeliaBooking\Application\Commands\CommandHandler;
6 use AmeliaBooking\Application\Commands\CommandResult;
7 use AmeliaBooking\Application\Common\Exceptions\AccessDeniedException;
8 use AmeliaBooking\Application\Services\Entity\EntityApplicationService;
9 use AmeliaBooking\Application\Services\User\ProviderApplicationService;
10 use AmeliaBooking\Application\Services\User\UserApplicationService;
11 use AmeliaBooking\Domain\Collection\Collection;
12 use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException;
13 use AmeliaBooking\Domain\Entity\Entities;
14 use AmeliaBooking\Domain\Entity\User\AbstractUser;
15 use AmeliaBooking\Domain\Entity\User\Provider;
16 use AmeliaBooking\Domain\Factory\User\UserFactory;
17 use AmeliaBooking\Domain\Services\Settings\SettingsService;
18 use AmeliaBooking\Domain\ValueObjects\String\Password;
19 use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException;
20 use AmeliaBooking\Infrastructure\Repository\User\ProviderRepository;
21 use AmeliaBooking\Infrastructure\Services\Apple\AbstractAppleCalendarService;
22 use AmeliaBooking\Infrastructure\WP\UserRoles\SuperAdminRoleService;
23 use Exception;
24 use AmeliaBooking\Domain\ValueObjects\String\Name;
25 use AmeliaBooking\Domain\ValueObjects\String\Phone;
26
27 /**
28 * Class UpdateProviderCommandHandler
29 *
30 * @package AmeliaBooking\Application\Commands\User\Provider
31 */
32 class UpdateProviderCommandHandler extends CommandHandler
33 {
34 /**
35 * @param UpdateProviderCommand $command
36 *
37 * @return CommandResult
38 * @throws AccessDeniedException
39 * @throws InvalidArgumentException
40 * @throws QueryExecutionException
41 * @throws Exception
42 */
43 public function handle(UpdateProviderCommand $command)
44 {
45 /** @var AbstractUser $currentUser */
46 $currentUser = $command->authorizeProviderWritePermission((int)$command->getArg('id'));
47
48 $result = new CommandResult();
49
50 $this->checkMandatoryFields($command);
51
52 /** @var ProviderRepository $providerRepository */
53 $providerRepository = $this->container->get('domain.users.providers.repository');
54
55 /** @var ProviderApplicationService $providerAS */
56 $providerAS = $this->container->get('application.user.provider.service');
57
58 /** @var SettingsService $settingsDS */
59 $settingsDS = $this->container->get('domain.settings.service');
60
61 $userId = (int)$command->getArg('id');
62
63 /** @var UserApplicationService $userAS */
64 $userAS = $this->getContainer()->get('application.user.service');
65
66 /** @var Provider $oldUser */
67 $oldUser = $providerAS->getProviderWithServicesAndSchedule($userId);
68
69 // If the current user is a provider and does not have write others permission, and the externalId is changed, throw an access denied exception
70 if (
71 $userAS->isProvider($currentUser) &&
72 !$command->getPermissionService()->currentUserCanWriteOthers(Entities::EMPLOYEES) &&
73 (int)$command->getField('externalId') &&
74 (!$oldUser->getExternalId() || $oldUser->getExternalId()->getValue() !== $command->getField('externalId'))
75 ) {
76 throw new AccessDeniedException('You are not allowed');
77 }
78
79 $command->setField('id', $userId);
80
81 $providerData = $command->getFields();
82
83 $providerData['type'] = Entities::PROVIDER;
84
85 if (!isset($providerData['stripeConnect'])) {
86 $providerData['stripeConnect'] = null;
87 }
88
89 if (!isset($providerData['zoomUserId'])) {
90 $providerData['zoomUserId'] = null;
91 }
92
93 if (!isset($providerData['appleCalendarId'])) {
94 $providerData['appleCalendarId'] = null;
95 }
96
97 if (!isset($providerData['employeeAppleCalendar'])) {
98 $providerData['employeeAppleCalendar'] = null;
99 } else {
100 /** @var AbstractAppleCalendarService $appleCalendarService */
101 $appleCalendarService = $this->container->get('infrastructure.apple.calendar.service');
102
103 $appleId = $providerData['employeeAppleCalendar']['iCloudId'];
104 $applePassword = $providerData['employeeAppleCalendar']['appSpecificPassword'];
105
106 $credentials = $appleCalendarService->handleAppleCredentials($appleId, $applePassword);
107
108 if (!$credentials) {
109 $providerData['employeeAppleCalendar'] = null;
110 }
111 }
112
113 /** @var EntityApplicationService $entityService */
114 $entityService = $this->container->get('application.entity.service');
115
116 $entityService->removeMissingEntitiesForProvider($providerData);
117
118 if (!!$oldUser->getBadgeId() && !isset($providerData['badgeId'])) {
119 $providerData['badgeId'] = null;
120 }
121
122 if ($oldUser->getTimeZone() && $settingsDS->isFeatureEnabled('timezones') === false) {
123 $providerData['timeZone'] = $oldUser->getTimeZone()->getValue();
124 }
125
126 $newUserData = array_merge($oldUser->toArray(), $providerData);
127
128 $newUserData = apply_filters('amelia_before_provider_updated_filter', $newUserData, $oldUser->toArray());
129
130 /** @var Provider $newUser */
131 $newUser = UserFactory::create($newUserData);
132
133 $oldExternalId = $oldUser->getExternalId() ? $oldUser->getExternalId()->getValue() : null;
134 $newExternalId = $newUser->getExternalId() ? $newUser->getExternalId()->getValue() : null;
135
136 $isAdminOrManager = $currentUser && (
137 $currentUser->getType() === AbstractUser::USER_ROLE_ADMIN ||
138 $currentUser->getType() === AbstractUser::USER_ROLE_MANAGER
139 );
140
141 // externalId === 0 is the front-end asking for a new WP user to be created for this employee.
142 // UserFactory drops empty values, so it never reaches $newExternalId and the comparison below
143 // cannot see it - it has to be detected on the raw field.
144 $createsWpUser = $command->getField('externalId') === 0;
145
146 if (($oldExternalId !== $newExternalId || $createsWpUser) && !$isAdminOrManager) {
147 // Non-admin/manager cannot change externalId at all, nor have a WP user created
148
149 $result->setResult(CommandResult::RESULT_ERROR);
150 $result->setMessage('Could not update user.');
151
152 return $result;
153 }
154
155 if (
156 $newExternalId &&
157 !$userAS->isRoleForExternalIdAllowed($newExternalId, Entities::PROVIDER)
158 ) {
159 // Linking to existing WP user must pass role check
160
161 $result->setResult(CommandResult::RESULT_ERROR);
162 $result->setMessage('Could not update user.');
163
164 return $result;
165 }
166
167 if ($newExternalId && SuperAdminRoleService::userHasRole((int)$newExternalId)) {
168 $result->setResult(CommandResult::RESULT_CONFLICT);
169 $result->setMessage('Superadmin users cannot be assigned Amelia roles.');
170 $result->setData([]);
171
172 return $result;
173 }
174
175 // If the phone is not set and the old phone is set, set the phone and country phone iso to null
176 if (empty($providerData['phone']) && $oldUser->getPhone() && $oldUser->getPhone()->getValue()) {
177 $newUser->setPhone(new Phone(null));
178 $newUser->setCountryPhoneIso(new Name(null));
179 }
180
181 $newUser->setDayOffList(
182 $providerAS->getModifiedDayList(
183 $newUser->getDayOffList(),
184 $oldUser->getDayOffList(),
185 !empty($newUserData['removedDayOffList'])
186 ? UserFactory::createDayOffList($newUserData['removedDayOffList'])
187 : new Collection()
188 )
189 );
190
191 $newUser->setSpecialDayList(
192 $providerAS->getModifiedDayList(
193 $newUser->getSpecialDayList(),
194 $oldUser->getSpecialDayList(),
195 !empty($newUserData['removedSpecialDayList'])
196 ? UserFactory::createSpecialDayList($newUserData['removedSpecialDayList'])
197 : new Collection()
198 )
199 );
200
201 if ($command->getUserApplicationService()->checkProviderPermissions($currentUser, $command->getToken())) {
202 $rolesSettings = $settingsDS->getCategorySettings('roles');
203
204 if (!$rolesSettings['allowConfigureServices']) {
205 $newUser->setServiceList($oldUser->getServiceList());
206 }
207
208 if (!$rolesSettings['allowConfigureSchedule']) {
209 $newUser->setWeekDayList($oldUser->getWeekDayList());
210 }
211
212 if (!$rolesSettings['allowConfigureDaysOff']) {
213 $newUser->setDayOffList($oldUser->getDayOffList());
214 }
215
216 if (!$rolesSettings['allowConfigureSpecialDays']) {
217 $newUser->setSpecialDayList($oldUser->getSpecialDayList());
218 }
219 }
220
221 $providerRepository->beginTransaction();
222
223 if (
224 $providerRepository->getByEmail($newUser->getEmail()->getValue()) &&
225 $oldUser->getEmail()->getValue() !== $newUser->getEmail()->getValue()
226 ) {
227 $result->setResult(CommandResult::RESULT_CONFLICT);
228 $result->setMessage('Email already exist.');
229 $result->setData('This email is already in use.');
230
231 return $result;
232 }
233
234 if ($command->getField('password')) {
235 $newPassword = new Password($command->getField('password'));
236
237 $providerRepository->updateFieldById($command->getArg('id'), $newPassword->getValue(), 'password');
238
239 $isAdmin = $currentUser && $currentUser->getType() === AbstractUser::USER_ROLE_ADMIN;
240 // $currentUser is null in token-only cabinet sessions (get_current_user_id() returns 0).
241 // Fall back to $oldUser which was resolved from the cabinet token and always matches $userId.
242 $callerId = $currentUser && $currentUser->getId() ? $currentUser->getId()->getValue() : null;
243 $isOwnProfile = $callerId === $userId || ($callerId === null && $oldUser->getId()->getValue() === $userId);
244
245 // Propagate to the linked WP user only when the caller is an admin or the provider
246 // updating their own profile. Blocks a Manager from resetting another provider's WP password.
247 if (
248 $newUser->getExternalId() &&
249 $newUser->getExternalId()->getValue() &&
250 ($isAdmin || $isOwnProfile)
251 ) {
252 add_filter('amelia_user_profile_updated', '__return_true');
253 wp_set_password($command->getField('password'), $newUser->getExternalId()->getValue());
254 remove_filter('amelia_user_profile_updated', '__return_true');
255 }
256 }
257
258 do_action('amelia_before_provider_updated', $newUser ? $newUser->toArray() : null, $oldUser ? $oldUser->toArray() : null);
259
260 try {
261 if (!$providerAS->update($oldUser, $newUser, $providerData)) {
262 $providerRepository->rollback();
263 return $result;
264 }
265
266 if (isset($providerData['googleCalendar']['blockedCalendars'])) {
267 $providerAS->updateProviderGoogleCalendarBlockedCalendars(
268 $userId,
269 $providerData['googleCalendar']['blockedCalendars']
270 );
271 }
272
273 $providerData = $this->getGoogleCalendarProviderData($providerData, $providerAS, $userId);
274
275 if (isset($providerData['outlookCalendar']['blockedCalendars'])) {
276 $providerAS->updateProviderOutlookCalendarBlockedCalendars(
277 $userId,
278 $providerData['outlookCalendar']['blockedCalendars']
279 );
280 }
281
282 $providerData = $this->getOutlookCalendarProviderData($providerData, $providerAS, $userId);
283
284 if ($createsWpUser && $isAdminOrManager) {
285 /** @var UserApplicationService $userAS */
286 $userAS = $this->getContainer()->get('application.user.service');
287
288 $userAS->setWpUserIdForNewUser($userId, $newUser, Entities::PROVIDER, $command->getField('password'));
289 } elseif ($newUser->getExternalId() && $newUser->getExternalId()->getValue()) {
290 add_filter('amelia_user_profile_updated', '__return_true');
291 wp_update_user(
292 [
293 'ID' => $newUser->getExternalId()->getValue(),
294 'first_name' => $newUser->getFirstName() ? $newUser->getFirstName()->getValue() : '',
295 'last_name' => $newUser->getLastName() ? $newUser->getLastName()->getValue() : '',
296 'user_email' => $newUser->getEmail() ? $newUser->getEmail()->getValue() : ''
297 ]
298 );
299
300 if ($uid = get_current_user_id()) {
301 clean_user_cache($uid);
302 }
303
304 remove_filter('amelia_user_profile_updated', '__return_true');
305 }
306 } catch (QueryExecutionException $e) {
307 $providerRepository->rollback();
308 throw $e;
309 }
310
311 $result = $userAS->getAuthenticatedUserResponse(
312 $newUser,
313 $oldUser->getEmail()->getValue() !== $newUser->getEmail()->getValue(),
314 true,
315 $oldUser->getLoginType(),
316 'provider'
317 );
318
319 $result->setData(
320 array_merge(
321 $result->getData(),
322 [
323 'sendEmployeePanelAccessEmail' =>
324 $command->getField('password') && $command->getField('sendEmployeePanelAccessEmail'),
325 'password' => $command->getField('password')
326 ]
327 )
328 );
329
330 $providerRepository->commit();
331
332 do_action('amelia_after_provider_updated', $newUser ? $newUser->toArray() : null, $oldUser ? $oldUser->toArray() : null);
333
334 return $result;
335 }
336
337 /**
338 * @param array $providerData
339 * @param ProviderApplicationService $providerAS
340 * @param $userId
341 * @return array
342 * @throws QueryExecutionException
343 */
344 public function getGoogleCalendarProviderData(array $providerData, ProviderApplicationService $providerAS, $userId): array
345 {
346 if (isset($providerData['googleCalendar'])) {
347 $googleCalendarSettings = [];
348
349 if (isset($providerData['googleCalendar']['insertPendingAppointments'])) {
350 $googleCalendarSettings['insertPendingAppointments'] = $providerData['googleCalendar']['insertPendingAppointments'];
351 }
352
353 if (isset($providerData['googleCalendar']['includeBufferTime'])) {
354 $googleCalendarSettings['includeBufferTime'] = $providerData['googleCalendar']['includeBufferTime'];
355 }
356
357 if (isset($providerData['googleCalendar']['title'])) {
358 $googleCalendarSettings['title'] = $providerData['googleCalendar']['title'];
359 }
360
361 if (isset($providerData['googleCalendar']['description'])) {
362 $googleCalendarSettings['description'] = $providerData['googleCalendar']['description'];
363 }
364
365 if (!empty($googleCalendarSettings)) {
366 $providerAS->updateProviderGoogleCalendarAccountSettings($userId, $googleCalendarSettings);
367 }
368 }
369 return $providerData;
370 }
371
372 /**
373 * @param array $providerData
374 * @param ProviderApplicationService $providerAS
375 * @param $userId
376 * @return array
377 * @throws QueryExecutionException
378 */
379 public function getOutlookCalendarProviderData(array $providerData, ProviderApplicationService $providerAS, $userId): array
380 {
381 if (isset($providerData['outlookCalendar'])) {
382 $outlookCalendarSettings = [];
383
384 if (isset($providerData['outlookCalendar']['insertPendingAppointments'])) {
385 $outlookCalendarSettings['insertPendingAppointments'] = $providerData['outlookCalendar']['insertPendingAppointments'];
386 }
387
388 if (isset($providerData['outlookCalendar']['includeBufferTime'])) {
389 $outlookCalendarSettings['includeBufferTime'] = $providerData['outlookCalendar']['includeBufferTime'];
390 }
391
392 if (isset($providerData['outlookCalendar']['title'])) {
393 $outlookCalendarSettings['title'] = $providerData['outlookCalendar']['title'];
394 }
395
396 if (isset($providerData['outlookCalendar']['description'])) {
397 $outlookCalendarSettings['description'] = $providerData['outlookCalendar']['description'];
398 }
399
400 if (!empty($outlookCalendarSettings)) {
401 $providerAS->updateProviderOutlookCalendarAccountSettings($userId, $outlookCalendarSettings);
402 }
403 }
404 return $providerData;
405 }
406 }
407