Failed Conditions
Pull Request — master (#1446)
by chihiro
61:21 queued 10:17
created

src/Eccube/Application.php (1 issue)

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 422
    public static function getInstance(array $values = array())
43
    {
44
        if (!is_object(self::$instance)) {
45
            self::$instance = new Application($values);
46
        }
47
48 422
        return self::$instance;
49 422
    }
50
51 766
    public static function clearInstance()
52
    {
53 766
        self::$instance = null;
54 766
    }
55
56
    final public function __clone()
57
    {
58
        throw new \Exception('Clone is not allowed against '.get_class($this));
59
    }
60
61 766
    public function __construct(array $values = array())
62
    {
63
        parent::__construct($values);
64
65
        if (is_null(self::$instance)) {
66 766
            self::$instance = $this;
67
        }
68
69
        // load config
70
        $this->initConfig();
71
72
        // init monolog
73
        $this->initLogger();
74
    }
75
76 780
    public function initConfig()
77
    {
78
        // load config
79
        $this['config'] = $this->share(function() {
80 769
            $ymlPath = __DIR__.'/../../app/config/eccube';
81 769
            $distPath = __DIR__.'/../../src/Eccube/Resource/config';
82
83 769
            $config = array();
84 769
            $config_yml = $ymlPath.'/config.yml';
85
            if (file_exists($config_yml)) {
86
                $config = Yaml::parse(file_get_contents($config_yml));
87
            }
88
89 769
            $config_dist = array();
90 769
            $config_yml_dist = $distPath.'/config.yml.dist';
91
            if (file_exists($config_yml_dist)) {
92
                $config_dist = Yaml::parse(file_get_contents($config_yml_dist));
93
            }
94
95 769
            $config_path = array();
96 769
            $path_yml = $ymlPath.'/path.yml';
97
            if (file_exists($path_yml)) {
98
                $config_path = Yaml::parse(file_get_contents($path_yml));
99
            }
100
101 769
            $config_constant = array();
102 769
            $constant_yml = $ymlPath.'/constant.yml';
103
            if (file_exists($constant_yml)) {
104
                $config_constant = Yaml::parse(file_get_contents($constant_yml));
105
                $config_constant = empty($config_constant) ? array() : $config_constant;
106
            }
107
108 769
            $config_constant_dist = array();
109 769
            $constant_yml_dist = $distPath.'/constant.yml.dist';
110
            if (file_exists($constant_yml_dist)) {
111
                $config_constant_dist = Yaml::parse(file_get_contents($constant_yml_dist));
112
            }
113
114
            $configAll = array_replace_recursive($config_constant_dist, $config_dist, $config_constant, $config_path, $config);
115
116 769
            $database = array();
117 769
            $yml = $ymlPath.'/database.yml';
118
            if (file_exists($yml)) {
119
                $database = Yaml::parse(file_get_contents($yml));
120
            }
121
122 769
            $mail = array();
123 769
            $yml = $ymlPath.'/mail.yml';
124
            if (file_exists($yml)) {
125
                $mail = Yaml::parse(file_get_contents($yml));
126
            }
127
            $configAll = array_replace_recursive($configAll, $database, $mail);
128
129 769
            $config_log = array();
130 769
            $yml = $ymlPath.'/log.yml';
131
            if (file_exists($yml)) {
132
                $config_log = Yaml::parse(file_get_contents($yml));
133
            }
134 769
            $config_log_dist = array();
135 769
            $log_yml_dist = $distPath.'/log.yml.dist';
136
            if (file_exists($log_yml_dist)) {
137
                $config_log_dist = Yaml::parse(file_get_contents($log_yml_dist));
138
            }
139
140
            $configAll = array_replace_recursive($configAll, $config_log_dist, $config_log);
141
142 769
            $config_nav = array();
143 769
            $yml = $ymlPath.'/nav.yml';
144
            if (file_exists($yml)) {
145
                $config_nav = array('nav' => Yaml::parse(file_get_contents($yml)));
146
            }
147 769
            $config_nav_dist = array();
148 769
            $nav_yml_dist = $distPath.'/nav.yml.dist';
149
            if (file_exists($nav_yml_dist)) {
150
                $config_nav_dist = array('nav' => Yaml::parse(file_get_contents($nav_yml_dist)));
151
            }
152
153
            $configAll = array_replace_recursive($configAll, $config_nav_dist, $config_nav);
154
155 769
            return $configAll;
156
        });
157 780
    }
158
159 780
    public function initLogger()
160
    {
161 780
        $app = $this;
162
        $this->register(new ServiceProvider\EccubeMonologServiceProvider($app));
163
        $this['monolog.logfile'] = __DIR__.'/../../app/log/site.log';
164
        $this['monolog.name'] = 'eccube';
165 780
    }
166
167 766
    public function initialize()
168
    {
169 766
        if ($this->initialized) {
170
            return;
171
        }
172
173
        // init locale
174
        $this->initLocale();
175
176
        // init session
177
        $this->initSession();
178
179
        // init twig
180
        $this->initRendering();
181
182
        // init provider
183
        $this->register(new \Silex\Provider\HttpFragmentServiceProvider());
184
        $this->register(new \Silex\Provider\UrlGeneratorServiceProvider());
185
        $this->register(new \Silex\Provider\FormServiceProvider());
186
        $this->register(new \Silex\Provider\SerializerServiceProvider());
187
        $this->register(new \Eccube\ServiceProvider\ValidatorServiceProvider());
188
189 766
        $app = $this;
190
        $this->error(function(\Exception $e, $code) use ($app) {
191
            if ($app['debug']) {
192 10
                return;
193
            }
194
195
            switch ($code) {
196
                case 403:
197
                    $title = 'アクセスできません。';
198
                    $message = 'お探しのページはアクセスができない状況にあるか、移動もしくは削除された可能性があります。';
199
                    break;
200
                case 404:
201
                    $title = 'ページがみつかりません。';
202
                    $message = 'URLに間違いがないかご確認ください。';
203
                    break;
204
                default:
205
                    $title = 'システムエラーが発生しました。';
206
                    $message = '大変お手数ですが、サイト管理者までご連絡ください。';
207
                    break;
208
            }
209
210
            return $app['twig']->render('error.twig', array(
211
                'error_title' => $title,
212
                'error_message' => $message,
213
            ));
214
        });
215
216
        // init mailer
217
        $this->initMailer();
218
219
        // init doctrine orm
220
        $this->initDoctrine();
221
222
        // Set up the DBAL connection now to check for a proper connection to the database.
223
        $this->checkDatabaseConnection();
224
225
        // init security
226
        $this->initSecurity();
227
228
        // init ec-cube service provider
229
        $this->register(new ServiceProvider\EccubeServiceProvider());
230
231
        // mount controllers
232
        $this->register(new \Silex\Provider\ServiceControllerServiceProvider());
233
        $this->mount('', new ControllerProvider\FrontControllerProvider());
234
        $this->mount('/'.trim($this['config']['admin_route'], '/').'/', new ControllerProvider\AdminControllerProvider());
235
        Request::enableHttpMethodParameterOverride(); // PUTやDELETEできるようにする
236
237 766
        $this->initialized = true;
238 766
    }
239
240 766
    public function initLocale()
241
    {
242
243
        // timezone
244
        if (!empty($this['config']['timezone'])) {
245
            date_default_timezone_set($this['config']['timezone']);
246
        }
247
248
        $this->register(new \Silex\Provider\TranslationServiceProvider(), array(
249 766
            'locale' => $this['config']['locale'],
250
        ));
251
        $this['translator'] = $this->share($this->extend('translator', function($translator, \Silex\Application $app) {
252
            $translator->addLoader('yaml', new \Symfony\Component\Translation\Loader\YamlFileLoader());
253
254
            $r = new \ReflectionClass('Symfony\Component\Validator\Validator');
255
            $file = dirname($r->getFilename()).'/Resources/translations/validators.'.$app['locale'].'.xlf';
256
            if (file_exists($file)) {
257
                $translator->addResource('xliff', $file, $app['locale'], 'validators');
258
            }
259
260
            $file = __DIR__.'/Resource/locale/validator.'.$app['locale'].'.yml';
261
            if (file_exists($file)) {
262
                $translator->addResource('yaml', $file, $app['locale'], 'validators');
263
            }
264
265
            $file = __DIR__.'/Resource/locale/message.'.$app['locale'].'.yml';
266
            if (file_exists($file)) {
267
                $translator->addResource('yaml', $file, $app['locale']);
268
            }
269
270 441
            return $translator;
271
        }));
272 766
    }
273
274 766
    public function initSession()
275
    {
276
        $this->register(new \Silex\Provider\SessionServiceProvider(), array(
277
            'session.storage.save_path' => $this['config']['root_dir'].'/app/cache/eccube/session',
278
            'session.storage.options' => array(
279 766
                'name' => 'eccube',
280
                'cookie_path' => $this['config']['root_urlpath'] ?: '/',
281 766
                'cookie_secure' => $this['config']['force_ssl'],
282 766
                'cookie_lifetime' => $this['config']['cookie_lifetime'],
283 766
                'cookie_httponly' => true,
284
                // cookie_domainは指定しない
285
                // http://blog.tokumaru.org/2011/10/cookiedomain.html
286 766
            ),
287
        ));
288 766
    }
289
290 766
    public function initRendering()
291
    {
292
        $this->register(new \Silex\Provider\TwigServiceProvider(), array(
293
            'twig.form.templates' => array('Form/form_layout.twig'),
294
        ));
295
        $this['twig'] = $this->share($this->extend('twig', function(\Twig_Environment $twig, \Silex\Application $app) {
296
            $twig->addExtension(new \Eccube\Twig\Extension\EccubeExtension($app));
297
            $twig->addExtension(new \Twig_Extension_StringLoader());
298
299 200
            return $twig;
300
        }));
301
302
        $this->before(function(Request $request, \Silex\Application $app) {
303
            // フロント or 管理画面ごとにtwigの探索パスを切り替える.
304
            $app['twig'] = $app->share($app->extend('twig', function(\Twig_Environment $twig, \Silex\Application $app) {
305 166
                $paths = array();
306
307
                // 互換性がないのでprofiler とproduction 時のcacheを分離する
308
309
                if (isset($app['profiler'])) {
310
                    $cacheBaseDir = __DIR__.'/../../app/cache/twig/profiler/';
311
                } else {
312 166
                    $cacheBaseDir = __DIR__.'/../../app/cache/twig/production/';
313
                }
314
                if (strpos($app['request']->getPathInfo(), '/'.trim($app['config']['admin_route'], '/')) === 0) {
315
                    if (file_exists(__DIR__.'/../../app/template/admin')) {
316 98
                        $paths[] = __DIR__.'/../../app/template/admin';
317
                    }
318
                    $paths[] = $app['config']['template_admin_realdir'];
319 98
                    $paths[] = __DIR__.'/../../app/Plugin';
320 98
                    $cache = $cacheBaseDir.'admin';
321
                } else {
322
                    if (file_exists($app['config']['template_realdir'])) {
323
                        $paths[] = $app['config']['template_realdir'];
324
                    }
325
                    $paths[] = $app['config']['template_default_realdir'];
326 68
                    $paths[] = __DIR__.'/../../app/Plugin';
327
                    $cache = $cacheBaseDir.$app['config']['template_code'];
328 98
                }
329
                $twig->setCache($cache);
330
                $app['twig.loader']->addLoader(new \Twig_Loader_Filesystem($paths));
331
332 166
                return $twig;
333
            }));
334
335
            // 管理画面のIP制限チェック.
336
            if (strpos($app['request']->getPathInfo(), '/'.trim($app['config']['admin_route'], '/')) === 0) {
337
                // IP制限チェック
338
                $allowHost = $app['config']['admin_allow_host'];
339
                if (count($allowHost) > 0) {
340
                    if (array_search($app['request']->getClientIp(), $allowHost) === false) {
341
                        throw new \Exception();
342
                    }
343
                }
344
            }
345
        }, self::EARLY_EVENT);
346
347
        // twigのグローバル変数を定義.
348 766
        $app = $this;
349
        $this->on(\Symfony\Component\HttpKernel\KernelEvents::CONTROLLER, function(\Symfony\Component\HttpKernel\Event\FilterControllerEvent $event) use ($app) {
350
            // ショップ基本情報
351
            $BaseInfo = $app['eccube.repository.base_info']->get();
352
            $app['twig']->addGlobal('BaseInfo', $BaseInfo);
353
354
            if (strpos($app['request']->getPathInfo(), '/'.trim($app['config']['admin_route'], '/')) === 0) {
355
                // 管理画面
356
                // 管理画面メニュー
357 98
                $menus = array('', '', '');
358
                $app['twig']->addGlobal('menus', $menus);
359
360
                $Member = $app->user();
361
                if (is_object($Member)) {
362
                    // ログインしていれば管理者のロールを取得
363
                    $AuthorityRoles = $app['eccube.repository.authority_role']->findBy(array('Authority' => $Member->getAuthority()));
364
365 95
                    $roles = array();
366
                    foreach ($AuthorityRoles as $AuthorityRole) {
367
                        // 管理画面でメニュー制御するため相対パス全てをセット
368
                        $roles[] = $app['request']->getBaseUrl().'/'.$app['config']['admin_route'].$AuthorityRole->getDenyUrl();
369 95
                    }
370
371
                    $app['twig']->addGlobal('AuthorityRoles', $roles);
372
                }
373
374
            } else {
375
                // フロント画面
376
                $request = $event->getRequest();
377
                $route = $request->attributes->get('_route');
378
379
                // ユーザ作成画面
380
                if ($route === trim($app['config']['user_data_route'])) {
381
                    $params = $request->attributes->get('_route_params');
382 2
                    $route = $params['route'];
383
                    // プレビュー画面
384
                } elseif ($request->get('preview')) {
385
                    $route = 'preview';
386 2
                }
387
388
                try {
389
                    $DeviceType = $app['eccube.repository.master.device_type']
390
                        ->find(\Eccube\Entity\Master\DeviceType::DEVICE_TYPE_PC);
391
                    $PageLayout = $app['eccube.repository.page_layout']->getByUrl($DeviceType, $route);
392
                } catch (\Doctrine\ORM\NoResultException $e) {
393
                    $PageLayout = $app['eccube.repository.page_layout']->newPageLayout($DeviceType);
394 34
                }
395
396
                $app['twig']->addGlobal('PageLayout', $PageLayout);
397
                $app['twig']->addGlobal('title', $PageLayout->getName());
398 98
            }
399
        });
400 766
    }
401
402 766
    public function initMailer()
403
    {
404
405
        // メール送信時の文字エンコード指定(デフォルトはUTF-8)
406
        if (isset($this['config']['mail']['charset_iso_2022_jp']) && is_bool($this['config']['mail']['charset_iso_2022_jp'])) {
407
            if ($this['config']['mail']['charset_iso_2022_jp'] === true) {
408
                \Swift::init(function() {
409
                    \Swift_DependencyContainer::getInstance()
410
                        ->register('mime.qpheaderencoder')
411
                        ->asAliasOf('mime.base64headerencoder');
412
                    \Swift_Preferences::getInstance()->setCharset('iso-2022-jp');
413
                });
414
            }
415
        }
416
417
        $this->register(new \Silex\Provider\SwiftmailerServiceProvider());
418
        $this['swiftmailer.options'] = $this['config']['mail'];
419
420
        if (isset($this['config']['mail']['spool']) && is_bool($this['config']['mail']['spool'])) {
421
            $this['swiftmailer.use_spool'] = $this['config']['mail']['spool'];
422
        }
423
        // デフォルトはsmtpを使用
424
        $transport = $this['config']['mail']['transport'];
425 766
        if ($transport == 'sendmail') {
426
            $this['swiftmailer.transport'] = \Swift_SendmailTransport::newInstance();
427 766
        } elseif ($transport == 'mail') {
428
            $this['swiftmailer.transport'] = \Swift_MailTransport::newInstance();
429
        }
430 766
    }
431
432 766
    public function initDoctrine()
433
    {
434
        $this->register(new \Silex\Provider\DoctrineServiceProvider(), array(
435
            'dbs.options' => array(
436 766
                'default' => $this['config']['database']
437
        )));
438
        $this->register(new \Saxulum\DoctrineOrmManagerRegistry\Silex\Provider\DoctrineOrmManagerRegistryProvider());
439
440
        // プラグインのmetadata定義を合わせて行う.
441 766
        $pluginBasePath = __DIR__.'/../../app/Plugin';
442 765
        $finder = Finder::create()
443 766
            ->in($pluginBasePath)
444 766
            ->directories()
445
            ->depth(0);
446
447 766
        $ormMappings = array();
448
        $ormMappings[] = array(
449 766
            'type' => 'yml',
450 766
            'namespace' => 'Eccube\Entity',
451
            'path' => array(
452 766
                __DIR__.'/Resource/doctrine',
453 766
                __DIR__.'/Resource/doctrine/master',
454 766
            ),
455 766
        );
456
457
        foreach ($finder as $dir) {
458
459
            $file = $dir->getRealPath().'/config.yml';
460
461
            if (file_exists($file)) {
462
                $config = Yaml::parse(file_get_contents($file));
463
            } else {
464
                $code = $dir->getBaseName();
465
                $this['monolog']->warning("skip {$code} orm.path loading. config.yml not found.", array('path' => $file));
466
                continue;
467
            }
468
469
            // Doctrine Extend
470
            if (isset($config['orm.path']) && is_array($config['orm.path'])) {
471
                $paths = array();
472
                foreach ($config['orm.path'] as $path) {
473
                    $paths[] = $pluginBasePath.'/'.$config['code'].$path;
474
                }
475
                $ormMappings[] = array(
476
                    'type' => 'yml',
477
                    'namespace' => 'Plugin\\'.$config['code'].'\\Entity',
478
                    'path' => $paths,
479
                );
480
            }
481 766
        }
482
483
        $this->register(new \Dflydev\Silex\Provider\DoctrineOrm\DoctrineOrmServiceProvider(), array(
484 766
            'orm.proxies_dir' => __DIR__.'/../../app/cache/doctrine',
485
            'orm.em.options' => array(
486
                'mappings' => $ormMappings,
487 766
            ),
488
        ));
489 766
    }
490
491 766
    public function initSecurity()
492
    {
493
        $this->register(new \Silex\Provider\SecurityServiceProvider());
494
        $this->register(new \Silex\Provider\RememberMeServiceProvider());
495
496 766
        $this['security.firewalls'] = array(
497
            'admin' => array(
498
                'pattern' => "^/{$this['config']['admin_route']}",
499
                'form' => array(
500
                    'login_path' => "/{$this['config']['admin_route']}/login",
501
                    'check_path' => "/{$this['config']['admin_route']}/login_check",
502 766
                    'username_parameter' => 'login_id',
503 766
                    'password_parameter' => 'password',
504 766
                    'with_csrf' => true,
505 766
                    'use_forward' => true,
506 766
                ),
507
                'logout' => array(
508
                    'logout_path' => "/{$this['config']['admin_route']}/logout",
509
                    'target_url' => "/{$this['config']['admin_route']}/",
510 766
                ),
511
                'users' => $this['orm.em']->getRepository('Eccube\Entity\Member'),
512 766
                'anonymous' => true,
513
            ),
514
            'customer' => array(
515 766
                'pattern' => '^/',
516
                'form' => array(
517
                    'login_path' => '/mypage/login',
518
                    'check_path' => '/login_check',
519
                    'username_parameter' => 'login_email',
520
                    'password_parameter' => 'login_pass',
521
                    'with_csrf' => true,
522
                    'use_forward' => true,
523 766
                ),
524
                'logout' => array(
525
                    'logout_path' => '/logout',
526
                    'target_url' => '/',
527 766
                ),
528
                'remember_me' => array(
529
                    'key' => sha1($this['config']['auth_magic']),
530 766
                    'name' => 'eccube_rememberme',
531
                    // lifetimeはデフォルトの1年間にする
532
                    // 'lifetime' => $this['config']['cookie_lifetime'],
533
                    'path' => $this['config']['root_urlpath'] ?: '/',
534 766
                    'secure' => $this['config']['force_ssl'],
535 766
                    'httponly' => true,
536 766
                    'always_remember_me' => false,
537 766
                    'remember_me_parameter' => 'login_memory',
538
                ),
539
                'users' => $this['orm.em']->getRepository('Eccube\Entity\Customer'),
540 766
                'anonymous' => true,
541
            ),
542
        );
543
544 766
        $this['security.access_rules'] = array(
545
            array("^/{$this['config']['admin_route']}/login", 'IS_AUTHENTICATED_ANONYMOUSLY'),
546
            array("^/{$this['config']['admin_route']}", 'ROLE_ADMIN'),
547 766
            array('^/mypage/login', 'IS_AUTHENTICATED_ANONYMOUSLY'),
548 766
            array('^/mypage/withdraw_complete', 'IS_AUTHENTICATED_ANONYMOUSLY'),
549 766
            array('^/mypage/change', 'IS_AUTHENTICATED_FULLY'),
550 766
            array('^/mypage', 'ROLE_USER'),
551
        );
552
553
        $this['eccube.password_encoder'] = $this->share(function($app) {
554
            return new \Eccube\Security\Core\Encoder\PasswordEncoder($app['config']);
555
        });
556
        $this['security.encoder_factory'] = $this->share(function($app) {
557
            return new \Symfony\Component\Security\Core\Encoder\EncoderFactory(array(
558 766
                'Eccube\Entity\Customer' => $app['eccube.password_encoder'],
559 766
                'Eccube\Entity\Member' => $app['eccube.password_encoder'],
560
            ));
561
        });
562
        $this['eccube.event_listner.security'] = $this->share(function($app) {
563
            return new \Eccube\EventListener\SecurityEventListener($app['orm.em']);
564
        });
565
        $this['user'] = function($app) {
566
            $token = $app['security']->getToken();
567
568
            return ($token !== null) ? $token->getUser() : null;
569
        };
570
571
        // ログイン時のイベントを設定.
572
        $this['dispatcher']->addListener(\Symfony\Component\Security\Http\SecurityEvents::INTERACTIVE_LOGIN, array($this['eccube.event_listner.security'], 'onInteractiveLogin'));
573
574
        // Voterの設定
575 766
        $app = $this;
576
        $this['authority_voter'] = $this->share(function($app) {
577
            return new \Eccube\Security\Voter\AuthorityVoter($app);
578
        });
579
580
        $app['security.voters'] = $app->extend('security.voters', function($voters) use ($app) {
581
            $voters[] = $app['authority_voter'];
582
583 766
            return $voters;
584
        });
585
586
        $this['security.access_manager'] = $this->share(function($app) {
587
            return new \Symfony\Component\Security\Core\Authorization\AccessDecisionManager($app['security.voters'], 'unanimous');
588
        });
589
590 766
    }
591
592
    public function initializePlugin()
593
    {
594
        if ($this->initializedPlugin) {
595
            return;
596
        }
597
598
        // setup event dispatcher
599
        $this->initPluginEventDispatcher();
600
601
        // load plugin
602
        $this->loadPlugin();
603
604
        $this->initializedPlugin = true;
605
    }
606
607 766
    public function initPluginEventDispatcher()
608
    {
609
        // EventDispatcher
610
        $this['eccube.event.dispatcher'] = $this->share(function() {
611
            return new EventDispatcher();
612
        });
613
614
        // hook point
615
        $this->before(function(Request $request, \Silex\Application $app) {
616
            $app['eccube.event.dispatcher']->dispatch('eccube.event.app.before');
617
        }, self::EARLY_EVENT);
618
619
        $this->before(function(Request $request, \Silex\Application $app) {
620
            $event = 'eccube.event.controller.'.$request->attributes->get('_route').'.before';
621
            $app['eccube.event.dispatcher']->dispatch($event);
622
        });
623
624 View Code Duplication
        $this->after(function(Request $request, Response $response, \Silex\Application $app) {
625
            $event = 'eccube.event.controller.'.$request->attributes->get('_route').'.after';
626
            $app['eccube.event.dispatcher']->dispatch($event);
627
        });
628
629
        $this->after(function(Request $request, Response $response, \Silex\Application $app) {
630
            $app['eccube.event.dispatcher']->dispatch('eccube.event.app.after');
631
        }, self::LATE_EVENT);
632
633 View Code Duplication
        $this->finish(function(Request $request, Response $response, \Silex\Application $app) {
634
            $event = 'eccube.event.controller.'.$request->attributes->get('_route').'.finish';
635
            $app['eccube.event.dispatcher']->dispatch($event);
636
        });
637
638 766
        $app = $this;
639
        $this->on(\Symfony\Component\HttpKernel\KernelEvents::RESPONSE, function(\Symfony\Component\HttpKernel\Event\FilterResponseEvent $event) use ($app) {
640
            $route = $event->getRequest()->attributes->get('_route');
641
            $app['eccube.event.dispatcher']->dispatch('eccube.event.render.'.$route.'.before', $event);
642
        });
643 766
    }
644
645
    public function loadPlugin()
646
    {
647
        // プラグインディレクトリを探索.
648
        $basePath = __DIR__.'/../../app/Plugin';
649
        $finder = Finder::create()
650
            ->in($basePath)
651
            ->directories()
652
            ->depth(0);
653
654
        $finder->sortByName();
655
656
        // ハンドラ優先順位をdbから持ってきてハッシュテーブルを作成
657
        $priorities = array();
658
        $handlers = $this['orm.em']
659
            ->getRepository('Eccube\Entity\PluginEventHandler')
660
            ->getHandlers();
661
        foreach ($handlers as $handler) {
662
            if ($handler->getPlugin()->getEnable() && !$handler->getPlugin()->getDelFlg()) {
663
664
                $priority = $handler->getPriority();
665
            } else {
666
                // Pluginがdisable、削除済みの場合、EventHandlerのPriorityを全て0とみなす
667
                $priority = \Eccube\Entity\PluginEventHandler::EVENT_PRIORITY_DISABLED;
668
            }
669
            $priorities[$handler->getPlugin()->getClassName()][$handler->getEvent()][$handler->getHandler()] = $priority;
670
        }
671
672
        // プラグインをロードする.
673
        // config.yml/event.ymlの定義に沿ってインスタンスの生成を行い, イベント設定を行う.
674
        foreach ($finder as $dir) {
675
            //config.ymlのないディレクトリは無視する
676
            $path = $dir->getRealPath();
677
            $code = $dir->getBaseName();
678
            try {
679
                $this['eccube.service.plugin']->checkPluginArchiveContent($path);
680
            } catch(\Eccube\Exception\PluginException $e) {
681
                $this['monolog']->warning("skip {$code} config loading. config.yml not foud or invalid.", array(
682
                    'path' =>  $path,
683
                    'original-message' => $e->getMessage()
684
                ));
685
                continue;
686
            }
687
            $config = $this['eccube.service.plugin']->readYml($dir->getRealPath().'/config.yml');
688
689
            $plugin = $this['orm.em']
690
                ->getRepository('Eccube\Entity\Plugin')
691
                ->findOneBy(array('code' => $config['code']));
692
693
            // const
694
            if (isset($config['const'])) {
695
                $this['config'] = $this->share($this->extend('config', function($eccubeConfig) use ($config) {
696
                    $eccubeConfig[$config['code']] = array(
697
                        'const' => $config['const'],
698
                    );
699
700
                    return $eccubeConfig;
701
                }));
702
            }
703
704
            if ($plugin && $plugin->getEnable() == Constant::DISABLED) {
705
                // プラグインが無効化されていれば読み込まない
706
                continue;
707
            }
708
709
            // Type: Event
710
            if (isset($config['event'])) {
711
                $class = '\\Plugin\\'.$config['code'].'\\'.$config['event'];
712
                $eventExists = true;
713
714 View Code Duplication
                if (!class_exists($class)) {
715
                    $this['monolog']->warning("skip {$code} loading. event class not foud.", array(
716
                        'class' =>  $class,
717
                    ));
718
                    $eventExists = false;
719
                }
720
721
                if ($eventExists && file_exists($dir->getRealPath().'/event.yml')) {
722
723
                    $subscriber = new $class($this);
724
725
                    foreach (Yaml::parse(file_get_contents($dir->getRealPath().'/event.yml')) as $event => $handlers) {
726
                        foreach ($handlers as $handler) {
727
                            if (!isset($priorities[$config['event']][$event][$handler[0]])) { // ハンドラテーブルに登録されていない(ソースにしか記述されていない)ハンドラは一番後ろにする
728
                                $priority = \Eccube\Entity\PluginEventHandler::EVENT_PRIORITY_LATEST;
729
                            } else {
730
                                $priority = $priorities[$config['event']][$event][$handler[0]];
731
                            }
732
                            // 優先度が0のプラグインは登録しない
733
                            if (\Eccube\Entity\PluginEventHandler::EVENT_PRIORITY_DISABLED != $priority) {
734
                                $this['eccube.event.dispatcher']->addListener($event, array($subscriber, $handler[0]), $priority);
735
                            }
736
                        }
737
                    }
738
                }
739
            }
740
            // Type: ServiceProvider
741
            if (isset($config['service'])) {
742
                foreach ($config['service'] as $service) {
743
                    $class = '\\Plugin\\'.$config['code'].'\\ServiceProvider\\'.$service;
744 View Code Duplication
                    if (!class_exists($class)) {
745
                        $this['monolog']->warning("skip {$code} loading. service provider class not foud.", array(
746
                            'class' =>  $class,
747
                        ));
748
                        continue;
749
                    }
750
                    $this->register(new $class($this));
751
                }
752
            }
753
        }
754
    }
755
756
    /**
757
     *
758
     * データベースの接続を確認
759
     * 成功 : trueを返却
760
     * 失敗 : \Doctrine\DBAL\DBALExceptionエラーが発生( 接続に失敗した場合 )、エラー画面を表示しdie()
761
     * 備考 : app['debug']がtrueの際は処理を行わない
762
     * @return boolean true
763
     *
764
     */
765 766
    protected function checkDatabaseConnection()
766
    {
767
        if ($this['debug']) {
768 766
            return;
769
        }
770
        try {
771
            $this['db']->connect();
772
        } catch (\Doctrine\DBAL\DBALException $e) {
773
            $this['monolog']->error($e->getMessage());
774
            $this['twig.path'] = array(__DIR__.'/Resource/template/exception');
775
            $html = $this['twig']->render('error.twig', array(
776
                'error_title' => 'データーベース接続エラー',
777
                'error_message' => 'データーベースを確認してください',
778
            ));
779
            $response = new Response();
780
            $response->setContent($html);
781
            $response->setStatusCode('500');
782
            $response->headers->set('Content-Type', 'text/html');
783
            $response->send();
784
            die();
0 ignored issues
show
Coding Style Compatibility introduced by
The method checkDatabaseConnection() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
785
        }
786
        return true;
787
    }
788
}