vendor/easycorp/easyadmin-bundle/src/Factory/AdminContextFactory.php line 62

  1. <?php
  2. namespace EasyCorp\Bundle\EasyAdminBundle\Factory;
  3. use EasyCorp\Bundle\EasyAdminBundle\Cache\CacheWarmer;
  4. use EasyCorp\Bundle\EasyAdminBundle\Config\Crud;
  5. use EasyCorp\Bundle\EasyAdminBundle\Config\Option\EA;
  6. use EasyCorp\Bundle\EasyAdminBundle\Config\Option\TextDirection;
  7. use EasyCorp\Bundle\EasyAdminBundle\Context\AdminContext;
  8. use EasyCorp\Bundle\EasyAdminBundle\Contracts\Controller\CrudControllerInterface;
  9. use EasyCorp\Bundle\EasyAdminBundle\Contracts\Controller\DashboardControllerInterface;
  10. use EasyCorp\Bundle\EasyAdminBundle\Contracts\Factory\MenuFactoryInterface;
  11. use EasyCorp\Bundle\EasyAdminBundle\Dto\ActionConfigDto;
  12. use EasyCorp\Bundle\EasyAdminBundle\Dto\AssetsDto;
  13. use EasyCorp\Bundle\EasyAdminBundle\Dto\CrudDto;
  14. use EasyCorp\Bundle\EasyAdminBundle\Dto\DashboardDto;
  15. use EasyCorp\Bundle\EasyAdminBundle\Dto\EntityDto;
  16. use EasyCorp\Bundle\EasyAdminBundle\Dto\FilterConfigDto;
  17. use EasyCorp\Bundle\EasyAdminBundle\Dto\I18nDto;
  18. use EasyCorp\Bundle\EasyAdminBundle\Dto\SearchDto;
  19. use EasyCorp\Bundle\EasyAdminBundle\Registry\CrudControllerRegistry;
  20. use EasyCorp\Bundle\EasyAdminBundle\Registry\TemplateRegistry;
  21. use Symfony\Component\HttpFoundation\Request;
  22. use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
  23. use Symfony\Component\Security\Core\User\UserInterface;
  24. use function Symfony\Component\String\u;
  25. use function Symfony\Component\Translation\t;
  26. use Symfony\Contracts\Translation\TranslatableInterface;
  27. /**
  28.  * @author Javier Eguiluz <javier.eguiluz@gmail.com>
  29.  */
  30. final class AdminContextFactory
  31. {
  32.     private string $cacheDir;
  33.     private ?TokenStorageInterface $tokenStorage;
  34.     private MenuFactoryInterface $menuFactory;
  35.     private CrudControllerRegistry $crudControllers;
  36.     private EntityFactory $entityFactory;
  37.     public function __construct(string $cacheDir, ?TokenStorageInterface $tokenStorage, MenuFactoryInterface $menuFactory, CrudControllerRegistry $crudControllers, EntityFactory $entityFactory)
  38.     {
  39.         $this->cacheDir = $cacheDir;
  40.         $this->tokenStorage = $tokenStorage;
  41.         $this->menuFactory = $menuFactory;
  42.         $this->crudControllers = $crudControllers;
  43.         $this->entityFactory = $entityFactory;
  44.     }
  45.     public function create(Request $request, DashboardControllerInterface $dashboardController, ?CrudControllerInterface $crudController): AdminContext
  46.     {
  47.         $crudAction = $request->query->get(EA::CRUD_ACTION);
  48.         $validPageNames = [Crud::PAGE_INDEX, Crud::PAGE_DETAIL, Crud::PAGE_EDIT, Crud::PAGE_NEW];
  49.         $pageName = \in_array($crudAction, $validPageNames, true) ? $crudAction : null;
  50.         $dashboardDto = $this->getDashboardDto($request, $dashboardController);
  51.         $assetDto = $this->getAssetDto($dashboardController, $crudController, $pageName);
  52.         $actionConfigDto = $this->getActionConfig($dashboardController, $crudController, $pageName);
  53.         $filters = $this->getFilters($dashboardController, $crudController);
  54.         $crudDto = $this->getCrudDto($this->crudControllers, $dashboardController, $crudController, $actionConfigDto, $filters, $crudAction, $pageName);
  55.         $entityDto = $this->getEntityDto($request, $crudDto);
  56.         $searchDto = $this->getSearchDto($request, $crudDto);
  57.         $i18nDto = $this->getI18nDto($request, $dashboardDto, $crudDto, $entityDto);
  58.         $templateRegistry = $this->getTemplateRegistry($dashboardController, $crudDto);
  59.         $user = $this->getUser($this->tokenStorage);
  60.         return new AdminContext($request, $user, $i18nDto, $this->crudControllers, $dashboardDto, $dashboardController, $assetDto, $crudDto, $entityDto, $searchDto, $this->menuFactory, $templateRegistry);
  61.     }
  62.     private function getDashboardDto(Request $request, DashboardControllerInterface $dashboardControllerInstance): DashboardDto
  63.     {
  64.         $dashboardRoutesCachePath = $this->cacheDir.'/'.CacheWarmer::DASHBOARD_ROUTES_CACHE;
  65.         $dashboardControllerRoutes = !file_exists($dashboardRoutesCachePath) ? [] : require $dashboardRoutesCachePath;
  66.         $dashboardController = $dashboardControllerInstance::class.'::index';
  67.         $dashboardRouteName = null;
  68.         foreach ($dashboardControllerRoutes as $routeName => $controller) {
  69.             if ($controller === $dashboardController) {
  70.                 // if present, remove the suffix of i18n route names (it's the content after the last dot
  71.                 // in the route name; e.g. 'dashboard.en' -> remove '.en', 'admin.index.en_US' -> remove '.en_US')
  72.                 $dashboardRouteName = preg_replace('~\.[a-z]{2}(_[A-Z]{2})?$~', '', $routeName);
  73.                 break;
  74.             }
  75.         }
  76.         if (null === $dashboardRouteName) {
  77.             throw new \RuntimeException(sprintf('The name of the route associated to "%s" cannot be determined. Clear the application cache to run the EasyAdmin cache warmer, which generates the needed data to find this route.', $dashboardController));
  78.         }
  79.         $dashboardDto = $dashboardControllerInstance->configureDashboard()->getAsDto();
  80.         $dashboardDto->setRouteName($dashboardRouteName);
  81.         return $dashboardDto;
  82.     }
  83.     private function getAssetDto(DashboardControllerInterface $dashboardController, ?CrudControllerInterface $crudController, ?string $pageName): AssetsDto
  84.     {
  85.         $defaultAssets = $dashboardController->configureAssets();
  86.         if (null === $crudController) {
  87.             return $defaultAssets->getAsDto();
  88.         }
  89.         return $crudController->configureAssets($defaultAssets)->getAsDto()->loadedOn($pageName);
  90.     }
  91.     private function getCrudDto(CrudControllerRegistry $crudControllers, DashboardControllerInterface $dashboardController, ?CrudControllerInterface $crudController, ActionConfigDto $actionConfigDto, FilterConfigDto $filters, ?string $crudAction, ?string $pageName): ?CrudDto
  92.     {
  93.         if (null === $crudController) {
  94.             return null;
  95.         }
  96.         $defaultCrud = $dashboardController->configureCrud();
  97.         $crudDto = $crudController->configureCrud($defaultCrud)->getAsDto();
  98.         $entityFqcn = $crudControllers->findEntityFqcnByCrudFqcn($crudController::class);
  99.         $crudDto->setControllerFqcn($crudController::class);
  100.         $crudDto->setActionsConfig($actionConfigDto);
  101.         $crudDto->setFiltersConfig($filters);
  102.         $crudDto->setCurrentAction($crudAction);
  103.         $crudDto->setEntityFqcn($entityFqcn);
  104.         $crudDto->setPageName($pageName);
  105.         return $crudDto;
  106.     }
  107.     private function getActionConfig(DashboardControllerInterface $dashboardController, ?CrudControllerInterface $crudController, ?string $pageName): ActionConfigDto
  108.     {
  109.         if (null === $crudController) {
  110.             return new ActionConfigDto();
  111.         }
  112.         $defaultActionConfig = $dashboardController->configureActions();
  113.         return $crudController->configureActions($defaultActionConfig)->getAsDto($pageName);
  114.     }
  115.     private function getFilters(DashboardControllerInterface $dashboardController, ?CrudControllerInterface $crudController): FilterConfigDto
  116.     {
  117.         if (null === $crudController) {
  118.             return new FilterConfigDto();
  119.         }
  120.         $defaultFilterConfig = $dashboardController->configureFilters();
  121.         return $crudController->configureFilters($defaultFilterConfig)->getAsDto();
  122.     }
  123.     private function getTemplateRegistry(DashboardControllerInterface $dashboardController, ?CrudDto $crudDto): TemplateRegistry
  124.     {
  125.         $templateRegistry = TemplateRegistry::new();
  126.         $defaultCrudDto = $dashboardController->configureCrud()->getAsDto();
  127.         $templateRegistry->setTemplates($defaultCrudDto->getOverriddenTemplates());
  128.         if (null !== $crudDto) {
  129.             $templateRegistry->setTemplates($crudDto->getOverriddenTemplates());
  130.         }
  131.         return $templateRegistry;
  132.     }
  133.     private function getI18nDto(Request $request, DashboardDto $dashboardDto, ?CrudDto $crudDto, ?EntityDto $entityDto): I18nDto
  134.     {
  135.         $locale = $request->getLocale();
  136.         $configuredTextDirection = $dashboardDto->getTextDirection();
  137.         $localePrefix = strtolower(substr($locale, 0, 2));
  138.         $defaultTextDirection = \in_array($localePrefix, ['ar', 'fa', 'he'], true) ? TextDirection::RTL : TextDirection::LTR;
  139.         $textDirection = $configuredTextDirection ?? $defaultTextDirection;
  140.         $translationDomain = $dashboardDto->getTranslationDomain();
  141.         $translationParameters = [];
  142.         if (null !== $crudDto) {
  143.             $translationParameters['%entity_name%'] = $entityName = basename(str_replace('\\', '/', $crudDto->getEntityFqcn()));
  144.             $translationParameters['%entity_as_string%'] = null === $entityDto ? '' : $entityDto->toString();
  145.             $translationParameters['%entity_id%'] = $entityId = $request->query->get(EA::ENTITY_ID);
  146.             $translationParameters['%entity_short_id%'] = null === $entityId ? null : u($entityId)->truncate(7)->toString();
  147.             $entityInstance = null === $entityDto ? null : $entityDto->getInstance();
  148.             $pageName = $crudDto->getCurrentPage();
  149.             $singularLabel = $crudDto->getEntityLabelInSingular($entityInstance, $pageName);
  150.             if (!$singularLabel instanceof TranslatableInterface) {
  151.                 $singularLabel = t($singularLabel ?? $entityName, $translationParameters, $translationDomain);
  152.             }
  153.             $pluralLabel = $crudDto->getEntityLabelInPlural($entityInstance, $pageName);
  154.             if (!$pluralLabel instanceof TranslatableInterface) {
  155.                 $pluralLabel = t($pluralLabel ?? $entityName, $translationParameters, $translationDomain);
  156.             }
  157.             $crudDto->setEntityLabelInSingular($singularLabel);
  158.             $crudDto->setEntityLabelInPlural($pluralLabel);
  159.             $translationParameters['%entity_label_singular%'] = $singularLabel;
  160.             $translationParameters['%entity_label_plural%'] = $pluralLabel;
  161.         }
  162.         return new I18nDto($locale, $textDirection, $translationDomain, $translationParameters);
  163.     }
  164.     public function getSearchDto(Request $request, ?CrudDto $crudDto): ?SearchDto
  165.     {
  166.         if (null === $crudDto) {
  167.             return null;
  168.         }
  169.         $queryParams = $request->query->all();
  170.         $searchableProperties = $crudDto->getSearchFields();
  171.         $query = $queryParams[EA::QUERY] ?? null;
  172.         $defaultSort = $crudDto->getDefaultSort();
  173.         $customSort = $queryParams[EA::SORT] ?? [];
  174.         $appliedFilters = $queryParams[EA::FILTERS] ?? [];
  175.         $searchMode = $crudDto->getSearchMode();
  176.         return new SearchDto($request, $searchableProperties, $query, $defaultSort, $customSort, $appliedFilters, $searchMode);
  177.     }
  178.     // Copied from https://github.com/symfony/twig-bridge/blob/master/AppVariable.php
  179.     // (c) Fabien Potencier <fabien@symfony.com> - MIT License
  180.     private function getUser(?TokenStorageInterface $tokenStorage): ?UserInterface
  181.     {
  182.         if (null === $token = $tokenStorage?->getToken()) {
  183.             return null;
  184.         }
  185.         $user = $token->getUser();
  186.         return \is_object($user) ? $user : null;
  187.     }
  188.     private function getEntityDto(Request $request, ?CrudDto $crudDto): ?EntityDto
  189.     {
  190.         if (null === $crudDto) {
  191.             return null;
  192.         }
  193.         return $this->entityFactory->create($crudDto->getEntityFqcn(), $request->query->get(EA::ENTITY_ID), $crudDto->getEntityPermission());
  194.     }
  195. }