Completed
Pull Request — master (#2001)
by k-yamamura
38:50
created

Application::initialize()   B

Complexity

Conditions 6
Paths 3

Size

Total Lines 84
Code Lines 47

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 31
CRAP Score 7.0839

Importance

Changes 0
Metric Value
cc 6
eloc 47
nc 3
nop 0
dl 0
loc 84
ccs 31
cts 45
cp 0.6889
crap 7.0839
rs 8.35
c 0
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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 Binfo\Silex\MobileDetectServiceProvider;
27
use Eccube\Application\ApplicationTrait;
28
use Eccube\Common\Constant;
29
use Eccube\Doctrine\ORM\Mapping\Driver\YamlDriver;
30
use Eccube\EventListener\TransactionListener;
31
use Symfony\Component\EventDispatcher\EventDispatcher;
32
use Symfony\Component\Finder\Finder;
33
use Symfony\Component\HttpFoundation\Request;
34
use Symfony\Component\HttpFoundation\Response;
35
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
36
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
37
use Symfony\Component\HttpKernel\Event\PostResponseEvent;
38
use Symfony\Component\HttpKernel\KernelEvents;
39
use Symfony\Component\Yaml\Yaml;
40
41
class Application extends ApplicationTrait
0 ignored issues
show
introduced by
Missing class doc comment
Loading history...
42
{
43
    protected static $instance;
44
45
    protected $initialized = false;
46
    protected $initializedPlugin = false;
47
    protected $testMode = false;
48
49 1093
    public static function getInstance(array $values = array())
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
50
    {
51 1093
        if (!is_object(self::$instance)) {
52 1086
            self::$instance = new Application($values);
53
        }
54
55 1093
        return self::$instance;
56
    }
57
58 1087
    public static function clearInstance()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
59
    {
60 1087
        self::$instance = null;
61
    }
62
63
    final public function __clone()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
64
    {
65
        throw new \Exception('Clone is not allowed against '.get_class($this));
66
    }
67
68 1091
    public function __construct(array $values = array())
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
69
    {
70 1091
        parent::__construct($values);
71
72 1091
        if (is_null(self::$instance)) {
73 1087
            self::$instance = $this;
74
        }
75
76
        // load config
77 1091
        $this->initConfig();
78
79
        // init monolog
80 1091
        $this->initLogger();
81
    }
82
83
    /**
84
     * Application::runが実行されているか親クラスのプロパティから判定
85
     *
86
     * @return bool
87
     */
88 1092
    public function isBooted()
89
    {
90 1092
        return $this->booted;
91
    }
92
93 1091
    public function initConfig()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
94
    {
95
        // load config
96 1091
        $app = $this;
97
        $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...
98 1091
            $configAll = array();
99 1091
            $app->parseConfig('constant', $configAll)
100 1091
                ->parseConfig('path', $configAll)
101 1091
                ->parseConfig('config', $configAll)
102 1091
                ->parseConfig('database', $configAll)
103 1091
                ->parseConfig('mail', $configAll)
104 1091
                ->parseConfig('log', $configAll)
105 1091
                ->parseConfig('nav', $configAll, true)
106 1091
                ->parseConfig('doctrine_cache', $configAll)
107 1091
                ->parseConfig('http_cache', $configAll)
108 1091
                ->parseConfig('session_handler', $configAll);
109
110 1091
            return $configAll;
111 1091
        });
112
    }
113
114 1093
    public function initLogger()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
115
    {
116 1093
        $app = $this;
117 1093
        $this->register(new ServiceProvider\LogServiceProvider($app));
0 ignored issues
show
Unused Code introduced by
The call to LogServiceProvider::__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...
118
    }
119
120 1090
    public function initialize()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
121
    {
122 1090
        if ($this->initialized) {
123 4
            return;
124
        }
125
126
        // init locale
127 1087
        $this->initLocale();
128
129
        // init session
130 1087
        if (!$this->isSessionStarted()) {
131 1087
            $this->initSession();
132
        }
133
134
        // init twig
135 1087
        $this->initRendering();
136
137
        // init provider
138 1087
        $this->register(new \Silex\Provider\HttpCacheServiceProvider(), array(
139 1087
            'http_cache.cache_dir' => __DIR__.'/../../app/cache/http/',
140
        ));
141 1087
        $this->register(new \Silex\Provider\HttpFragmentServiceProvider());
142 1087
        $this->register(new \Silex\Provider\UrlGeneratorServiceProvider());
143 1087
        $this->register(new \Silex\Provider\FormServiceProvider());
144 1087
        $this->register(new \Silex\Provider\SerializerServiceProvider());
145 1087
        $this->register(new \Silex\Provider\ValidatorServiceProvider());
146 1087
        $this->register(new MobileDetectServiceProvider());
147
148 1087
        $app = $this;
149
        $this->error(function (\Exception $e, $code) use ($app) {
150 18
            if ($app['debug']) {
151 18
                return;
152
            }
153
154
            switch ($code) {
155
                case 403:
156
                    $title = 'アクセスできません。';
157
                    $message = 'お探しのページはアクセスができない状況にあるか、移動もしくは削除された可能性があります。';
158
                    break;
159
                case 404:
160
                    $title = 'ページがみつかりません。';
161
                    $message = 'URLに間違いがないかご確認ください。';
162
                    break;
163
                default:
164
                    $title = 'システムエラーが発生しました。';
165
                    $message = '大変お手数ですが、サイト管理者までご連絡ください。';
166
                    break;
167
            }
168
169
            return $app->render('error.twig', array(
170
                'error_title' => $title,
171
                'error_message' => $message,
172
            ));
173 1087
        });
174
175
        // init mailer
176 1087
        $this->initMailer();
177
178
        // init doctrine orm
179 1087
        $this->initDoctrine();
180
181
        // Set up the DBAL connection now to check for a proper connection to the database.
182 1087
        $this->checkDatabaseConnection();
183
184
        // init security
185 1087
        $this->initSecurity();
186
187
        // init ec-cube service provider
188 1087
        $this->register(new ServiceProvider\EccubeServiceProvider());
189
190
        // mount controllers
191 1087
        $this->register(new \Silex\Provider\ServiceControllerServiceProvider());
192 1087
        $this->mount('', new ControllerProvider\FrontControllerProvider());
193 1087
        $this->mount('/'.trim($this['config']['admin_route'], '/').'/', new ControllerProvider\AdminControllerProvider());
194 1087
        Request::enableHttpMethodParameterOverride(); // PUTやDELETEできるようにする
195
196
        // add transaction listener
197 1087
        $this['dispatcher']->addSubscriber(new TransactionListener($this));
198
199
        // init http cache
200 1087
        $this->initCacheRequest();
201
202 1087
        $this->initialized = true;
203
    }
