Failed Conditions
Pull Request — 4.0 (#4528)
by Kentaro
07:39
created

TwigInitializeListener::getDisplayEccubeNav()   B

Complexity

Conditions 9
Paths 10

Size

Total Lines 28

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 90

Importance

Changes 0
Metric Value
cc 9
nc 10
nop 3
dl 0
loc 28
ccs 0
cts 0
cp 0
crap 90
rs 8.0555
c 0
b 0
f 0
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\RequestEvent;
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
0 ignored issues
show
Bug introduced by
There is no parameter named $mobileDetector. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
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 RequestEvent $event
152 158
     *
153 92
     * @throws NoResultException
154
     * @throws \Doctrine\ORM\NonUniqueResultException
155 92
     */
156 92
    public function onKernelRequest(RequestEvent $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 RequestEvent $event
175
     *
176
     * @throws \Doctrine\ORM\NonUniqueResultException
177 275
     */
178 275
    public function setFrontVariables(RequestEvent $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 RequestEvent $event
250
     */
251
    public function setAdminGlobals(RequestEvent $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