src/Eccube/EventListener/TwigInitializeListener.php line 156

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