204
205 1087
    public function initLocale()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
206
    {
207
208
        // timezone
209 1087
        if (!empty($this['config']['timezone'])) {
210 1087
            date_default_timezone_set($this['config']['timezone']);
211
        }
212
213 1087
        $this->register(new \Silex\Provider\TranslationServiceProvider(), array(
214 1087
            'locale' => $this['config']['locale'],
215 1087
            'translator.cache_dir' => $this['debug'] ? null : $this['config']['root_dir'].'/app/cache/translator',
216
        ));
217
        $this['translator'] = $this->share($this->extend('translator', function ($translator, \Silex\Application $app) {
218 730
            $translator->addLoader('yaml', new \Symfony\Component\Translation\Loader\YamlFileLoader());
219
220 730
            $file = __DIR__.'/Resource/locale/validator.'.$app['locale'].'.yml';
221 730
            if (file_exists($file)) {
222 730
                $translator->addResource('yaml', $file, $app['locale'], 'validators');
223
            }
224
225 730
            $file = __DIR__.'/Resource/locale/message.'.$app['locale'].'.yml';
226 730
            if (file_exists($file)) {
227 730
                $translator->addResource('yaml', $file, $app['locale']);
228
            }
229
230 730
            return $translator;
231 1087
        }));
232
    }
233
234 1087
    public function initSession()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
235
    {
236 1087
        $this->register(new \Silex\Provider\SessionServiceProvider(), array(
237 1087
            'session.storage.save_path' => $this['config']['root_dir'].'/app/cache/eccube/session',
238
            'session.storage.options' => array(
239 1087
                'name' => $this['config']['cookie_name'],
240 1087
                'cookie_path' => $this['config']['root_urlpath'] ?: '/',
241 1087
                'cookie_secure' => $this['config']['force_ssl'],
242 1087
                'cookie_lifetime' => $this['config']['cookie_lifetime'],
243
                'cookie_httponly' => true,
244
                // cookie_domainは指定しない
245
                // http://blog.tokumaru.org/2011/10/cookiedomain.html
246
            ),
247
        ));
248
249 1087
        $options = $this['config']['session_handler'];
250
251 1087
        if ($options['enabled']) {
252
            // @see http://silex.sensiolabs.org/doc/providers/session.html#custom-session-configurations
253
            $this['session.storage.handler'] = null;
254
            ini_set('session.save_handler', $options['save_handler']);
255
            ini_set('session.save_path', $options['save_path']);
256
        }
257
    }
258
259 1087
    public function initRendering()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
260
    {
261 1087
        $this->register(new \Silex\Provider\TwigServiceProvider(), array(
262 1087
            'twig.form.templates' => array('Form/form_layout.twig'),
263
        ));
264
        $this['twig'] = $this->share($this->extend('twig', function (\Twig_Environment $twig, \Silex\Application $app) {
265 483
            $twig->addExtension(new \Eccube\Twig\Extension\EccubeExtension($app));
266 483
            $twig->addExtension(new \Twig_Extension_StringLoader());
267
268 483
            return $twig;
269 1087
        }));
270
271
        $this->before(function (Request $request, \Silex\Application $app) {
272 472
            $app['admin'] = false;
273 472
            $app['front'] = false;
274 472
            $pathinfo = rawurldecode($request->getPathInfo());
275 472
            if (strpos($pathinfo, '/'.trim($app['config']['admin_route'], '/').'/') === 0) {
276 300
                $app['admin'] = true;
277
            } else {
278 174
                $app['front'] = true;
279
            }
280
281
            // フロント or 管理画面ごとにtwigの探索パスを切り替える.
282
            $app['twig'] = $app->share($app->extend('twig', function (\Twig_Environment $twig, \Silex\Application $app) {
283 470
                $paths = array();
284
285
                // 互換性がないのでprofiler とproduction 時のcacheを分離する
286 470
                if (isset($app['profiler'])) {
287
                    $cacheBaseDir = __DIR__.'/../../app/cache/twig/profiler/';
288
                } else {
289 470
                    $cacheBaseDir = __DIR__.'/../../app/cache/twig/production/';
290
                }
291
292 470
                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...
293 300
                    if (file_exists(__DIR__.'/../../app/template/admin')) {
294 300
                        $paths[] = __DIR__.'/../../app/template/admin';
295
                    }
296 300
                    $paths[] = $app['config']['template_admin_realdir'];
297 300
                    $paths[] = __DIR__.'/../../app/Plugin';
298 300
                    $cache = $cacheBaseDir.'admin';
299
0 ignored issues
show
Coding Style introduced by
Blank line found at end of control structure
Loading history...
300
                } else {
301 172
                    if (file_exists($app['config']['template_realdir'])) {
302 172
                        $paths[] = $app['config']['template_realdir'];
303
                    }
304 172
                    $paths[] = $app['config']['template_default_realdir'];
305 172
                    $paths[] = __DIR__.'/../../app/Plugin';
306 172
                    $cache = $cacheBaseDir.$app['config']['template_code'];
307 172
                    $app['front'] = true;
308
                }
309 470
                $twig->setCache($cache);
310 470
                $app['twig.loader']->addLoader(new \Twig_Loader_Filesystem($paths));
311
312 470
                return $twig;
313 472
            }));
314
315
            // 管理画面のIP制限チェック.
316 472
            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...
317
                // IP制限チェック
318 300
                $allowHost = $app['config']['admin_allow_host'];
319 300
                if (count($allowHost) > 0) {
320
                    if (array_search($app['request']->getClientIp(), $allowHost) === false) {
321
                        throw new \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException();
322
                    }
323
                }
324
            }
325 1087
        }, self::EARLY_EVENT);
326
327
        // twigのグローバル変数を定義.
328 1087
        $app = $this;
