Failed Conditions
Pull Request — experimental/3.1 (#2526)
by Kentaro
49:12 queued 42:52
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 1074
    public static function getInstance(array $values = array())
68
    {
69 1074
        if (!is_object(self::$instance)) {
70 1074
            self::$instance = new Application($values);
71
        }
72
73 1074
        return self::$instance;
74
    }
75
76 1074
    public static function clearInstance()
77
    {
78 1074
        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 1075
    public function __construct(array $values = array())
87
    {
88 1075
        parent::__construct($values);
89
90 1075
        if (is_null(self::$instance)) {
91 1075
            self::$instance = $this;
92
        }
93
94
        // load config
95 1075
        $this->initConfig();
96
97
        // init monolog
98 1075
        $this->initLogger();
99
    }
100
101
    /**
102
     * Application::runが実行されているか親クラスのプロパティから判定
103
     *
104
     * @return bool
105
     */
106 1074
    public function isBooted()
107
    {
108 1074
        return $this->booted;
109
    }
110
111 1075
    public function initConfig()
112
    {
113
        // load .env
114 1075
        $envFile = __DIR__.'/../../.env';
115 1075
        if (file_exists($envFile)) {
116
            (new Dotenv())->load($envFile);
117
        }
118
119
        // load config
120
        $this['config'] = function() {
121 1075
            $configAll = array();
122 1075
            $this->parseConfig('constant', $configAll)
123 1075
                ->parseConfig('path', $configAll)
124 1075
                ->parseConfig('config', $configAll)
125 1075
                ->parseConfig('database', $configAll)
126 1075
                ->parseConfig('mail', $configAll)
127 1075
                ->parseConfig('log', $configAll)
128 1075
                ->parseConfig('nav', $configAll, true)
129 1075
                ->parseConfig('doctrine_cache', $configAll)
130 1075
                ->parseConfig('http_cache', $configAll)
131 1075
                ->parseConfig('session_handler', $configAll);
132
133 1075
            return $configAll;
134
        };
135
    }
136
137 1075
    public function initLogger()
138
    {
139 1075
        $app = $this;
140 1075
        $this->register(new ServiceProvider\LogServiceProvider($app));
141
    }
142
143 1074
    public function initialize()
144
    {
145 1074
        if ($this->initialized) {
146 2
            return;
147
        }
148
149
        // init locale
150 1074
        $this->initLocale();
151
152
        // init session
153 1074
        if (!$this->isSessionStarted()) {
154 1074
            $this->initSession();
155
        }
156
157
        // init twig
158 1074
        $this->initRendering();
159
160
        // init provider
161 1074
        $this->register(new \Silex\Provider\HttpCacheServiceProvider(), array(
162 1074
            'http_cache.cache_dir' => __DIR__.'/../../app/cache/http/',
163
        ));
164 1074
        $this->register(new \Silex\Provider\HttpFragmentServiceProvider());
165 1074
        $this->register(new \Silex\Provider\FormServiceProvider());
166 1074
        $this->register(new \Silex\Provider\SerializerServiceProvider());
167 1074
        $this->register(new \Silex\Provider\ValidatorServiceProvider());
168 1074
        $this->register(new \Saxulum\Validator\Provider\SaxulumValidatorProvider());
169 1074
        $this->register(new MobileDetectServiceProvider());
170 1074
        $this->register(new TwigLintServiceProvider());
171
172
        $this->error(function (\Exception $e, Request $request, $code) {
173 25
            if ($this['debug']) {
174 25
                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 1074
        });
197
198
        // init mailer
199 1074
        $this->initMailer();
200
201 1074
        $this->register(new \Sergiors\Silex\Provider\DoctrineCacheServiceProvider());
202 1074
        $this->register(new \Sergiors\Silex\Provider\AnnotationsServiceProvider(), [
203 1074
            'annotations.debug' => $this['debug'],
204
            'annotations.options' => [
205 1074
                'cache_driver' => $this['debug'] ? 'array' : 'filesystem',
206 1074
                'cache_dir' => $this['debug'] ? null : __DIR__.'/../../app/cache/annotation'
207
            ]
208
        ]);
209
210
        // init doctrine orm
211 1074
        $this->initDoctrine();
212
213
        // Set up the DBAL connection now to check for a proper connection to the database.
214 1074
        $this->checkDatabaseConnection();
215
216
        // init security
217 1074
        $this->initSecurity();
218
219 1074
        $this->register(new \Sergiors\Silex\Provider\RoutingServiceProvider(), [
220 1074
            'routing.cache_dir' => $this['debug'] ? null : __DIR__.'/../../app/cache/routing'
221
        ]);
222 1074
        $this->register(new \Sergiors\Silex\Provider\TemplatingServiceProvider());
223 1074
        $this->register(new \Sergiors\Silex\Provider\SensioFrameworkExtraServiceProvider(), [
224 1074
            'request' => [
225
                'auto_convert' => true
226
            ]
227
        ]);
228
        // init proxy
229 1074
        $this->initProxy();
230
231
        // init ec-cube service provider
232 1074
        $this->register(new DiServiceProvider(), [
233
            'eccube.di.scanners' => [
234 1074
                new \Eccube\Di\Scanner\ComponentScanner([
235 1074
                    $this['config']['root_dir'].'/app/Acme/Controller',
236 1074
                    $this['config']['root_dir'].'/src/Eccube/Controller'
237
                ]),
238 1074
                new \Eccube\Di\Scanner\FormTypeScanner([
239 1074
                    $this['config']['root_dir'].'/src/Eccube/Form/Type'
240
                ]),
241 1074
                new \Eccube\Di\Scanner\FormExtensionScanner([
242 1074
                    $this['config']['root_dir'].'/src/Eccube/Form/Extension'
243
                ]),
244 1074
                new \Eccube\Di\Scanner\ServiceScanner([
245 1074
                    $this['config']['root_dir'].'/src/Eccube/Service'
246
                ]),
247 1074
                new \Eccube\Di\Scanner\RepositoryScanner([
248 1074
                    $this['config']['root_dir'].'/src/Eccube/Repository'
249
                ]),
250 1074
                new \Eccube\Di\Scanner\QueryExtensionScanner([
251 1074
                    $this['config']['root_dir'].'/src/Eccube/Repository'
252
                ])
253
            ],
254 1074
            'eccube.di.generator.dir' => $this['config']['root_dir'].'/app/cache/provider'
255
        ]);
256
257 1074
        $this->register(new CompatRepositoryProvider());
258 1074
        $this->register(new CompatServiceProvider());
259 1074
        $this->register(new ServiceProvider\EccubeServiceProvider());
260
261 1074
        $this->register(new \Silex\Provider\ServiceControllerServiceProvider());
262 1074
        Request::enableHttpMethodParameterOverride(); // PUTやDELETEできるようにする
263
264
        // ルーティングの設定
265
        // TODO EccubeRoutingServiceProviderに移植する.
266 1074
        $app = $this;
267
        $this['eccube.router'] = $this->protect(function($resoure, $cachePrefix) use ($app) {
268
            $options = [
269 1074
                'debug' => $app['debug'],
270 1074
                'cache_dir' => $app['routing.cache_dir'],
271 1074
                'matcher_base_class' => $app['request_matcher_class'],
272 1074
                'matcher_class' => $app['request_matcher_class'],
273 1074
                'matcher_cache_class' => $cachePrefix.'UrlMatcher',
274 1074
                'generator_cache_class' => $cachePrefix.'UrlGenerator'
275
            ];
276 1074
            $router = new EccubeRouter(
277 1074
                $app['routing.loader'],
278 1074
                $resoure,
279 1074
                $options,
280 1074
                $app['request_context'],
281 1074
                $app['logger']
282
            );
283
284 1074
            $router->setAdminPrefix($app['config']['admin_route']);
285 1074
            $router->setUserDataPrefix($app['config']['user_data_route']);
286 1074
            $router->setRequireHttps($app['config']['force_ssl']);
287
288 1074
            return $router;
289 1074
        });
290
291
        $this['eccube.router.origin'] = function ($app) {
292 1074
            $resource = __DIR__.'/Controller';
293 1074
            $cachePrefix = 'Origin';
294
295 1074
            return $app['eccube.router']($resource, $cachePrefix);
296
        };
297
298
        $this['eccube.routers.plugin'] = function ($app) {
299
            // TODO 有効なプラグインを対象とする必要がある.
300 1074
            $dirs = Finder::create()
301 1074
                ->in($app['config']['root_dir'].'/app/Plugin')
302 1074
                ->name('Controller')
303 1074
                ->directories();
304
305 1074
            $routers = [];
306 1074
            foreach ($dirs as $dir) {
307 1074
                $realPath = $dir->getRealPath();
308 1074
                $pluginCode = basename(dirname($realPath));
309 1074
                $routers[] = $app['eccube.router']($realPath, 'Plugin'.$pluginCode);
310
            }
311
312 1074
            return $routers;
313
        };
314
315
        $this['eccube.router.extend'] = function ($app) {
316
            // TODO ディレクトリ名は暫定
317 1074
            $resource = $app['config']['root_dir'].'/app/Acme/Controller';
318 1074
            $cachePrefix = 'Extend';
319
320 1074
            $router = $app['eccube.router']($resource, $cachePrefix);
321
322 1074
            return $router;
323
        };
324
325 View Code Duplication
        $this->extend('request_matcher', function ($matcher, $app) {
326 1074
            $matchers = [];
327 1074
            $matchers[] = $app['eccube.router.extend'];
328 1074
            foreach ($app['eccube.routers.plugin'] as $router) {
329 1074
                $matchers[] = $router;
330
            };
331 1074
            $matchers[] = $app['eccube.router.origin'];
332 1074
            $matchers[] = $matcher;
333
334 1074
            return new ChainUrlMatcher($matchers, $app['request_context']);
335 1074
        });
336
337 View Code Duplication
        $this->extend('url_generator', function ($generator, $app) {
338 1074
            $generators = [];
339 1074
            $generators[] = $app['eccube.router.extend'];
340 1074
            foreach ($app['eccube.routers.plugin'] as $router) {
341 1074
                $generators[] = $router;
342
            };
343 1074
            $generators[] = $app['eccube.router.origin'];
344 1074
            $generators[] = $generator;
345
346 1074
            return new ChainUrlGenerator($generators, $app['request_context']);
347 1074
        });
348
349
        // Route CollectionにEC-CUBEで定義したルーティングを追加(debug tool barに出力するため)
350
        $this->extend('routes', function ($routes, $app) {
351 1074
            $routes->addCollection($app['eccube.router.extend']->getRouteCollection());
352 1074
            foreach ($app['eccube.routers.plugin'] as $router) {
353 1074
                $routes->addCollection($router->getRouteCollection());
354
            };
355 1074
            $routes->addCollection($app['eccube.router.origin']->getRouteCollection());
356
357 1074
            return $routes;
358 1074
        });
359
360
        // init http cache
361 1074
        $this->initCacheRequest();
362
363 1074
        $this->initialized = true;
364
    }
365
366 1074
    public function initLocale()
367
    {
368
        // locale
369 1074
        if (!empty($this['config']['locale'])) {
370 1074
            \Locale::setDefault($this['config']['locale']);
371
        };
372
373
        // timezone
374 1074
        if (!empty($this['config']['timezone'])) {
375 1074
            date_default_timezone_set($this['config']['timezone']);
376
        }
377
378 1074
        $this->register(new \Silex\Provider\TranslationServiceProvider(), array(
379 1074
            'locale' => $this['config']['locale'],
380 1074
            'translator.cache_dir' => $this['debug'] ? null : $this['config']['root_dir'].'/app/cache/translator',
381
            'locale_fallbacks' => ['ja', 'en'],
382
        ));
383
        $this->extend('translator', function ($translator, \Silex\Application $app) {
384 1074
            $translator->addLoader('php', new \Symfony\Component\Translation\Loader\PhpFileLoader());
385
386 1074
            $file = __DIR__.'/Resource/locale/messages.'.$app['locale'].'.php';
387 1074
            if (file_exists($file)) {
388 1074
                $translator->addResource('php', $file, $app['locale']);
389 1074
                $translator->addResource('php', $file, $app['locale'], 'validators');
390
            }
391
392 1074
            return $translator;
393 1074
        });
394
    }
395
396 1074
    public function initSession()
397
    {
398 1074
        $this->register(new \Silex\Provider\SessionServiceProvider(), array(
399 1074
            'session.storage.save_path' => $this['config']['root_dir'].'/app/cache/eccube/session',
400
            'session.storage.options' => array(
401 1074
                'name' => $this['config']['cookie_name'],
402 1074
                'cookie_path' => $this['config']['root_urlpath'] ?: '/',
403 1074
                'cookie_secure' => $this['config']['force_ssl'],
404 1074
                'cookie_lifetime' => $this['config']['cookie_lifetime'],
405
                'cookie_httponly' => true,
406
                // cookie_domainは指定しない
407
                // http://blog.tokumaru.org/2011/10/cookiedomain.html
408
            ),
409
        ));
410
411 1074
        $options = $this['config']['session_handler'];
412
413 1074
        if ($options['enabled']) {
414
            // @see http://silex.sensiolabs.org/doc/providers/session.html#custom-session-configurations
415
            $this['session.storage.handler'] = null;
416
            ini_set('session.save_handler', $options['save_handler']);
417
            ini_set('session.save_path', $options['save_path']);
418
        }
419
    }
420
421 1074
    public function initRendering()
422
    {
423 1074
        $this->register(new \Silex\Provider\TwigServiceProvider(), array(
424 1074
            'twig.form.templates' => array('Form/form_layout.twig'),
425
        ));
426
        $this->extend('twig', function (\Twig_Environment $twig, \Silex\Application $app) {
427 1074
            $twig->addExtension(new \Eccube\Twig\Extension\EccubeExtension($app));
428 1074
            $twig->addExtension(new \Twig_Extension_StringLoader());
429
430 1074
            return $twig;
431 1074
        });
432
433
        $this->before(function (Request $request, \Silex\Application $app) {
434 319
            $app['admin'] = $app['front'] = false;
435 319
            $pathinfo = rawurldecode($request->getPathInfo());
436 319
            if (strpos($pathinfo, '/'.trim($app['config']['admin_route'], '/').'/') === 0) {
437 221
                $app['admin'] = true;
438
            } else {
439 98
                $app['front'] = true;
440
            }
441
442
            // フロント or 管理画面ごとにtwigの探索パスを切り替える.
443 319
            if ($app->isAdminRequest()) {
444 221
                if (file_exists(__DIR__.'/../../app/template/admin')) {
445 221
                    $paths[] = __DIR__.'/../../app/template/admin';
446
                }
447 221
                $paths[] = $app['config']['template_admin_realdir'];
448 221
                $paths[] = __DIR__.'/../../app/Plugin';
449 221
                $cacheDir =  __DIR__.'/../../app/cache/twig/admin';
450
            } else {
451
                // モバイル端末時、smartphoneディレクトリを探索パスに追加する.
452 98
                if ($app['mobile_detect.device_type'] == \Eccube\Entity\Master\DeviceType::DEVICE_TYPE_SP) {
453
                    if (file_exists(__DIR__.'/../../app/template/smartphone')) {
454
                        $paths[] = __DIR__.'/../../app/template/smartphone';
455
                    }
456
                    $paths[] = __DIR__.'/Resource/template/smartphone';
457
                }
458
459 98
                if (file_exists($app['config']['template_realdir'])) {
460 98
                    $paths[] = $app['config']['template_realdir'];
461
                }
462 98
                $paths[] = $app['config']['template_default_realdir'];
463 98
                $paths[] = __DIR__.'/../../app/Plugin';
464 98
                $cacheDir =  __DIR__.'/../../app/cache/twig/'.$app['config']['template_code'];
465
            }
466 319
            $app['twig']->setCache($app['debug'] ? null : $cacheDir);
467 319
            $app['twig.loader']->addLoader(new \Twig_Loader_Filesystem($paths));
468
469
            // 管理画面のIP制限チェック.
470 319
            if ($app->isAdminRequest()) {
471
                // IP制限チェック
472 221
                $allowHost = $app['config']['admin_allow_host'];
473 221
                if (count($allowHost) > 0) {
474
                    if (array_search($app['request_stack']->getCurrentRequest()->getClientIp(), $allowHost) === false) {
475
                        throw new \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException();
476
                    }
477
                }
478
            }
479 1074
        }, self::EARLY_EVENT);
480
481
        // twigのグローバル変数を定義.
482
        $this->on(\Symfony\Component\HttpKernel\KernelEvents::CONTROLLER, function (\Symfony\Component\HttpKernel\Event\FilterControllerEvent $event) {
483
            // 未ログイン時にマイページや管理画面以下にアクセスするとSubRequestで実行されるため,
484
            // $event->isMasterRequest()ではなく、グローバル変数が初期化済かどうかの判定を行う
485 317
            if (isset($this['twig_global_initialized']) && $this['twig_global_initialized'] === true) {
486 67
                return;
487
            }
488
            // ショップ基本情報
489 317
            $this['twig']->addGlobal('BaseInfo', $this[BaseInfo::class]);
490
491 317
            if ($this->isAdminRequest()) {
492
                // 管理画面
493
                // 管理画面メニュー
494 221
                $menus = array('', '', '');
495 221
                $this['twig']->addGlobal('menus', $menus);
496
497 221
                $Member = $this->user();
498 221
                if (is_object($Member)) {
499
                    // ログインしていれば管理者のロールを取得
500 218
                    $AuthorityRoles = $this['eccube.repository.authority_role']->findBy(array('Authority' => $Member->getAuthority()));
501
502 218
                    $roles = array();
503 218
                    $request = $event->getRequest();
504 218
                    foreach ($AuthorityRoles as $AuthorityRole) {
505
                        // 管理画面でメニュー制御するため相対パス全てをセット
506 3
                        $roles[] = $request->getBaseUrl().'/'.$this['config']['admin_route'].$AuthorityRole->getDenyUrl();
507
                    }
508
509 221
                    $this['twig']->addGlobal('AuthorityRoles', $roles);
510
                }
511
512
            } else {
513
                // フロント画面
514 96
                $request = $event->getRequest();
515 96
                $route = $request->attributes->get('_route');
516
517
                // ユーザ作成画面
518 96
                if ($route === 'user_data') {
519 2
                    $params = $request->attributes->get('_route_params');
520 2
                    $route = $params['route'];
521
                    // プレビュー画面
522 94
                } elseif ($request->get('preview')) {
523
                    $route = 'preview';
524
                }
525
526
                try {
527 96
                    $device_type_id = $this['mobile_detect.device_type'];
528
529
                    // TODO デバッグ用
530 96
                    if ($request->query->has('device_type_id')) {
531
                        $device_type_id = $request->get('device_type_id', \Eccube\Entity\Master\DeviceType::DEVICE_TYPE_PC);
532
                    }
533
534 96
                    $DeviceType = $this['eccube.repository.master.device_type']
535 96
                        ->find($device_type_id);
536 96
                    $qb = $this['eccube.repository.page']->createQueryBuilder('p');
537 96
                    $Page = $qb->select('p, pll,l, bp, b')
538 96
                        ->leftJoin('p.PageLayouts', 'pll')
539 96
                        ->leftJoin('pll.Layout', 'l')
540 96
                        ->leftJoin('l.BlockPositions', 'bp')
541 96
                        ->leftJoin('bp.Block', 'b')
542 96
                        ->where('p.url = :route')
543 96
                        ->andWhere('l.DeviceType = :DeviceType')
544 96
                        ->orderBy('bp.block_row', 'ASC')
545 96
                        ->setParameter('route', $route)
546 96
                        ->setParameter('DeviceType', $DeviceType)
547 96
                        ->getQuery()
548 96
                        ->getSingleResult();
549 34
                } catch (\Doctrine\ORM\NoResultException $e) {
550 34
                    $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...
551
                }
552
553 96
                $this['twig']->addGlobal('Page', $Page);
554 96
                $this['twig']->addGlobal('title', $Page->getName());
555
            }
556
557 317
            $this['twig_global_initialized'] = true;
558 1074
        });
559
    }
560
561 1074
    public function initMailer()
562
    {
563
564
        // メール送信時の文字エンコード指定(デフォルトはUTF-8)
565 1074
        if (isset($this['config']['mail']['charset_iso_2022_jp']) && is_bool($this['config']['mail']['charset_iso_2022_jp'])) {
566
            if ($this['config']['mail']['charset_iso_2022_jp'] === true) {
567
                \Swift::init(function () {
568
                    \Swift_DependencyContainer::getInstance()
569
                        ->register('mime.qpheaderencoder')
570
                        ->asAliasOf('mime.base64headerencoder');
571
                    \Swift_Preferences::getInstance()->setCharset('iso-2022-jp');
572
                });
573
            }
574
        }
575
576 1074
        $this->register(new \Silex\Provider\SwiftmailerServiceProvider());
577 1074
        $this['swiftmailer.options'] = $this['config']['mail'];
578
579 1074
        if (isset($this['config']['mail']['spool']) && is_bool($this['config']['mail']['spool'])) {
580 1074
            $this['swiftmailer.use_spool'] = $this['config']['mail']['spool'];
581
        }
582
        // デフォルトはsmtpを使用
583 1074
        $transport = $this['config']['mail']['transport'];
584 1074
        if ($transport == 'sendmail') {
585
            $this['swiftmailer.transport'] = \Swift_SendmailTransport::newInstance();
586 1074
        } elseif ($transport == 'mail') {
587
            $this['swiftmailer.transport'] = \Swift_MailTransport::newInstance();
588
        }
589
    }
590
591 1074
    public function initDoctrine()
592
    {
593 1074
        $this->register(new EntityEventServiceProvider());
594 1074
        $this->register(new \Silex\Provider\DoctrineServiceProvider(), array(
595
            'dbs.options' => array(
596 1074
                'default' => $this['config']['database']
597
            )
598
        ));
599 1074
        $this->register(new \Saxulum\DoctrineOrmManagerRegistry\Provider\DoctrineOrmManagerRegistryProvider());
600
601 1074
        $app = $this;
602
        $this->extend('db.event_manager', function ($evm) use ($app) {
603 1074
            $initSubscriber = new InitSubscriber($app);
604 1074
            $evm->addEventSubscriber($initSubscriber);
605
606 1074
            return $evm;
607 1074
        });
608
609
        // UTCで保存
610
        // @see http://doctrine-orm.readthedocs.org/projects/doctrine-orm/en/latest/cookbook/working-with-datetime.html
611 1074
        UTCDateTimeType::setTimeZone($this['config']['timezone']);
612 1074
        UTCDateTimeTzType::setTimeZone($this['config']['timezone']);
613 1074
        Type::overrideType('datetime', UTCDateTimeType::class);
614 1074
        Type::overrideType('datetimetz', UTCDateTimeTzType::class);
615
616
        // プラグインのmetadata定義を合わせて行う.
617 1074
        $pluginConfigs = PluginConfigManager::getPluginConfigAll($this['debug']);
618 1074
        $ormMappings = array();
619 1074
        $ormMappings[] = array(
620
             'type' => 'annotation',
621
             'namespace' => 'Eccube\Entity',
622
             'path' => array(
623
                 __DIR__.'/Entity'
624
             ),
625
             'use_simple_annotation_reader' => false,
626
         );
627
628
        // TODO namespace は暫定
629 1074
        $ormMappings[] = array(
630
            'type' => 'annotation',
631
            'namespace' => 'Acme\Entity',
632
            'path' => array(
633
                __DIR__.'/../../app/Acme/Entity',
634
            ),
635
            'use_simple_annotation_reader' => false,
636
        );
637
638 1074
        foreach ($pluginConfigs as $code) {
639 1074
            $config = $code['config'];
640
            // Doctrine Extend
641 1074
            if (isset($config['orm.path']) && is_array($config['orm.path'])) {
642
                $paths = array();
643 View Code Duplication
                foreach ($config['orm.path'] as $path) {
644
                    $paths[] = $this['config']['plugin_realdir'].'/'.$config['code'].$path;
645
                }
646
                $ormMappings[] = array(
647
                    'type' => 'yml',
648
                    'namespace' => 'Plugin\\'.$config['code'].'\\Entity',
649
                    'path' => $paths,
650
                );
651
                $ormMappings[] = array(
652 1074
                    'type' => 'annotation',
653
                    'namespace' => 'Plugin\\'.$config['code'].'\\Entity',
654
                    'path' => $paths,
655
                    'use_simple_annotation_reader' => false,
656
                );
657
            }
658
        }
659
660
        $options = array(
661 1074
            'mappings' => $ormMappings
662
        );
663
664 1074
        if (!$this['debug']) {
665
            $cacheDrivers = array();
666
            if (array_key_exists('doctrine_cache', $this['config'])) {
667
                $cacheDrivers = $this['config']['doctrine_cache'];
668
            }
669
670
            if (array_key_exists('metadata_cache', $cacheDrivers)) {
671
                $options['metadata_cache'] = $cacheDrivers['metadata_cache'];
672
            }
673
            if (array_key_exists('query_cache', $cacheDrivers)) {
674
                $options['query_cache'] = $cacheDrivers['query_cache'];
675
            }
676
            if (array_key_exists('result_cache', $cacheDrivers)) {
677
                $options['result_cache'] = $cacheDrivers['result_cache'];
678
            }
679
            if (array_key_exists('hydration_cache', $cacheDrivers)) {
680
                $options['hydration_cache'] = $cacheDrivers['hydration_cache'];
681
            }
682
        }
683
684 1074
        $this->register(new \Dflydev\Provider\DoctrineOrm\DoctrineOrmServiceProvider(), array(
685 1074
            'orm.proxies_dir' => __DIR__.'/../../app/cache/doctrine/proxies',
686 1074
            'orm.em.options' => $options,
687
            'orm.custom.functions.string' => array(
688
                'NORMALIZE' => 'Eccube\Doctrine\ORM\Query\Normalize',
689
            ),
690
            'orm.custom.functions.numeric' => array(
691
                'EXTRACT' => 'Eccube\Doctrine\ORM\Query\Extract',
692
            ),
693
        ));
694
695 1074
        $this->extend(
696 1074
            'orm.em.config',
697
            function (\Doctrine\ORM\Configuration $config, \Silex\Application $app) {
698
699
                /** @var $chain \Doctrine\Common\Persistence\Mapping\Driver\MappingDriverChain */
700 1074
                $chain = $config->getMetadataDriverImpl();
701 1074
                $drivers = $chain->getDrivers();
702 1074
                foreach ($drivers as $namespace => $oldDriver) {
703 1074
                    if ('Eccube\Entity' === $namespace) {
704 1074
                        $newDriver = new AnnotationDriver(
705 1074
                            $app['annotations'],
706 1074
                            $oldDriver->getPaths());
707 1074
                        $newDriver->setFileExtension($oldDriver->getFileExtension());
708 1074
                        $newDriver->addExcludePaths($oldDriver->getExcludePaths());
709 1074
                        $newDriver->setTraitProxiesDirectory(
710 1074
                            realpath(__DIR__.'/../../app/proxy/entity'));
711 1074
                        $chain->addDriver($newDriver, $namespace);
712
                    }
713
                }
714
715 1074
                return $config;
716 1074
            }
717
        );
718
719
        $this->extend('orm.em', function (\Doctrine\ORM\EntityManager $em, \Silex\Application $app) {
720
            // save
721 1074
            $saveEventSubscriber = new \Eccube\Doctrine\EventSubscriber\SaveEventSubscriber($app);
722 1074
            $em->getEventManager()->addEventSubscriber($saveEventSubscriber);
723
724
            // load
725 1074
            $loadEventSubscriber = new \Eccube\Doctrine\EventSubscriber\LoadEventSubscriber($app);
726 1074
            $em->getEventManager()->addEventSubscriber($loadEventSubscriber);
727
728
            // clear cache
729 1074
            $clearCacheEventSubscriber = new \Eccube\Doctrine\EventSubscriber\ClearCacheEventSubscriber($app);
730 1074
            $em->getEventManager()->addEventSubscriber($clearCacheEventSubscriber);
731
732
            // filters
733 1074
            $config = $em->getConfiguration();
734 1074
            $config->addFilter("nostock_hidden", '\Eccube\Doctrine\Filter\NoStockHiddenFilter');
735 1074
            $config->addFilter("incomplete_order_status_hidden", '\Eccube\Doctrine\Filter\OrderStatusFilter');
736
737 1074
            return $em;
738 1074
        });
739
740 1074
        if (!$this['debug']) {
741
            // second level cacheの設定.
742
            $this->extend(
743
                'orm.em.config',
744
                function (\Doctrine\ORM\Configuration $config, \Silex\Application $app) {
745
                    $config->setSecondLevelCacheEnabled();
746
                    $cacheConfig = $config->getSecondLevelCacheConfiguration();
747
                    $regionConfig = $cacheConfig->getRegionsConfiguration();
748
                    // TODO キャッシュ先は設定で切り替えられるように
749
                    $cache = $this['orm.cache.factory'](
750
                        'filesystem',
751
                        [
752
                            'path' => __DIR__.'/../../app/cache/doctrine/second'
753
                        ]
754
                    );
755
                    $factory = new \Doctrine\ORM\Cache\DefaultCacheFactory($regionConfig, $cache);
756
                    $cacheConfig->setCacheFactory($factory);
757
758
                    return $config;
759
                }
760
            );
761
        }
762
    }
763
764 1074
    public function initSecurity()
765
    {
766 1074
        $this->register(new \Silex\Provider\SecurityServiceProvider());
767 1074
        $this->register(new \Silex\Provider\CsrfServiceProvider());
768 1074
        $this->register(new \Silex\Provider\RememberMeServiceProvider());
769
770 1074
        $this['security.firewalls'] = array(
771 1074
            'admin' => array(
772 1074
                'pattern' => "^/{$this['config']['admin_route']}/",
773
                'form' => array(
774 1074
                    'login_path' => "/{$this['config']['admin_route']}/login",
775 1074
                    'check_path' => "/{$this['config']['admin_route']}/login_check",
776 1074
                    'username_parameter' => 'login_id',
777 1074
                    'password_parameter' => 'password',
778
                    'with_csrf' => true,
779
                    'use_forward' => true,
780
                ),
781
                'logout' => array(
782 1074
                    'logout_path' => "/{$this['config']['admin_route']}/logout",
783 1074
                    'target_url' => "/{$this['config']['admin_route']}/",
784
                ),
785 1074
                'users' => $this['orm.em']->getRepository('Eccube\Entity\Member'),
786
                'anonymous' => true,
787
            ),
788
            'customer' => array(
789 1074
                'pattern' => '^/',
790
                'form' => array(
791
                    'login_path' => '/mypage/login',
792
                    'check_path' => '/login_check',
793
                    'username_parameter' => 'login_email',
794
                    'password_parameter' => 'login_pass',
795
                    'with_csrf' => true,
796
                    'use_forward' => true,
797
                ),
798
                'logout' => array(
799
                    'logout_path' => '/logout',
800
                    'target_url' => '/',
801
                ),
802
                'remember_me' => array(
803 1074
                    'key' => sha1($this['config']['auth_magic']),
804 1074
                    'name' => $this['config']['cookie_name'].'_rememberme',
805
                    // lifetimeはデフォルトの1年間にする
806
                    // 'lifetime' => $this['config']['cookie_lifetime'],
807 1074
                    'path' => $this['config']['root_urlpath'] ?: '/',
808 1074
                    'secure' => $this['config']['force_ssl'],
809
                    'httponly' => true,
810
                    'always_remember_me' => false,
811 1074
                    'remember_me_parameter' => 'login_memory',
812
                ),
813 1074
                'users' => $this['orm.em']->getRepository('Eccube\Entity\Customer'),
814
                'anonymous' => true,
815
            ),
816
        );
817
818 1074
        $channel = null;
819
        // 強制SSL
820 1074
        if ($this['config']['force_ssl'] == \Eccube\Common\Constant::ENABLED) {
821
            $channel = "https";
822
        }
823
824 1074
        $this['security.access_rules'] = array(
825 1074
            array("^/{$this['config']['admin_route']}/login", 'IS_AUTHENTICATED_ANONYMOUSLY', $channel),
826 1074
            array("^/{$this['config']['admin_route']}/", 'ROLE_ADMIN', $channel),
827 1074
            array('^/mypage/login', 'IS_AUTHENTICATED_ANONYMOUSLY', $channel),
828 1074
            array('^/mypage/withdraw_complete', 'IS_AUTHENTICATED_ANONYMOUSLY', $channel),
829 1074
            array('^/mypage/change', 'IS_AUTHENTICATED_FULLY', $channel),
830 1074
            array('^/mypage', 'ROLE_USER', $channel),
831
        );
832
833
        $this['eccube.password_encoder'] = function ($app) {
834 1072
            return new \Eccube\Security\Core\Encoder\PasswordEncoder($app['config']);
835
        };
836
        $this['security.encoder_factory'] = function ($app) {
837 1072
            return new \Symfony\Component\Security\Core\Encoder\EncoderFactory(array(
838 1072
                'Eccube\Entity\Customer' => $app['eccube.password_encoder'],
839 1072
                'Eccube\Entity\Member' => $app['eccube.password_encoder'],
840
            ));
841
        };
842
        $this['eccube.event_listner.security'] = function ($app) {
843 1074
            return new \Eccube\EventListener\SecurityEventListener($app['orm.em']);
844
        };
845
846
        // Voterの設定
847
        $this['authority_voter'] = function ($app) {
848 1072
            return new \Eccube\Security\Voter\AuthorityVoter($app);
849
        };
850
851
        $this->extend('security.voters', function ($voters, \Silex\Application $app) {
852 1072
            $voters[] = $app['authority_voter'];
853
854 1072
            return $voters;
855 1074
        });
856
857
        $this['security.access_manager'] = function ($app) {
858 1072
            return new \Symfony\Component\Security\Core\Authorization\AccessDecisionManager($app['security.voters'], 'unanimous');
859
        };
860
861 1074
        $this->on(\Symfony\Component\Security\Http\SecurityEvents::INTERACTIVE_LOGIN, array($this['eccube.event_listner.security'], 'onInteractiveLogin'));
862
    }
863
864
    /**
865
     * ロードバランサー、プロキシサーバの設定を行う
866
     */
867 1074
    public function initProxy()
868
    {
869 1074
        $config = $this['config'];
870 1074
        if (isset($config['trusted_proxies_connection_only']) && !empty($config['trusted_proxies_connection_only'])) {
871
            $this->on(KernelEvents::REQUEST, function (GetResponseEvent $event) use ($config) {
872
                // サブリクエストのREMOTE_ADDRも動的に設定を行う必要があるため、KernelEvents::REQUESTを使用する
873
                Request::setTrustedProxies(array_merge(array($event->getRequest()->server->get('REMOTE_ADDR')), $config['trusted_proxies']));
874
            }, self::EARLY_EVENT);
875 1074 View Code Duplication
        } elseif (isset($config['trusted_proxies']) && !empty($config['trusted_proxies'])) {
876
            Request::setTrustedProxies($config['trusted_proxies']);
877
        }
878
    }
879
880 1072
    public function initializePlugin()
881
    {
882 1072
        if ($this->initializedPlugin) {
883
            return;
884
        }
885 1072
        $this->register(new ServiceProvider\EccubePluginServiceProvider());
886
887
        // TODO Acme\ServiceProvider の初期化はここで OK?
888 1072
        if (array_key_exists('service',$this['config'])) {
889
            foreach ($this['config']['service'] as $service) {
890
                $this->register(new $service);
891
            }
892
        }
893 1072
        $this->initializedPlugin = true;
894
    }
895
896
    /**
897
     * PHPUnit を実行中かどうかを設定する.
898
     *
899
     * @param boolean $testMode PHPUnit を実行中の場合 true
900
     */
901 1064
    public function setTestMode($testMode)
902
    {
903 1064
        $this->testMode = $testMode;
904
    }
905
906
    /**
907
     * PHPUnit を実行中かどうか.
908
     *
909
     * @return boolean PHPUnit を実行中の場合 true
910
     */
911 319
    public function isTestMode()
912
    {
913 319
        return $this->testMode;
914
    }
915
916
    /**
917
     *
918
     * データベースの接続を確認
919
     * 成功 : trueを返却
920
     * 失敗 : \Doctrine\DBAL\DBALExceptionエラーが発生( 接続に失敗した場合 )、エラー画面を表示しdie()
921
     * 備考 : app['debug']がtrueの際は処理を行わない
922
     *
923
     * @return boolean true
924
     *
925
     */
926 1074
    protected function checkDatabaseConnection()
927
    {
928 1074
        if ($this['debug']) {
929 1074
            return;
930
        }
931
        try {
932
            $this['db']->connect();
933
        } catch (\Doctrine\DBAL\DBALException $e) {
934
            $this['monolog']->error($e->getMessage());
935
            $this['twig.path'] = array(__DIR__.'/Resource/template/exception');
936
            $html = $this['twig']->render('error.twig', array(
937
                'error_title' => 'データーベース接続エラー',
938
                'error_message' => 'データーベースを確認してください',
939
            ));
940
            $response = new Response();
941
            $response->setContent($html);
942
            $response->setStatusCode('500');
943
            $response->headers->set('Content-Type', 'text/html');
944
            $response->send();
945
            die();
946
        }
947
948
        return true;
949
    }
950
951
    /**
952
     * Config ファイルをパースし、連想配列を返します.
953
     *
954
     * $config_name.yml ファイルをパースし、連想配列を返します.
955
     * $config_name.php が存在する場合は、 PHP ファイルに記述された連想配列を使用します。
956
     *
957
     * @param string $config_name Config 名称
958
     * @param array $configAll Config の連想配列
959
     * @param boolean $wrap_key Config の連想配列に config_name のキーを生成する場合 true, デフォルト false
960
     * @param string $ymlPath config yaml を格納したディレクトリ
961
     * @param string $distPath config yaml dist を格納したディレクトリ
962
     * @return Application
963
     */
964 1075
    public function parseConfig($config_name, array &$configAll, $wrap_key = false, $ymlPath = null, $distPath = null)
965
    {
966 1075
        $ymlPath = $ymlPath ? $ymlPath : __DIR__.'/../../app/config/eccube';
967 1075
        $distPath = $distPath ? $distPath : __DIR__.'/../../src/Eccube/Resource/config';
968
969 1075
        $config = [];
970 1075
        $config_php = $ymlPath.'/'.$config_name.'.php';
971 1075
        if (file_exists($config_php)) {
972 1075
            $config = require $config_php;
973
        }
974
975
        // `%ROOT_DIR%`を絶対パスに変換
976 1075
        $rootDir = realpath(__DIR__.'/../../');
977
        array_walk($config, function(&$value) use ($rootDir) {
978 1075
            $value = str_replace('%ROOT_DIR%', $rootDir, $value);
979 1075
        });
980
981 1075
        $config_php_dist = $distPath.'/'.$config_name.'.php';
982 1075
        $config_dist = require $config_php_dist;
983
984 1075
        if ($wrap_key) {
985 1075
            $configAll = array_replace_recursive($configAll, array($config_name => $config_dist), array($config_name => $config));
986
        } else {
987 1075
            $configAll = array_replace_recursive($configAll, $config_dist, $config);
988
        }
989
990 1075
        return $this;
991
    }
992
993
    /**
994
     * セッションが開始されているかどうか.
995
     *
996
     * @return boolean セッションが開始済みの場合 true
997
     * @link http://php.net/manual/ja/function.session-status.php#113468
998
     */
999 1074
    protected function isSessionStarted()
1000
    {
1001 1074
        if (php_sapi_name() !== 'cli') {
1002 1074
            if (version_compare(phpversion(), '5.4.0', '>=')) {
1003 1074
                return session_status() === PHP_SESSION_ACTIVE ? true : false;
1004
            } else {
1005
                return session_id() === '' ? false : true;
1006
            }
1007
        }
1008
1009
        return false;
1010
    }
1011
1012
    /**
1013
     * Http Cache対応
1014
     */
1015 1074
    protected function initCacheRequest()
1016
    {
1017
        // httpキャッシュが無効の場合はイベント設定を行わない.
1018 1074
        if (!$this['config']['http_cache']['enabled']) {
1019 1074
            return;
1020
        }
1021
1022
        $app = $this;
1023
1024
        // Response Event(http cache対応、event実行は一番遅く設定)
1025
        $this->on(\Symfony\Component\HttpKernel\KernelEvents::RESPONSE, function (\Symfony\Component\HttpKernel\Event\FilterResponseEvent $event) use ($app) {
1026
1027
            if (!$event->isMasterRequest()) {
1028
                return;
1029
            }
1030
1031
            $request = $event->getRequest();
1032
            $response = $event->getResponse();
1033
1034
            $route = $request->attributes->get('_route');
1035
1036
            $etag = md5($response->getContent());
1037
1038
            if (strpos($route, 'admin') === 0) {
1039
                // 管理画面
1040
1041
                // 管理画面ではコンテンツの中身が変更された時点でキャッシュを更新し、キャッシュの適用範囲はprivateに設定
1042
                $response->setCache(array(
1043
                    'etag' => $etag,
1044
                    'private' => true,
1045
                ));
1046
1047
                if ($response->isNotModified($request)) {
1048
                    return $response;
1049
                }
1050
1051
            } else {
1052
                // フロント画面
1053
                $cacheRoute = $app['config']['http_cache']['route'];
1054
1055
                if (in_array($route, $cacheRoute) === true) {
1056
                    // キャッシュ対象となる画面lが含まれていた場合、キャッシュ化
1057
                    // max-ageを設定しているためExpiresは不要
1058
                    // Last-Modifiedだと比較する項目がないためETagで対応
1059
                    // max-ageを設定していた場合、contentの中身が変更されても変更されない
1060
1061
                    $age = $app['config']['http_cache']['age'];
1062
1063
                    $response->setCache(array(
1064
                        'etag' => $etag,
1065
                        'max_age' => $age,
1066
                        's_maxage' => $age,
1067
                        'public' => true,
1068
                    ));
1069
1070
                    if ($response->isNotModified($request)) {
1071
                        return $response;
1072
                    }
1073
                }
1074
            }
1075
1076
        }, -1024);
1077
    }
1078
}
1079