Completed
Push — master ( 290ae6...f67c79 )
by Yangsin
251:47 queued 245:46
created

Application::initSecurity()   B

Complexity

Conditions 4
Paths 4

Size

Total Lines 106
Code Lines 70

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 48
CRAP Score 4.0001

Importance

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