329
        $this->on(\Symfony\Component\HttpKernel\KernelEvents::CONTROLLER, function (\Symfony\Component\HttpKernel\Event\FilterControllerEvent $event) use ($app) {
330
            // 未ログイン時にマイページや管理画面以下にアクセスするとSubRequestで実行されるため,
331
            // $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...
332 470
            if (isset($app['twig_global_initialized']) && $app['twig_global_initialized'] === true) {
333 121
                return;
334
            }
335
            // ショップ基本情報
336 470
            $BaseInfo = $app['eccube.repository.base_info']->get();
337 470
            $app['twig']->addGlobal('BaseInfo', $BaseInfo);
338
339 470
            if ($app->isAdminRequest()) {
340
                // 管理画面
341
                // 管理画面メニュー
342 300
                $menus = array('', '', '');
343 300
                $app['twig']->addGlobal('menus', $menus);
344
345 300
                $Member = $app->user();
346 300
                if (is_object($Member)) {
347
                    // ログインしていれば管理者のロールを取得
348 294
                    $AuthorityRoles = $app['eccube.repository.authority_role']->findBy(array('Authority' => $Member->getAuthority()));
349
350 294
                    $roles = array();
351 294
                    foreach ($AuthorityRoles as $AuthorityRole) {
352
                        // 管理画面でメニュー制御するため相対パス全てをセット
353 294
                        $roles[] = $app['request']->getBaseUrl().'/'.$app['config']['admin_route'].$AuthorityRole->getDenyUrl();
354
                    }
355
356 300
                    $app['twig']->addGlobal('AuthorityRoles', $roles);
357
                }
358
0 ignored issues
show
Coding Style introduced by
Blank line found at end of control structure
Loading history...
359
            } else {
360
                // フロント画面
361 170
                $request = $event->getRequest();
362 170
                $route = $request->attributes->get('_route');
363
364
                // ユーザ作成画面
365 170
                if ($route === 'user_data') {
366 2
                    $params = $request->attributes->get('_route_params');
367 2
                    $route = $params['route'];
368
                    // プレビュー画面
369 168
                } elseif ($request->get('preview')) {
370
                    $route = 'preview';
371
                }
372
373
                try {
374 170
                    $DeviceType = $app['eccube.repository.master.device_type']
375 170
                        ->find(\Eccube\Entity\Master\DeviceType::DEVICE_TYPE_PC);
376 170
                    $PageLayout = $app['eccube.repository.page_layout']->getByUrl($DeviceType, $route);
377 67
                } catch (\Doctrine\ORM\NoResultException $e) {
378 67
                    $PageLayout = $app['eccube.repository.page_layout']->newPageLayout($DeviceType);
379
                }
380
381 170
                $app['twig']->addGlobal('PageLayout', $PageLayout);
382 170
                $app['twig']->addGlobal('title', $PageLayout->getName());
383
            }
384
385 470
            $app['twig_global_initialized'] = true;
386 1087
        });
387
    }
388
389 1087
    public function initMailer()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
390
    {
391
392
        // メール送信時の文字エンコード指定(デフォルトは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...
393 1087
        if (isset($this['config']['mail']['charset_iso_2022_jp']) && is_bool($this['config']['mail']['charset_iso_2022_jp'])) {
394 1087
            if ($this['config']['mail']['charset_iso_2022_jp'] === true) {
395
                \Swift::init(function () {
396
                    \Swift_DependencyContainer::getInstance()
397
                        ->register('mime.qpheaderencoder')
398
                        ->asAliasOf('mime.base64headerencoder');
399
                    \Swift_Preferences::getInstance()->setCharset('iso-2022-jp');
400
                });
401
            }
402
        }
403
404 1087
        $this->register(new \Silex\Provider\SwiftmailerServiceProvider());
405 1087
        $this['swiftmailer.options'] = $this['config']['mail'];
406
407 1087
        if (isset($this['config']['mail']['spool']) && is_bool($this['config']['mail']['spool'])) {
408
            $this['swiftmailer.use_spool'] = $this['config']['mail']['spool'];
409
        }
410
        // デフォルトはsmtpを使用
411 1087
        $transport = $this['config']['mail']['transport'];
412 1087
        if ($transport == 'sendmail') {
413
            $this['swiftmailer.transport'] = \Swift_SendmailTransport::newInstance();
414 1087
        } elseif ($transport == 'mail') {
415
            $this['swiftmailer.transport'] = \Swift_MailTransport::newInstance();
416
        }
417
    }
418
419 1087
    public function initDoctrine()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
420
    {
421 1087
        $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...
422
            'dbs.options' => array(
0 ignored issues
show
introduced by
Add a comma after each item in a multi-line array
Loading history...
423 1087
                'default' => $this['config']['database']
424
            )));
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...
425 1087
        $this->register(new \Saxulum\DoctrineOrmManagerRegistry\Silex\Provider\DoctrineOrmManagerRegistryProvider());
426
427
        // プラグインのmetadata定義を合わせて行う.
428 1087
        $pluginConfigs = $this->getPluginConfigAll();
429 1087
        $ormMappings = array();
430 1087
        $ormMappings[] = array(
431
            'type' => 'yml',
432
            'namespace' => 'Eccube\Entity',
433
            'path' => array(
434
                __DIR__.'/Resource/doctrine',
435
                __DIR__.'/Resource/doctrine/master',
436
            ),
437
        );
438
439 1087
        foreach ($pluginConfigs as $code) {
440 140
            $config = $code['config'];
441
            // Doctrine Extend
442 140
            if (isset($config['orm.path']) && is_array($config['orm.path'])) {
443
                $paths = array();
444
                foreach ($config['orm.path'] as $path) {
445
                    $paths[] = $this['config']['plugin_realdir'].'/'.$config['code'].$path;
446
                }
447
                $ormMappings[] = array(
448
                    'type' => 'yml',
449
                    'namespace' => 'Plugin\\'.$config['code'].'\\Entity',
450 1087
                    'path' => $paths,
451
                );
452
            }
453
        }
454
455
        $options = array(
0 ignored issues
show
introduced by
Add a comma after each item in a multi-line array
Loading history...
456 1087
            'mappings' => $ormMappings
457
        );
458
459 1087
        if (!$this['debug']) {
460 1
            $cacheDrivers = array();
461 1
            if (array_key_exists('doctrine_cache', $this['config'])) {
462 1
                $cacheDrivers = $this['config']['doctrine_cache'];
463
            }
464
465 1
            if (array_key_exists('metadata_cache', $cacheDrivers)) {
466 1
                $options['metadata_cache'] = $cacheDrivers['metadata_cache'];
467
            }
468 1
            if (array_key_exists('query_cache', $cacheDrivers)) {
469 1
                $options['query_cache'] = $cacheDrivers['query_cache'];
470
            }
471 1
            if (array_key_exists('result_cache', $cacheDrivers)) {
472 1
                $options['result_cache'] = $cacheDrivers['result_cache'];
473
            }
474 1
            if (array_key_exists('hydration_cache', $cacheDrivers)) {
475 1
                $options['hydration_cache'] = $cacheDrivers['hydration_cache'];
476
            }
477
        }
