Failed Conditions
Pull Request — master (#1861)
by k-yamamura
501:04 queued 494:33
created

Application   F

Complexity

Total Complexity 136

Size/Duplication

Total Lines 1105
Duplicated Lines 15.38 %

Coupling/Cohesion

Components 2
Dependencies 53

Test Coverage

Coverage 80.12%

Importance

Changes 0
Metric Value
wmc 136
lcom 2
cbo 53
dl 170
loc 1105
ccs 520
cts 649
cp 0.8012
rs 0.5217
c 0
b 0
f 0

23 Methods

Rating   Name   Duplication   Size   Complexity  
A __clone() 0 4 1
A getInstance() 0 8 2
A clearInstance() 0 4 1
A __construct() 0 14 2
A isBooted() 0 4 1
A initConfig() 0 20 1
A initLogger() 0 5 1
B initialize() 0 83 6
B initLocale() 0 28 5
B initSession() 0 24 3
D loadPlugin() 12 110 20
A setTestMode() 0 4 1
A isTestMode() 0 4 1
B checkDatabaseConnection() 0 24 3
D parseConfig() 6 41 13
B isSessionStarted() 0 12 5
B initCacheRequest() 0 63 7
D initRendering() 0 129 17
C initMailer() 0 29 8
F initDoctrine() 0 99 13
B initSecurity() 0 100 3
A initializePlugin() 0 14 2
D initPluginEventDispatcher() 152 204 20

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like Application often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Application, and based on these observations, apply Extract Interface, too.

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 Eccube\Doctrine\ORM\Mapping\Driver\YamlDriver;
29
use Eccube\EventListener\TransactionListener;
30
use Symfony\Component\EventDispatcher\EventDispatcher;
31
use Symfony\Component\Finder\Finder;
32
use Symfony\Component\HttpFoundation\Request;
33
use Symfony\Component\HttpFoundation\Response;
34
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
35
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
36
use Symfony\Component\HttpKernel\Event\PostResponseEvent;
37
use Symfony\Component\HttpKernel\KernelEvents;
38
use Symfony\Component\Yaml\Yaml;
39
40
class Application extends ApplicationTrait
0 ignored issues
show
introduced by
Missing class doc comment
Loading history...
41
{
42
    protected static $instance;
43
44
    protected $initialized = false;
45
    protected $initializedPlugin = false;
46
    protected $testMode = false;
47
48 1058
    public static function getInstance(array $values = array())
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
49
    {
50 1058
        if (!is_object(self::$instance)) {
51 1054
            self::$instance = new Application($values);
52 1054
        }
53
54 1058
        return self::$instance;
55
    }
56
57 1055
    public static function clearInstance()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
58
    {
59 1055
        self::$instance = null;
60 1055
    }
61
62
    final public function __clone()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
63
    {
64
        throw new \Exception('Clone is not allowed against '.get_class($this));
65
    }
66
67 1069
    public function __construct(array $values = array())
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
68 1069
    {
69 1069
        parent::__construct($values);
70
71 1069
        if (is_null(self::$instance)) {
72 1055
            self::$instance = $this;
73 1055
        }
74
75
        // load config
76 1069
        $this->initConfig();
77
78
        // init monolog
79 1069
        $this->initLogger();
80 1069
    }
81
82
    /**
83
     * Application::runが実行されているか親クラスのプロパティから判定
84
     *
85
     * @return bool
86
     */
87 1062
    public function isBooted()
88
    {
89 1062
        return $this->booted;
90
    }
91
92 1069
    public function initConfig()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
93
    {
94
        // load config
95 1069
        $app = $this;
96
        $this['config'] = $this->share(function() use ($app) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
97 1069
            $configAll = array();
98 1069
            $app->parseConfig('constant', $configAll)
99 1069
                ->parseConfig('path', $configAll)
100 1069
                ->parseConfig('config', $configAll)
101 1069
                ->parseConfig('database', $configAll)
102 1069
                ->parseConfig('mail', $configAll)
103 1069
                ->parseConfig('log', $configAll)
104 1069
                ->parseConfig('nav', $configAll, true)
105 1069
                ->parseConfig('doctrine_cache', $configAll)
106 1069
                ->parseConfig('http_cache', $configAll)
107 1069
                ->parseConfig('session_handler', $configAll);
108
109 1069
            return $configAll;
110 1069
        });
111 1069
    }
112
113 1069
    public function initLogger()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
114
    {
115 1069
        $app = $this;
116 1069
        $this->register(new ServiceProvider\EccubeMonologServiceProvider($app));
0 ignored issues
show
Unused Code introduced by
The call to EccubeMonologServiceProvider::__construct() has too many arguments starting with $app.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
117 1069
    }
118
119 1070
    public function initialize()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
120
    {
121 1059
        if ($this->initialized) {
122 1069
            return;
123
        }
124
125
        // init locale
126 1070
        $this->initLocale();
127
128
        // init session
129 1059
        if (!$this->isSessionStarted()) {
130 1070
            $this->initSession();
131 1059
        }
132
133
        // init twig
134 1059
        $this->initRendering();
135
136
        // init provider
137 1059
        $this->register(new \Silex\Provider\HttpCacheServiceProvider(), array(
138 1059
            'http_cache.cache_dir' => __DIR__.'/../../app/cache/http/',
139 1059
        ));
140 1059
        $this->register(new \Silex\Provider\HttpFragmentServiceProvider());
141 1059
        $this->register(new \Silex\Provider\UrlGeneratorServiceProvider());
142 1059
        $this->register(new \Silex\Provider\FormServiceProvider());
143 1059
        $this->register(new \Silex\Provider\SerializerServiceProvider());
144 1059
        $this->register(new \Silex\Provider\ValidatorServiceProvider());
145
146 1059
        $app = $this;
147
        $this->error(function (\Exception $e, $code) use ($app) {
148 17
            if ($app['debug']) {
149 1069
                return;
150
            }
151
152
            switch ($code) {
153 1069
                case 403:
154
                    $title = 'アクセスできません。';
155 1069
                    $message = 'お探しのページはアクセスができない状況にあるか、移動もしくは削除された可能性があります。';
156 1069
                    break;
157 1069
                case 404:
158 1069
                    $title = 'ページがみつかりません。';
159 1069
                    $message = 'URLに間違いがないかご確認ください。';
160
                    break;
161
                default:
162
                    $title = 'システムエラーが発生しました。';
163
                    $message = '大変お手数ですが、サイト管理者までご連絡ください。';
164
                    break;
165
            }
166
167
            return $app->render('error.twig', array(
168
                'error_title' => $title,
169
                'error_message' => $message,
170
            ));
171 1059
        });
172
173
        // init mailer
174 1059
        $this->initMailer();
175
176
        // init doctrine orm
177 1059
        $this->initDoctrine();
178
179
        // Set up the DBAL connection now to check for a proper connection to the database.
180 1059
        $this->checkDatabaseConnection();
181
182
        // init security
183 1059
        $this->initSecurity();
184
185
        // init ec-cube service provider
186 1059
        $this->register(new ServiceProvider\EccubeServiceProvider());
187
188
        // mount controllers
189 1059
        $this->register(new \Silex\Provider\ServiceControllerServiceProvider());
190 1059
        $this->mount('', new ControllerProvider\FrontControllerProvider());
191 1059
        $this->mount('/'.trim($this['config']['admin_route'], '/').'/', new ControllerProvider\AdminControllerProvider());
192 1059
        Request::enableHttpMethodParameterOverride(); // PUTやDELETEできるようにする
193
194
        // add transaction listener
195 1059
        $this['dispatcher']->addSubscriber(new TransactionListener($this));
196
197
        // init http cache
198 1059
        $this->initCacheRequest();
199
200 1059
        $this->initialized = true;
201 1059
    }
202
203 1059
    public function initLocale()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
204
    {
205
206
        // timezone
207 1059
        if (!empty($this['config']['timezone'])) {
208 1059
            date_default_timezone_set($this['config']['timezone']);
209 1059
        }
210
211 1059
        $this->register(new \Silex\Provider\TranslationServiceProvider(), array(
212 1059
            'locale' => $this['config']['locale'],
213 1059
            'translator.cache_dir' => $this['debug'] ? null : $this['config']['root_dir'].'/app/cache/translator',
214 1059
        ));
215
        $this['translator'] = $this->share($this->extend('translator', function ($translator, \Silex\Application $app) {
216 715
            $translator->addLoader('yaml', new \Symfony\Component\Translation\Loader\YamlFileLoader());
217
218 715
            $file = __DIR__.'/Resource/locale/validator.'.$app['locale'].'.yml';
219 715
            if (file_exists($file)) {
220 715
                $translator->addResource('yaml', $file, $app['locale'], 'validators');
221 715
            }
222
223 715
            $file = __DIR__.'/Resource/locale/message.'.$app['locale'].'.yml';
224 715
            if (file_exists($file)) {
225 715
                $translator->addResource('yaml', $file, $app['locale']);
226 715
            }
227
228 715
            return $translator;
229 1059
        }));
230 1059
    }
231
232 1059
    public function initSession()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
233
    {
234 1059
        $this->register(new \Silex\Provider\SessionServiceProvider(), array(
235 1059
            'session.storage.save_path' => $this['config']['root_dir'].'/app/cache/eccube/session',
236
            'session.storage.options' => array(
237 1059
                'name' => 'eccube',
238 1059
                'cookie_path' => $this['config']['root_urlpath'] ?: '/',
239 1059
                'cookie_secure' => $this['config']['force_ssl'],
240 1059
                'cookie_lifetime' => $this['config']['cookie_lifetime'],
241 1059
                'cookie_httponly' => true,
242
                // cookie_domainは指定しない
243
                // http://blog.tokumaru.org/2011/10/cookiedomain.html
244 1059
            ),
245 1059
        ));
246
247 1059
        $options = $this['config']['session_handler'];
248
249 1059
        if ($options['enabled']) {
250
            // @see http://silex.sensiolabs.org/doc/providers/session.html#custom-session-configurations
251
            $this['session.storage.handler'] = null;
252
            ini_set('session.save_handler', $options['save_handler']);
253
            ini_set('session.save_path', $options['save_path']);
254
        }
255 1059
    }
256
257 1059
    public function initRendering()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
258
    {
259 1059
        $this->register(new \Silex\Provider\TwigServiceProvider(), array(
260 1059
            'twig.form.templates' => array('Form/form_layout.twig'),
261 1059
        ));
262
        $this['twig'] = $this->share($this->extend('twig', function (\Twig_Environment $twig, \Silex\Application $app) {
263 472
            $twig->addExtension(new \Eccube\Twig\Extension\EccubeExtension($app));
264 472
            $twig->addExtension(new \Twig_Extension_StringLoader());
265
266 472
            return $twig;
267 1059
        }));
268
269
        $this->before(function (Request $request, \Silex\Application $app) {
270 460
            $app['admin'] = false;
271 460
            $app['front'] = false;
272 460
            $pathinfo = rawurldecode($request->getPathInfo());
273 460
            if (strpos($pathinfo, '/'.trim($app['config']['admin_route'], '/').'/') === 0) {
274 291
                $app['admin'] = true;
275 291
            } else {
276 171
                $app['front'] = true;
277
            }
278
279
            // フロント or 管理画面ごとにtwigの探索パスを切り替える.
280
            $app['twig'] = $app->share($app->extend('twig', function (\Twig_Environment $twig, \Silex\Application $app) {
281 458
                $paths = array();
282
283
                // 互換性がないのでprofiler とproduction 時のcacheを分離する
284 458
                if (isset($app['profiler'])) {
285
                    $cacheBaseDir = __DIR__.'/../../app/cache/twig/profiler/';
286
                } else {
287 458
                    $cacheBaseDir = __DIR__.'/../../app/cache/twig/production/';
288
                }
289
290 458
                if ($app->isAdminRequest()) {
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class Silex\Application as the method isAdminRequest() does only exist in the following sub-classes of Silex\Application: Eccube\Application, Eccube\Application\ApplicationTrait, Eccube\InstallApplication. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
291 291
                    if (file_exists(__DIR__.'/../../app/template/admin')) {
292 291
                        $paths[] = __DIR__.'/../../app/template/admin';
293 291
                    }
294 291
                    $paths[] = $app['config']['template_admin_realdir'];
295 291
                    $paths[] = __DIR__.'/../../app/Plugin';
296 291
                    $cache = $cacheBaseDir.'admin';
297
0 ignored issues
show
Coding Style introduced by
Blank line found at end of control structure
Loading history...
298 291
                } else {
299 169
                    if (file_exists($app['config']['template_realdir'])) {
300 169
                        $paths[] = $app['config']['template_realdir'];
301 169
                    }
302 169
                    $paths[] = $app['config']['template_default_realdir'];
303 169
                    $paths[] = __DIR__.'/../../app/Plugin';
304 169
                    $cache = $cacheBaseDir.$app['config']['template_code'];
305 169
                    $app['front'] = true;
306
                }
307 458
                $twig->setCache($cache);
308 459
                $app['twig.loader']->addLoader(new \Twig_Loader_Filesystem($paths));
309
310 458
                return $twig;
311 460
            }));
312
313
            // 管理画面のIP制限チェック.
314 460
            if ($app->isAdminRequest()) {
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class Silex\Application as the method isAdminRequest() does only exist in the following sub-classes of Silex\Application: Eccube\Application, Eccube\Application\ApplicationTrait, Eccube\InstallApplication. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
315
                // IP制限チェック
316 291
                $allowHost = $app['config']['admin_allow_host'];
317 291
                if (count($allowHost) > 0) {
318
                    if (array_search($app['request']->getClientIp(), $allowHost) === false) {
319
                        throw new \Exception();
320
                    }
321
                }
322 291
            }
323 1059
        }, self::EARLY_EVENT);
324
325
        // twigのグローバル変数を定義.
326 1059
        $app = $this;
327
        $this->on(\Symfony\Component\HttpKernel\KernelEvents::CONTROLLER, function (\Symfony\Component\HttpKernel\Event\FilterControllerEvent $event) use ($app) {
328
            // 未ログイン時にマイページや管理画面以下にアクセスするとSubRequestで実行されるため,
329
            // $event->isMasterRequest()ではなく、グローバル変数が初期化済かどうかの判定を行う
0 ignored issues
show
Unused Code Comprehensibility introduced by
58% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
330 458
            if (isset($app['twig_global_initialized']) && $app['twig_global_initialized'] === true) {
331 113
                return;
332
            }
333
            // ショップ基本情報
334 458
            $BaseInfo = $app['eccube.repository.base_info']->get();
335 458
            $app['twig']->addGlobal('BaseInfo', $BaseInfo);
336
337 458
            if ($app->isAdminRequest()) {
338
                // 管理画面
339
                // 管理画面メニュー
340 291
                $menus = array('', '', '');
341 291
                $app['twig']->addGlobal('menus', $menus);
342
343 291
                $Member = $app->user();
344 291
                if (is_object($Member)) {
345
                    // ログインしていれば管理者のロールを取得
346 285
                    $AuthorityRoles = $app['eccube.repository.authority_role']->findBy(array('Authority' => $Member->getAuthority()));
347
348 285
                    $roles = array();
349 285
                    foreach ($AuthorityRoles as $AuthorityRole) {
350
                        // 管理画面でメニュー制御するため相対パス全てをセット
351 3
                        $roles[] = $app['request']->getBaseUrl().'/'.$app['config']['admin_route'].$AuthorityRole->getDenyUrl();
352 285
                    }
353
354 285
                    $app['twig']->addGlobal('AuthorityRoles', $roles);
355 285
                }
356
0 ignored issues
show
Coding Style introduced by
Blank line found at end of control structure
Loading history...
357 291
            } else {
358
                // フロント画面
359 167
                $request = $event->getRequest();
360 167
                $route = $request->attributes->get('_route');
361
362
                // ユーザ作成画面
363 167
                if ($route === 'user_data') {
364 2
                    $params = $request->attributes->get('_route_params');
365 2
                    $route = $params['route'];
366
                    // プレビュー画面
367 167
                } elseif ($request->get('preview')) {
368
                    $route = 'preview';
369
                }
370
371 1
                try {
372 167
                    $DeviceType = $app['eccube.repository.master.device_type']
373 167
                        ->find(\Eccube\Entity\Master\DeviceType::DEVICE_TYPE_PC);
374 167
                    $PageLayout = $app['eccube.repository.page_layout']->getByUrl($DeviceType, $route);
375 167
                } catch (\Doctrine\ORM\NoResultException $e) {
376 65
                    $PageLayout = $app['eccube.repository.page_layout']->newPageLayout($DeviceType);
377
                }
378
379 167
                $app['twig']->addGlobal('PageLayout', $PageLayout);
380 167
                $app['twig']->addGlobal('title', $PageLayout->getName());
381
            }
382
383 458
            $app['twig_global_initialized'] = true;
384 1059
        });
385 1059
    }
386
387 1059
    public function initMailer()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
388
    {
389
390
        // メール送信時の文字エンコード指定(デフォルトはUTF-8)
0 ignored issues
show
Unused Code Comprehensibility introduced by
43% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
391 1059
        if (isset($this['config']['mail']['charset_iso_2022_jp']) && is_bool($this['config']['mail']['charset_iso_2022_jp'])) {
392 1059
            if ($this['config']['mail']['charset_iso_2022_jp'] === true) {
393
                \Swift::init(function () {
394
                    \Swift_DependencyContainer::getInstance()
395
                        ->register('mime.qpheaderencoder')
396
                        ->asAliasOf('mime.base64headerencoder');
397
                    \Swift_Preferences::getInstance()->setCharset('iso-2022-jp');
398
                });
399
            }
400 1059
        }
401
402 1059
        $this->register(new \Silex\Provider\SwiftmailerServiceProvider());
403 1059
        $this['swiftmailer.options'] = $this['config']['mail'];
404
405 1059
        if (isset($this['config']['mail']['spool']) && is_bool($this['config']['mail']['spool'])) {
406
            $this['swiftmailer.use_spool'] = $this['config']['mail']['spool'];
407
        }
408
        // デフォルトはsmtpを使用
409 1059
        $transport = $this['config']['mail']['transport'];
410 1059
        if ($transport == 'sendmail') {
411
            $this['swiftmailer.transport'] = \Swift_SendmailTransport::newInstance();
412 1059
        } elseif ($transport == 'mail') {
413
            $this['swiftmailer.transport'] = \Swift_MailTransport::newInstance();
414
        }
415 1059
    }
416
417 1059
    public function initDoctrine()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
418
    {
419 1059
        $this->register(new \Silex\Provider\DoctrineServiceProvider(), array(
0 ignored issues
show
introduced by
Add a comma after each item in a multi-line array
Loading history...
420
            'dbs.options' => array(
0 ignored issues
show
introduced by
Add a comma after each item in a multi-line array
Loading history...
421 1059
                'default' => $this['config']['database']
422 1059
            )));
0 ignored issues
show
Coding Style introduced by
This line of the multi-line function call does not seem to be indented correctly. Expected 8 spaces, but found 12.
Loading history...
423 1059
        $this->register(new \Saxulum\DoctrineOrmManagerRegistry\Silex\Provider\DoctrineOrmManagerRegistryProvider());
424
425
        // プラグインのmetadata定義を合わせて行う.
426 1059
        $pluginBasePath = __DIR__.'/../../app/Plugin';
427 1059
        $finder = Finder::create()
428 1059
            ->in($pluginBasePath)
429 1059
            ->directories()
430 1059
            ->depth(0);
431
432 1059
        $ormMappings = array();
433 1059
        $ormMappings[] = array(
434 1059
            'type' => 'yml',
435 1059
            'namespace' => 'Eccube\Entity',
436
            'path' => array(
437 1059
                __DIR__.'/Resource/doctrine',
438 1059
                __DIR__.'/Resource/doctrine/master',
439 1059
            ),
440
        );
441
442 1059
        foreach ($finder as $dir) {
0 ignored issues
show
Coding Style introduced by
Blank line found at start of control structure
Loading history...
443
444 139
            $file = $dir->getRealPath().'/config.yml';
445
446 139
            if (file_exists($file)) {
447 139
                $config = Yaml::parse(file_get_contents($file));
448 139
            } else {
449
                $code = $dir->getBaseName();
450
                $this['monolog']->warning("skip {$code} orm.path loading. config.yml not found.", array('path' => $file));
451
                continue;
452
            }
453
454
            // Doctrine Extend
455 139
            if (isset($config['orm.path']) && is_array($config['orm.path'])) {
456
                $paths = array();
457
                foreach ($config['orm.path'] as $path) {
458
                    $paths[] = $pluginBasePath.'/'.$config['code'].$path;
459
                }
460
                $ormMappings[] = array(
461
                    'type' => 'yml',
462
                    'namespace' => 'Plugin\\'.$config['code'].'\\Entity',
463
                    'path' => $paths,
464
                );
465
            }
466 1059
        }
467
468
        $options = array(
0 ignored issues
show
introduced by
Add a comma after each item in a multi-line array
Loading history...
469
            'mappings' => $ormMappings
470 1059
        );
471
472 1059
        if (!$this['debug']) {
473 4
            $cacheDrivers = array();
474 4
            if (array_key_exists('doctrine_cache', $this['config'])) {
475 4
                $cacheDrivers = $this['config']['doctrine_cache'];
476 4
            }
477
478 4
            if (array_key_exists('metadata_cache', $cacheDrivers)) {
479 4
                $options['metadata_cache'] = $cacheDrivers['metadata_cache'];
480 4
            }
481 4
            if (array_key_exists('query_cache', $cacheDrivers)) {
482 4
                $options['query_cache'] = $cacheDrivers['query_cache'];
483 4
            }
484 4
            if (array_key_exists('result_cache', $cacheDrivers)) {
485 4
                $options['result_cache'] = $cacheDrivers['result_cache'];
486 4
            }
487 4
            if (array_key_exists('hydration_cache', $cacheDrivers)) {
488 4
                $options['hydration_cache'] = $cacheDrivers['hydration_cache'];
489 4
            }
490 4
        }
491
492 1059
        $this->register(new \Dflydev\Silex\Provider\DoctrineOrm\DoctrineOrmServiceProvider(), array(
493 1059
            'orm.proxies_dir' => __DIR__.'/../../app/cache/doctrine/proxies',
494 1059
            'orm.em.options' => $options,
495
            'orm.custom.functions.numeric' => array(
496 1059
                'EXTRACT' => 'Eccube\Doctrine\ORM\Query\Extract',
497 1059
            ),
498 1059
        ));
499
500
        /**
501
         * YamlDriverのPHP7対応. Doctrine2.4で修正されれば不要.
502
         * @see https://github.com/EC-CUBE/ec-cube/issues/1338
503
         */
504 1059
        $config = $this['orm.em']->getConfiguration();
505
        /** @var $driver \Doctrine\Common\Persistence\Mapping\Driver\MappingDriverChain */
506 1059
        $chain = $config->getMetadataDriverImpl();
507
        // $ormMappingsの1要素ごとにDriverが生成されている.
508 1059
        $drivers = $chain->getDrivers();
509 1059
        foreach ($drivers as $namespace => $oldDriver) {
510
            /** @var $newDriver \Eccube\Doctrine\ORM\Mapping\Driver\YamlDriver */
511 1059
            $newDriver = new YamlDriver($oldDriver->getLocator());
512
            // 修正したDriverに差し替える. メソッド名はaddだけど実際はsetしてる.
513 1059
            $chain->addDriver($newDriver, $namespace);
514 1059
        }
515 1059
    }
516
517 1059
    public function initSecurity()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
518
    {
519 1059
        $this->register(new \Silex\Provider\SecurityServiceProvider());
520 1059
        $this->register(new \Silex\Provider\RememberMeServiceProvider());
521
522 1059
        $this['security.firewalls'] = array(
523
            'admin' => array(
524 1059
                'pattern' => "^/{$this['config']['admin_route']}/",
525
                'form' => array(
526 1059
                    'login_path' => "/{$this['config']['admin_route']}/login",
527 1059
                    'check_path' => "/{$this['config']['admin_route']}/login_check",
528 1059
                    'username_parameter' => 'login_id',
529 1059
                    'password_parameter' => 'password',
530 1059
                    'with_csrf' => true,
531 1059
                    'use_forward' => true,
532 1059
                ),
533
                'logout' => array(
534 1059
                    'logout_path' => "/{$this['config']['admin_route']}/logout",
535 1059
                    'target_url' => "/{$this['config']['admin_route']}/",
536 1059
                ),
537 1059
                'users' => $this['orm.em']->getRepository('Eccube\Entity\Member'),
538 1059
                'anonymous' => true,
539 1059
            ),
540
            'customer' => array(
541 1059
                'pattern' => '^/',
542
                'form' => array(
543 1059
                    'login_path' => '/mypage/login',
544 1059
                    'check_path' => '/login_check',
545 1059
                    'username_parameter' => 'login_email',
546 1059
                    'password_parameter' => 'login_pass',
547 1059
                    'with_csrf' => true,
548 1059
                    'use_forward' => true,
549 1059
                ),
550
                'logout' => array(
551 1059
                    'logout_path' => '/logout',
552 1059
                    'target_url' => '/',
553 1059
                ),
554
                'remember_me' => array(
555 1059
                    'key' => sha1($this['config']['auth_magic']),
556 1059
                    'name' => 'eccube_rememberme',
557
                    // lifetimeはデフォルトの1年間にする
558
                    // 'lifetime' => $this['config']['cookie_lifetime'],
0 ignored issues
show
Unused Code Comprehensibility introduced by
77% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
559 1059
                    'path' => $this['config']['root_urlpath'] ?: '/',
560 1059
                    'secure' => $this['config']['force_ssl'],
561 1059
                    'httponly' => true,
562 1059
                    'always_remember_me' => false,
563 1059
                    'remember_me_parameter' => 'login_memory',
564 1059
                ),
565 1059
                'users' => $this['orm.em']->getRepository('Eccube\Entity\Customer'),
566 1059
                'anonymous' => true,
567 1059
            ),
568
        );
569
570 1059
        $this['security.access_rules'] = array(
571 1059
            array("^/{$this['config']['admin_route']}/login", 'IS_AUTHENTICATED_ANONYMOUSLY'),
572 1059
            array("^/{$this['config']['admin_route']}/", 'ROLE_ADMIN'),
573 1059
            array('^/mypage/login', 'IS_AUTHENTICATED_ANONYMOUSLY'),
574 1059
            array('^/mypage/withdraw_complete', 'IS_AUTHENTICATED_ANONYMOUSLY'),
575 1059
            array('^/mypage/change', 'IS_AUTHENTICATED_FULLY'),
576 1059
            array('^/mypage', 'ROLE_USER'),
577
        );
578
579
        $this['eccube.password_encoder'] = $this->share(function ($app) {
580 1059
            return new \Eccube\Security\Core\Encoder\PasswordEncoder($app['config']);
581 1059
        });
582
        $this['security.encoder_factory'] = $this->share(function ($app) {
583 1059
            return new \Symfony\Component\Security\Core\Encoder\EncoderFactory(array(
584 1059
                'Eccube\Entity\Customer' => $app['eccube.password_encoder'],
585 1059
                'Eccube\Entity\Member' => $app['eccube.password_encoder'],
586 1059
            ));
587 1059
        });
588
        $this['eccube.event_listner.security'] = $this->share(function ($app) {
589 1059
            return new \Eccube\EventListener\SecurityEventListener($app['orm.em']);
590 1059
        });
591
        $this['user'] = function ($app) {
592 1058
            $token = $app['security']->getToken();
593
594 1058
            return ($token !== null) ? $token->getUser() : null;
595
        };
596
597
        // ログイン時のイベントを設定.
598 1059
        $this['dispatcher']->addListener(\Symfony\Component\Security\Http\SecurityEvents::INTERACTIVE_LOGIN, array($this['eccube.event_listner.security'], 'onInteractiveLogin'));
599
600
        // Voterの設定
601 1059
        $app = $this;
602
        $this['authority_voter'] = $this->share(function ($app) {
603 1059
            return new \Eccube\Security\Voter\AuthorityVoter($app);
604 1059
        });
605
606
        $app['security.voters'] = $app->extend('security.voters', function ($voters) use ($app) {
607 1059
            $voters[] = $app['authority_voter'];
608
609 1059
            return $voters;
610 1059
        });
611
612
        $this['security.access_manager'] = $this->share(function ($app) {
613 1059
            return new \Symfony\Component\Security\Core\Authorization\AccessDecisionManager($app['security.voters'], 'unanimous');
614 1059
        });
615
616 1059
    }
617
618 1059
    public function initializePlugin()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
619
    {
620 1059
        if ($this->initializedPlugin) {
621
            return;
622
        }
623
624
        // setup event dispatcher
625 1059
        $this->initPluginEventDispatcher();
626
627
        // load plugin
628 1059
        $this->loadPlugin();
629
630 1059
        $this->initializedPlugin = true;
631 1059
    }
632
633 1059
    public function initPluginEventDispatcher()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
634
    {
635
        // EventDispatcher
636
        $this['eccube.event.dispatcher'] = $this->share(function () {
637 474
            return new EventDispatcher();
638 1059
        });
639
640 1059
        $app = $this;
641
642
        // hook point
643
        $this->on(KernelEvents::REQUEST, function (GetResponseEvent $event) use ($app) {
644 460
            if (!$event->isMasterRequest()) {
645 72
                return;
646
            }
647 460
            $hookpoint = 'eccube.event.app.before';
648 460
            $app['eccube.event.dispatcher']->dispatch($hookpoint, $event);
649 1059
        }, self::EARLY_EVENT);
650
651 View Code Duplication
        $this->on(KernelEvents::REQUEST, function (GetResponseEvent $event) use ($app) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
652 459
            if (!$event->isMasterRequest()) {
653 72
                return;
654
            }
655 457
            $route = $event->getRequest()->attributes->get('_route');
656 457
            $hookpoint = "eccube.event.controller.$route.before";
657 457
            $app['eccube.event.dispatcher']->dispatch($hookpoint, $event);
658 1059
        });
659
660 View Code Duplication
        $this->on(KernelEvents::RESPONSE, function (FilterResponseEvent $event) use ($app) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
661 447
            if (!$event->isMasterRequest()) {
662 72
                return;
663
            }
664 447
            $route = $event->getRequest()->attributes->get('_route');
665 447
            $hookpoint = "eccube.event.controller.$route.after";
666 447
            $app['eccube.event.dispatcher']->dispatch($hookpoint, $event);
667 1059
        });
