vendor/ibexa/admin-ui/src/lib/EventListener/UserProfileListener.php line 70

Open in your IDE?
  1. <?php
  2. /**
  3.  * @copyright Copyright (C) Ibexa AS. All rights reserved.
  4.  * @license For full copyright and license information view LICENSE file distributed with this source code.
  5.  */
  6. declare(strict_types=1);
  7. namespace Ibexa\AdminUi\EventListener;
  8. use Ibexa\AdminUi\Specification\UserProfile\IsProfileAvailable;
  9. use Ibexa\AdminUi\UserProfile\UserProfileConfigurationInterface;
  10. use Ibexa\ContentForms\Data\User\UserUpdateData;
  11. use Ibexa\ContentForms\Event\ContentFormEvents;
  12. use Ibexa\ContentForms\Event\FormActionEvent;
  13. use Ibexa\Contracts\Core\Repository\ContentService;
  14. use Ibexa\Contracts\Core\Repository\PermissionResolver;
  15. use Ibexa\Contracts\Core\Repository\UserService;
  16. use Ibexa\Contracts\Core\Repository\Values\User\User;
  17. use Ibexa\Contracts\Core\Repository\Values\User\UserUpdateStruct;
  18. use Ibexa\Core\FieldType\User\Type as UserFieldType;
  19. use Ibexa\Core\Repository\Repository;
  20. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  21. use Symfony\Component\HttpFoundation\RedirectResponse;
  22. use Symfony\Component\HttpFoundation\RequestStack;
  23. use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
  24. final class UserProfileListener implements EventSubscriberInterface
  25. {
  26.     private UrlGeneratorInterface $urlGenerator;
  27.     private Repository $repository;
  28.     private PermissionResolver $permissionResolver;
  29.     private ContentService $contentService;
  30.     private UserService $userService;
  31.     private UserProfileConfigurationInterface $configuration;
  32.     private RequestStack $requestStack;
  33.     public function __construct(
  34.         Repository $repository,
  35.         PermissionResolver $permissionResolver,
  36.         ContentService $contentService,
  37.         UserService $userService,
  38.         UrlGeneratorInterface $urlGenerator,
  39.         UserProfileConfigurationInterface $configuration,
  40.         RequestStack $requestStack
  41.     ) {
  42.         $this->repository $repository;
  43.         $this->permissionResolver $permissionResolver;
  44.         $this->contentService $contentService;
  45.         $this->userService $userService;
  46.         $this->urlGenerator $urlGenerator;
  47.         $this->configuration $configuration;
  48.         $this->requestStack $requestStack;
  49.     }
  50.     public static function getSubscribedEvents(): array
  51.     {
  52.         return [
  53.             ContentFormEvents::USER_UPDATE => ['onUserUpdate'30],
  54.             ContentFormEvents::USER_CANCEL => ['onUserCancel'30],
  55.         ];
  56.     }
  57.     public function onUserUpdate(FormActionEvent $event): void
  58.     {
  59.         $form $event->getForm();
  60.         $data $event->getData();
  61.         if (!($data instanceof UserUpdateData) || !$this->isSupported($data)) {
  62.             return;
  63.         }
  64.         $user $data->user;
  65.         $updateStruct $this->createUpdateStruct($data$form->getConfig()->getOption('languageCode'));
  66.         // user / selfedit policy is enough to edit own profile (checked in
  67.         $this->repository->sudo(function () use ($user$updateStruct): void {
  68.             $this->userService->updateUser($user$updateStruct);
  69.         });
  70.         $event->setResponse($this->createRedirectToUserProfile($user));
  71.         $event->stopPropagation();
  72.     }
  73.     public function onUserCancel(FormActionEvent $event): void
  74.     {
  75.         $data $event->getData();
  76.         if (!($data instanceof UserUpdateData) || !$this->isSupported($data)) {
  77.             return;
  78.         }
  79.         $event->setResponse($this->createRedirectToUserProfile($data->user));
  80.         $event->stopPropagation();
  81.     }
  82.     private function createRedirectToUserProfile(User $user): RedirectResponse
  83.     {
  84.         return new RedirectResponse(
  85.             $this->urlGenerator->generate(
  86.                 'ibexa.user.profile.view',
  87.                 [
  88.                     'userId' => $user->getUserId(),
  89.                 ]
  90.             )
  91.         );
  92.     }
  93.     private function isSupported(UserUpdateData $data): bool
  94.     {
  95.         return
  96.             $this->doesOriginateFromProfileEditing() &&
  97.             $this->isUserProfileUpdate($data) &&
  98.             $this->canEditUserProfile($data->user);
  99.     }
  100.     private function createUpdateStruct(UserUpdateData $datastring $languageCode): UserUpdateStruct
  101.     {
  102.         $updateStruct $this->userService->newUserUpdateStruct();
  103.         $updateStruct->contentUpdateStruct $this->contentService->newContentUpdateStruct();
  104.         foreach ($data->fieldsData as $fieldDefIdentifier => $fieldData) {
  105.             $updateStruct->contentUpdateStruct->setField($fieldDefIdentifier$fieldData->value$languageCode);
  106.         }
  107.         return $updateStruct;
  108.     }
  109.     private function isUserProfileUpdate(UserUpdateData $data): bool
  110.     {
  111.         $currentUserId $this->permissionResolver->getCurrentUserReference()->getUserId();
  112.         if ($currentUserId !== $data->user->getUserId()) {
  113.             return false;
  114.         }
  115.         foreach ($data->fieldsData as $fieldData) {
  116.             if ($fieldData->getFieldTypeIdentifier() === UserFieldType::class) {
  117.                 return false;
  118.             }
  119.         }
  120.         return true;
  121.     }
  122.     private function canEditUserProfile(User $user): bool
  123.     {
  124.         return
  125.             $this->permissionResolver->canUser('user''selfedit'$user)
  126.             && (new IsProfileAvailable($this->configuration))->isSatisfiedBy($user);
  127.     }
  128.     private function doesOriginateFromProfileEditing(): bool
  129.     {
  130.         $request $this->requestStack->getMainRequest();
  131.         if ($request === null) {
  132.             return false;
  133.         }
  134.         return $request->attributes->get('_route') === 'ibexa.user.profile.edit';
  135.     }
  136. }