478
479 1087
        $this->register(new \Dflydev\Silex\Provider\DoctrineOrm\DoctrineOrmServiceProvider(), array(
480 1087
            'orm.proxies_dir' => __DIR__.'/../../app/cache/doctrine/proxies',
481 1087
            'orm.em.options' => $options,
482
            'orm.custom.functions.string' => array(
483
                'NORMALIZE' => 'Eccube\Doctrine\ORM\Query\Normalize',
484
            ),
485
            'orm.custom.functions.numeric' => array(
486
                'EXTRACT' => 'Eccube\Doctrine\ORM\Query\Extract',
487
            ),
488
        ));
489
490
        /**
491
         * YamlDriverのPHP7対応. Doctrine2.4で修正されれば不要.
492
         * @see https://github.com/EC-CUBE/ec-cube/issues/1338
493
         */
494 1087
        $config = $this['orm.em']->getConfiguration();
495
        /** @var $driver \Doctrine\Common\Persistence\Mapping\Driver\MappingDriverChain */
496 1087
        $chain = $config->getMetadataDriverImpl();
497
        // $ormMappingsの1要素ごとにDriverが生成されている.
498 1087
        $drivers = $chain->getDrivers();
499 1087
        foreach ($drivers as $namespace => $oldDriver) {
500
            /** @var $newDriver \Eccube\Doctrine\ORM\Mapping\Driver\YamlDriver */
501 1087
            $newDriver = new YamlDriver($oldDriver->getLocator());
502
            // 修正したDriverに差し替える. メソッド名はaddだけど実際はsetしてる.
503 1087
            $chain->addDriver($newDriver, $namespace);
504
        }
505
    }
506
507 1089
    public function initSecurity()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
508
    {
509 1087
        $this->register(new \Silex\Provider\SecurityServiceProvider());
510 1087
        $this->register(new \Silex\Provider\RememberMeServiceProvider());
511
512 1087
        $this['security.firewalls'] = array(
513
            'admin' => array(
514 1087
                'pattern' => "^/{$this['config']['admin_route']}/",
515
                'form' => array(
516 1087
                    'login_path' => "/{$this['config']['admin_route']}/login",
517 1087
                    'check_path' => "/{$this['config']['admin_route']}/login_check",
518 1087
                    'username_parameter' => 'login_id',
519 1087
                    'password_parameter' => 'password',
520
                    'with_csrf' => true,
521
                    'use_forward' => true,
522
                ),
523
                'logout' => array(
524 1087
                    'logout_path' => "/{$this['config']['admin_route']}/logout",
525 1087
                    'target_url' => "/{$this['config']['admin_route']}/",
526
                ),
527 1087
                'users' => $this['orm.em']->getRepository('Eccube\Entity\Member'),
528
                'anonymous' => true,
529 1087
            ),
530
            'customer' => array(
531 1087
                'pattern' => '^/',
532
                'form' => array(
533
                    'login_path' => '/mypage/login',
534
                    'check_path' => '/login_check',
535
                    'username_parameter' => 'login_email',
536
                    'password_parameter' => 'login_pass',
537
                    'with_csrf' => true,
538
                    'use_forward' => true,
539
                ),
540
                'logout' => array(
541
                    'logout_path' => '/logout',
542
                    'target_url' => '/',
543
                ),
544
                'remember_me' => array(
545 1087
                    'key' => sha1($this['config']['auth_magic']),
546 1087
                    'name' => $this['config']['cookie_name'].'_rememberme',
547
                    // lifetimeはデフォルトの1年間にする
548
                    // '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...
549 1087
                    'path' => $this['config']['root_urlpath'] ?: '/',
550 1087
                    'secure' => $this['config']['force_ssl'],
551
                    'httponly' => true,
552
                    'always_remember_me' => false,
553 1087
                    'remember_me_parameter' => 'login_memory',
554
                ),
555 1087
                'users' => $this['orm.em']->getRepository('Eccube\Entity\Customer'),
556
                'anonymous' => true,
557
            ),
558
        );
559
560 1087
        $this['security.access_rules'] = array(
561 1087
            array("^/{$this['config']['admin_route']}/login", 'IS_AUTHENTICATED_ANONYMOUSLY'),
562 1087
            array("^/{$this['config']['admin_route']}/", 'ROLE_ADMIN'),
563
            array('^/mypage/login', 'IS_AUTHENTICATED_ANONYMOUSLY'),
564
            array('^/mypage/withdraw_complete', 'IS_AUTHENTICATED_ANONYMOUSLY'),
565
            array('^/mypage/change', 'IS_AUTHENTICATED_FULLY'),
566
            array('^/mypage', 'ROLE_USER'),
567
        );
568
569
        $this['eccube.password_encoder'] = $this->share(function ($app) {
570 1087
            return new \Eccube\Security\Core\Encoder\PasswordEncoder($app['config']);
571 1087
        });
572
        $this['security.encoder_factory'] = $this->share(function ($app) {
573 1087
            return new \Symfony\Component\Security\Core\Encoder\EncoderFactory(array(
574 1087
                'Eccube\Entity\Customer' => $app['eccube.password_encoder'],
575 1087
                'Eccube\Entity\Member' => $app['eccube.password_encoder'],
576
            ));
577 1087
        });
578
        $this['eccube.event_listner.security'] = $this->share(function ($app) {
579 1087
            return new \Eccube\EventListener\SecurityEventListener($app['orm.em']);
580 1087
        });
581
        $this['user'] = function ($app) {
582 1089
            $token = $app['security']->getToken();
583
584 1089
            return ($token !== null) ? $token->getUser() : null;
585
        };
586
587
        // ログイン時のイベントを設定.
588 1087
        $this['dispatcher']->addListener(\Symfony\Component\Security\Http\SecurityEvents::INTERACTIVE_LOGIN, array($this['eccube.event_listner.security'], 'onInteractiveLogin'));
589
590
        // Voterの設定
591 1087
        $app = $this;
592
        $this['authority_voter'] = $this->share(function ($app) {
593 1087
            return new \Eccube\Security\Voter\AuthorityVoter($app);
594 1087
        });
595
596
        $app['security.voters'] = $app->extend('security.voters', function ($voters) use ($app) {
597 1087
            $voters[] = $app['authority_voter'];
598
599 1087
            return $voters;
600 1087
        });
601
602
        $this['security.access_manager'] = $this->share(function ($app) {
603 1087
            return new \Symfony\Component\Security\Core\Authorization\AccessDecisionManager($app['security.voters'], 'unanimous');
604 1087
        });
605
606
    }