668
669
        $this->on(KernelEvents::RESPONSE, function (FilterResponseEvent $event) use ($app) {
670 447
            if (!$event->isMasterRequest()) {
671 72
                return;
672
            }
673 447
            $hookpoint = 'eccube.event.app.after';
674 447
            $app['eccube.event.dispatcher']->dispatch($hookpoint, $event);
675 1059
        }, self::LATE_EVENT);
676
677
        $this->on(KernelEvents::TERMINATE, function (PostResponseEvent $event) use ($app) {
678 447
            $route = $event->getRequest()->attributes->get('_route');
679 447
            $hookpoint = "eccube.event.controller.$route.finish";
680 447
            $app['eccube.event.dispatcher']->dispatch($hookpoint, $event);
681 1059
        });
682
683
        $this->on(\Symfony\Component\HttpKernel\KernelEvents::RESPONSE, function (\Symfony\Component\HttpKernel\Event\FilterResponseEvent $event) use ($app) {
684 447
            if (!$event->isMasterRequest()) {
685 72
                return;
686
            }
687 447
            $route = $event->getRequest()->attributes->get('_route');
688 447
            $app['eccube.event.dispatcher']->dispatch('eccube.event.render.'.$route.'.before', $event);
689 1059
        });
690
691
        // Request Event
