PluginProbe ʕ •ᴥ•ʔ
Booking for Appointments and Events Calendar – Amelia / 2.4.9
Booking for Appointments and Events Calendar – Amelia v2.4.9
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 3 weeks ago
UpdateProviderCommandHandler.php
415 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 $providerRepository->rollback();
228
229 $result->setResult(CommandResult::RESULT_CONFLICT);
230 $result->setMessage('Email already exist.');
231 $result->setData('This email is already in use.');
232
233 return $result;
234 }
235
236 $canWriteWpCredentials = $userAS->canWriteLinkedWpCredentials($currentUser, $oldUser);
237 $emailChanged = $oldUser->getEmail()->getValue() !== $newUser->getEmail()->getValue();
238 $linkedWpId = $newUser->getExternalId() ? $newUser->getExternalId()->getValue() : null;
239
240 if ($linkedWpId && $emailChanged && !$canWriteWpCredentials) {
241 $providerRepository->rollback();
242
243 $result->setResult(CommandResult::RESULT_ERROR);
244 $result->setMessage('You are not allowed to change the linked WordPress account email.');
245
246 return $result;
247 }
248
249 if ($command->getField('password')) {
250 $newPassword = new Password($command->getField('password'));
251
252 $providerRepository->updateFieldById($command->getArg('id'), $newPassword->getValue(), 'password');
253
254 // Propagate to the linked WP user only when the caller is an admin or the provider
255 // updating their own profile. Blocks a Manager from resetting another provider's WP password.
256 if ($linkedWpId && $canWriteWpCredentials) {
257 add_filter('amelia_user_profile_updated', '__return_true');
258 wp_set_password($command->getField('password'), $linkedWpId);
259 remove_filter('amelia_user_profile_updated', '__return_true');
260 }
261 }
262
263 do_action('amelia_before_provider_updated', $newUser ? $newUser->toArray() : null, $oldUser ? $oldUser->toArray() : null);
264
265 try {
266 if (!$providerAS->update($oldUser, $newUser, $providerData)) {
267 $providerRepository->rollback();
268 return $result;
269 }
270
271 if (isset($providerData['googleCalendar']['blockedCalendars'])) {
272 $providerAS->updateProviderGoogleCalendarBlockedCalendars(
273 $userId,
274 $providerData['googleCalendar']['blockedCalendars']
275 );
276 }
277
278 $providerData = $this->getGoogleCalendarProviderData($providerData, $providerAS, $userId);
279
280 if (isset($providerData['outlookCalendar']['blockedCalendars'])) {
281 $providerAS->updateProviderOutlookCalendarBlockedCalendars(
282 $userId,
283 $providerData['outlookCalendar']['blockedCalendars']
284 );
285 }
286
287 $providerData = $this->getOutlookCalendarProviderData($providerData, $providerAS, $userId);
288
289 if ($createsWpUser && $isAdminOrManager) {
290 /** @var UserApplicationService $userAS */
291 $userAS = $this->getContainer()->get('application.user.service');
292
293 $userAS->setWpUserIdForNewUser($userId, $newUser, Entities::PROVIDER, $command->getField('password'));
294 } elseif ($linkedWpId) {
295 $wpUserData = [
296 'ID' => $linkedWpId,
297 'first_name' => $newUser->getFirstName() ? $newUser->getFirstName()->getValue() : '',
298 'last_name' => $newUser->getLastName() ? $newUser->getLastName()->getValue() : '',
299 ];
300
301 if ($emailChanged && $canWriteWpCredentials) {
302 $wpUserData['user_email'] = $newUser->getEmail() ? $newUser->getEmail()->getValue() : '';
303 }
304
305 add_filter('amelia_user_profile_updated', '__return_true');
306 wp_update_user($wpUserData);
307
308 if ($uid = get_current_user_id()) {
309 clean_user_cache($uid);
310 }
311
312 remove_filter('amelia_user_profile_updated', '__return_true');
313 }
314 } catch (QueryExecutionException $e) {
315 $providerRepository->rollback();
316 throw $e;
317 }
318
319 $result = $userAS->getAuthenticatedUserResponse(
320 $newUser,
321 $oldUser->getEmail()->getValue() !== $newUser->getEmail()->getValue(),
322 true,
323 $oldUser->getLoginType(),
324 'provider'
325 );
326
327 $result->setData(
328 array_merge(
329 $result->getData(),
330 [
331 'sendEmployeePanelAccessEmail' =>
332 $command->getField('password') && $command->getField('sendEmployeePanelAccessEmail'),
333 'password' => $command->getField('password')
334 ]
335 )
336 );
337
338 $providerRepository->commit();
339
340 do_action('amelia_after_provider_updated', $newUser ? $newUser->toArray() : null, $oldUser ? $oldUser->toArray() : null);
341
342 return $result;
343 }
344
345 /**
346 * @param array $providerData
347 * @param ProviderApplicationService $providerAS
348 * @param $userId
349 * @return array
350 * @throws QueryExecutionException
351 */
352 public function getGoogleCalendarProviderData(array $providerData, ProviderApplicationService $providerAS, $userId): array
353 {
354 if (isset($providerData['googleCalendar'])) {
355 $googleCalendarSettings = [];
356
357 if (isset($providerData['googleCalendar']['insertPendingAppointments'])) {
358 $googleCalendarSettings['insertPendingAppointments'] = $providerData['googleCalendar']['insertPendingAppointments'];
359 }
360
361 if (isset($providerData['googleCalendar']['includeBufferTime'])) {
362 $googleCalendarSettings['includeBufferTime'] = $providerData['googleCalendar']['includeBufferTime'];
363 }
364
365 if (isset($providerData['googleCalendar']['title'])) {
366 $googleCalendarSettings['title'] = $providerData['googleCalendar']['title'];
367 }
368
369 if (isset($providerData['googleCalendar']['description'])) {
370 $googleCalendarSettings['description'] = $providerData['googleCalendar']['description'];
371 }
372
373 if (!empty($googleCalendarSettings)) {
374 $providerAS->updateProviderGoogleCalendarAccountSettings($userId, $googleCalendarSettings);
375 }
376 }
377 return $providerData;
378 }
379
380 /**
381 * @param array $providerData
382 * @param ProviderApplicationService $providerAS
383 * @param $userId
384 * @return array
385 * @throws QueryExecutionException
386 */
387 public function getOutlookCalendarProviderData(array $providerData, ProviderApplicationService $providerAS, $userId): array
388 {
389 if (isset($providerData['outlookCalendar'])) {
390 $outlookCalendarSettings = [];
391
392 if (isset($providerData['outlookCalendar']['insertPendingAppointments'])) {
393 $outlookCalendarSettings['insertPendingAppointments'] = $providerData['outlookCalendar']['insertPendingAppointments'];
394 }
395
396 if (isset($providerData['outlookCalendar']['includeBufferTime'])) {
397 $outlookCalendarSettings['includeBufferTime'] = $providerData['outlookCalendar']['includeBufferTime'];
398 }
399
400 if (isset($providerData['outlookCalendar']['title'])) {
401 $outlookCalendarSettings['title'] = $providerData['outlookCalendar']['title'];
402 }
403
404 if (isset($providerData['outlookCalendar']['description'])) {
405 $outlookCalendarSettings['description'] = $providerData['outlookCalendar']['description'];
406 }
407
408 if (!empty($outlookCalendarSettings)) {
409 $providerAS->updateProviderOutlookCalendarAccountSettings($userId, $outlookCalendarSettings);
410 }
411 }
412 return $providerData;
413 }
414 }
415