607
608 1087
    public function initializePlugin()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
609
    {
610 1087
        if ($this->initializedPlugin) {
611
            return;
612
        }
613
614
        // setup event dispatcher
615 1087
        $this->initPluginEventDispatcher();
616
617
        // load plugin
618 1087
        $this->loadPlugin();
619
620 1087
        $this->initializedPlugin = true;
621
    }
622
623 1087
    public function initPluginEventDispatcher()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
624
    {
625
        // EventDispatcher
626
        $this['eccube.event.dispatcher'] = $this->share(function () {
627 485
            return new EventDispatcher();
628 1087
        });
629
630 1087
        $app = $this;
631
632
        // hook point
633
        $this->on(KernelEvents::REQUEST, function (GetResponseEvent $event) use ($app) {
634 472
            if (!$event->isMasterRequest()) {
635 71
                return;
636
            }
637 472
            $hookpoint = 'eccube.event.app.before';
638 472
            $app['eccube.event.dispatcher']->dispatch($hookpoint, $event);
639 1087
        }, self::EARLY_EVENT);
640
641 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...
642 471
            if (!$event->isMasterRequest()) {
643 71
                return;
644
            }
645 469
            $route = $event->getRequest()->attributes->get('_route');
646 469
            $hookpoint = "eccube.event.controller.$route.before";
647 469
            $app['eccube.event.dispatcher']->dispatch($hookpoint, $event);
648 1087
        });
649
650 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...
651 458
            if (!$event->isMasterRequest()) {
652 71
                return;
653
            }
654 458
            $route = $event->getRequest()->attributes->get('_route');
655 458
            $hookpoint = "eccube.event.controller.$route.after";
656 458
            $app['eccube.event.dispatcher']->dispatch($hookpoint, $event);
657 1087
        });
658
659
        $this->on(KernelEvents::RESPONSE, function (FilterResponseEvent $event) use ($app) {
660 458
            if (!$event->isMasterRequest()) {
661 71
                return;
662
            }
663 458
            $hookpoint = 'eccube.event.app.after';
664 458
            $app['eccube.event.dispatcher']->dispatch($hookpoint, $event);
665 1087
        }, self::LATE_EVENT);
666
667
        $this->on(KernelEvents::TERMINATE, function (PostResponseEvent $event) use ($app) {
668 458
            $route = $event->getRequest()->attributes->get('_route');
669 458
            $hookpoint = "eccube.event.controller.$route.finish";
670 458
            $app['eccube.event.dispatcher']->dispatch($hookpoint, $event);
671 1087
        });
672
673
        $this->on(\Symfony\Component\HttpKernel\KernelEvents::RESPONSE, function (\Symfony\Component\HttpKernel\Event\FilterResponseEvent $event) use ($app) {
674 458
            if (!$event->isMasterRequest()) {
675 71
                return;
676
            }
677 458
            $route = $event->getRequest()->attributes->get('_route');
678 458
            $app['eccube.event.dispatcher']->dispatch('eccube.event.render.'.$route.'.before', $event);
679 1087
        });
680
681
        // Request Event
682 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...
683
684 471
            if (!$event->isMasterRequest()) {
685 71
                return;
686
            }
687
688 471
            $route = $event->getRequest()->attributes->get('_route');
689
690 471
            if (is_null($route)) {
691
                return;
692
            }
693
694 471
            $app['monolog']->debug('KernelEvents::REQUEST '.$route);
695
696
            // 全体
697 471
            $app['eccube.event.dispatcher']->dispatch('eccube.event.app.request', $event);
698
699 471
            if (strpos($route, 'admin') === 0) {
700
                // 管理画面
701 300
                $app['eccube.event.dispatcher']->dispatch('eccube.event.admin.request', $event);
702
            } else {
703
                // フロント画面
704 173
                $app['eccube.event.dispatcher']->dispatch('eccube.event.front.request', $event);
705
            }
706
707
            // ルーティング単位
708 471
            $app['eccube.event.dispatcher']->dispatch("eccube.event.route.{$route}.request", $event);
709
710 1087
        }, 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...
711
712
        // Controller Event
713 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...
714
715 470
            if (!$event->isMasterRequest()) {
716 71
                return;
717
            }
718
719 468
            $route = $event->getRequest()->attributes->get('_route');
720
721 468
            if (is_null($route)) {
722
                return;
723
            }
724
725 468
            $app['monolog']->debug('KernelEvents::CONTROLLER '.$route);
726
727
            // 全体
728 468
            $app['eccube.event.dispatcher']->dispatch('eccube.event.app.controller', $event);
729
730 468
            if (strpos($route, 'admin') === 0) {
731
                // 管理画面
732 298
                $app['eccube.event.dispatcher']->dispatch('eccube.event.admin.controller', $event);
733
            } else {
734
                // フロント画面
735 172
                $app['eccube.event.dispatcher']->dispatch('eccube.event.front.controller', $event);
736
            }
737
738
            // ルーティング単位
739 468
            $app['eccube.event.dispatcher']->dispatch("eccube.event.route.{$route}.controller", $event);
740 1087
        });
741
742
        // Response Event
743 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...
744 458
            if (!$event->isMasterRequest()) {
745 71
                return;
746
            }
747
748 458
            $route = $event->getRequest()->attributes->get('_route');
749
750 458
            if (is_null($route)) {
751 1
                return;
752
            }
753
754 457
            $app['monolog']->debug('KernelEvents::RESPONSE '.$route);
755
756
            // ルーティング単位
757 457
            $app['eccube.event.dispatcher']->dispatch("eccube.event.route.{$route}.response", $event);
758
759 457
            if (strpos($route, 'admin') === 0) {
760
                // 管理画面
761 293
                $app['eccube.event.dispatcher']->dispatch('eccube.event.admin.response', $event);
762
            } else {
763
                // フロント画面
764 166
                $app['eccube.event.dispatcher']->dispatch('eccube.event.front.response', $event);
765
            }
766
767
            // 全体
768 457
            $app['eccube.event.dispatcher']->dispatch('eccube.event.app.response', $event);
769 1087
        });
770
771
        // Exception Event
772 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...
773
774 20
            if (!$event->isMasterRequest()) {
775
                return;
776
            }
777
778 20
            $route = $event->getRequest()->attributes->get('_route');