692 View Code Duplication
        $this->on(\Symfony\Component\HttpKernel\KernelEvents::REQUEST, function (\Symfony\Component\HttpKernel\Event\GetResponseEvent $event) use ($app) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
693
694 459
            if (!$event->isMasterRequest()) {
695 72
                return;
696
            }
697
698 459
            $route = $event->getRequest()->attributes->get('_route');
699
700 459
            if (is_null($route)) {
701
                return;
702
            }
703
704 459
            $app['monolog']->debug('KernelEvents::REQUEST '.$route);
705
706
            // 全体
707 459
            $app['eccube.event.dispatcher']->dispatch('eccube.event.app.request', $event);
708
709 459
            if (strpos($route, 'admin') === 0) {
710
                // 管理画面
711 291
                $app['eccube.event.dispatcher']->dispatch('eccube.event.admin.request', $event);
712 291
            } else {
713
                // フロント画面
714 170
                $app['eccube.event.dispatcher']->dispatch('eccube.event.front.request', $event);
715
            }
716
717
            // ルーティング単位
718 459
            $app['eccube.event.dispatcher']->dispatch("eccube.event.route.{$route}.request", $event);
719
720 1059
        }, 30); // Routing(32)が解決しし, 認証判定(8)が実行される前のタイミング.
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
721
722
        // Controller Event
