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