779
780 20
            if (is_null($route)) {
781
                return;
782
            }
783
784 20
            $app['monolog']->debug('KernelEvents::EXCEPTION '.$route);
785
786
            // ルーティング単位
787 20
            $app['eccube.event.dispatcher']->dispatch("eccube.event.route.{$route}.exception", $event);
788
789 20
            if (strpos($route, 'admin') === 0) {
790
                // 管理画面
791 9
                $app['eccube.event.dispatcher']->dispatch('eccube.event.admin.exception', $event);
792
            } else {
793
                // フロント画面
794 11
                $app['eccube.event.dispatcher']->dispatch('eccube.event.front.exception', $event);
795
            }
796
797
            // 全体
798 20
            $app['eccube.event.dispatcher']->dispatch('eccube.event.app.exception', $event);
799 1087
        });
800
801
        // Terminate Event
802 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...
803
804 458
            $route = $event->getRequest()->attributes->get('_route');
805
806 458
            if (is_null($route)) {
807 1
                return;
808
            }
809
810 457
            $app['monolog']->debug('KernelEvents::TERMINATE '.$route);
811
812
            // ルーティング単位
813 457
            $app['eccube.event.dispatcher']->dispatch("eccube.event.route.{$route}.terminate", $event);
814
815 457
            if (strpos($route, 'admin') === 0) {
816
                // 管理画面
817 293
                $app['eccube.event.dispatcher']->dispatch('eccube.event.admin.terminate', $event);
818
            } else {
819
                // フロント画面
820 166
                $app['eccube.event.dispatcher']->dispatch('eccube.event.front.terminate', $event);
821
            }
822
823
            // 全体
824 457
            $app['eccube.event.dispatcher']->dispatch('eccube.event.app.terminate', $event);
825 1087
        });
826
    }
827
828 1087
    public function loadPlugin()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
829
    {
830
        // プラグインディレクトリを探索.
831 1087
        $basePath = $this['config']['plugin_realdir'];
832 1087
        $pluginConfigs = $this->getPluginConfigAll();
833
834
        // ハンドラ優先順位をdbから持ってきてハッシュテーブルを作成
835 1087
        $priorities = array();
836 1087
        $handlers = $this['orm.em']
837 1087
            ->getRepository('Eccube\Entity\PluginEventHandler')
838 1087
            ->getHandlers();
839
840 1087
        foreach ($handlers as $handler) {
841 1
            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...
842
843
                $priority = $handler->getPriority();
844
            } else {
845
                // Pluginがdisable、削除済みの場合、EventHandlerのPriorityを全て0とみなす
846 1
                $priority = \Eccube\Entity\PluginEventHandler::EVENT_PRIORITY_DISABLED;
847
            }
848 1087
            $priorities[$handler->getPlugin()->getClassName()][$handler->getEvent()][$handler->getHandler()] = $priority;
849
        }
850
851
        // プラグインをロードする.
852
        // config.yml/event.ymlの定義に沿ってインスタンスの生成を行い, イベント設定を行う.
853 1087
        foreach ($pluginConfigs as $code => $pluginConfig) {
854
            // 正しい形式の pluginConfig のみ読み込む
855 142
            $path = $basePath.'/'.$code;
856
            try {
857 142
                $this['eccube.service.plugin']->checkPluginArchiveContent($path, $pluginConfig['config']);
858
            } catch (\Eccube\Exception\PluginException $e) {
859
                $this['monolog']->warning("Configuration file config.yml for plugin {$code} not found or is invalid. Skipping loading.", array(
0 ignored issues
show
introduced by
Add a comma after each item in a multi-line array
Loading history...
860
                    'path' => $path,
861
                    'original-message' => $e->getMessage()
862
                ));
863
                continue;
864
            }
865 142
            $config = $pluginConfig['config'];
866
867 142
            $plugin = $this['orm.em']
868 142
                ->getRepository('Eccube\Entity\Plugin')
869 142
                ->findOneBy(array('code' => $config['code']));
870
871
            // const
872 142
            if (isset($config['const'])) {
873
                $this['config'] = $this->share($this->extend('config', function ($eccubeConfig) use ($config) {
874 2
                    $eccubeConfig[$config['code']] = array(
875 2
                        'const' => $config['const'],
876
                    );
877
878 2
                    return $eccubeConfig;
879 2
                }));
880
            }
881
882 142
            if ($plugin && $plugin->getEnable() == Constant::DISABLED) {
883
                // プラグインが無効化されていれば読み込まない
884 2
                continue;
885
            }
886
887
            // Type: Event
888 140
            if (isset($config['event'])) {
889 140
                $class = '\\Plugin\\'.$config['code'].'\\'.$config['event'];
890 140
                $eventExists = true;
891
892 140 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...
893
                    $this['monolog']->warning("Event class for plugin {$code} not exists.", array(
894
                        'class' => $class,
895
                    ));
896
                    $eventExists = false;
897
                }
898
899 140
                if ($eventExists && isset($config['event'])) {
0 ignored issues
show
Coding Style introduced by
Blank line found at start of control structure
Loading history...
900
901 140
                    $subscriber = new $class($this);
902
903 140
                    foreach ($pluginConfig['event'] as $event => $handlers) {
904 140
                        foreach ($handlers as $handler) {
905 140
                            if (!isset($priorities[$config['event']][$event][$handler[0]])) { // ハンドラテーブルに登録されていない(ソースにしか記述されていない)ハンドラは一番後ろにする
906 140
                                $priority = \Eccube\Entity\PluginEventHandler::EVENT_PRIORITY_LATEST;
907
                            } else {
908
                                $priority = $priorities[$config['event']][$event][$handler[0]];
909
                            }
910
                            // 優先度が0のプラグインは登録しない
911 140
                            if (\Eccube\Entity\PluginEventHandler::EVENT_PRIORITY_DISABLED != $priority) {
912 140
                                $this['eccube.event.dispatcher']->addListener($event, array($subscriber, $handler[0]), $priority);
913
                            }
914
                        }
915
                    }
916
                }
917
            }
918
            // Type: ServiceProvider
919 140
            if (isset($config['service'])) {
920
                foreach ($config['service'] as $service) {
921
                    $class = '\\Plugin\\'.$config['code'].'\\ServiceProvider\\'.$service;
922 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...
923
                        $this['monolog']->warning("Service provider class for plugin {$code} not exists.", array(
924
                            'class' => $class,
925
                        ));
926
                        continue;
927
                    }
928 1087
                    $this->register(new $class($this));
929
                }
930
            }
931
        }