723 View Code Duplication
        $this->on(\Symfony\Component\HttpKernel\KernelEvents::CONTROLLER, function (\Symfony\Component\HttpKernel\Event\FilterControllerEvent $event) use ($app) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
724
725 458
            if (!$event->isMasterRequest()) {
726 72
                return;
727
            }
728
729 456
            $route = $event->getRequest()->attributes->get('_route');
730
731 456
            if (is_null($route)) {
732
                return;
733
            }
734
735 456
            $app['monolog']->debug('KernelEvents::CONTROLLER '.$route);
736
737
            // 全体
738 456
            $app['eccube.event.dispatcher']->dispatch('eccube.event.app.controller', $event);
739
740 456
            if (strpos($route, 'admin') === 0) {
741
                // 管理画面
742 289
                $app['eccube.event.dispatcher']->dispatch('eccube.event.admin.controller', $event);
743 289
            } else {
744
                // フロント画面
745 169
                $app['eccube.event.dispatcher']->dispatch('eccube.event.front.controller', $event);
746
            }
747
748
            // ルーティング単位
749 456
            $app['eccube.event.dispatcher']->dispatch("eccube.event.route.{$route}.controller", $event);
750 1059
        });
751
752
        // Response Event
753 View Code Duplication
        $this->on(\Symfony\Component\HttpKernel\KernelEvents::RESPONSE, function (\Symfony\Component\HttpKernel\Event\FilterResponseEvent $event) use ($app) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
754 447
            if (!$event->isMasterRequest()) {
755 72
                return;
756
            }
757
758 447
            $route = $event->getRequest()->attributes->get('_route');
759
760 447
            if (is_null($route)) {
761 1
                return;
762
            }
763
764 446
            $app['monolog']->debug('KernelEvents::RESPONSE '.$route);
765
766
            // ルーティング単位
767 446
            $app['eccube.event.dispatcher']->dispatch("eccube.event.route.{$route}.response", $event);
768
769 446
            if (strpos($route, 'admin') === 0) {
770
                // 管理画面
771 284
                $app['eccube.event.dispatcher']->dispatch('eccube.event.admin.response', $event);
772 284
            } else {
773
                // フロント画面
774 164
                $app['eccube.event.dispatcher']->dispatch('eccube.event.front.response', $event);
775
            }
776
777
            // 全体
778 446
            $app['eccube.event.dispatcher']->dispatch('eccube.event.app.response', $event);
779 1059
        });
