Failed Conditions
Pull Request — experimental/3.1 (#2526)
by Kentaro
40:11 queued 13:18
created

src/Eccube/Application.php (1 issue)

Labels
Severity

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/*
3
 * This file is part of EC-CUBE
4
 *
5
 * Copyright(c) 2000-2015 LOCKON CO.,LTD. All Rights Reserved.
6
 *
7
 * http://www.lockon.co.jp/
8
 *
9
 * This program is free software; you can redistribute it and/or
10
 * modify it under the terms of the GNU General Public License
11
 * as published by the Free Software Foundation; either version 2
12
 * of the License, or (at your option) any later version.
13
 *
14
 * This program is distributed in the hope that it will be useful,
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
 * GNU General Public License for more details.
18
 *
19
 * You should have received a copy of the GNU General Public License
20
 * along with this program; if not, write to the Free Software
21
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22
 */
23
24
namespace Eccube;
25
26
use Doctrine\DBAL\Types\Type;
27
use Eccube\Doctrine\DBAL\Types\UTCDateTimeType;
28
use Eccube\Doctrine\DBAL\Types\UTCDateTimeTzType;
29
use Eccube\Doctrine\EventSubscriber\InitSubscriber;
30
use Eccube\Doctrine\ORM\Mapping\Driver\AnnotationDriver;
31
use Eccube\Entity\BaseInfo;
32
use Eccube\Plugin\ConfigManager as PluginConfigManager;
33
use Eccube\Routing\EccubeRouter;
34
use Eccube\ServiceProvider\CompatRepositoryProvider;
35
use Eccube\ServiceProvider\CompatServiceProvider;
36
use Eccube\ServiceProvider\DiServiceProvider;
37
use Eccube\ServiceProvider\EntityEventServiceProvider;
38
use Eccube\ServiceProvider\MobileDetectServiceProvider;
39
use Eccube\ServiceProvider\TwigLintServiceProvider;
40
use Sergiors\Silex\Routing\ChainUrlGenerator;
41
use Sergiors\Silex\Routing\ChainUrlMatcher;
42
use Symfony\Component\Dotenv\Dotenv;
43
use Symfony\Component\Finder\Finder;
44
use Symfony\Component\HttpFoundation\Request;
45
use Symfony\Component\HttpFoundation\Response;
46
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
47
use Symfony\Component\HttpKernel\KernelEvents;
48
49
class Application extends \Silex\Application
50
{
51
    use \Silex\Application\FormTrait;
52
    use \Silex\Application\UrlGeneratorTrait;
53
    use \Silex\Application\MonologTrait;
54
    use \Silex\Application\SwiftmailerTrait;
55
    use \Silex\Application\SecurityTrait;
56
    use \Silex\Application\TranslationTrait;
57
    use \Eccube\Application\ApplicationTrait;
58
    use \Eccube\Application\SecurityTrait;
59
    use \Eccube\Application\TwigTrait;
60
61
    protected static $instance;
62
63
    protected $initialized = false;
64
    protected $initializedPlugin = false;
65
    protected $testMode = false;
66
67 1094
    public static function getInstance(array $values = array())
68
    {
69 1094
        if (!is_object(self::$instance)) {
70 1094
            self::$instance = new Application($values);
71
        }
72
73 1094
        return self::$instance;
74
    }
75
76 1094
    public static function clearInstance()
77
    {
78 1094
        self::$instance = null;
79
    }
80
81
    final public function __clone()
82
    {
83
        throw new \Exception('Clone is not allowed against '.get_class($this));
84
    }
85
86 1095
    public function __construct(array $values = array())
87
    {
88 1095
        parent::__construct($values);
89
90 1095
        if (is_null(self::$instance)) {
91 1095
            self::$instance = $this;
92
        }
93
94
        // load config
95 1095
        $this->initConfig();
96
97
        // init monolog
98 1095
        $this->initLogger();
99
    }
100
101
    /**
102
     * Application::runが実行されているか親クラスのプロパティから判定
103
     *
104
     * @return bool
105
     */
106 1094
    public function isBooted()
107
    {
108 1094
        return $this->booted;
109
    }
110
111 1095
    public function initConfig()
112
    {
113
        // load .env
114 1095
        $envFile = __DIR__.'/../../.env';
115 1095
        if (file_exists($envFile)) {
116
            (new Dotenv())->load($envFile);
117
        }
118
119
        // load config
120
        $this['config'] = function() {
121 1095
            $configAll = array();
122 1095
            $this->parseConfig('constant', $configAll)
123 1095
                ->parseConfig('path', $configAll)
124 1095
                ->parseConfig('config', $configAll)
125 1095
                ->parseConfig('database', $configAll)
126 1095
                ->parseConfig('mail', $configAll)
127 1095
                ->parseConfig('log', $configAll)
128 1095
                ->parseConfig('nav', $configAll, true)
129 1095
                ->parseConfig('doctrine_cache', $configAll)
130 1095
                ->parseConfig('http_cache', $configAll)
131 1095
                ->parseConfig('session_handler', $configAll);
132
133 1095
            return $configAll;
134
        };
135
    }
136
137 1095
    public function initLogger()
138
    {
139 1095
        $app = $this;
140 1095
        $this->register(new ServiceProvider\LogServiceProvider($app));
141
    }
142
143 1094
    public function initialize()
144
    {
145 1094
        if ($this->initialized) {
146 2
            return;
147
        }
148
149
        // init locale
150 1094
        $this->initLocale();
151
152
        // init session
153 1094
        if (!$this->isSessionStarted()) {
154 1094
            $this->initSession();
155
        }
156
157
        // init twig
158 1094
        $this->initRendering();
159
160
        // init provider
161 1094
        $this->register(new \Silex\Provider\HttpCacheServiceProvider(), array(
162 1094
            'http_cache.cache_dir' => __DIR__.'/../../app/cache/http/',
163
        ));
164 1094
        $this->register(new \Silex\Provider\HttpFragmentServiceProvider());
165 1094
        $this->register(new \Silex\Provider\FormServiceProvider());
166 1094
        $this->register(new \Silex\Provider\SerializerServiceProvider());
167 1094
        $this->register(new \Silex\Provider\ValidatorServiceProvider());
168 1094
        $this->register(new \Saxulum\Validator\Provider\SaxulumValidatorProvider());
169 1094
        $this->register(new MobileDetectServiceProvider());
170 1094
        $this->register(new TwigLintServiceProvider());
171
172
        $this->error(function (\Exception $e, Request $request, $code) {
173 23
            if ($this['debug']) {
174 23
                return;
175
            }
176
177
            switch ($code) {
178
                case 403:
179
                    $title = 'アクセスできません。';
180
                    $message = 'お探しのページはアクセスができない状況にあるか、移動もしくは削除された可能性があります。';
181
                    break;
182
                case 404:
183
                    $title = 'ページがみつかりません。';
184
                    $message = 'URLに間違いがないかご確認ください。';
185
                    break;
186
                default:
187
                    $title = 'システムエラーが発生しました。';
188
                    $message = '大変お手数ですが、サイト管理者までご連絡ください。';
189
                    break;
190
            }
191
192
            return $this->render('error.twig', array(
193
                'error_title' => $title,
194
                'error_message' => $message,
195
            ));
196 1094
        });
197
198
        // init mailer
199 1094
        $this->initMailer();
200
201 1094
        $this->register(new \Sergiors\Silex\Provider\DoctrineCacheServiceProvider());
202 1094
        $this->register(new \Sergiors\Silex\Provider\AnnotationsServiceProvider(), [
203 1094
            'annotations.debug' => $this['debug'],
204
            'annotations.options' => [
205 1094
                'cache_driver' => $this['debug'] ? 'array' : 'filesystem',
206 1094
                'cache_dir' => $this['debug'] ? null : __DIR__.'/../../app/cache/annotation'
207
            ]
208
        ]);
209
210
        // init doctrine orm
211 1094
        $this->initDoctrine();
212
213
        // Set up the DBAL connection now to check for a proper connection to the database.
214 1094
        $this->checkDatabaseConnection();
215
216
        // init security
217 1094
        $this->initSecurity();
218
219 1094
        $this->register(new \Sergiors\Silex\Provider\RoutingServiceProvider(), [
220 1094
            'routing.cache_dir' => $this['debug'] ? null : __DIR__.'/../../app/cache/routing'
221
        ]);
222 1094
        $this->register(new \Sergiors\Silex\Provider\TemplatingServiceProvider());
223 1094
        $this->register(new \Sergiors\Silex\Provider\SensioFrameworkExtraServiceProvider(), [
224 1094
            'request' => [
225
                'auto_convert' => true
226
            ]
227
        ]);
228
        // init proxy
229 1094
        $this->initProxy();
230
231
        // init ec-cube service provider
232 1094
        $this->register(new DiServiceProvider(), [
233
            'eccube.di.scanners' => [
234 1094
                new \Eccube\Di\Scanner\ComponentScanner([
235 1094
                    $this['config']['root_dir'].'/app/Acme/Controller',
236 1094
                    $this['config']['root_dir'].'/src/Eccube/Controller'
237
                ]),
238 1094
                new \Eccube\Di\Scanner\FormTypeScanner([
239 1094
                    $this['config']['root_dir'].'/src/Eccube/Form/Type'
240
                ]),
241 1094
                new \Eccube\Di\Scanner\FormExtensionScanner([
242 1094
                    $this['config']['root_dir'].'/src/Eccube/Form/Extension'
243
                ]),
244 1094
                new \Eccube\Di\Scanner\ServiceScanner([
245 1094
                    $this['config']['root_dir'].'/src/Eccube/Service'
246
                ]),
247 1094
                new \Eccube\Di\Scanner\RepositoryScanner([
248 1094
                    $this['config']['root_dir'].'/src/Eccube/Repository'
249
                ])
250
            ],
251 1094
            'eccube.di.generator.dir' => $this['config']['root_dir'].'/app/cache/provider'
252
        ]);
253
254 1094
        $this->register(new CompatRepositoryProvider());
255 1094
        $this->register(new CompatServiceProvider());
256 1094
        $this->register(new ServiceProvider\EccubeServiceProvider());
257
258 1094
        $this->register(new \Silex\Provider\ServiceControllerServiceProvider());
259 1094
        Request::enableHttpMethodParameterOverride(); // PUTやDELETEできるようにする
260
261
        // ルーティングの設定
262
        // TODO EccubeRoutingServiceProviderに移植する.
263 1094
        $app = $this;
264
        $this['eccube.router'] = $this->protect(function($resoure, $cachePrefix) use ($app) {
265
            $options = [
266 1094
                'debug' => $app['debug'],
267 1094
                'cache_dir' => $app['routing.cache_dir'],
268 1094
                'matcher_base_class' => $app['request_matcher_class'],
269 1094
                'matcher_class' => $app['request_matcher_class'],
270 1094
                'matcher_cache_class' => $cachePrefix.'UrlMatcher',
271 1094
                'generator_cache_class' => $cachePrefix.'UrlGenerator'
272
            ];
273 1094
            $router = new EccubeRouter(
274 1094
                $app['routing.loader'],
275 1094
                $resoure,
276 1094
                $options,
277 1094
                $app['request_context'],
278 1094
                $app['logger']
279
            );
280
281 1094
            $router->setAdminPrefix($app['config']['admin_route']);
282 1094
            $router->setUserDataPrefix($app['config']['user_data_route']);
283 1094
            $router->setRequireHttps($app['config']['force_ssl']);
284
285 1094
            return $router;
286 1094
        });
287
288
        $this['eccube.router.origin'] = function ($app) {
289 1094
            $resource = __DIR__.'/Controller';
290 1094
            $cachePrefix = 'Origin';
291
292 1094
            return $app['eccube.router']($resource, $cachePrefix);
293
        };
294
295
        $this['eccube.routers.plugin'] = function ($app) {
296
            // TODO 有効なプラグインを対象とする必要がある.
297 1094
            $dirs = Finder::create()
298 1094
                ->in($app['config']['root_dir'].'/app/Plugin')
299 1094
                ->name('Controller')
300 1094
                ->directories();
301
302 1094
            $routers = [];
303 1094
            foreach ($dirs as $dir) {
304 1094
                $realPath = $dir->getRealPath();
305 1094
                $pluginCode = basename(dirname($realPath));
306 1094
                $routers[] = $app['eccube.router']($realPath, 'Plugin'.$pluginCode);
307
            }
308
309 1094
            return $routers;
310
        };
311
312
        $this['eccube.router.extend'] = function ($app) {
313
            // TODO ディレクトリ名は暫定
314 1094
            $resource = $app['config']['root_dir'].'/app/Acme/Controller';
315 1094
            $cachePrefix = 'Extend';
316
317 1094
            $router = $app['eccube.router']($resource, $cachePrefix);
318
319 1094
            return $router;
320
        };
321
322 View Code Duplication
        $this->extend('request_matcher', function ($matcher, $app) {
323 1094
            $matchers = [];
324 1094
            $matchers[] = $app['eccube.router.extend'];
325 1094
            foreach ($app['eccube.routers.plugin'] as $router) {
326 1094
                $matchers[] = $router;
327
            };
328 1094
            $matchers[] = $app['eccube.router.origin'];
329 1094
            $matchers[] = $matcher;
330
331 1094
            return new ChainUrlMatcher($matchers, $app['request_context']);
332 1094
        });
333
334 View Code Duplication
        $this->extend('url_generator', function ($generator, $app) {
335 1094
            $generators = [];
336 1094
            $generators[] = $app['eccube.router.extend'];
337 1094
            foreach ($app['eccube.routers.plugin'] as $router) {
338 1094
                $generators[] = $router;
339
            };
340 1094
            $generators[] = $app['eccube.router.origin'];
341 1094
            $generators[] = $generator;
342
343 1094
            return new ChainUrlGenerator($generators, $app['request_context']);
344 1094
        });
345
346
        // Route CollectionにEC-CUBEで定義したルーティングを追加(debug tool barに出力するため)
347
        $this->extend('routes', function ($routes, $app) {
348 1094
            $routes->addCollection($app['eccube.router.extend']->getRouteCollection());
349 1094
            foreach ($app['eccube.routers.plugin'] as $router) {
350 1094
                $routes->addCollection($router->getRouteCollection());
351
            };
352 1094
            $routes->addCollection($app['eccube.router.origin']->getRouteCollection());
353
354 1094
            return $routes;
355 1094
        });
356
357
        // init http cache
358 1094
        $this->initCacheRequest();
359
360 1094
        $this->initialized = true;
361
    }
362
363 1094
    public function initLocale()
364
    {
365
        // locale
366 1094
        if (!empty($this['config']['locale'])) {
367 1094
            \Locale::setDefault($this['config']['locale']);
368
        };
369
370
        // timezone
371 1094
        if (!empty($this['config']['timezone'])) {
372 1094
            date_default_timezone_set($this['config']['timezone']);
373
        }
374
375 1094
        $this->register(new \Silex\Provider\TranslationServiceProvider(), array(
376 1094
            'locale' => $this['config']['locale'],
377 1094
            'translator.cache_dir' => $this['debug'] ? null : $this['config']['root_dir'].'/app/cache/translator',
378
            'locale_fallbacks' => ['ja', 'en'],
379
        ));
380
        $this->extend('translator', function ($translator, \Silex\Application $app) {
381 1094
            $translator->addLoader('php', new \Symfony\Component\Translation\Loader\PhpFileLoader());
382
383 1094
            $file = __DIR__.'/Resource/locale/messages.'.$app['locale'].'.php';
384 1094
            if (file_exists($file)) {
385 1094
                $translator->addResource('php', $file, $app['locale']);
386 1094
                $translator->addResource('php', $file, $app['locale'], 'validators');
387
            }
388
389 1094
            return $translator;
390 1094
        });
391
    }
392
393 1094
    public function initSession()
394
    {
395 1094
        $this->register(new \Silex\Provider\SessionServiceProvider(), array(
396 1094
            'session.storage.save_path' => $this['config']['root_dir'].'/app/cache/eccube/session',
397
            'session.storage.options' => array(
398 1094
                'name' => $this['config']['cookie_name'],
399 1094
                'cookie_path' => $this['config']['root_urlpath'] ?: '/',
400 1094
                'cookie_secure' => $this['config']['force_ssl'],
401 1094
                'cookie_lifetime' => $this['config']['cookie_lifetime'],
402
                'cookie_httponly' => true,
403
                // cookie_domainは指定しない
404
                // http://blog.tokumaru.org/2011/10/cookiedomain.html
405
            ),
406
        ));
407
408 1094
        $options = $this['config']['session_handler'];
409
410 1094
        if ($options['enabled']) {
411
            // @see http://silex.sensiolabs.org/doc/providers/session.html#custom-session-configurations
412
            $this['session.storage.handler'] = null;
413
            ini_set('session.save_handler', $options['save_handler']);
414
            ini_set('session.save_path', $options['save_path']);
415
        }
416
    }
417
418 1094
    public function initRendering()
419
    {
420 1094
        $this->register(new \Silex\Provider\TwigServiceProvider(), array(
421 1094
            'twig.form.templates' => array('Form/form_layout.twig'),
422
        ));
423
        $this->extend('twig', function (\Twig_Environment $twig, \Silex\Application $app) {
424 1094
            $twig->addExtension(new \Eccube\Twig\Extension\EccubeExtension($app));
425 1094
            $twig->addExtension(new \Twig_Extension_StringLoader());
426
427 1094
            return $twig;
428 1094
        });
429
430
        $this->before(function (Request $request, \Silex\Application $app) {
431 318
            $app['admin'] = $app['front'] = false;
432 318
            $pathinfo = rawurldecode($request->getPathInfo());
433 318
            if (strpos($pathinfo, '/'.trim($app['config']['admin_route'], '/').'/') === 0) {
434 221
                $app['admin'] = true;
435
            } else {
436 97
                $app['front'] = true;
437
            }
438
439
            // フロント or 管理画面ごとにtwigの探索パスを切り替える.
440 318
            if ($app->isAdminRequest()) {
441 221
                if (file_exists(__DIR__.'/../../app/template/admin')) {
442 221
                    $paths[] = __DIR__.'/../../app/template/admin';
443
                }
444 221
                $paths[] = $app['config']['template_admin_realdir'];
445 221
                $paths[] = __DIR__.'/../../app/Plugin';
446 221
                $cacheDir =  __DIR__.'/../../app/cache/twig/admin';
447
            } else {
448
                // モバイル端末時、smartphoneディレクトリを探索パスに追加する.
449 97
                if ($app['mobile_detect.device_type'] == \Eccube\Entity\Master\DeviceType::DEVICE_TYPE_SP) {
450
                    if (file_exists(__DIR__.'/../../app/template/smartphone')) {
451
                        $paths[] = __DIR__.'/../../app/template/smartphone';
452
                    }
453
                    $paths[] = __DIR__.'/Resource/template/smartphone';
454
                }
455
456 97
                if (file_exists($app['config']['template_realdir'])) {
457 97
                    $paths[] = $app['config']['template_realdir'];
458
                }
459 97
                $paths[] = $app['config']['template_default_realdir'];
460 97
                $paths[] = __DIR__.'/../../app/Plugin';
461 97
                $cacheDir =  __DIR__.'/../../app/cache/twig/'.$app['config']['template_code'];
462
            }
463 318
            $app['twig']->setCache($app['debug'] ? null : $cacheDir);
464 318
            $app['twig.loader']->addLoader(new \Twig_Loader_Filesystem($paths));
465
466
            // 管理画面のIP制限チェック.
467 318
            if ($app->isAdminRequest()) {
468
                // IP制限チェック
469 221
                $allowHost = $app['config']['admin_allow_host'];
470 221
                if (count($allowHost) > 0) {
471
                    if (array_search($app['request_stack']->getCurrentRequest()->getClientIp(), $allowHost) === false) {
472
                        throw new \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException();
473
                    }
474
                }
475
            }
476 1094
        }, self::EARLY_EVENT);
477
478
        // twigのグローバル変数を定義.
479
        $this->on(\Symfony\Component\HttpKernel\KernelEvents::CONTROLLER, function (\Symfony\Component\HttpKernel\Event\FilterControllerEvent $event) {
480
            // 未ログイン時にマイページや管理画面以下にアクセスするとSubRequestで実行されるため,
481
            // $event->isMasterRequest()ではなく、グローバル変数が初期化済かどうかの判定を行う
482 316
            if (isset($this['twig_global_initialized']) && $this['twig_global_initialized'] === true) {
483 71
                return;
484
            }
485
            // ショップ基本情報
486 316
            $this['twig']->addGlobal('BaseInfo', $this[BaseInfo::class]);
487
488 316
            if ($this->isAdminRequest()) {
489
                // 管理画面
490
                // 管理画面メニュー
491 221
                $menus = array('', '', '');
492 221
                $this['twig']->addGlobal('menus', $menus);
493
494 221
                $Member = $this->user();
495 221
                if (is_object($Member)) {
496
                    // ログインしていれば管理者のロールを取得
497 218
                    $AuthorityRoles = $this['eccube.repository.authority_role']->findBy(array('Authority' => $Member->getAuthority()));
498
499 218
                    $roles = array();
500 218
                    $request = $event->getRequest();
501 218
                    foreach ($AuthorityRoles as $AuthorityRole) {
502
                        // 管理画面でメニュー制御するため相対パス全てをセット
503 3
                        $roles[] = $request->getBaseUrl().'/'.$this['config']['admin_route'].$AuthorityRole->getDenyUrl();
504
                    }
505
506 221
                    $this['twig']->addGlobal('AuthorityRoles', $roles);
507
                }
508
509
            } else {
510
                // フロント画面
511 95
                $request = $event->getRequest();
512 95
                $route = $request->attributes->get('_route');
513
514
                // ユーザ作成画面
515 95
                if ($route === 'user_data') {
516 2
                    $params = $request->attributes->get('_route_params');
517 2
                    $route = $params['route'];
518
                    // プレビュー画面
519 93
                } elseif ($request->get('preview')) {
520
                    $route = 'preview';
521
                }
522
523
                try {
524 95
                    $device_type_id = $this['mobile_detect.device_type'];
525
526
                    // TODO デバッグ用
527 95
                    if ($request->query->has('device_type_id')) {
528
                        $device_type_id = $request->get('device_type_id', \Eccube\Entity\Master\DeviceType::DEVICE_TYPE_PC);
529
                    }
530
531 95
                    $DeviceType = $this['eccube.repository.master.device_type']
532 95
                        ->find($device_type_id);
533 95
                    $qb = $this['eccube.repository.page']->createQueryBuilder('p');
534 95
                    $Page = $qb->select('p, pll,l, bp, b')
535 95
                        ->leftJoin('p.PageLayouts', 'pll')
536 95
                        ->leftJoin('pll.Layout', 'l')
537 95
                        ->leftJoin('l.BlockPositions', 'bp')
538 95
                        ->leftJoin('bp.Block', 'b')
539 95
                        ->where('p.url = :route')
540 95
                        ->andWhere('l.DeviceType = :DeviceType')
541 95
                        ->orderBy('bp.block_row', 'ASC')
542 95
                        ->setParameter('route', $route)
543 95
                        ->setParameter('DeviceType', $DeviceType)
544 95
                        ->getQuery()
545 95
                        ->getSingleResult();
546 33
                } catch (\Doctrine\ORM\NoResultException $e) {
547 33
                    $Page = $this['eccube.repository.page']->newPage($DeviceType);
0 ignored issues
show
The variable $DeviceType does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
548
                }
549
550 95
                $this['twig']->addGlobal('Page', $Page);
551 95
                $this['twig']->addGlobal('title', $Page->getName());
552
            }
553
554 316
            $this['twig_global_initialized'] = true;
555 1094
        });
556
    }
557
558 1094
    public function initMailer()
559
    {
560
561
        // メール送信時の文字エンコード指定(デフォルトはUTF-8)
562 1094
        if (isset($this['config']['mail']['charset_iso_2022_jp']) && is_bool($this['config']['mail']['charset_iso_2022_jp'])) {
563
            if ($this['config']['mail']['charset_iso_2022_jp'] === true) {
564
                \Swift::init(function () {
565
                    \Swift_DependencyContainer::getInstance()
566
                        ->register('mime.qpheaderencoder')
567
                        ->asAliasOf('mime.base64headerencoder');
568
                    \Swift_Preferences::getInstance()->setCharset('iso-2022-jp');
569
                });
570
            }
571
        }
572
573 1094
        $this->register(new \Silex\Provider\SwiftmailerServiceProvider());
574 1094
        $this['swiftmailer.options'] = $this['config']['mail'];
575
576 1094
        if (isset($this['config']['mail']['spool']) && is_bool($this['config']['mail']['spool'])) {
577 1094
            $this['swiftmailer.use_spool'] = $this['config']['mail']['spool'];
578
        }
579
        // デフォルトはsmtpを使用
580 1094
        $transport = $this['config']['mail']['transport'];
581 1094
        if ($transport == 'sendmail') {
582
            $this['swiftmailer.transport'] = \Swift_SendmailTransport::newInstance();
583 1094
        } elseif ($transport == 'mail') {
584
            $this['swiftmailer.transport'] = \Swift_MailTransport::newInstance();
585
        }
586
    }
587
588 1094
    public function initDoctrine()
589
    {
590 1094
        $this->register(new EntityEventServiceProvider());
591 1094
        $this->register(new \Silex\Provider\DoctrineServiceProvider(), array(
592
            'dbs.options' => array(
593 1094
                'default' => $this['config']['database']
594
            )
595
        ));
596 1094
        $this->register(new \Saxulum\DoctrineOrmManagerRegistry\Provider\DoctrineOrmManagerRegistryProvider());
597
598 1094
        $app = $this;
599
        $this->extend('db.event_manager', function ($evm) use ($app) {
600 1094
            $initSubscriber = new InitSubscriber($app);
601 1094
            $evm->addEventSubscriber($initSubscriber);
602
603 1094
            return $evm;
604 1094
        });
605
606
        // UTCで保存
607
        // @see http://doctrine-orm.readthedocs.org/projects/doctrine-orm/en/latest/cookbook/working-with-datetime.html
608 1094
        UTCDateTimeType::setTimeZone($this['config']['timezone']);
609 1094
        UTCDateTimeTzType::setTimeZone($this['config']['timezone']);
610 1094
        Type::overrideType('datetime', UTCDateTimeType::class);
611 1094
        Type::overrideType('datetimetz', UTCDateTimeTzType::class);
612
613
        // プラグインのmetadata定義を合わせて行う.
614 1094
        $pluginConfigs = PluginConfigManager::getPluginConfigAll($this['debug']);
615 1094
        $ormMappings = array();
616 1094
        $ormMappings[] = array(
617
             'type' => 'annotation',
618
             'namespace' => 'Eccube\Entity',
619
             'path' => array(
620
                 __DIR__.'/Entity'
621
             ),
622
             'use_simple_annotation_reader' => false,
623
         );
624
625
        // TODO namespace は暫定
626 1094
        $ormMappings[] = array(
627
            'type' => 'annotation',
628
            'namespace' => 'Acme\Entity',
629
            'path' => array(
630
                __DIR__.'/../../app/Acme/Entity',
631
            ),
632
            'use_simple_annotation_reader' => false,
633
        );
634
635 1094
        foreach ($pluginConfigs as $code) {
636 1094
            $config = $code['config'];
637
            // Doctrine Extend
638 1094
            if (isset($config['orm.path']) && is_array($config['orm.path'])) {
639
                $paths = array();
640 View Code Duplication
                foreach ($config['orm.path'] as $path) {
641
                    $paths[] = $this['config']['plugin_realdir'].'/'.$config['code'].$path;
642
                }
643
                $ormMappings[] = array(
644
                    'type' => 'yml',
645
                    'namespace' => 'Plugin\\'.$config['code'].'\\Entity',
646
                    'path' => $paths,
647
                );
648
                $ormMappings[] = array(
649 1094
                    'type' => 'annotation',
650
                    'namespace' => 'Plugin\\'.$config['code'].'\\Entity',
651
                    'path' => $paths,
652
                    'use_simple_annotation_reader' => false,
653
                );
654
            }
655
        }
656
657
        $options = array(
658 1094
            'mappings' => $ormMappings
659
        );
660
661 1094
        if (!$this['debug']) {
662
            $cacheDrivers = array();
663
            if (array_key_exists('doctrine_cache', $this['config'])) {
664
                $cacheDrivers = $this['config']['doctrine_cache'];
665
            }
666
667
            if (array_key_exists('metadata_cache', $cacheDrivers)) {
668
                $options['metadata_cache'] = $cacheDrivers['metadata_cache'];
669
            }
670
            if (array_key_exists('query_cache', $cacheDrivers)) {
671
                $options['query_cache'] = $cacheDrivers['query_cache'];
672
            }
673
            if (array_key_exists('result_cache', $cacheDrivers)) {
674
                $options['result_cache'] = $cacheDrivers['result_cache'];
675
            }
676
            if (array_key_exists('hydration_cache', $cacheDrivers)) {
677
                $options['hydration_cache'] = $cacheDrivers['hydration_cache'];
678
            }
679
        }
680
681 1094
        $this->register(new \Dflydev\Provider\DoctrineOrm\DoctrineOrmServiceProvider(), array(
682 1094
            'orm.proxies_dir' => __DIR__.'/../../app/cache/doctrine/proxies',
683 1094
            'orm.em.options' => $options,
684
            'orm.custom.functions.string' => array(
685
                'NORMALIZE' => 'Eccube\Doctrine\ORM\Query\Normalize',
686
            ),
687
            'orm.custom.functions.numeric' => array(
688
                'EXTRACT' => 'Eccube\Doctrine\ORM\Query\Extract',
689
            ),
690
        ));
691
692 1094
        $this->extend(
693 1094
            'orm.em.config',
694
            function (\Doctrine\ORM\Configuration $config, \Silex\Application $app) {
695
696
                /** @var $chain \Doctrine\Common\Persistence\Mapping\Driver\MappingDriverChain */
697 1094
                $chain = $config->getMetadataDriverImpl();
698 1094
                $drivers = $chain->getDrivers();
699 1094
                foreach ($drivers as $namespace => $oldDriver) {
700 1094
                    if ('Eccube\Entity' === $namespace) {
701 1094
                        $newDriver = new AnnotationDriver(
702 1094
                            $app['annotations'],
703 1094
                            $oldDriver->getPaths());
704 1094
                        $newDriver->setFileExtension($oldDriver->getFileExtension());
705 1094
                        $newDriver->addExcludePaths($oldDriver->getExcludePaths());
706 1094
                        $newDriver->setTraitProxiesDirectory(
707 1094
                            realpath(__DIR__.'/../../app/proxy/entity'));
708 1094
                        $chain->addDriver($newDriver, $namespace);
709
                    }
710
                }
711
712 1094
                return $config;
713 1094
            }
714
        );
715
716
        $this->extend('orm.em', function (\Doctrine\ORM\EntityManager $em, \Silex\Application $app) {
717
            // save
718 1094
            $saveEventSubscriber = new \Eccube\Doctrine\EventSubscriber\SaveEventSubscriber($app);
719 1094
            $em->getEventManager()->addEventSubscriber($saveEventSubscriber);
720
721
            // clear cache
722 1094
            $clearCacheEventSubscriber = new \Eccube\Doctrine\EventSubscriber\ClearCacheEventSubscriber($app);
723 1094
            $em->getEventManager()->addEventSubscriber($clearCacheEventSubscriber);
724
725
            // filters
726 1094
            $config = $em->getConfiguration();
727 1094
            $config->addFilter("nostock_hidden", '\Eccube\Doctrine\Filter\NoStockHiddenFilter');
728 1094
            $config->addFilter("incomplete_order_status_hidden", '\Eccube\Doctrine\Filter\OrderStatusFilter');
729
730 1094
            return $em;
731 1094
        });
732
733 1094
        if (!$this['debug']) {
734
            // second level cacheの設定.
735
            $this->extend(
736
                'orm.em.config',
737
                function (\Doctrine\ORM\Configuration $config, \Silex\Application $app) {
738
                    $config->setSecondLevelCacheEnabled();
739
                    $cacheConfig = $config->getSecondLevelCacheConfiguration();
740
                    $regionConfig = $cacheConfig->getRegionsConfiguration();
741
                    // TODO キャッシュ先は設定で切り替えられるように
742
                    $cache = $this['orm.cache.factory'](
743
                        'filesystem',
744
                        [
745
                            'path' => __DIR__.'/../../app/cache/doctrine/second'
746
                        ]
747
                    );
748
                    $factory = new \Doctrine\ORM\Cache\DefaultCacheFactory($regionConfig, $cache);
749
                    $cacheConfig->setCacheFactory($factory);
750
751
                    return $config;
752
                }
753
            );
754
        }
755
    }
756
757 1094
    public function initSecurity()
758
    {
759 1094
        $this->register(new \Silex\Provider\SecurityServiceProvider());
760 1094
        $this->register(new \Silex\Provider\CsrfServiceProvider());
761 1094
        $this->register(new \Silex\Provider\RememberMeServiceProvider());
762
763 1094
        $this['security.firewalls'] = array(
764 1094
            'admin' => array(
765 1094
                'pattern' => "^/{$this['config']['admin_route']}/",
766
                'form' => array(
767 1094
                    'login_path' => "/{$this['config']['admin_route']}/login",
768 1094
                    'check_path' => "/{$this['config']['admin_route']}/login_check",
769 1094
                    'username_parameter' => 'login_id',
770 1094
                    'password_parameter' => 'password',
771
                    'with_csrf' => true,
772
                    'use_forward' => true,
773
                ),
774
                'logout' => array(
775 1094
                    'logout_path' => "/{$this['config']['admin_route']}/logout",
776 1094
                    'target_url' => "/{$this['config']['admin_route']}/",
777
                ),
778 1094
                'users' => $this['orm.em']->getRepository('Eccube\Entity\Member'),
779
                'anonymous' => true,
780
            ),
781
            'customer' => array(
782 1094
                'pattern' => '^/',
783
                'form' => array(
784
                    'login_path' => '/mypage/login',
785
                    'check_path' => '/login_check',
786
                    'username_parameter' => 'login_email',
787
                    'password_parameter' => 'login_pass',
788
                    'with_csrf' => true,
789
                    'use_forward' => true,
790
                ),
791
                'logout' => array(
792
                    'logout_path' => '/logout',
793
                    'target_url' => '/',
794
                ),
795
                'remember_me' => array(
796 1094
                    'key' => sha1($this['config']['auth_magic']),
797 1094
                    'name' => $this['config']['cookie_name'].'_rememberme',
798
                    // lifetimeはデフォルトの1年間にする
799
                    // 'lifetime' => $this['config']['cookie_lifetime'],
800 1094
                    'path' => $this['config']['root_urlpath'] ?: '/',
801 1094
                    'secure' => $this['config']['force_ssl'],
802
                    'httponly' => true,
803
                    'always_remember_me' => false,
804 1094
                    'remember_me_parameter' => 'login_memory',
805
                ),
806 1094
                'users' => $this['orm.em']->getRepository('Eccube\Entity\Customer'),
807
                'anonymous' => true,
808
            ),
809
        );
810
811 1094
        $channel = null;
812
        // 強制SSL
813 1094
        if ($this['config']['force_ssl'] == \Eccube\Common\Constant::ENABLED) {
814
            $channel = "https";
815
        }
816
817 1094
        $this['security.access_rules'] = array(
818 1094
            array("^/{$this['config']['admin_route']}/login", 'IS_AUTHENTICATED_ANONYMOUSLY', $channel),
819 1094
            array("^/{$this['config']['admin_route']}/", 'ROLE_ADMIN', $channel),
820 1094
            array('^/mypage/login', 'IS_AUTHENTICATED_ANONYMOUSLY', $channel),
821 1094
            array('^/mypage/withdraw_complete', 'IS_AUTHENTICATED_ANONYMOUSLY', $channel),
822 1094
            array('^/mypage/change', 'IS_AUTHENTICATED_FULLY', $channel),
823 1094
            array('^/mypage', 'ROLE_USER', $channel),
824
        );
825
826
        $this['eccube.password_encoder'] = function ($app) {
827 1092
            return new \Eccube\Security\Core\Encoder\PasswordEncoder($app['config']);
828
        };
829
        $this['security.encoder_factory'] = function ($app) {
830 1092
            return new \Symfony\Component\Security\Core\Encoder\EncoderFactory(array(
831 1092
                'Eccube\Entity\Customer' => $app['eccube.password_encoder'],
832 1092
                'Eccube\Entity\Member' => $app['eccube.password_encoder'],
833
            ));
834
        };
835
        $this['eccube.event_listner.security'] = function ($app) {
836 1094
            return new \Eccube\EventListener\SecurityEventListener($app['orm.em']);
837
        };
838
839
        // Voterの設定
840
        $this['authority_voter'] = function ($app) {
841 1092
            return new \Eccube\Security\Voter\AuthorityVoter($app);
842
        };
843
844
        $this->extend('security.voters', function ($voters, \Silex\Application $app) {
845 1092
            $voters[] = $app['authority_voter'];
846
847 1092
            return $voters;
848 1094
        });
849
850
        $this['security.access_manager'] = function ($app) {
851 1092
            return new \Symfony\Component\Security\Core\Authorization\AccessDecisionManager($app['security.voters'], 'unanimous');
852
        };
853
854 1094
        $this->on(\Symfony\Component\Security\Http\SecurityEvents::INTERACTIVE_LOGIN, array($this['eccube.event_listner.security'], 'onInteractiveLogin'));
855
    }
856
857
    /**
858
     * ロードバランサー、プロキシサーバの設定を行う
859
     */
860 1094
    public function initProxy()
861
    {
862 1094
        $config = $this['config'];
863 1094
        if (isset($config['trusted_proxies_connection_only']) && !empty($config['trusted_proxies_connection_only'])) {
864
            $this->on(KernelEvents::REQUEST, function (GetResponseEvent $event) use ($config) {
865
                // サブリクエストのREMOTE_ADDRも動的に設定を行う必要があるため、KernelEvents::REQUESTを使用する
866
                Request::setTrustedProxies(array_merge(array($event->getRequest()->server->get('REMOTE_ADDR')), $config['trusted_proxies']));
867
            }, self::EARLY_EVENT);
868 1094 View Code Duplication
        } elseif (isset($config['trusted_proxies']) && !empty($config['trusted_proxies'])) {
869
            Request::setTrustedProxies($config['trusted_proxies']);
870
        }
871
    }
872
873 1092
    public function initializePlugin()
874
    {
875 1092
        if ($this->initializedPlugin) {
876
            return;
877
        }
878 1092
        $this->register(new ServiceProvider\EccubePluginServiceProvider());
879
880
        // TODO Acme\ServiceProvider の初期化はここで OK?
881 1092
        if (array_key_exists('service',$this['config'])) {
882
            foreach ($this['config']['service'] as $service) {
883
                $this->register(new $service);
884
            }
885
        }
886 1092
        $this->initializedPlugin = true;
887
    }
888
889
    /**
890
     * PHPUnit を実行中かどうかを設定する.
891
     *
892
     * @param boolean $testMode PHPUnit を実行中の場合 true
893
     */
894 1084
    public function setTestMode($testMode)
895
    {
896 1084
        $this->testMode = $testMode;
897
    }
898
899
    /**
900
     * PHPUnit を実行中かどうか.
901
     *
902
     * @return boolean PHPUnit を実行中の場合 true
903
     */
904 318
    public function isTestMode()
905
    {
906 318
        return $this->testMode;
907
    }
908
909
    /**
910
     *
911
     * データベースの接続を確認
912
     * 成功 : trueを返却
913
     * 失敗 : \Doctrine\DBAL\DBALExceptionエラーが発生( 接続に失敗した場合 )、エラー画面を表示しdie()
914
     * 備考 : app['debug']がtrueの際は処理を行わない
915
     *
916
     * @return boolean true
917
     *
918
     */
919 1094
    protected function checkDatabaseConnection()
920
    {
921 1094
        if ($this['debug']) {
922 1094
            return;
923
        }
924
        try {
925
            $this['db']->connect();
926
        } catch (\Doctrine\DBAL\DBALException $e) {
927
            $this['monolog']->error($e->getMessage());
928
            $this['twig.path'] = array(__DIR__.'/Resource/template/exception');
929
            $html = $this['twig']->render('error.twig', array(
930
                'error_title' => 'データーベース接続エラー',
931
                'error_message' => 'データーベースを確認してください',
932
            ));
933
            $response = new Response();
934
            $response->setContent($html);
935
            $response->setStatusCode('500');
936
            $response->headers->set('Content-Type', 'text/html');
937
            $response->send();
938
            die();
939
        }
940
941
        return true;
942
    }
943
944
    /**
945
     * Config ファイルをパースし、連想配列を返します.
946
     *
947
     * $config_name.yml ファイルをパースし、連想配列を返します.
948
     * $config_name.php が存在する場合は、 PHP ファイルに記述された連想配列を使用します。
949
     *
950
     * @param string $config_name Config 名称
951
     * @param array $configAll Config の連想配列
952
     * @param boolean $wrap_key Config の連想配列に config_name のキーを生成する場合 true, デフォルト false
953
     * @param string $ymlPath config yaml を格納したディレクトリ
954
     * @param string $distPath config yaml dist を格納したディレクトリ
955
     * @return Application
956
     */
957 1095
    public function parseConfig($config_name, array &$configAll, $wrap_key = false, $ymlPath = null, $distPath = null)
958
    {
959 1095
        $ymlPath = $ymlPath ? $ymlPath : __DIR__.'/../../app/config/eccube';
960 1095
        $distPath = $distPath ? $distPath : __DIR__.'/../../src/Eccube/Resource/config';
961
962 1095
        $config = [];
963 1095
        $config_php = $ymlPath.'/'.$config_name.'.php';
964 1095
        if (file_exists($config_php)) {
965 1095
            $config = require $config_php;
966
        }
967
968
        // `%ROOT_DIR%`を絶対パスに変換
969 1095
        $rootDir = realpath(__DIR__.'/../../');
970
        array_walk($config, function(&$value) use ($rootDir) {
971 1095
            $value = str_replace('%ROOT_DIR%', $rootDir, $value);
972 1095
        });
973
974 1095
        $config_php_dist = $distPath.'/'.$config_name.'.php';
975 1095
        $config_dist = require $config_php_dist;
976
977 1095
        if ($wrap_key) {
978 1095
            $configAll = array_replace_recursive($configAll, array($config_name => $config_dist), array($config_name => $config));
979
        } else {
980 1095
            $configAll = array_replace_recursive($configAll, $config_dist, $config);
981
        }
982
983 1095
        return $this;
984
    }
985
986
    /**
987
     * セッションが開始されているかどうか.
988
     *
989
     * @return boolean セッションが開始済みの場合 true
990
     * @link http://php.net/manual/ja/function.session-status.php#113468
991
     */
992 1094
    protected function isSessionStarted()
993
    {
994 1094
        if (php_sapi_name() !== 'cli') {
995 1094
            if (version_compare(phpversion(), '5.4.0', '>=')) {
996 1094
                return session_status() === PHP_SESSION_ACTIVE ? true : false;
997
            } else {
998
                return session_id() === '' ? false : true;
999
            }
1000
        }
1001
1002
        return false;
1003
    }
1004
1005
    /**
1006
     * Http Cache対応
1007
     */
1008 1094
    protected function initCacheRequest()
1009
    {
1010
        // httpキャッシュが無効の場合はイベント設定を行わない.
1011 1094
        if (!$this['config']['http_cache']['enabled']) {
1012 1094
            return;
1013
        }
1014
1015
        $app = $this;
1016
1017
        // Response Event(http cache対応、event実行は一番遅く設定)
1018
        $this->on(\Symfony\Component\HttpKernel\KernelEvents::RESPONSE, function (\Symfony\Component\HttpKernel\Event\FilterResponseEvent $event) use ($app) {
1019
1020
            if (!$event->isMasterRequest()) {
1021
                return;
1022
            }
1023
1024
            $request = $event->getRequest();
1025
            $response = $event->getResponse();
1026
1027
            $route = $request->attributes->get('_route');
1028
1029
            $etag = md5($response->getContent());
1030
1031
            if (strpos($route, 'admin') === 0) {
1032
                // 管理画面
1033
1034
                // 管理画面ではコンテンツの中身が変更された時点でキャッシュを更新し、キャッシュの適用範囲はprivateに設定
1035
                $response->setCache(array(
1036
                    'etag' => $etag,
1037
                    'private' => true,
1038
                ));
1039
1040
                if ($response->isNotModified($request)) {
1041
                    return $response;
1042
                }
1043
1044
            } else {
1045
                // フロント画面
1046
                $cacheRoute = $app['config']['http_cache']['route'];
1047
1048
                if (in_array($route, $cacheRoute) === true) {
1049
                    // キャッシュ対象となる画面lが含まれていた場合、キャッシュ化
1050
                    // max-ageを設定しているためExpiresは不要
1051
                    // Last-Modifiedだと比較する項目がないためETagで対応
1052
                    // max-ageを設定していた場合、contentの中身が変更されても変更されない
1053
1054
                    $age = $app['config']['http_cache']['age'];
1055
1056
                    $response->setCache(array(
1057
                        'etag' => $etag,
1058
                        'max_age' => $age,
1059
                        's_maxage' => $age,
1060
                        'public' => true,
1061
                    ));
1062
1063
                    if ($response->isNotModified($request)) {
1064
                        return $response;
1065
                    }
1066
                }
1067
            }
1068
1069
        }, -1024);
1070
    }
1071
}
1072