src/FMT/Application/Controller/Admin/Crud/ExternalUserController.php line 118

Open in your IDE?
  1. <?php
  2. namespace FMT\Application\Controller\Admin\Crud;
  3. use Doctrine\ORM\EntityManagerInterface;
  4. use Doctrine\ORM\QueryBuilder;
  5. use EasyCorp\Bundle\EasyAdminBundle\Collection\FieldCollection;
  6. use EasyCorp\Bundle\EasyAdminBundle\Collection\FilterCollection;
  7. use EasyCorp\Bundle\EasyAdminBundle\Config\Action;
  8. use EasyCorp\Bundle\EasyAdminBundle\Config\Actions;
  9. use EasyCorp\Bundle\EasyAdminBundle\Config\Assets;
  10. use EasyCorp\Bundle\EasyAdminBundle\Config\Crud;
  11. use EasyCorp\Bundle\EasyAdminBundle\Config\Filters;
  12. use EasyCorp\Bundle\EasyAdminBundle\Config\KeyValueStore;
  13. use EasyCorp\Bundle\EasyAdminBundle\Context\AdminContext;
  14. use EasyCorp\Bundle\EasyAdminBundle\Dto\EntityDto;
  15. use EasyCorp\Bundle\EasyAdminBundle\Dto\SearchDto;
  16. use EasyCorp\Bundle\EasyAdminBundle\Router\AdminUrlGenerator;
  17. use FMT\Application\Controller\AbstractCrudController;
  18. use FMT\Application\FormType\Admin\ExternalUserCrudType;
  19. use FMT\Application\FormType\Admin\Filters\ArrayFilterType;
  20. use FMT\Application\FormType\Admin\Filters\FosUserRoleFilter;
  21. use FMT\Application\FormType\Admin\MajorType;
  22. use FMT\Data\Entity\User;
  23. use FMT\Data\Entity\UserMajor;
  24. use FMT\Data\Entity\UserProfile;
  25. use FMT\Data\Repository\UserRepository;
  26. use FMT\Domain\Service\Manager\UserManager;
  27. use FMT\Domain\Service\Synchronizer\MajorSynchronizer;
  28. use FMT\Infrastructure\Service\AmazonS3\StorageInterface;
  29. use Symfony\Bridge\Doctrine\Form\Type\EntityType;
  30. use Symfony\Component\Form\CallbackTransformer;
  31. use Symfony\Component\Form\FormBuilderInterface;
  32. use Symfony\Component\Form\FormEvent;
  33. use Symfony\Component\Form\FormEvents;
  34. use Symfony\Component\Form\FormInterface;
  35. use Symfony\Component\HttpFoundation\File\File;
  36. use Symfony\Component\HttpFoundation\Request;
  37. use Symfony\Component\HttpFoundation\Session\SessionInterface;
  38. use Symfony\Component\Routing\Annotation\Route;
  39. use Symfony\Component\HttpFoundation\RequestStack;
  40. use Symfony\Component\Security\Core\Security;
  41. class ExternalUserController extends AbstractCrudController
  42. {
  43.     public const EXTERNAL_USER_ROLES = [
  44.         'fmt.user.role.donor' => User::ROLE_DONOR,
  45.         'fmt.user.role.student' => User::ROLE_STUDENT,
  46.     ];
  47.     public static function getEntityFqcn(): string
  48.     {
  49.         return User::class;
  50.     }
  51.     private UserManager $manager;
  52.     private AdminUrlGenerator $adminUrlGenerator;
  53.     private ExternalUserCrudType $userCrudType;
  54.     private UserRepository $userRepository;
  55.     private SessionInterface $session;
  56.     private StorageInterface $avatarStorage;
  57.     private MajorSynchronizer $majorSynchronizer;
  58.     private RequestStack $requestStack;
  59.     private Security $security;
  60.     public function __construct(
  61.         UserManager $manager,
  62.         AdminUrlGenerator $adminUrlGenerator,
  63.         ExternalUserCrudType $userCrudType,
  64.         UserRepository $userRepository,
  65.         SessionInterface $session,
  66.         StorageInterface $avatarStorage,
  67.         MajorSynchronizer $majorSynchronizer,
  68.         RequestStack $requestStack,
  69.         Security $security
  70.     ) {
  71.         $this->manager $manager;
  72.         $this->adminUrlGenerator $adminUrlGenerator;
  73.         $this->userCrudType $userCrudType;
  74.         $this->userRepository $userRepository;
  75.         $this->session $session;
  76.         $this->avatarStorage $avatarStorage;
  77.         $this->majorSynchronizer $majorSynchronizer;
  78.         $this->requestStack $requestStack;
  79.         $this->security $security;
  80.     }
  81.     public function createIndexQueryBuilder(
  82.         SearchDto $searchDto,
  83.         EntityDto $entityDto,
  84.         FieldCollection $fields,
  85.         FilterCollection $filters
  86.     ): QueryBuilder {
  87.         $queryBuilder parent::createIndexQueryBuilder($searchDto$entityDto$fields$filters);
  88.         // Check custom filter
  89.         $request $this->requestStack->getCurrentRequest();
  90.         $userType $request->query->get('filters')['userType'] ?? null;
  91.         if ($userType === 'STUDENT') {
  92.             $queryBuilder->andWhere('entity.roles LIKE :role')
  93.                 ->setParameter('role''%ROLE_STUDENT%');
  94.         } elseif ($userType === 'DONOR') {
  95.             $queryBuilder->andWhere('entity.roles LIKE :role')
  96.                 ->setParameter('role''%ROLE_DONOR%');
  97.         }
  98.         return $this->userRepository->getUserByRoleQueryBuilder($queryBuilderself::EXTERNAL_USER_ROLES$searchDto);
  99.     }
  100.     public function createEditFormBuilder(
  101.         EntityDto $entityDto,
  102.         KeyValueStore $formOptions,
  103.         AdminContext $context
  104.     ): FormBuilderInterface {
  105.         $fields $entityDto->getFields();
  106.         if ($entityDto->getInstance()->isSuperAdmin()) {
  107.             $this->disableFields($fields);
  108.         }
  109.         $builder parent::createEditFormBuilder($entityDto$formOptions$context);
  110.         if ($builder->has('profile_avatar_filename')) {
  111.             $builder->get('profile_avatar_filename')->addModelTransformer(new CallbackTransformer(
  112.                 function ($file) use ($context) {
  113.                     /** @var User $user */
  114.                     $user $context->getEntity()->getInstance();
  115.                     $fileName $user->getProfile()->getAvatar()->getFilename();
  116.                     if (!$fileName) {
  117.                         return $file;
  118.                     }
  119.                     $newPath sprintf($this->avatarStorage->getFilePath($fileName));
  120.                     return new File($newPathfalse);
  121.                 },
  122.                 function ($tagsAsString) {
  123.                     return $tagsAsString;
  124.                 }
  125.             ));
  126.         }
  127.         $formModifier = function (FormInterface $form, array $options$school) {
  128.             $form->remove('profile_major');
  129.             $majors $this->majorSynchronizer->synchronizeBySchool($school)->getValues();
  130.             $options['choices'] = $majors;
  131.             $form->add('profile_major'MajorType::class, $options);
  132.         };
  133.         $builder->addEventListener(
  134.             FormEvents::PRE_SUBMIT,
  135.             function (FormEvent $event) use ($formModifier) {
  136.                 $data $event->getData();
  137.                 $form $event->getForm();
  138.                 if (array_key_exists('profile_school'$data)) {
  139.                     $majorForm $form->get('profile_major');
  140.                     $options $majorForm->getConfig()->getOptions();
  141.                     $options['ea_crud_form_arch'] = $majorForm->getConfig()->getAttributes();
  142.                     $formModifier($event->getForm(), $options$data['profile_school']);
  143.                 }
  144.             });
  145.         return $builder;
  146.     }
  147.     public function configureFields(string $pageName): iterable
  148.     {
  149.         $action Action::new('getMajorsForSchool')
  150.             ->setLabel('Test School API')
  151.             ->linkToRoute('admin_majors')
  152.             ->setCssClass('btn btn-primary');
  153.         $url $this->adminUrlGenerator
  154.             ->setController(ExternalUserController::class)
  155.             ->setAction($action)
  156.             ->generateUrl();
  157.         $user $this->getContext()->getEntity()->getInstance();
  158.         return $this->userCrudType->getUserCrudFields(
  159.             $this->getContext()->getCrud()->getCurrentAction(),
  160.             $this->avatarStorage,
  161.             $user,
  162.             $url
  163.         );
  164.     }
  165.     /**
  166.      * @param string $entityFqcn
  167.      * @return User
  168.      */
  169.     public function createEntity(string $entityFqcn)
  170.     {
  171.         $user parent::createEntity($entityFqcn);
  172.         $user->getProfile()->setVisible(UserProfile::VISIBILITY_NON);
  173.         return $user;
  174.     }
  175.     /**
  176.      * @param EntityManagerInterface $entityManager
  177.      * @param $entityInstance
  178.      * @return void
  179.      */
  180.     public function deleteEntity(EntityManagerInterface $entityManager$entityInstance): void
  181.     {
  182.         return;
  183.     }
  184.     /**
  185.      * @param EntityManagerInterface $entityManager
  186.      * @param $user
  187.      * @return void
  188.      */
  189.     public function persistEntity(EntityManagerInterface $entityManager$user): void
  190.     {
  191.         $this->manager->create($user);
  192.         parent::persistEntity($entityManager$user);
  193.     }
  194.     public function configureFilters(Filters $filters): Filters
  195.     {
  196.         return $filters;
  197.             /*->add(
  198.                 FosUserRoleFilter::new('roles')
  199.                     ->setChoices(self::EXTERNAL_USER_ROLES)
  200.                     ->setFormType(ArrayFilterType::class)
  201.                     ->canSelectMultiple()
  202.                     ->setFormTypeOption('required', false)
  203.             );*/
  204.     }
  205.     public function configureCrud(Crud $crud): Crud
  206.     {
  207.         // Get the request and check the userType filter
  208.         $request $this->requestStack->getCurrentRequest();
  209.         $userType $request->query->get('filters')['userType'] ?? 'Users';
  210.         // Customize the header dynamically
  211.         $pageTitle = match (strtoupper($userType)) {
  212.             'STUDENT' => 'Student Users',
  213.             'DONOR' => 'Donor Users',
  214.             default => 'Users',
  215.         };
  216.         $crud parent::configureCrud($crud);
  217.         $crud
  218.             ->setSearchFields(['profile.firstName''profile.lastName'])
  219.             ->setDefaultSort(['profile.lastName' => 'ASC'])
  220.             ->overrideTemplate('crud/edit''admin/crud/edit.html.twig')
  221.             ->setFormOptions(['validation_groups' => ['Admin''Default']]);
  222.         $crud
  223.             ->setEntityLabelInPlural($pageTitle)
  224.             ->setEntityLabelInSingular('User')
  225.             ->setPaginatorPageSize(PHP_INT_MAX)
  226.             ->setPageTitle('index'$pageTitle)->setPageTitle('edit'"Edit " rtrim($pageTitle,"s"));  // Adjusts the H1 title
  227.         return $crud;
  228.     }
  229.     public function configureActions(Actions $actions): Actions
  230.     {
  231.         $loggedInUser $this->security->getUser();
  232.         $isSchoolAdmin $loggedInUser->hasRole(User::ROLE_SCHOOL_ADMIN);
  233.        
  234.         
  235.         // Conditionally show or hide actions dropdown
  236.         if ($isSchoolAdmin) {
  237.             return $actions
  238.             ->disable(Action::DELETE)
  239.             ->disable(Action::NEW)
  240.             ->disable(Action::EDIT);
  241.         } else {
  242.             return $actions
  243.                 ->disable(Action::DELETE)
  244.                 ->disable(Action::NEW)
  245.                 ->add(Crud::PAGE_INDEXAction::DETAIL);
  246.         }
  247.         
  248.     }
  249.     private function disableFields(?FieldCollection $fields): void
  250.     {
  251.         foreach ($fields as $field) {
  252.             if ($field->getProperty() === 'roles') {
  253.                 $field->setFormTypeOption('disabled'true);
  254.                 $field->setFormTypeOption('choices'self::EXTERNAL_USER_ROLES);
  255.             }
  256.             if ($field->getProperty() === 'login') {
  257.                 $field->setFormTypeOption('disabled'true);
  258.             }
  259.         }
  260.     }
  261.     public function configureAssets(Assets $assets): Assets
  262.     {
  263.         return parent::configureAssets($assets)
  264.             ->addWebpackEncoreEntry('sign_up')
  265.             ->addWebpackEncoreEntry('admin_profile_major')
  266.             ->addWebpackEncoreEntry('admin_crud_edit');
  267.     }
  268.     /**
  269.      * @Route("/admin/getMajorsForSchool",
  270.      *     methods={"GET"},
  271.      *     name="admin_majors"
  272.      * )
  273.      */
  274.     public function getMajorsForSchool(Request $request)
  275.     {
  276.         $schoolId $request->get('schoolId');
  277.         $majors $this->majorSynchronizer->synchronizeBySchool($schoolId);
  278.         $majorNew = new UserMajor();
  279.         $form $this->createFormBuilder($majorNew)
  280.             ->add('User_profile_major'EntityType::class, [
  281.                 'required' => true,
  282.                 'class' => UserMajor::class,
  283.                 'label' => 'fmt.form.major',
  284.                 'choice_label' => 'name',
  285.                 'mapped' => false,
  286.                 'choices' => $majors,
  287.                 'by_reference' => false,
  288.             ])
  289.             ->getForm();
  290.         return $this->render('admin/form/major.html.twig', [
  291.             'form' => $form->createView(),
  292.         ]);
  293.     }
  294. }