780
781
        // Exception Event
782 View Code Duplication
        $this->on(\Symfony\Component\HttpKernel\KernelEvents::EXCEPTION, function (\Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent $event) use ($app) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
783
784 19
            if (!$event->isMasterRequest()) {
785
                return;
786
            }
787
788 19
            $route = $event->getRequest()->attributes->get('_route');
789
790 19
            if (is_null($route)) {
791
                return;
792
            }
793
794 19
            $app['monolog']->debug('KernelEvents::EXCEPTION '.$route);
795
796
            // ルーティング単位
797 19
            $app['eccube.event.dispatcher']->dispatch("eccube.event.route.{$route}.exception", $event);
798
799 19
            if (strpos($route, 'admin') === 0) {
800
                // 管理画面
801 9
                $app['eccube.event.dispatcher']->dispatch('eccube.event.admin.exception', $event);
802 9
            } else {
803
                // フロント画面
804 10
                $app['eccube.event.dispatcher']->dispatch('eccube.event.front.exception', $event);
805
            }
806
807
            // 全体
808 19
            $app['eccube.event.dispatcher']->dispatch('eccube.event.app.exception', $event);
809 1059
        });
810
811
        // Terminate Event
812 View Code Duplication
        $this->on(\Symfony\Component\HttpKernel\KernelEvents::TERMINATE, function (\Symfony\Component\HttpKernel\Event\PostResponseEvent $event) use ($app) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
813
814 447
            $route = $event->getRequest()->attributes->get('_route');
815
816 447
            if (is_null($route)) {
817 1
                return;
818
            }
819
820 446
            $app['monolog']->debug('KernelEvents::TERMINATE '.$route);
821
822
            // ルーティング単位
823 446
            $app['eccube.event.dispatcher']->dispatch("eccube.event.route.{$route}.terminate", $event);
824
825 446
            if (strpos($route, 'admin') === 0) {
826
                // 管理画面
827 284
                $app['eccube.event.dispatcher']->dispatch('eccube.event.admin.terminate', $event);
828 284
            } else {
829
                // フロント画面
830 164
                $app['eccube.event.dispatcher']->dispatch('eccube.event.front.terminate', $event);
831
            }
832
833
            // 全体
834 446
            $app['eccube.event.dispatcher']->dispatch('eccube.event.app.terminate', $event);
835 1059
        });