932
    }
933
934
    /**
935
     * PHPUnit を実行中かどうかを設定する.
936
     *
937
     * @param boolean $testMode PHPUnit を実行中の場合 true
938
     */
939 1077
    public function setTestMode($testMode)
940
    {
941 1077
        $this->testMode = $testMode;
942
    }
943
944
    /**
945
     * PHPUnit を実行中かどうか.
946
     *
947
     * @return boolean PHPUnit を実行中の場合 true
948
     */
949 472
    public function isTestMode()
950
    {
951 472
        return $this->testMode;
952
    }
953
954
    /**
955
     *
956
     * データベースの接続を確認
957
     * 成功 : trueを返却
958
     * 失敗 : \Doctrine\DBAL\DBALExceptionエラーが発生( 接続に失敗した場合 )、エラー画面を表示しdie()
959
     * 備考 : app['debug']がtrueの際は処理を行わない
960
     *
961
     * @return boolean true
962
     *
963
     */
964 1087
    protected function checkDatabaseConnection()
965
    {
966 1087
        if ($this['debug']) {
967 1086
            return;
968
        }
969
        try {
970 1
            $this['db']->connect();
971
        } catch (\Doctrine\DBAL\DBALException $e) {
972
            $this['monolog']->error($e->getMessage());
973
            $this['twig.path'] = array(__DIR__.'/Resource/template/exception');
974
            $html = $this['twig']->render('error.twig', array(
975
                'error_title' => 'データーベース接続エラー',
976
                'error_message' => 'データーベースを確認してください',
977
            ));
978
            $response = new Response();
979
            $response->setContent($html);
980
            $response->setStatusCode('500');
981
            $response->headers->set('Content-Type', 'text/html');
982
            $response->send();
983
            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...
984
        }
985
986 1
        return true;
987
    }
988
989
    /**
990
     * Config ファイルをパースし、連想配列を返します.
991
     *
992
     * $config_name.yml ファイルをパースし、連想配列を返します.
993
     * $config_name.php が存在する場合は、 PHP ファイルに記述された連想配列を使用します。
994
     *
995
     * @param string $config_name Config 名称
0 ignored issues
show
introduced by
Expected 2 spaces after parameter type; 1 found
Loading history...
996
     * @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...
997
     * @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...
998
     * @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...
999
     * @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...
1000
     * @return Application
1001
     */
1002 1091
    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...
1003
    {
1004 1091
        $ymlPath = $ymlPath ? $ymlPath : __DIR__.'/../../app/config/eccube';
1005 1091
        $distPath = $distPath ? $distPath : __DIR__.'/../../src/Eccube/Resource/config';
1006 1091
        $config = array();
1007 1091
        $config_php = $ymlPath.'/'.$config_name.'.php';
1008 1091
        if (!file_exists($config_php)) {
1009 1091
            $config_yml = $ymlPath.'/'.$config_name.'.yml';
1010 1091
            if (file_exists($config_yml)) {
1011 1091
                $config = Yaml::parse(file_get_contents($config_yml));
1012 1091
                $config = empty($config) ? array() : $config;
1013 1091 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...
1014 1091
                    file_put_contents($config_php, sprintf('<?php return %s', var_export($config, true)).';');
1015
                }
1016
            }
1017
        } else {
1018
            $config = require $config_php;
1019
        }
1020
1021 1091
        $config_dist = array();
1022 1091
        $config_php_dist = $distPath.'/'.$config_name.'.dist.php';
1023 1091
        if (!file_exists($config_php_dist)) {
1024 1091
            $config_yml_dist = $distPath.'/'.$config_name.'.yml.dist';
1025 1091
            if (file_exists($config_yml_dist)) {
1026 1091
                $config_dist = Yaml::parse(file_get_contents($config_yml_dist));
1027 1091 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...
1028 1091
                    file_put_contents($config_php_dist, sprintf('<?php return %s', var_export($config_dist, true)).';');
1029
                }
1030
            }
1031
        } else {
1032
            $config_dist = require $config_php_dist;
1033
        }
1034
1035 1091
        if ($wrap_key) {
1036 1091
            $configAll = array_replace_recursive($configAll, array($config_name => $config_dist), array($config_name => $config));
1037
        } else {
1038 1091
            $configAll = array_replace_recursive($configAll, $config_dist, $config);
1039
        }
1040
1041 1091
        return $this;
1042
    }
1043
1044
    /**
1045
     * セッションが開始されているかどうか.
1046
     *
1047
     * @return boolean セッションが開始済みの場合 true
1048
     * @link http://php.net/manual/ja/function.session-status.php#113468
1049
     */
1050 1087
    protected function isSessionStarted()
1051
    {
1052 1087
        if (php_sapi_name() !== 'cli') {
1053 1087
            if (version_compare(phpversion(), '5.4.0', '>=')) {
1054 1087
                return session_status() === PHP_SESSION_ACTIVE ? true : false;
1055
            } else {
1056
                return session_id() === '' ? false : true;
1057
            }
1058
        }
1059
1060
        return false;
1061
    }
1062
1063
    /**
1064
     * Http Cache対応
1065
     */
1066 1087
    protected function initCacheRequest()
1067
    {
1068
        // httpキャッシュが無効の場合はイベント設定を行わない.
1069 1087
        if (!$this['config']['http_cache']['enabled']) {
1070 1087
            return;
1071
        }
1072
1073
        $app = $this;
1074
1075
        // Response Event(http cache対応、event実行は一番遅く設定)
1076
        $this->on(\Symfony\Component\HttpKernel\KernelEvents::RESPONSE, function (\Symfony\Component\HttpKernel\Event\FilterResponseEvent $event) use ($app) {
1077
1078
            if (!$event->isMasterRequest()) {
1079
                return;
1080
            }
1081
1082
            $request = $event->getRequest();
1083
            $response = $event->getResponse();
1084
1085
            $route = $request->attributes->get('_route');
1086
1087
            $etag = md5($response->getContent());
1088
1089
            if (strpos($route, 'admin') === 0) {
1090
                // 管理画面
1091
1092
                // 管理画面ではコンテンツの中身が変更された時点でキャッシュを更新し、キャッシュの適用範囲はprivateに設定
1093
                $response->setCache(array(
1094
                    'etag' => $etag,
1095
                    'private' => true,
1096
                ));
1097
1098
                if ($response->isNotModified($request)) {
1099
                    return $response;
1100
                }
1101
0 ignored issues
show
Coding Style introduced by
Blank line found at end of control structure
Loading history...
1102
            } else {
1103
                // フロント画面
1104
                $cacheRoute = $app['config']['http_cache']['route'];
1105
1106
                if (in_array($route, $cacheRoute) === true) {
1107
                    // キャッシュ対象となる画面lが含まれていた場合、キャッシュ化
1108
                    // max-ageを設定しているためExpiresは不要
1109
                    // Last-Modifiedだと比較する項目がないためETagで対応
1110
                    // max-ageを設定していた場合、contentの中身が変更されても変更されない
1111
1112
                    $age = $app['config']['http_cache']['age'];
1113
1114
                    $response->setCache(array(
1115
                        'etag' => $etag,
1116
                        'max_age' => $age,
1117
                        's_maxage' => $age,
1118
                        'public' => true,
1119
                    ));
1120
1121
                    if ($response->isNotModified($request)) {
1122
                        return $response;
1123
                    }
1124
                }
1125
            }
1126
1127
        }, -1024);
1128
    }
