src/Eccube/EventListener/TwigInitializeListener.php line 149

Open in your IDE?
  1. <?php
  2. /*
  3.  * This file is part of EC-CUBE
  4.  *
  5.  * Copyright(c) EC-CUBE CO.,LTD. All Rights Reserved.
  6.  *
  7.  * http://www.ec-cube.co.jp/
  8.  *
  9.  * For the full copyright and license information, please view the LICENSE
  10.  * file that was distributed with this source code.
  11.  */
  12. namespace Eccube\EventListener;
  13. use Detection\MobileDetect;
  14. use Doctrine\ORM\NoResultException;
  15. use Eccube\Common\EccubeConfig;
  16. use Eccube\Entity\AuthorityRole;
  17. use Eccube\Entity\Layout;
  18. use Eccube\Entity\Master\DeviceType;
  19. use Eccube\Entity\Member;
  20. use Eccube\Entity\Page;
  21. use Eccube\Entity\PageLayout;
  22. use Eccube\Repository\AuthorityRoleRepository;
  23. use Eccube\Repository\BaseInfoRepository;
  24. use Eccube\Repository\BlockPositionRepository;
  25. use Eccube\Repository\LayoutRepository;
  26. use Eccube\Repository\Master\DeviceTypeRepository;
  27. use Eccube\Repository\PageLayoutRepository;
  28. use Eccube\Repository\PageRepository;
  29. use Eccube\Request\Context;
  30. use Eccube\Service\SystemService;
  31. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  32. use Symfony\Component\HttpKernel\Event\RequestEvent;
  33. use Symfony\Component\HttpKernel\KernelEvents;
  34. use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
  35. use Twig\Environment;
  36. class TwigInitializeListener implements EventSubscriberInterface
  37. {
  38.     /**
  39.      * @var bool 初期化済かどうか.
  40.      */
  41.     protected $initialized false;
  42.     /**
  43.      * @var Environment
  44.      */
  45.     protected $twig;
  46.     /**
  47.      * @var BaseInfoRepository
  48.      */
  49.     protected $baseInfoRepository;
  50.     /**
  51.      * @var DeviceTypeRepository
  52.      */
  53.     protected $deviceTypeRepository;
  54.     /**
  55.      * @var PageRepository
  56.      */
  57.     protected $pageRepository;
  58.     /**
  59.      * @var PageLayoutRepository
  60.      */
  61.     protected $pageLayoutRepository;
  62.     /**
  63.      * @var BlockPositionRepository
  64.      */
  65.     protected $blockPositionRepository;
  66.     /**
  67.      * @var Context
  68.      */
  69.     protected $requestContext;
  70.     /**
  71.      * @var AuthorityRoleRepository
  72.      */
  73.     private $authorityRoleRepository;
  74.     /**
  75.      * @var EccubeConfig
  76.      */
  77.     private $eccubeConfig;
  78.     /**
  79.      * @var MobileDetect
  80.      */
  81.     private $mobileDetector;
  82.     /**
  83.      * @var UrlGeneratorInterface
  84.      */
  85.     private $router;
  86.     /**
  87.      * @var LayoutRepository
  88.      */
  89.     private $layoutRepository;
  90.     /**
  91.      * @var SystemService
  92.      */
  93.     protected $systemService;
  94.     /**
  95.      * TwigInitializeListener constructor.
  96.      */
  97.     public function __construct(
  98.         Environment $twig,
  99.         BaseInfoRepository $baseInfoRepository,
  100.         PageRepository $pageRepository,
  101.         PageLayoutRepository $pageLayoutRepository,
  102.         BlockPositionRepository $blockPositionRepository,
  103.         DeviceTypeRepository $deviceTypeRepository,
  104.         AuthorityRoleRepository $authorityRoleRepository,
  105.         EccubeConfig $eccubeConfig,
  106.         Context $context,
  107.         MobileDetect $mobileDetector,
  108.         UrlGeneratorInterface $router,
  109.         LayoutRepository $layoutRepository,
  110.         SystemService $systemService
  111.     ) {
  112.         $this->twig $twig;
  113.         $this->baseInfoRepository $baseInfoRepository;
  114.         $this->pageRepository $pageRepository;
  115.         $this->pageLayoutRepository $pageLayoutRepository;
  116.         $this->blockPositionRepository $blockPositionRepository;
  117.         $this->deviceTypeRepository $deviceTypeRepository;
  118.         $this->authorityRoleRepository $authorityRoleRepository;
  119.         $this->eccubeConfig $eccubeConfig;
  120.         $this->requestContext $context;
  121.         $this->mobileDetector $mobileDetector;
  122.         $this->router $router;
  123.         $this->layoutRepository $layoutRepository;
  124.         $this->systemService $systemService;
  125.     }
  126.     /**
  127.      * @throws NoResultException
  128.      * @throws \Doctrine\ORM\NonUniqueResultException
  129.      */
  130.     public function onKernelRequest(RequestEvent $event)
  131.     {
  132.         if ($this->initialized) {
  133.             return;
  134.         }
  135.         $this->twig->addGlobal('BaseInfo'$this->baseInfoRepository->get());
  136.         if ($this->requestContext->isAdmin()) {
  137.             $this->setAdminGlobals($event);
  138.         } else {
  139.             $this->setFrontVariables($event);
  140.         }
  141.         $this->initialized true;
  142.     }
  143.     /**
  144.      * @throws \Doctrine\ORM\NonUniqueResultException
  145.      */
  146.     public function setFrontVariables(RequestEvent $event)
  147.     {
  148.         $request $event->getRequest();
  149.         /** @var \Symfony\Component\HttpFoundation\ParameterBag $attributes */
  150.         $attributes $request->attributes;
  151.         $route $attributes->get('_route');
  152.         if ($route == 'user_data') {
  153.             $routeParams $attributes->get('_route_params', []);
  154.             $route = isset($routeParams['route']) ? $routeParams['route'] : $attributes->get('route''');
  155.         }
  156.         $type DeviceType::DEVICE_TYPE_PC;
  157.         if ($this->mobileDetector->isMobile()) {
  158.             $type DeviceType::DEVICE_TYPE_MB;
  159.         }
  160.         // URLからPageを取得
  161.         /** @var Page $Page */
  162.         $Page $this->pageRepository->getPageByRoute($route);
  163.         /** @var PageLayout[] $PageLayouts */
  164.         $PageLayouts $Page->getPageLayouts();
  165.         // Pageに紐づくLayoutからDeviceTypeが一致するLayoutを探す
  166.         $Layout null;
  167.         foreach ($PageLayouts as $PageLayout) {
  168.             if ($PageLayout->getDeviceTypeId() == $type) {
  169.                 $Layout $PageLayout->getLayout();
  170.                 break;
  171.             }
  172.         }
  173.         // Pageに紐づくLayoutにDeviceTypeが一致するLayoutがない場合はPCのレイアウトを探す
  174.         if (!$Layout) {
  175.             log_info('fallback to PC layout');
  176.             foreach ($PageLayouts as $PageLayout) {
  177.                 if ($PageLayout->getDeviceTypeId() == DeviceType::DEVICE_TYPE_PC) {
  178.                     $Layout $PageLayout->getLayout();
  179.                     break;
  180.                 }
  181.             }
  182.         }
  183.         // 管理者ログインしている場合にページレイアウトのプレビューが可能
  184.         if ($request->get('preview')) {
  185.             $is_admin $request->getSession()->has('_security_admin');
  186.             if ($is_admin) {
  187.                 $Layout $this->layoutRepository->get(Layout::DEFAULT_LAYOUT_PREVIEW_PAGE);
  188.                 $this->twig->addGlobal('Layout'$Layout);
  189.                 $this->twig->addGlobal('Page'$Page);
  190.                 $this->twig->addGlobal('title'$Page->getName());
  191.                 return;
  192.             }
  193.         }
  194.         if ($Layout) {
  195.             // lazy loadを制御するため, Layoutを取得しなおす.
  196.             $Layout $this->layoutRepository->get($Layout->getId());
  197.         } else {
  198.             // Layoutのデータがない場合は空のLayoutをセット
  199.             $Layout = new Layout();
  200.         }
  201.         $this->twig->addGlobal('Layout'$Layout);
  202.         $this->twig->addGlobal('Page'$Page);
  203.         $this->twig->addGlobal('title'$Page->getName());
  204.         $this->twig->addGlobal('isMaintenance'$this->systemService->isMaintenanceMode());
  205.     }
  206.     public function setAdminGlobals(RequestEvent $event)
  207.     {
  208.         // メニュー表示用配列.
  209.         $menus = [];
  210.         $this->twig->addGlobal('menus'$menus);
  211.         // メニューの権限制御.
  212.         $eccubeNav $this->eccubeConfig['eccube_nav'];
  213.         $Member $this->requestContext->getCurrentUser();
  214.         if ($Member instanceof Member) {
  215.             $AuthorityRoles $this->authorityRoleRepository->findBy(['Authority' => $Member->getAuthority()]);
  216.             $baseUrl $event->getRequest()->getBaseUrl().'/'.$this->eccubeConfig['eccube_admin_route'];
  217.             $eccubeNav $this->getDisplayEccubeNav($eccubeNav$AuthorityRoles$baseUrl);
  218.         }
  219.         $this->twig->addGlobal('eccubeNav'$eccubeNav);
  220.         $this->twig->addGlobal('isMaintenance'$this->systemService->isMaintenanceMode());
  221.     }
  222.     /**
  223.      * URLに対する権限有無チェックして表示するNavを返す
  224.      *
  225.      * @param array $parentNav
  226.      * @param AuthorityRole[] $AuthorityRoles
  227.      * @param string $baseUrl
  228.      *
  229.      * @return array
  230.      */
  231.     private function getDisplayEccubeNav($parentNav$AuthorityRoles$baseUrl)
  232.     {
  233.         $restrictUrls $this->eccubeConfig['eccube_restrict_file_upload_urls'];
  234.         foreach ($parentNav as $key => $childNav) {
  235.             if (array_key_exists('children'$childNav) && count($childNav['children']) > 0) {
  236.                 // 子のメニューがある場合は子の権限チェック
  237.                 $parentNav[$key]['children'] = $this->getDisplayEccubeNav($childNav['children'], $AuthorityRoles$baseUrl);
  238.                 if (count($parentNav[$key]['children']) <= 0) {
  239.                     // 子が存在しない場合は配列から削除
  240.                     unset($parentNav[$key]);
  241.                 }
  242.             } elseif (array_key_exists('url'$childNav)) {
  243.                 // 子のメニューがなく、URLが設定されている場合は権限があるURLか確認
  244.                 $param array_key_exists('param'$childNav) ? $childNav['param'] : [];
  245.                 $url $this->router->generate($childNav['url'], $param);
  246.                 foreach ($AuthorityRoles as $AuthorityRole) {
  247.                     $denyUrl str_replace('/''\/'$baseUrl.$AuthorityRole->getDenyUrl());
  248.                     if (preg_match("/^({$denyUrl})/i"$url)) {
  249.                         // 権限がないURLの場合は配列から削除
  250.                         unset($parentNav[$key]);
  251.                         break;
  252.                     }
  253.                 }
  254.                 if ($this->eccubeConfig['eccube_restrict_file_upload'] === '1' && in_array($childNav['url'], $restrictUrls)) {
  255.                     unset($parentNav[$key]);
  256.                 }
  257.             }
  258.         }
  259.         return $parentNav;
  260.     }
  261.     /**
  262.      * {@inheritdoc}
  263.      */
  264.     public static function getSubscribedEvents()
  265.     {
  266.         return [
  267.             KernelEvents::REQUEST => [
  268.                 // SecurityServiceProviderで、認証処理が完了した後に実行.
  269.                 ['onKernelRequest'6],
  270.             ],
  271.         ];
  272.     }
  273. }