836 1059
    }
837
838 1059
    public function loadPlugin()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
839
    {
840
        // プラグインディレクトリを探索.
841 1059
        $basePath = __DIR__.'/../../app/Plugin';
842 1059
        $finder = Finder::create()
843 1059
            ->in($basePath)
844 1059
            ->directories()
845 1059
            ->depth(0);
846
847 1059
        $finder->sortByName();
848
849
        // ハンドラ優先順位をdbから持ってきてハッシュテーブルを作成
850 1059
        $priorities = array();
851 1059
        $handlers = $this['orm.em']
852 1059
            ->getRepository('Eccube\Entity\PluginEventHandler')
853 1059
            ->getHandlers();
854 1059
        foreach ($handlers as $handler) {
855
            if ($handler->getPlugin()->getEnable() && !$handler->getPlugin()->getDelFlg()) {
0 ignored issues
show
Coding Style introduced by
Blank line found at start of control structure
Loading history...
856
857
                $priority = $handler->getPriority();
858
            } else {
859
                // Pluginがdisable、削除済みの場合、EventHandlerのPriorityを全て0とみなす
860
                $priority = \Eccube\Entity\PluginEventHandler::EVENT_PRIORITY_DISABLED;
861
            }
862
            $priorities[$handler->getPlugin()->getClassName()][$handler->getEvent()][$handler->getHandler()] = $priority;
863 1059
        }
864
865
        // プラグインをロードする.
866
        // config.yml/event.ymlの定義に沿ってインスタンスの生成を行い, イベント設定を行う.
867 1059
        foreach ($finder as $dir) {
868
            //config.ymlのないディレクトリは無視する
869 140
            $path = $dir->getRealPath();
870 140
            $code = $dir->getBaseName();
871
            try {
872 140
                $this['eccube.service.plugin']->checkPluginArchiveContent($path);
873 140
            } catch (\Eccube\Exception\PluginException $e) {
874
                $this['monolog']->warning("skip {$code} config loading. config.yml not foud or invalid.", array(
0 ignored issues
show
introduced by
Add a comma after each item in a multi-line array
Loading history...
875
                    'path' => $path,
876
                    'original-message' => $e->getMessage()
877
                ));
878
                continue;
879
            }
880 140
            $config = $this['eccube.service.plugin']->readYml($dir->getRealPath().'/config.yml');
881
882 140
            $plugin = $this['orm.em']
883 140
                ->getRepository('Eccube\Entity\Plugin')
884 140
                ->findOneBy(array('code' => $config['code']));
885
886
            // const
887 140
            if (isset($config['const'])) {
888
                $this['config'] = $this->share($this->extend('config', function ($eccubeConfig) use ($config) {
889 1
                    $eccubeConfig[$config['code']] = array(
890 1
                        'const' => $config['const'],
891
                    );
892
893 1
                    return $eccubeConfig;
894 1
                }));
895 1
            }
896
897 140
            if ($plugin && $plugin->getEnable() == Constant::DISABLED) {
898
                // プラグインが無効化されていれば読み込まない
899 1
                continue;
900
            }
901
902
            // Type: Event
903 139
            if (isset($config['event'])) {
904 139
                $class = '\\Plugin\\'.$config['code'].'\\'.$config['event'];
905 139
                $eventExists = true;
906
907 139 View Code Duplication
                if (!class_exists($class)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
908
                    $this['monolog']->warning("skip {$code} loading. event class not foud.", array(
909
                        'class' => $class,
910
                    ));
911
                    $eventExists = false;
912
                }
913
914 139
                if ($eventExists && file_exists($dir->getRealPath().'/event.yml')) {
0 ignored issues
show
Coding Style introduced by
Blank line found at start of control structure
Loading history...
915
916 139
                    $subscriber = new $class($this);
917
918 139
                    foreach (Yaml::parse(file_get_contents($dir->getRealPath().'/event.yml')) as $event => $handlers) {
919 139
                        foreach ($handlers as $handler) {
920 139
                            if (!isset($priorities[$config['event']][$event][$handler[0]])) { // ハンドラテーブルに登録されていない(ソースにしか記述されていない)ハンドラは一番後ろにする
921 139
                                $priority = \Eccube\Entity\PluginEventHandler::EVENT_PRIORITY_LATEST;
922 139
                            } else {
923
                                $priority = $priorities[$config['event']][$event][$handler[0]];
924
                            }
925
                            // 優先度が0のプラグインは登録しない
926 139
                            if (\Eccube\Entity\PluginEventHandler::EVENT_PRIORITY_DISABLED != $priority) {
927 139
                                $this['eccube.event.dispatcher']->addListener($event, array($subscriber, $handler[0]), $priority);
928 139
                            }
929 139
                        }
930 139
                    }
931 139
                }
932 139
            }
933
            // Type: ServiceProvider
934 139
            if (isset($config['service'])) {
935
                foreach ($config['service'] as $service) {
936
                    $class = '\\Plugin\\'.$config['code'].'\\ServiceProvider\\'.$service;
937 View Code Duplication
                    if (!class_exists($class)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
938
                        $this['monolog']->warning("skip {$code} loading. service provider class not foud.", array(
939
                            'class' => $class,
940
                        ));
941
                        continue;
942
                    }
943
                    $this->register(new $class($this));
944
                }
945
            }
946 1059
        }
947 1059
    }
