Failed Conditions
Pull Request — master (#1543)
by Tsuyoshi
489:47 queued 481:38
created

src/Eccube/Application.php (2 issues)

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 Eccube\Application\ApplicationTrait;
27
use Eccube\Common\Constant;
28
use Monolog\Logger;
29
use Symfony\Component\EventDispatcher\EventDispatcher;
30
use Symfony\Component\Finder\Finder;
31
use Symfony\Component\HttpFoundation\Request;
32
use Symfony\Component\HttpFoundation\Response;
33
use Symfony\Component\Yaml\Yaml;
34
35
class Application extends ApplicationTrait
36
{
37
    protected static $instance;
38
39
    protected $initialized = false;
40
    protected $initializedPlugin = false;
41
42
    public $package;
43
    public $rootDir;
44
45 805
    public static function getInstance(array $values = array())
46
    {
47
        if (!is_object(self::$instance)) {
48 458
            self::$instance = new Application($values);
49
        }
50
51 347
        return self::$instance;
52 805
    }
53
54 457
    public static function clearInstance()
55
    {
56 457
        self::$instance = null;
57 457
    }
58
59
    final public function __clone()
60
    {
61
        throw new \Exception('Clone is not allowed against '.get_class($this));
62
    }
63
64 473
    public function __construct(array $values = array())
65
    {
66 View Code Duplication
        if (\Phar::running(false)) {
67
            // phar
68
            $this->package = 'phar';
69
            $this->rootDir = dirname(\Phar::running(false));
70
        } elseif (file_exists(__DIR__.'/../../../../../vendor/ec-cube/ec-cube')) {
71
            // composer
72
            $this->package = 'composer';
73
            $this->rootDir = __DIR__.'/../../../../..';
74
        } else {
75
            // other
76 473
            $this->package = 'general';
77 473
            $this->rootDir = __DIR__.'/../..';
78
        }
79
80
        parent::__construct($values);
81
82
        if (is_null(self::$instance)) {
83 459
            self::$instance = $this;
84
        }
85
86
        // load config
87
        $this->initConfig();
88
89
        // init monolog
90 473
        $this->initLogger();
91 473
    }
92
93 473
    public function initConfig()
94
    {
95
        // load config
96 473
        $app = $this;
97
        $this['config'] = $this->share(function() use ($app) {
98 457
            $ymlPath =  $app->rootDir.'/app/config/eccube';
99 457
            $distPath =  __DIR__.'/Resource/config';
100
101 457
            $config = array();
102 457
            $config_yml = $ymlPath.'/config.yml';
103
            if (file_exists($config_yml)) {
104
                $config = Yaml::parse(file_get_contents($config_yml));
105
            }
106
107 457
            $config_dist = array();
108 457
            $config_yml_dist = $distPath.'/config.yml.dist';
109
            if (file_exists($config_yml_dist)) {
110
                $config_dist = Yaml::parse(file_get_contents($config_yml_dist));
111
            }
112
113 457
            $config_path = array();
114 457
            $path_yml = $ymlPath.'/path.yml';
115
            if (file_exists($path_yml)) {
116
                $config_path = Yaml::parse(file_get_contents($path_yml));
117 457
                $config_path['block_default_realdir'] = __DIR__.'/Resource/template/default/Block';
118 457
                $config_path['template_default_realdir'] = __DIR__.'/Resource/template/default';
119 457
                $config_path['template_admin_realdir'] = __DIR__.'/Resource/template/admin';
120
            }
121
122 457
            $config_constant = array();
123 457
            $constant_yml = $ymlPath.'/constant.yml';
124
            if (file_exists($constant_yml)) {
125
                $config_constant = Yaml::parse(file_get_contents($constant_yml));
126
                $config_constant = empty($config_constant) ? array() : $config_constant;
127
            }
128
129 457
            $config_constant_dist = array();
130 457
            $constant_yml_dist = $distPath.'/constant.yml.dist';
131
            if (file_exists($constant_yml_dist)) {
132
                $config_constant_dist = Yaml::parse(file_get_contents($constant_yml_dist));
133
            }
134
135
            $configAll = array_replace_recursive($config_constant_dist, $config_dist, $config_constant, $config_path, $config);
136
137 457
            $database = array();
138 457
            $yml = $ymlPath.'/database.yml';
139
            if (file_exists($yml)) {
140
                $database = Yaml::parse(file_get_contents($yml));
141
            }
142
143 457
            $mail = array();
144 457
            $yml = $ymlPath.'/mail.yml';
145
            if (file_exists($yml)) {
146
                $mail = Yaml::parse(file_get_contents($yml));
147
            }
148
            $configAll = array_replace_recursive($configAll, $database, $mail);
149
150 457
            $config_log = array();
151 457
            $yml = $ymlPath.'/log.yml';
152
            if (file_exists($yml)) {
153
                $config_log = Yaml::parse(file_get_contents($yml));
154
            }
155 457
            $config_log_dist = array();
156 457
            $log_yml_dist = $distPath.'/log.yml.dist';
157
            if (file_exists($log_yml_dist)) {
158
                $config_log_dist = Yaml::parse(file_get_contents($log_yml_dist));
159
            }
160
161
            $configAll = array_replace_recursive($configAll, $config_log_dist, $config_log);
162
163 457
            $config_nav = array();
164 457
            $yml = $ymlPath.'/nav.yml';
165
            if (file_exists($yml)) {
166
                $config_nav = array('nav' => Yaml::parse(file_get_contents($yml)));
167
            }
168 457
            $config_nav_dist = array();
169 457
            $nav_yml_dist = $distPath.'/nav.yml.dist';
170
            if (file_exists($nav_yml_dist)) {
171
                $config_nav_dist = array('nav' => Yaml::parse(file_get_contents($nav_yml_dist)));
172
            }
173
174
            $configAll = array_replace_recursive($configAll, $config_nav_dist, $config_nav);
175
176 457
            return $configAll;
177
        });
178 473
    }
179
180 472
    public function initLogger()
181
    {
182 472
        $this->register(new ServiceProvider\EccubeMonologServiceProvider($app));
0 ignored issues
show
The variable $app does not exist. Did you forget to declare it?

This check marks access to variables or properties that have not been declared yet. While PHP has no explicit notion of declaring a variable, accessing it before a value is assigned to it is most likely a bug.

Loading history...
183
        $this['monolog.logfile'] = $this->rootDir.'/app/log/site.log';
184
        $this['monolog.name'] = 'eccube';
185
    }
186
187 457
    public function initialize()
188
    {
189 457
        if ($this->initialized) {
190
            return;
191
        }
192
193
        // init locale
194
        $this->initLocale();
195
196
        // init session
197
        $this->initSession();
198
199
        // init twig
200
        $this->initRendering();
201
202
        // init provider
203
        $this->register(new \Silex\Provider\HttpFragmentServiceProvider());
204
        $this->register(new \Silex\Provider\UrlGeneratorServiceProvider());
205
        $this->register(new \Silex\Provider\FormServiceProvider());
206
        $this->register(new \Silex\Provider\SerializerServiceProvider());
207
        $this->register(new \Eccube\ServiceProvider\ValidatorServiceProvider());
208
209 457
        $app = $this;
210
        $this->error(function(\Exception $e, $code) use ($app) {
211
            if ($app['debug']) {
212
                return;
213
            }
214
215
            switch ($code) {
216
                case 403:
217
                    $title = 'アクセスできません。';
218
                    $message = 'お探しのページはアクセスができない状況にあるか、移動もしくは削除された可能性があります。';
219
                    break;
220
                case 404:
221
                    $title = 'ページがみつかりません。';
222
                    $message = 'URLに間違いがないかご確認ください。';
223
                    break;
224
                default:
225
                    $title = 'システムエラーが発生しました。';
226
                    $message = '大変お手数ですが、サイト管理者までご連絡ください。';
227
                    break;
228
            }
229
230
            return $app->render('error.twig', array(
231
                'error_title' => $title,
232
                'error_message' => $message,
233
            ));
234
        });
235
236
        // init mailer
237
        $this->initMailer();
238
239
        // init doctrine orm
240
        $this->initDoctrine();
241
242
        // Set up the DBAL connection now to check for a proper connection to the database.
243
        $this->checkDatabaseConnection();
244
245
        // init security
246
        $this->initSecurity();
247
248
        // init ec-cube service provider
249
        $this->register(new ServiceProvider\EccubeServiceProvider());
250
251
        // mount controllers
252
        $this->register(new \Silex\Provider\ServiceControllerServiceProvider());
253
        $this->mount('', new ControllerProvider\FrontControllerProvider());
254
        $this->mount('/'.trim($this['config']['admin_route'], '/').'/', new ControllerProvider\AdminControllerProvider());
255
        Request::enableHttpMethodParameterOverride(); // PUTやDELETEできるようにする
256
257 457
        $this->initialized = true;
258 457
    }
259
260 457
    public function initLocale()
261
    {
262
        // timezone
263
        if (!empty($this['config']['timezone'])) {
264
            date_default_timezone_set($this['config']['timezone']);
265
        }
266
267
        $this->register(new \Silex\Provider\TranslationServiceProvider(), array(
268 457
            'locale' => $this['config']['locale'],
269
        ));
270
        $this['translator'] = $this->share($this->extend('translator', function($translator, \Silex\Application $app) {
271
            $translator->addLoader('yaml', new \Symfony\Component\Translation\Loader\YamlFileLoader());
272
273
            $r = new \ReflectionClass('Symfony\Component\Validator\Validator');
274
            $file = dirname($r->getFilename()).'/Resources/translations/validators.'.$app['locale'].'.xlf';
275
            if (file_exists($file)) {
276
                $translator->addResource('xliff', $file, $app['locale'], 'validators');
277
            }
278
279
            $file = __DIR__.'/Resource/locale/validator.'.$app['locale'].'.yml';
280
            if (file_exists($file)) {
281
                $translator->addResource('yaml', $file, $app['locale'], 'validators');
282
            }
283
284
            $file = __DIR__.'/Resource/locale/message.'.$app['locale'].'.yml';
285
            if (file_exists($file)) {
286
                $translator->addResource('yaml', $file, $app['locale']);
287
            }
288
289 126
            return $translator;
290
        }));
291 457
    }
292
293 457
    public function initSession()
294
    {
295
        $this->register(new \Silex\Provider\SessionServiceProvider(), array(
296 457
            'session.storage.save_path' => $this->rootDir.'/app/cache/eccube/session',
297
            'session.storage.options' => array(
298 457
                'name' => 'eccube',
299
                'cookie_path' => $this['config']['root_urlpath'] ?: '/',
300 457
                'cookie_secure' => $this['config']['force_ssl'],
301 457
                'cookie_lifetime' => $this['config']['cookie_lifetime'],
302 457
                'cookie_httponly' => true,
303
                // cookie_domainは指定しない
304
                // http://blog.tokumaru.org/2011/10/cookiedomain.html
305 457
            ),
306
        ));
307 457
    }
308
309 457
    public function initRendering()
310
    {
311
        $this->register(new \Silex\Provider\TwigServiceProvider(), array(
312
            'twig.form.templates' => array('Form/form_layout.twig'),
313
        ));
314
        $this['twig'] = $this->share($this->extend('twig', function(\Twig_Environment $twig, \Silex\Application $app) {
315
            $twig->addExtension(new \Eccube\Twig\Extension\EccubeExtension($app));
316
            $twig->addExtension(new \Twig_Extension_StringLoader());
317
318 5
            return $twig;
319
        }));
320
321
        $this->before(function(Request $request, \Silex\Application $app) {
322
            // フロント or 管理画面ごとにtwigの探索パスを切り替える.
323
            $app['twig'] = $app->share($app->extend('twig', function(\Twig_Environment $twig, \Silex\Application $app) {
324
                $paths = array();
325
326
                // 互換性がないのでprofiler とproduction 時のcacheを分離する
327
328
                $app['admin'] = false;
329
                $app['front'] = false;
330
331
                if (isset($app['profiler'])) {
332
                    $cacheBaseDir = $app->rootDir.'/app/cache/twig/profiler/';
0 ignored issues
show
The property rootDir does not seem to exist in Silex\Application.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
333
                } else {
334
                    $cacheBaseDir = $app->rootDir.'/app/cache/twig/production/';
335
                }
336
                if (strpos($app['request']->getPathInfo(), '/'.trim($app['config']['admin_route'], '/')) === 0) {
337
                    if (file_exists($app->rootDir.'/app/template/admin')) {
338
                        $paths[] = $app->rootDir.'/app/template/admin';
339
                    }
340
                    $paths[] = $app['config']['template_admin_realdir'];
341
                    $paths[] = $app->rootDir.'/app/Plugin';
342
                    $cache = $cacheBaseDir.'admin';
343
                    $app['admin'] = true;
344
                } else {
345
                    if (file_exists($app['config']['template_realdir'])) {
346
                        $paths[] = $app['config']['template_realdir'];
347
                    }
348
                    $paths[] = $app['config']['template_default_realdir'];
349
                    $paths[] = $app->rootDir.'/app/Plugin';
350
                    $cache = $cacheBaseDir.$app['config']['template_code'];
351
                    $app['front'] = true;
352
                }
353
                $twig->setCache($cache);
354
                $app['twig.loader']->addLoader(new \Twig_Loader_Filesystem($paths));
355
356
                return $twig;
357
            }));
358
359
            // 管理画面のIP制限チェック.
360
            if (strpos($app['request']->getPathInfo(), '/'.trim($app['config']['admin_route'], '/')) === 0) {
361
                // IP制限チェック
362
                $allowHost = $app['config']['admin_allow_host'];
363
                if (count($allowHost) > 0) {
364
                    if (array_search($app['request']->getClientIp(), $allowHost) === false) {
365
                        throw new \Exception();
366
                    }
367
                }
368
            }
369
        }, self::EARLY_EVENT);
370
371
        // twigのグローバル変数を定義.
372 457
        $app = $this;
373
        $this->on(\Symfony\Component\HttpKernel\KernelEvents::CONTROLLER, function(\Symfony\Component\HttpKernel\Event\FilterControllerEvent $event) use ($app) {
374
            // ショップ基本情報
375
            $BaseInfo = $app['eccube.repository.base_info']->get();
376
            $app['twig']->addGlobal('BaseInfo', $BaseInfo);
377
378
            if (strpos($app['request']->getPathInfo(), '/'.trim($app['config']['admin_route'], '/')) === 0) {
379
                // 管理画面
380
                // 管理画面メニュー
381
                $menus = array('', '', '');
382
                $app['twig']->addGlobal('menus', $menus);
383
384
                $Member = $app->user();
385
                if (is_object($Member)) {
386
                    // ログインしていれば管理者のロールを取得
387
                    $AuthorityRoles = $app['eccube.repository.authority_role']->findBy(array('Authority' => $Member->getAuthority()));
388
389
                    $roles = array();
390
                    foreach ($AuthorityRoles as $AuthorityRole) {
391
                        // 管理画面でメニュー制御するため相対パス全てをセット
392
                        $roles[] = $app['request']->getBaseUrl().'/'.$app['config']['admin_route'].$AuthorityRole->getDenyUrl();
393
                    }
394
395
                    $app['twig']->addGlobal('AuthorityRoles', $roles);
396
                }
397
398
            } else {
399
                // フロント画面
400
                $request = $event->getRequest();
401
                $route = $request->attributes->get('_route');
402
403
                // ユーザ作成画面
404
                if ($route === trim($app['config']['user_data_route'])) {
405
                    $params = $request->attributes->get('_route_params');
406
                    $route = $params['route'];
407
                    // プレビュー画面
408
                } elseif ($request->get('preview')) {
409
                    $route = 'preview';
410
                }
411
412
                try {
413
                    $DeviceType = $app['eccube.repository.master.device_type']
414
                        ->find(\Eccube\Entity\Master\DeviceType::DEVICE_TYPE_PC);
415
                    $PageLayout = $app['eccube.repository.page_layout']->getByUrl($DeviceType, $route);
416
                } catch (\Doctrine\ORM\NoResultException $e) {
417
                    $PageLayout = $app['eccube.repository.page_layout']->newPageLayout($DeviceType);
418
                }
419
420
                $app['twig']->addGlobal('PageLayout', $PageLayout);
421
                $app['twig']->addGlobal('title', $PageLayout->getName());
422
            }
423
        });
424 457
    }
425
426 457
    public function initMailer()
427
    {
428
429
        // メール送信時の文字エンコード指定(デフォルトはUTF-8)
430
        if (isset($this['config']['mail']['charset_iso_2022_jp']) && is_bool($this['config']['mail']['charset_iso_2022_jp'])) {
431
            if ($this['config']['mail']['charset_iso_2022_jp'] === true) {
432
                \Swift::init(function() {
433
                    \Swift_DependencyContainer::getInstance()
434
                        ->register('mime.qpheaderencoder')
435
                        ->asAliasOf('mime.base64headerencoder');
436
                    \Swift_Preferences::getInstance()->setCharset('iso-2022-jp');
437
                });
438
            }
439
        }
440
441
        $this->register(new \Silex\Provider\SwiftmailerServiceProvider());
442
        $this['swiftmailer.options'] = $this['config']['mail'];
443
444
        if (isset($this['config']['mail']['spool']) && is_bool($this['config']['mail']['spool'])) {
445
            $this['swiftmailer.use_spool'] = $this['config']['mail']['spool'];
446
        }
447
        // デフォルトはsmtpを使用
448
        $transport = $this['config']['mail']['transport'];
449 457
        if ($transport == 'sendmail') {
450
            $this['swiftmailer.transport'] = \Swift_SendmailTransport::newInstance();
451 457
        } elseif ($transport == 'mail') {
452
            $this['swiftmailer.transport'] = \Swift_MailTransport::newInstance();
453
        }
454 457
    }
455
456 457
    public function initDoctrine()
457
    {
458
        $this->register(new \Silex\Provider\DoctrineServiceProvider(), array(
459
            'dbs.options' => array(
460 457
                'default' => $this['config']['database']
461
        )));
462
        $this->register(new \Saxulum\DoctrineOrmManagerRegistry\Silex\Provider\DoctrineOrmManagerRegistryProvider());
463
464
        // プラグインのmetadata定義を合わせて行う.
465 457
        $pluginBasePath = $this->rootDir.'/app/Plugin';
466 456
        $finder = Finder::create()
467 457
            ->in($pluginBasePath)
468 457
            ->directories()
469
            ->depth(0);
470
471 457
        $ormMappings = array();
472
        $ormMappings[] = array(
473 457
            'type' => 'yml',
474 457
            'namespace' => 'Eccube\Entity',
475
            'path' => array(
476 457
                __DIR__.'/Resource/doctrine',
477 457
                __DIR__.'/Resource/doctrine/master',
478 457
            ),
479 457
        );
480
481
        foreach ($finder as $dir) {
482
483
            $file = $dir->getRealPath().'/config.yml';
484
485
            if (file_exists($file)) {
486
                $config = Yaml::parse(file_get_contents($file));
487
            } else {
488
                $code = $dir->getBaseName();
489
                $this['monolog']->warning("skip {$code} orm.path loading. config.yml not found.", array('path' => $file));
490
                continue;
491 70
            }
492
493
            // Doctrine Extend
494 70
            if (isset($config['orm.path']) && is_array($config['orm.path'])) {
495
                $paths = array();
496
                foreach ($config['orm.path'] as $path) {
497
                    $paths[] = $pluginBasePath.'/'.$config['code'].$path;
498
                }
499
                $ormMappings[] = array(
500
                    'type' => 'yml',
501
                    'namespace' => 'Plugin\\'.$config['code'].'\\Entity',
502
                    'path' => $paths,
503
                );
504
            }
505 387
        }
506
507
        $this->register(new \Dflydev\Silex\Provider\DoctrineOrm\DoctrineOrmServiceProvider(), array(
508 457
            'orm.proxies_dir' => $this->rootDir.'/app/cache/doctrine',
509
            'orm.em.options' => array(
510
                'mappings' => $ormMappings,
511 457
            ),
512
        ));
513 457
    }
514
515 457
    public function initSecurity()
516
    {
517
        $this->register(new \Silex\Provider\SecurityServiceProvider());
518
        $this->register(new \Silex\Provider\RememberMeServiceProvider());
519
520 457
        $this['security.firewalls'] = array(
521
            'admin' => array(
522
                'pattern' => "^/{$this['config']['admin_route']}",
523
                'form' => array(
524
                    'login_path' => "/{$this['config']['admin_route']}/login",
525
                    'check_path' => "/{$this['config']['admin_route']}/login_check",
526 457
                    'username_parameter' => 'login_id',
527 457
                    'password_parameter' => 'password',
528 457
                    'with_csrf' => true,
529 457
                    'use_forward' => true,
530 457
                ),
531
                'logout' => array(
532
                    'logout_path' => "/{$this['config']['admin_route']}/logout",
533
                    'target_url' => "/{$this['config']['admin_route']}/",
534 457
                ),
535
                'users' => $this['orm.em']->getRepository('Eccube\Entity\Member'),
536 457
                'anonymous' => true,
537
            ),
538
            'customer' => array(
539 457
                'pattern' => '^/',
540
                'form' => array(
541
                    'login_path' => '/mypage/login',
542
                    'check_path' => '/login_check',
543
                    'username_parameter' => 'login_email',
544
                    'password_parameter' => 'login_pass',
545
                    'with_csrf' => true,
546
                    'use_forward' => true,
547 457
                ),
548
                'logout' => array(
549
                    'logout_path' => '/logout',
550
                    'target_url' => '/',
551 457
                ),
552
                'remember_me' => array(
553
                    'key' => sha1($this['config']['auth_magic']),
554 457
                    'name' => 'eccube_rememberme',
555
                    // lifetimeはデフォルトの1年間にする
556
                    // 'lifetime' => $this['config']['cookie_lifetime'],
557
                    'path' => $this['config']['root_urlpath'] ?: '/',
558 457
                    'secure' => $this['config']['force_ssl'],
559 457
                    'httponly' => true,
560 457
                    'always_remember_me' => false,
561 457
                    'remember_me_parameter' => 'login_memory',
562
                ),
563
                'users' => $this['orm.em']->getRepository('Eccube\Entity\Customer'),
564 457
                'anonymous' => true,
565
            ),
566
        );
567
568 457
        $this['security.access_rules'] = array(
569
            array("^/{$this['config']['admin_route']}/login", 'IS_AUTHENTICATED_ANONYMOUSLY'),
570
            array("^/{$this['config']['admin_route']}", 'ROLE_ADMIN'),
571 457
            array('^/mypage/login', 'IS_AUTHENTICATED_ANONYMOUSLY'),
572 457
            array('^/mypage/withdraw_complete', 'IS_AUTHENTICATED_ANONYMOUSLY'),
573 457
            array('^/mypage/change', 'IS_AUTHENTICATED_FULLY'),
574 457
            array('^/mypage', 'ROLE_USER'),
575
        );
576
577
        $this['eccube.password_encoder'] = $this->share(function($app) {
578
            return new \Eccube\Security\Core\Encoder\PasswordEncoder($app['config']);
579
        });
580
        $this['security.encoder_factory'] = $this->share(function($app) {
581
            return new \Symfony\Component\Security\Core\Encoder\EncoderFactory(array(
582 457
                'Eccube\Entity\Customer' => $app['eccube.password_encoder'],
583 457
                'Eccube\Entity\Member' => $app['eccube.password_encoder'],
584
            ));
585
        });
586
        $this['eccube.event_listner.security'] = $this->share(function($app) {
587
            return new \Eccube\EventListener\SecurityEventListener($app['orm.em']);
588
        });
589
        $this['user'] = function($app) {
590
            $token = $app['security']->getToken();
591
592
            return ($token !== null) ? $token->getUser() : null;
593
        };
594
595
        // ログイン時のイベントを設定.
596
        $this['dispatcher']->addListener(\Symfony\Component\Security\Http\SecurityEvents::INTERACTIVE_LOGIN, array($this['eccube.event_listner.security'], 'onInteractiveLogin'));
597
598
        // Voterの設定
599 457
        $app = $this;
600
        $this['authority_voter'] = $this->share(function($app) {
601
            return new \Eccube\Security\Voter\AuthorityVoter($app);
602
        });
603
604
        $app['security.voters'] = $app->extend('security.voters', function($voters) use ($app) {
605
            $voters[] = $app['authority_voter'];
606
607 457
            return $voters;
608
        });
609
610
        $this['security.access_manager'] = $this->share(function($app) {
611
            return new \Symfony\Component\Security\Core\Authorization\AccessDecisionManager($app['security.voters'], 'unanimous');
612
        });
613
614 457
    }
615
616 457
    public function initializePlugin()
617
    {
618 457
        if ($this->initializedPlugin) {
619
            return;
620
        }
621
622
        // setup event dispatcher
623
        $this->initPluginEventDispatcher();
624
625
        // load plugin
626
        $this->loadPlugin();
627
628 457
        $this->initializedPlugin = true;
629 457
    }
630
631 168
    public function initPluginEventDispatcher()
632
    {
633
        // EventDispatcher
634
        $this['eccube.event.dispatcher'] = $this->share(function() {
635
            return new EventDispatcher();
636
        });
637
638
        // hook point
639
        $this->before(function(Request $request, \Silex\Application $app) {
640
            $app['eccube.event.dispatcher']->dispatch('eccube.event.app.before');
641
        }, self::EARLY_EVENT);
642
643
        $this->before(function(Request $request, \Silex\Application $app) {
644
            $event = 'eccube.event.controller.'.$request->attributes->get('_route').'.before';
645
            $app['eccube.event.dispatcher']->dispatch($event);
646
        });
647
648 View Code Duplication
        $this->after(function(Request $request, Response $response, \Silex\Application $app) {
649
            $event = 'eccube.event.controller.'.$request->attributes->get('_route').'.after';
650
            $app['eccube.event.dispatcher']->dispatch($event);
651
        });
652
653
        $this->after(function(Request $request, Response $response, \Silex\Application $app) {
654
            $app['eccube.event.dispatcher']->dispatch('eccube.event.app.after');
655
        }, self::LATE_EVENT);
656
657 View Code Duplication
        $this->finish(function(Request $request, Response $response, \Silex\Application $app) {
658
            $event = 'eccube.event.controller.'.$request->attributes->get('_route').'.finish';
659
            $app['eccube.event.dispatcher']->dispatch($event);
660
        });
661
662
        $app = $this;
663
        $this->on(\Symfony\Component\HttpKernel\KernelEvents::RESPONSE, function(\Symfony\Component\HttpKernel\Event\FilterResponseEvent $event) use ($app) {
664
            $route = $event->getRequest()->attributes->get('_route');
665
            $app['eccube.event.dispatcher']->dispatch('eccube.event.render.'.$route.'.before', $event);
666
        });
667
668
        // Request Event
669 View Code Duplication
        $this->on(\Symfony\Component\HttpKernel\KernelEvents::REQUEST, function(\Symfony\Component\HttpKernel\Event\GetResponseEvent $event) use ($app) {
670
671
            if (\Symfony\Component\HttpKernel\HttpKernelInterface::MASTER_REQUEST !== $event->getRequestType()) {
672
                return;
673
            }
674
675
            $route = $event->getRequest()->attributes->get('_route');
676
677
            if (is_null($route)) {
678
                return;
679
            }
680
681 168
            $app['monolog']->debug('KernelEvents::REQUEST '.$route);
682
683
            // 全体
684
            $app['eccube.event.dispatcher']->dispatch('eccube.event.app.request', $event);
685
686
            if (strpos($route, 'admin') === 0) {
687
                // 管理画面
688
                $app['eccube.event.dispatcher']->dispatch('eccube.event.admin.request', $event);
689
            } else {
690
                // フロント画面
691
                $app['eccube.event.dispatcher']->dispatch('eccube.event.front.request', $event);
692
            }
693
694
            // ルーティング単位
695
            $app['eccube.event.dispatcher']->dispatch("eccube.event.route.{$route}.request", $event);
696
697
        }, 30); // Routing(32)が解決しし, 認証判定(8)が実行される前のタイミング.
698
699
        // Controller Event
700 View Code Duplication
        $this->on(\Symfony\Component\HttpKernel\KernelEvents::CONTROLLER, function(\Symfony\Component\HttpKernel\Event\FilterControllerEvent $event) use ($app) {
701
702
            if (\Symfony\Component\HttpKernel\HttpKernelInterface::MASTER_REQUEST !== $event->getRequestType()) {
703
                return;
704
            }
705
706
707
            $route = $event->getRequest()->attributes->get('_route');
708
709
            if (is_null($route)) {
710
                return;
711
            }
712
713
            $app['monolog']->debug('KernelEvents::CONTROLLER '.$route);
714
715
            // 全体
716
            $app['eccube.event.dispatcher']->dispatch('eccube.event.app.controller', $event);
717
718
            if (strpos($route, 'admin') === 0) {
719
                // 管理画面
720
                $app['eccube.event.dispatcher']->dispatch('eccube.event.admin.controller', $event);
721
            } else {
722
                // フロント画面
723
                $app['eccube.event.dispatcher']->dispatch('eccube.event.front.controller', $event);
724
            }
725
726
            // ルーティング単位
727
            $app['eccube.event.dispatcher']->dispatch("eccube.event.route.{$route}.controller", $event);
728
        });
729
730
        // Response Event
731 View Code Duplication
        $this->on(\Symfony\Component\HttpKernel\KernelEvents::RESPONSE, function(\Symfony\Component\HttpKernel\Event\FilterResponseEvent $event) use ($app) {
732
733
            if (\Symfony\Component\HttpKernel\HttpKernelInterface::MASTER_REQUEST !== $event->getRequestType()) {
734
                return;
735
            }
736
737
            $route = $event->getRequest()->attributes->get('_route');
738
739
            if (is_null($route)) {
740
                return;
741
            }
742
743
            $app['monolog']->debug('KernelEvents::RESPONSE '.$route);
744
745
            // ルーティング単位
746
            $app['eccube.event.dispatcher']->dispatch("eccube.event.route.{$route}.response", $event);
747
748
            if (strpos($route, 'admin') === 0) {
749
                // 管理画面
750
                $app['eccube.event.dispatcher']->dispatch('eccube.event.admin.response', $event);
751
            } else {
752
                // フロント画面
753
                $app['eccube.event.dispatcher']->dispatch('eccube.event.front.response', $event);
754
            }
755
756
            // 全体
757
            $app['eccube.event.dispatcher']->dispatch('eccube.event.app.response', $event);
758
        });
759
760
        // Exception Event
761 View Code Duplication
        $this->on(\Symfony\Component\HttpKernel\KernelEvents::EXCEPTION, function(\Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent $event) use ($app) {
762
763
            if (\Symfony\Component\HttpKernel\HttpKernelInterface::MASTER_REQUEST !== $event->getRequestType()) {
764
                return;
765
            }
766
767
            $route = $event->getRequest()->attributes->get('_route');
768
769
            if (is_null($route)) {
770
                return;
771
            }
772
773 168
            $app['monolog']->debug('KernelEvents::EXCEPTION '.$route);
774
775
            // ルーティング単位
776
            $app['eccube.event.dispatcher']->dispatch("eccube.event.route.{$route}.exception", $event);
777
778
            if (strpos($route, 'admin') === 0) {
779
                // 管理画面
780
                $app['eccube.event.dispatcher']->dispatch('eccube.event.admin.exception', $event);
781
            } else {
782
                // フロント画面
783
                $app['eccube.event.dispatcher']->dispatch('eccube.event.front.exception', $event);
784
            }
785
786
            // 全体
787
            $app['eccube.event.dispatcher']->dispatch('eccube.event.app.exception', $event);
788
        });
789
790
        // Terminate Event
791 View Code Duplication
        $this->on(\Symfony\Component\HttpKernel\KernelEvents::TERMINATE, function(\Symfony\Component\HttpKernel\Event\PostResponseEvent $event) use ($app) {
792
793
            $route = $event->getRequest()->attributes->get('_route');
794
795
            if (is_null($route)) {
796
                return;
797
            }
798
799
            $app['monolog']->debug('KernelEvents::TERMINATE '.$route);
800
801
            // ルーティング単位
802
            $app['eccube.event.dispatcher']->dispatch("eccube.event.route.{$route}.terminate", $event);
803
804
            if (strpos($route, 'admin') === 0) {
805
                // 管理画面
806
                $app['eccube.event.dispatcher']->dispatch('eccube.event.admin.terminate', $event);
807
            } else {
808
                // フロント画面
809
                $app['eccube.event.dispatcher']->dispatch('eccube.event.front.terminate', $event);
810
            }
811
812
            // 全体
813
            $app['eccube.event.dispatcher']->dispatch('eccube.event.app.terminate', $event);
814
        });
815
    }
816
817 457
    public function loadPlugin()
818
    {
819
        // プラグインディレクトリを探索.
820 457
        $basePath = $this->rootDir.'/app/Plugin';
821 457
        $finder = Finder::create()
822 457
            ->in($basePath)
823 457
            ->directories()
824
            ->depth(0);
825
826
        $finder->sortByName();
827
828
        // ハンドラ優先順位をdbから持ってきてハッシュテーブルを作成
829 457
        $priorities = array();
830
        $handlers = $this['orm.em']
831
            ->getRepository('Eccube\Entity\PluginEventHandler')
832
            ->getHandlers();
833
        foreach ($handlers as $handler) {
834
            if ($handler->getPlugin()->getEnable() && !$handler->getPlugin()->getDelFlg()) {
835
836
                $priority = $handler->getPriority();
837
            } else {
838
                // Pluginがdisable、削除済みの場合、EventHandlerのPriorityを全て0とみなす
839
                $priority = \Eccube\Entity\PluginEventHandler::EVENT_PRIORITY_DISABLED;
840
            }
841
            $priorities[$handler->getPlugin()->getClassName()][$handler->getEvent()][$handler->getHandler()] = $priority;
842 457
        }
843
844
        // プラグインをロードする.
845
        // config.yml/event.ymlの定義に沿ってインスタンスの生成を行い, イベント設定を行う.
846
        foreach ($finder as $dir) {
847
            //config.ymlのないディレクトリは無視する
848
            $path = $dir->getRealPath();
849
            $code = $dir->getBaseName();
850
            try {
851
                $this['eccube.service.plugin']->checkPluginArchiveContent($path);
852
            } catch (\Eccube\Exception\PluginException $e) {
853
                $this['monolog']->warning("skip {$code} config loading. config.yml not foud or invalid.", array(
854
                    'path' =>  $path,
855
                    'original-message' => $e->getMessage()
856
                ));
857
                continue;
858 70
            }
859
            $config = $this['eccube.service.plugin']->readYml($dir->getRealPath().'/config.yml');
860
861
            $plugin = $this['orm.em']
862
                ->getRepository('Eccube\Entity\Plugin')
863
                ->findOneBy(array('code' => $config['code']));
864
865
            // const
866 70
            if (isset($config['const'])) {
867
                $this['config'] = $this->share($this->extend('config', function($eccubeConfig) use ($config) {
868
                    $eccubeConfig[$config['code']] = array(
869
                        'const' => $config['const'],
870
                    );
871
872
                    return $eccubeConfig;
873
                }));
874
            }
875
876 70
            if ($plugin && $plugin->getEnable() == Constant::DISABLED) {
877
                // プラグインが無効化されていれば読み込まない
878
                continue;
879
            }
880
881
            // Type: Event
882 70
            if (isset($config['event'])) {
883 70
                $class = '\\Plugin\\'.$config['code'].'\\'.$config['event'];
884 70
                $eventExists = true;
885
886 View Code Duplication
                if (!class_exists($class)) {
887
                    $this['monolog']->warning("skip {$code} loading. event class not foud.", array(
888
                        'class' =>  $class,
889
                    ));
890
                    $eventExists = false;
891
                }
892
893
                if ($eventExists && file_exists($dir->getRealPath().'/event.yml')) {
894
895
                    $subscriber = new $class($this);
896
897
                    foreach (Yaml::parse(file_get_contents($dir->getRealPath().'/event.yml')) as $event => $handlers) {
898
                        foreach ($handlers as $handler) {
899
                            if (!isset($priorities[$config['event']][$event][$handler[0]])) { // ハンドラテーブルに登録されていない(ソースにしか記述されていない)ハンドラは一番後ろにする
900
                                $priority = \Eccube\Entity\PluginEventHandler::EVENT_PRIORITY_LATEST;
901
                            } else {
902
                                $priority = $priorities[$config['event']][$event][$handler[0]];
903
                            }
904
                            // 優先度が0のプラグインは登録しない
905
                            if (\Eccube\Entity\PluginEventHandler::EVENT_PRIORITY_DISABLED != $priority) {
906
                                $this['eccube.event.dispatcher']->addListener($event, array($subscriber, $handler[0]), $priority);
907
                            }
908
                        }
909
                    }
910
                }
911
            }
912
            // Type: ServiceProvider
913 70
            if (isset($config['service'])) {
914
                foreach ($config['service'] as $service) {
915
                    $class = '\\Plugin\\'.$config['code'].'\\ServiceProvider\\'.$service;
916 View Code Duplication
                    if (!class_exists($class)) {
917
                        $this['monolog']->warning("skip {$code} loading. service provider class not foud.", array(
918
                            'class' =>  $class,
919
                        ));
920
                        continue;
921
                    }
922
                    $this->register(new $class($this));
923
                }
924
            }
925 387
        }
926
    }
927
928
    /**
929
     *
930
     * データベースの接続を確認
931
     * 成功 : trueを返却
932
     * 失敗 : \Doctrine\DBAL\DBALExceptionエラーが発生( 接続に失敗した場合 )、エラー画面を表示しdie()
933
     * 備考 : app['debug']がtrueの際は処理を行わない
934
     * @return boolean true
935
     *
936
     */
937 457
    protected function checkDatabaseConnection()
938
    {
939
        if ($this['debug']) {
940 457
            return;
941
        }
942
        try {
943
            $this['db']->connect();
944
        } catch (\Doctrine\DBAL\DBALException $e) {
945
            $this['monolog']->error($e->getMessage());
946
            $this['twig.path'] = array(__DIR__.'/Resource/template/exception');
947
            $html = $this['twig']->render('error.twig', array(
948
                'error_title' => 'データーベース接続エラー',
949
                'error_message' => 'データーベースを確認してください',
950
            ));
951
            $response = new Response();
952
            $response->setContent($html);
953
            $response->setStatusCode('500');
954
            $response->headers->set('Content-Type', 'text/html');
955
            $response->send();
956
            die();
957
        }
958
        return true;
959
    }
960
}
961