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