948
949
    /**
950
     * PHPUnit を実行中かどうかを設定する.
951
     *
952
     * @param boolean $testMode PHPUnit を実行中の場合 true
953
     */
954 1045
    public function setTestMode($testMode)
955
    {
956 1045
        $this->testMode = $testMode;
957 1045
    }
958
959
    /**
960
     * PHPUnit を実行中かどうか.
961
     *
962
     * @return boolean PHPUnit を実行中の場合 true
963
     */
964 460
    public function isTestMode()
965
    {
966 460
        return $this->testMode;
967
    }
968
969
    /**
970
     *
971
     * データベースの接続を確認
972
     * 成功 : trueを返却
973
     * 失敗 : \Doctrine\DBAL\DBALExceptionエラーが発生( 接続に失敗した場合 )、エラー画面を表示しdie()
974
     * 備考 : app['debug']がtrueの際は処理を行わない
975
     *
976
     * @return boolean true
977
     *
978
     */
979 1059
    protected function checkDatabaseConnection()
980
    {
981 1059
        if ($this['debug']) {
982 1055
            return;
983
        }
984
        try {
985 4
            $this['db']->connect();
986 4
        } catch (\Doctrine\DBAL\DBALException $e) {
987
            $this['monolog']->error($e->getMessage());
988
            $this['twig.path'] = array(__DIR__.'/Resource/template/exception');
989
            $html = $this['twig']->render('error.twig', array(
990
                'error_title' => 'データーベース接続エラー',
991
                'error_message' => 'データーベースを確認してください',
992
            ));
993
            $response = new Response();
994
            $response->setContent($html);
995
            $response->setStatusCode('500');
996
            $response->headers->set('Content-Type', 'text/html');
997
            $response->send();
998
            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...
999
        }
1000
1001 4
        return true;
1002
    }