1129
1130
    /**
1131
     * すべてのプラグインの設定情報を返す.
1132
     *
1133
     * すべてのプラグインの config.yml 及び event.yml を読み込み、連想配列で返す.
1134
     * キャッシュファイルが存在する場合は、キャッシュを利用する.
1135
     * キャッシュファイルが存在しない場合は、キャッシュを生成する.
1136
     * $app['debug'] = true の場合は、キャッシュを利用しない.
1137
     *
1138
     * @return array
1139
     */
1140 1088
    public function getPluginConfigAll()
0 ignored issues
show
introduced by
Declare public methods first, then protected ones and finally private ones
Loading history...
1141
    {
1142 1088
        if ($this['debug']) {
1143 1087
            return $this->parsePluginConfigs();
1144
        }
1145 2
        $pluginConfigCache = $this->getPluginConfigCacheFile();
1146 2
        if (file_exists($pluginConfigCache)) {
1147 1
            return require $pluginConfigCache;
1148
        }
1149 2
        if ($this->writePluginConfigCache($pluginConfigCache) === false) {
1150
            return $this->parsePluginConfigs();
1151
        } else {
1152 2
            return require $pluginConfigCache;
1153
        }
1154
    }
1155
1156
    /**
1157
     * プラグイン設定情報のキャッシュを書き込む.
1158
     *
1159
     * @param string $cacheFile
1160
     * @return int|boolean file_put_contents() の結果
1161
     */
1162 7
    public function writePluginConfigCache($cacheFile = null)
1163
    {
1164 7
        if (is_null($cacheFile)) {
1165 6
            $cacheFile = $this->getPluginConfigCacheFile();
1166
        }
1167 7
        $pluginConfigs = $this->parsePluginConfigs();
1168 7
        if (!file_exists($this['config']['plugin_temp_realdir'])) {
1169 1
            @mkdir($this['config']['plugin_temp_realdir']);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
1170
        }
1171 7
        $this['monolog']->debug("write plugin config cache", array($pluginConfigs));
1172 7
        return file_put_contents($cacheFile, sprintf('<?php return %s', var_export($pluginConfigs, true)).';');
0 ignored issues
show
introduced by
Missing blank line before return statement
Loading history...
1173
    }
1174
1175
    /**
1176
     * プラグイン設定情報のキャッシュファイルを削除する.
1177
     *
1178
     * @return boolean
1179
     */
1180 9
    public function removePluginConfigCache()
1181
    {
1182 9
        $cacheFile = $this->getPluginConfigCacheFile();
1183 9
        if (file_exists($cacheFile)) {
1184 8
            $this['monolog']->debug("remove plugin config cache");
1185 8
            return unlink($cacheFile);
0 ignored issues
show
introduced by
Missing blank line before return statement
Loading history...
1186
        }
1187 5
        return false;
0 ignored issues
show
introduced by
Missing blank line before return statement
Loading history...
1188
    }
1189
1190
    /**
1191
     * プラグイン設定情報のキャッシュファイルパスを返す.
1192
     *
1193
     * @return string
1194
     */
1195 10
    public function getPluginConfigCacheFile()
1196
    {
1197 10
        return $this['config']['plugin_temp_realdir'].'/config_cache.php';
1198
    }
1199
1200
    /**
1201
     * プラグイン設定情報をパースし, 連想配列で返す.
1202
     *
1203
     * すべてのプラグインを探索し、 config.yml 及び event.yml をパースする.
1204
     * パースした情報を連想配列で返す.
1205
     *
1206
     * @return array
1207
     */
1208 1088
    public function parsePluginConfigs()
1209
    {
1210
1211 1088
        $finder = Finder::create()
1212 1088
            ->in($this['config']['plugin_realdir'])
1213 1088
            ->directories()
1214 1088
            ->depth(0);
1215 1088
        $finder->sortByName();
1216
1217 1088
        $pluginConfigs = array();
1218 1088
        foreach ($finder as $dir) {
1219 146
            $code = $dir->getBaseName();
1220 146
            if (!$code) {
1221
                //PHP5.3のgetBaseNameバグ対応
1222
                if (PHP_VERSION_ID < 50400) {
1223
                    $code = $dir->getFilename();
1224
                }
1225
            }
1226 146
            $file = $dir->getRealPath().'/config.yml';
1227 146
            $config = null;
0 ignored issues
show
Unused Code introduced by
$config is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
1228 146 View Code Duplication
            if (file_exists($file)) {
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...
1229 146
                $config = Yaml::parse(file_get_contents($file));
1230
            } else {
1231
                $this['monolog']->warning("skip {$code} orm.path loading. config.yml not found.", array('path' => $file));
1232
                continue;
1233
            }
1234
1235 146
            $file = $dir->getRealPath().'/event.yml';
1236 146
            $event = null;
1237 146 View Code Duplication
            if (file_exists($file)) {
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...
1238 142
                $event = Yaml::parse(file_get_contents($file));
1239
            } else {
1240 4
                $this['monolog']->info("skip {$code} event.yml not found.", array('path' => $file));
1241
            }
1242 146
            if (!is_null($config)) {
1243 146
                $pluginConfigs[$code] = array(
0 ignored issues
show
introduced by
Add a comma after each item in a multi-line array
Loading history...
1244 146
                    'config' => $config,
1245 146
                    'event' => $event
1246
                );
1247 1088
                $this['monolog']->debug("parse {$code} config", array($code => $pluginConfigs[$code]));
1248
            }
1249
        }
1250
1251 1088
        return $pluginConfigs;
1252
    }
1253
}
1254