TwigInitializeListener::setFrontVariables()   F
last analyzed

Complexity

Conditions 12
Paths 360

Size

Total Lines 69

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 12

Importance

Changes 0
Metric Value
cc 12
nc 360
nop 1
dl 0
loc 69
ccs 9
cts 9
cp 1
crap 12
rs 3.983
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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