1003
1004
    /**
1005
     * Config ファイルをパースし、連想配列を返します.
1006
     *
1007
     * $config_name.yml ファイルをパースし、連想配列を返します.
1008
     * $config_name.php が存在する場合は、 PHP ファイルに記述された連想配列を使用します。
1009
     *
1010
     * @param string $config_name Config 名称
0 ignored issues
show
introduced by
Expected 2 spaces after parameter type; 1 found
Loading history...
1011
     * @param array $configAll Config の連想配列
0 ignored issues
show
introduced by
Expected 3 spaces after parameter type; 1 found
Loading history...
introduced by
Expected 3 spaces after parameter name; 1 found
Loading history...
1012
     * @param boolean $wrap_key Config の連想配列に config_name のキーを生成する場合 true, デフォルト false
0 ignored issues
show
introduced by
Expected 4 spaces after parameter name; 1 found
Loading history...
1013
     * @param string $ymlPath config yaml を格納したディレクトリ
0 ignored issues
show
introduced by
Expected 2 spaces after parameter type; 1 found
Loading history...
introduced by
Expected 5 spaces after parameter name; 1 found
Loading history...
1014
     * @param string $distPath config yaml dist を格納したディレクトリ
0 ignored issues
show
introduced by
Expected 2 spaces after parameter type; 1 found
Loading history...
introduced by
Expected 4 spaces after parameter name; 1 found
Loading history...
1015
     * @return Application
1016
     */
1017 1069
    public function parseConfig($config_name, array &$configAll, $wrap_key = false, $ymlPath = null, $distPath = null)
0 ignored issues
show
introduced by
Declare public methods first, then protected ones and finally private ones
Loading history...
1018
    {
1019 1069
        $ymlPath = $ymlPath ? $ymlPath : __DIR__.'/../../app/config/eccube';
1020 1069
        $distPath = $distPath ? $distPath : __DIR__.'/../../src/Eccube/Resource/config';
1021 1069
        $config = array();
1022 1069
        $config_php = $ymlPath.'/'.$config_name.'.php';
1023 1069
        if (!file_exists($config_php)) {
1024 1069
            $config_yml = $ymlPath.'/'.$config_name.'.yml';
1025 1069
            if (file_exists($config_yml)) {
1026 1069
                $config = Yaml::parse(file_get_contents($config_yml));
1027 1069
                $config = empty($config) ? array() : $config;
1028 1069 View Code Duplication
                if (isset($this['output_config_php']) && $this['output_config_php']) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1029
                    file_put_contents($config_php, sprintf('<?php return %s', var_export($config, true)).';');
1030
                }
1031 1069
            }
1032 1069
        } else {
1033
            $config = require $config_php;
1034
        }
1035
1036 1069
        $config_dist = array();
1037 1069
        $config_php_dist = $distPath.'/'.$config_name.'.dist.php';
1038 1069
        if (!file_exists($config_php_dist)) {
1039 1069
            $config_yml_dist = $distPath.'/'.$config_name.'.yml.dist';
1040 1069
            if (file_exists($config_yml_dist)) {
1041 1069
                $config_dist = Yaml::parse(file_get_contents($config_yml_dist));
1042 1069 View Code Duplication
                if (isset($this['output_config_php']) && $this['output_config_php']) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1043
                    file_put_contents($config_php_dist, sprintf('<?php return %s', var_export($config_dist, true)).';');
1044
                }
1045 1069
            }
1046 1069
        } else {
1047
            $config_dist = require $config_php_dist;
1048
        }
1049
1050 1069
        if ($wrap_key) {
1051 1069
            $configAll = array_replace_recursive($configAll, array($config_name => $config_dist), array($config_name => $config));
1052 1069
        } else {
1053 1069
            $configAll = array_replace_recursive($configAll, $config_dist, $config);
1054
        }
1055
1056 1069
        return $this;
1057
    }
1058
1059
    /**
1060
     * セッションが開始されているかどうか.
1061
     *
1062
     * @return boolean セッションが開始済みの場合 true
1063
     * @link http://php.net/manual/ja/function.session-status.php#113468
1064
     */
1065 1059
    protected function isSessionStarted()
1066
    {
1067 1059
        if (php_sapi_name() !== 'cli') {
1068
            if (version_compare(phpversion(), '5.4.0', '>=')) {
1069
                return session_status() === PHP_SESSION_ACTIVE ? true : false;
1070
            } else {
1071
                return session_id() === '' ? false : true;
1072
            }
1073
        }
1074
1075 1059
        return false;
1076
    }
1077
1078
    /**
1079
     * Http Cache対応
1080
     */
1081 1059
    protected function initCacheRequest()
1082
    {
1083
        // httpキャッシュが無効の場合はイベント設定を行わない.
1084 1059
        if (!$this['config']['http_cache']['enabled']) {
1085 1059
            return;
1086
        }
1087
1088
        $app = $this;
1089
1090
        // Response Event(http cache対応、event実行は一番遅く設定)
1091
        $this->on(\Symfony\Component\HttpKernel\KernelEvents::RESPONSE, function (\Symfony\Component\HttpKernel\Event\FilterResponseEvent $event) use ($app) {
1092
1093
            if (!$event->isMasterRequest()) {
1094
                return;
1095
            }
1096
1097
            $request = $event->getRequest();
1098
            $response = $event->getResponse();
1099
1100
            $route = $request->attributes->get('_route');
1101
1102
            $etag = md5($response->getContent());
1103
1104
            if (strpos($route, 'admin') === 0) {
1105
                // 管理画面
1106
1107
                // 管理画面ではコンテンツの中身が変更された時点でキャッシュを更新し、キャッシュの適用範囲はprivateに設定
1108
                $response->setCache(array(
1109
                    'etag' => $etag,
1110
                    'private' => true,
1111
                ));
1112
1113
                if ($response->isNotModified($request)) {
1114
                    return $response;
1115
                }
1116
0 ignored issues
show
Coding Style introduced by
Blank line found at end of control structure
Loading history...
1117
            } else {
1118
                // フロント画面
1119
                $cacheRoute = $app['config']['http_cache']['route'];
1120
1121
                if (in_array($route, $cacheRoute) === true) {
1122
                    // キャッシュ対象となる画面lが含まれていた場合、キャッシュ化
1123
                    // max-ageを設定しているためExpiresは不要
1124
                    // Last-Modifiedだと比較する項目がないためETagで対応
1125
                    // max-ageを設定していた場合、contentの中身が変更されても変更されない
1126
1127
                    $age = $app['config']['http_cache']['age'];
1128
1129
                    $response->setCache(array(
1130
                        'etag' => $etag,
1131
                        'max_age' => $age,
1132
                        's_maxage' => $age,
1133
                        'public' => true,
1134
                    ));
1135
1136
                    if ($response->isNotModified($request)) {
1137
                        return $response;
1138
                    }
1139
                }
1140
            }
1141
1142
        }, -1024);
1143
    }
1144
}
1145