src/Eccube/EventListener/TwigInitializeListener.php line 264

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