Failed Conditions
Pull Request — 4.0 (#3831)
by Ryo
31:54 queued 17:09
created

TwigInitializeListener::setFrontVariables()   F

Complexity

Conditions 15
Paths 864

Size

Total Lines 75

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 15

Importance

Changes 0
Metric Value
cc 15
nc 864
nop 1
dl 0
loc 75
rs 2.0964
c 0
b 0
f 0
ccs 9
cts 9
cp 1
crap 15

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) LOCKON CO.,LTD. All Rights Reserved.
7
 *
8
 * http://www.lockon.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->findOneBy(['url' => $route]);
197
198
        // 該当するPageがない場合は空のページをセット
199
        if (!$Page) {
200
            $Page = $this->pageRepository->newPage();
201
        }
202
203
        /** @var PageLayout[] $PageLayouts */
204
        $PageLayouts = $Page->getPageLayouts();
205
206
        // Pageに紐づくLayoutからDeviceTypeが一致するLayoutを探す
207
        $Layout = null;
208
        foreach ($PageLayouts as $PageLayout) {
209
            if ($PageLayout->getDeviceTypeId() == $type) {
210
                $Layout = $PageLayout->getLayout();
211
                break;
212
            }
213
        }
214
215
        // Pageに紐づくLayoutにDeviceTypeが一致するLayoutがない場合はPCのレイアウトを探す
216
        if (!$Layout) {
217
            log_info('fallback to PC layout');
218
            foreach ($PageLayouts as $PageLayout) {
219
                if ($PageLayout->getDeviceTypeId() == DeviceType::DEVICE_TYPE_PC) {
220
                    $Layout = $PageLayout->getLayout();
221
                    break;
222
                }
223
            }
224
        }
225
226
        // 管理者ログインしている場合にページレイアウトのプレビューが可能
227
        if ($request->get('preview')) {
228
            $is_admin = $request->getSession()->has('_security_admin');
229
            if ($is_admin) {
230
                $Page->getPageLayouts()->clear();
231
                $PageLayouts = $this->pageLayoutRepository->findBy(['layout_id' => 0]);
232
                foreach ($PageLayouts as $PageLayout) {
233
                    $Page->addPageLayout($PageLayout);
234
                }
235
236
                $Layout->getBlockPositions()->clear();
237
                $BlockPositions = $this->blockPositionRepository->findBy(['layout_id' => 0]);
238
                foreach ($BlockPositions as $BlockPosition) {
239
                    $Layout->addBlockPosition($BlockPosition);
240
                }
241
            }
242
        }
243
244
        // Layoutのデータがない場合は空のLayoutをセット
245
        if (!$Layout) {
246
            $Layout = new Layout();
247
        }
248
249
        $this->twig->addGlobal('Layout', $Layout);
250
        $this->twig->addGlobal('Page', $Page);
251
        $this->twig->addGlobal('title', $Page->getName());
252
    }
253
254
    /**
255
     * @param GetResponseEvent $event
256
     */
257
    public function setAdminGlobals(GetResponseEvent $event)
258
    {
259
        // メニュー表示用配列.
260
        $menus = [];
261
        $this->twig->addGlobal('menus', $menus);
262
263
        // メニューの権限制御.
264
        $eccubeNav = $this->eccubeConfig['eccube_nav'];
265
266
        $Member = $this->requestContext->getCurrentUser();
267
        if ($Member instanceof Member) {
268
            $AuthorityRoles = $this->authorityRoleRepository->findBy(['Authority' => $Member->getAuthority()]);
269
            $baseUrl = $event->getRequest()->getBaseUrl().'/'.$this->eccubeConfig['eccube_admin_route'];
270
            $eccubeNav = $this->getDisplayEccubeNav($eccubeNav, $AuthorityRoles, $baseUrl);
271
        }
272
        $this->twig->addGlobal('eccubeNav', $eccubeNav);
273
    }
274
275
    /**
276
     * URLに対する権限有無チェックして表示するNavを返す
277
     *
278
     * @param array $parentNav
279
     * @param AuthorityRole[] $AuthorityRoles
280
     * @param string $baseUrl
281
     *
282
     * @return array
283
     */
284
    private function getDisplayEccubeNav($parentNav, $AuthorityRoles, $baseUrl)
285
    {
286
        foreach ($parentNav as $key => $childNav) {
287
            if (array_key_exists('children', $childNav) && count($childNav['children']) > 0) {
288
                // 子のメニューがある場合は子の権限チェック
289
                $parentNav[$key]['children'] = $this->getDisplayEccubeNav($childNav['children'], $AuthorityRoles, $baseUrl);
290
291
                if (count($parentNav[$key]['children']) <= 0) {
292
                    // 子が存在しない場合は配列から削除
293
                    unset($parentNav[$key]);
294
                }
295
            } elseif (array_key_exists('url', $childNav)) {
296
                // 子のメニューがなく、URLが設定されている場合は権限があるURLか確認
297
                $param = array_key_exists('param', $childNav) ? $childNav['param'] : [];
298
                $url = $this->router->generate($childNav['url'], $param);
299
                foreach ($AuthorityRoles as $AuthorityRole) {
300
                    $denyUrl = str_replace('/', '\/', $baseUrl.$AuthorityRole->getDenyUrl());
301
                    if (preg_match("/^({$denyUrl})/i", $url)) {
302
                        // 権限がないURLの場合は配列から削除
303
                        unset($parentNav[$key]);
304
                        break;
305
                    }
306
                }
307
            }
308
        }
309
310
        return $parentNav;
311
    }
312
313
    /**
314
     * {@inheritdoc}
315
     */
316
    public static function getSubscribedEvents()
317
    {
318
        return [
319
            KernelEvents::REQUEST => [
320
                // SecurityServiceProviderで、認証処理が完了した後に実行.
321
                ['onKernelRequest', 6],
322
            ],
323
        ];
324
    }
325
}
326