Application::initDoctrine()   F
last analyzed

Complexity

Conditions 12
Paths 264

Size

Total Lines 87
Code Lines 50

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 29
CRAP Score 12

Importance

Changes 0
Metric Value
cc 12
eloc 50
nc 264
nop 0
dl 0
loc 87
rs 3.7956
c 0
b 0
f 0
ccs 29
cts 29
cp 1
crap 12

How to fix   Long Method    Complexity   

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
    public static function getInstance(array $values = array())
0 ignored issues
show
introduced by chihiro-adachi
Missing function doc comment
Loading history...
50
    {
51
        if (!is_object(self::$instance)) {
52
            self::$instance = new Application($values);
53 641
        }
54
55
        return self::$instance;
56
    }
57 629
58 629
    public static function clearInstance()
0 ignored issues
show
introduced by chihiro-adachi
Missing function doc comment
Loading history...
59
    {
60 629
        self::$instance = null;
61 629
    }
62
63
    final public function __clone()
0 ignored issues
show
introduced by chihiro-adachi
Missing function doc comment
Loading history...
64
    {
65
        throw new \Exception('Clone is not allowed against '.get_class($this));
66 629
    }
67 629
68
    public function __construct(array $values = array())
0 ignored issues
show
introduced by TSURU
Missing function doc comment
Loading history...
69
    {
70
        parent::__construct($values);
71
72 629
        if (is_null(self::$instance)) {
73 629
            self::$instance = $this;
74
        }
75
76
        // load config
77
        $this->initConfig();
78 629
79 629
        // init monolog
80
        $this->initLogger();
81
    }
82
83
    /**
84
     * Application::runが実行されているか親クラスのプロパティから判定
85 629
     *
86 629
     * @return bool
87
     */
88
    public function isBooted()
89
    {
90
        return $this->booted;
91
    }
92
93 629
    public function initConfig()
0 ignored issues
show
introduced by chihiro-adachi
Missing function doc comment
Loading history...
94 629
    {
95
        // load config
96
        $app = $this;
97
        $this['config'] = $this->share(function() use ($app) {
0 ignored issues
show
Coding Style introduced by Scrutinizer Auto-Fixer
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
98
            $configAll = array();
99 629
            $app->parseConfig('constant', $configAll)
100 629
                ->parseConfig('path', $configAll)
101
                ->parseConfig('config', $configAll)
102
                ->parseConfig('database', $configAll)
103
                ->parseConfig('mail', $configAll)
104
                ->parseConfig('log', $configAll)
105
                ->parseConfig('nav', $configAll, true)
106 629
                ->parseConfig('doctrine_cache', $configAll)
107 629
                ->parseConfig('http_cache', $configAll)
108
                ->parseConfig('session_handler', $configAll);
109
110
            return $configAll;
111 629
        });
112 629
    }
113
114
    public function initLogger()
0 ignored issues
show
introduced by chihiro-adachi
Missing function doc comment
Loading history...
115
    {
116
        $app = $this;
117
        $this->register(new ServiceProvider\LogServiceProvider($app));
0 ignored issues
show
Unused Code introduced by TSURU
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 629
120 629
    public function initialize()
0 ignored issues
show
introduced by Kiyoshi Yamamura
Missing function doc comment
Loading history...
121
    {
122
        if ($this->initialized) {
123
            return;
124 629
        }
125 629
126
        // init locale
127
        $this->initLocale();
128
129
        // init session
130
        if (!$this->isSessionStarted()) {
131
            $this->initSession();
132 629
        }
133
134 641
        // init twig
135
        $this->initRendering();
136 641
137
        // init provider
138 641
        $this->register(new \Silex\Provider\HttpCacheServiceProvider(), array(
139
            'http_cache.cache_dir' => __DIR__.'/../../app/cache/http/',
140
        ));
141 641
        $this->register(new \Silex\Provider\HttpFragmentServiceProvider());
142
        $this->register(new \Silex\Provider\UrlGeneratorServiceProvider());
143 626
        $this->register(new \Silex\Provider\FormServiceProvider());
144
        $this->register(new \Silex\Provider\SerializerServiceProvider());
145
        $this->register(new \Silex\Provider\ValidatorServiceProvider());
146
        $this->register(new MobileDetectServiceProvider());
147
148
        $app = $this;
149
        $this->error(function (\Exception $e, $code) use ($app) {
150
            if ($app['debug']) {
151
                return;
152
            }
153
154
            switch ($code) {
155
                case 403:
156
                    $title = 'アクセスできません。';
157
                    $message = 'お探しのページはアクセスができない状況にあるか、移動もしくは削除された可能性があります。';
158
                    break;
159
                case 404:
160
                    $title = 'ページがみつかりません。';
161 626
                    $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
        });
174
175
        // init mailer
176
        $this->initMailer();
177
178
        // init doctrine orm
179
        $this->initDoctrine();
180
181
        // Set up the DBAL connection now to check for a proper connection to the database.
182
        $this->checkDatabaseConnection();
183
184
        // init security
185
        $this->initSecurity();
186
187
        // init proxy
188
        $this->initProxy();
189
190
        // init ec-cube service provider
191
        $this->register(new ServiceProvider\EccubeServiceProvider());
192
193
        // mount controllers
194
        $this->register(new \Silex\Provider\ServiceControllerServiceProvider());
195
        $this->mount('', new ControllerProvider\FrontControllerProvider());
196
        $this->mount('/'.trim($this['config']['admin_route'], '/').'/', new ControllerProvider\AdminControllerProvider());
197
        Request::enableHttpMethodParameterOverride(); // PUTやDELETEできるようにする
198
199
        // add transaction listener
200
        $this['dispatcher']->addSubscriber(new TransactionListener($this));
201 626
202
        // init http cache
203 626
        $this->initCacheRequest();
204
205
        $this->initialized = true;
206
    }
207
208
    public function initLocale()
0 ignored issues
show
introduced by chihiro-adachi
Missing function doc comment
Loading history...
209
    {
210
211
        // timezone
212 626
        if (!empty($this['config']['timezone'])) {
213
            date_default_timezone_set($this['config']['timezone']);
214
        }
215
216
        $this->register(new \Silex\Provider\TranslationServiceProvider(), array(
217
            'locale' => $this['config']['locale'],
218
            'translator.cache_dir' => $this['debug'] ? null : $this['config']['root_dir'].'/app/cache/translator',
219
        ));
220
        $this['translator'] = $this->share($this->extend('translator', function ($translator, \Silex\Application $app) {
221
            $translator->addLoader('yaml', new \Symfony\Component\Translation\Loader\YamlFileLoader());
222
223
            $file = __DIR__.'/Resource/locale/validator.'.$app['locale'].'.yml';
224
            if (file_exists($file)) {
225
                $translator->addResource('yaml', $file, $app['locale'], 'validators');
226
            }
227
228
            $file = __DIR__.'/Resource/locale/message.'.$app['locale'].'.yml';
229
            if (file_exists($file)) {
230
                $translator->addResource('yaml', $file, $app['locale']);
231
            }
232
233 317
            return $translator;
234
        }));
235 626
    }
236
237 626
    public function initSession()
0 ignored issues
show
introduced by Kiyoshi Yamamura
Missing function doc comment
Loading history...
238
    {
239
        $this->register(new \Silex\Provider\SessionServiceProvider(), array(
240
            'session.storage.save_path' => $this['config']['root_dir'].'/app/cache/eccube/session',
241 626
            'session.storage.options' => array(
242
                'name' => $this['config']['cookie_name'],
243 626
                'cookie_path' => $this['config']['root_urlpath'] ?: '/',
244 626
                'cookie_secure' => $this['config']['force_ssl'],
245 626
                'cookie_lifetime' => $this['config']['cookie_lifetime'],
246
                'cookie_httponly' => true,
247
                // cookie_domainは指定しない
248 626
                // http://blog.tokumaru.org/2011/10/cookiedomain.html
249
            ),
250 626
        ));
251
252
        $options = $this['config']['session_handler'];
253
254 626
        if ($options['enabled']) {
255
            // @see http://silex.sensiolabs.org/doc/providers/session.html#custom-session-configurations
256
            $this['session.storage.handler'] = null;
257
            ini_set('session.save_handler', $options['save_handler']);
258
            ini_set('session.save_path', $options['save_path']);
259
        }
260
    }
261 626
262
    public function initRendering()
0 ignored issues
show
introduced by chihiro-adachi
Missing function doc comment
Loading history...
263 626
    {
264
        $this->register(new \Silex\Provider\TwigServiceProvider(), array(
265
            'twig.form.templates' => array('Form/form_layout.twig'),
266
        ));
267
        $this['twig'] = $this->share($this->extend('twig', function (\Twig_Environment $twig, \Silex\Application $app) {
268
            $twig->addExtension(new \Eccube\Twig\Extension\EccubeExtension($app));
269
            $twig->addExtension(new \Twig_Extension_StringLoader());
270
271
            return $twig;
272 80
        }));
273
274
        $this->before(function (Request $request, \Silex\Application $app) {
275
            $app['admin'] = false;
276
            $app['front'] = false;
277
            $pathinfo = rawurldecode($request->getPathInfo());
278 71
            if (strpos($pathinfo, '/'.trim($app['config']['admin_route'], '/').'/') === 0) {
279
                $app['admin'] = true;
280
            } else {
281
                $app['front'] = true;
282
            }
283
284
            // フロント or 管理画面ごとにtwigの探索パスを切り替える.
285 71
            $app['twig'] = $app->share($app->extend('twig', function (\Twig_Environment $twig, \Silex\Application $app) {
286
                $paths = array();
287
288
                // 互換性がないのでprofiler とproduction 時のcacheを分離する
289 50
                if (isset($app['profiler'])) {
290
                    $cacheBaseDir = __DIR__.'/../../app/cache/twig/profiler/';
291
                } else {
292 50
                    $cacheBaseDir = __DIR__.'/../../app/cache/twig/production/';
293 50
                }
294
295
                if ($app->isAdminRequest()) {
0 ignored issues
show
Bug introduced by chihiro-adachi
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...
296
                    if (file_exists(__DIR__.'/../../app/template/admin')) {
297
                        $paths[] = __DIR__.'/../../app/template/admin';
298
                    }
299 21
                    $paths[] = $app['config']['template_admin_realdir'];
300
                    $paths[] = __DIR__.'/../../app/Plugin';
301 50
                    $cache = $cacheBaseDir.'admin';
302
0 ignored issues
show
Coding Style introduced by Kiyoshi Yamamura
Blank line found at end of control structure
Loading history...
303
                } else {
304
                    if (file_exists($app['config']['template_realdir'])) {
305 71
                        $paths[] = $app['config']['template_realdir'];
306
                    }
307
                    $paths[] = $app['config']['template_default_realdir'];
308
                    $paths[] = __DIR__.'/../../app/Plugin';
309
                    $cache = $cacheBaseDir.$app['config']['template_code'];
310
                    $app['front'] = true;
311
                }
312
                $twig->setCache($cache);
313
                $app['twig.loader']->addLoader(new \Twig_Loader_Filesystem($paths));
314
315
                return $twig;
316
            }));
317
318
            // 管理画面のIP制限チェック.
319
            if ($app->isAdminRequest()) {
0 ignored issues
show
Bug introduced by chihiro-adachi
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...
320
                // IP制限チェック
321 626
                $allowHost = $app['config']['admin_allow_host'];
322
                if (count($allowHost) > 0) {
323
                    if (array_search($app['request']->getClientIp(), $allowHost) === false) {
324
                        throw new \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException();
325
                    }
326
                }
327
            }
328
        }, self::EARLY_EVENT);
329
330 50
        // twigのグローバル変数を定義.
331
        $app = $this;
332
        $this->on(\Symfony\Component\HttpKernel\KernelEvents::CONTROLLER, function (\Symfony\Component\HttpKernel\Event\FilterControllerEvent $event) use ($app) {
333
            // 未ログイン時にマイページや管理画面以下にアクセスするとSubRequestで実行されるため,
334
            // $event->isMasterRequest()ではなく、グローバル変数が初期化済かどうかの判定を行う
0 ignored issues
show
Unused Code Comprehensibility introduced by chihiro-adachi
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...
335
            if (isset($app['twig_global_initialized']) && $app['twig_global_initialized'] === true) {
336
                return;
337
            }
338
            // ショップ基本情報
339
            $BaseInfo = $app['eccube.repository.base_info']->get();
340
            $app['twig']->addGlobal('BaseInfo', $BaseInfo);
341
342
            if ($app->isAdminRequest()) {
343
                // 管理画面
344
                // 管理画面メニュー
345
                $menus = array('', '', '');
346
                $app['twig']->addGlobal('menus', $menus);
347
348
                $Member = $app->user();
349
                if (is_object($Member)) {
350
                    // ログインしていれば管理者のロールを取得
351
                    $AuthorityRoles = $app['eccube.repository.authority_role']->findBy(array('Authority' => $Member->getAuthority()));
352 7
353
                    $roles = array();
354
                    foreach ($AuthorityRoles as $AuthorityRole) {
355
                        // 管理画面でメニュー制御するため相対パス全てをセット
356 50
                        $roles[] = $app['request']->getBaseUrl().'/'.$app['config']['admin_route'].$AuthorityRole->getDenyUrl();
357
                    }
358 626
359
                    $app['twig']->addGlobal('AuthorityRoles', $roles);
360 626
                }
361
0 ignored issues
show
Coding Style introduced by Kiyoshi Yamamura
Blank line found at end of control structure
Loading history...
362
            } else {
363
                // フロント画面
364
                $request = $event->getRequest();
365
                $route = $request->attributes->get('_route');
366
                $page = $route;
367
                // ユーザ作成画面
368
                if ($route === 'user_data') {
369
                    $params = $request->attributes->get('_route_params');
370
                    $route = $params['route'];
371
                    // プレビュー画面
372
                } elseif ($request->get('preview')) {
373
                    $route = 'preview';
374
                }
375
376
                try {
377
                    $DeviceType = $app['eccube.repository.master.device_type']
378
                        ->find(\Eccube\Entity\Master\DeviceType::DEVICE_TYPE_PC);
379
                    $PageLayout = $app['eccube.repository.page_layout']->getByUrl($DeviceType, $route, $page);
380
                } catch (\Doctrine\ORM\NoResultException $e) {
381
                    $PageLayout = $app['eccube.repository.page_layout']->newPageLayout($DeviceType);
382
                }
383 626
384
                $app['twig']->addGlobal('PageLayout', $PageLayout);
385 626
                $app['twig']->addGlobal('title', $PageLayout->getName());
386
            }
387
388 626
            $app['twig_global_initialized'] = true;
389
        });
390 626
    }
391
392
    public function initMailer()
0 ignored issues
show
introduced by chihiro-adachi
Missing function doc comment
Loading history...
393
    {
394 626
395 626
        // メール送信時の文字エンコード指定(デフォルトはUTF-8)
0 ignored issues
show
Unused Code Comprehensibility introduced by Kiyoshi Yamamura
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...
396
        if (isset($this['config']['mail']['charset_iso_2022_jp']) && is_bool($this['config']['mail']['charset_iso_2022_jp'])) {
397
            if ($this['config']['mail']['charset_iso_2022_jp'] === true) {
398
                \Swift::init(function () {
399
                    \Swift_DependencyContainer::getInstance()
400 626
                        ->register('mime.qpheaderencoder')
401 625
                        ->asAliasOf('mime.base64headerencoder');
402 626
                    \Swift_Preferences::getInstance()->setCharset('iso-2022-jp');
403 626
                });
404
            }
405
        }
406 626
407
        $this->register(new \Silex\Provider\SwiftmailerServiceProvider());
408 626
        $this['swiftmailer.options'] = $this['config']['mail'];
409 626
410
        if (isset($this['config']['mail']['use_spool']) && is_bool($this['config']['mail']['use_spool'])) {
411 626
            $this['swiftmailer.use_spool'] = $this['config']['mail']['use_spool'];
412 626
        }
413 626
        // デフォルトはsmtpを使用
414 626
        $transport = $this['config']['mail']['transport'];
415
        if ($transport == 'sendmail') {
416
            $this['swiftmailer.transport'] = \Swift_SendmailTransport::newInstance();
417
        } elseif ($transport == 'mail') {
418
            $this['swiftmailer.transport'] = \Swift_MailTransport::newInstance();
419
        }
420
    }
421
422
    public function initDoctrine()
0 ignored issues
show
introduced by chihiro-adachi
Missing function doc comment
Loading history...
423
    {
424
        $this->register(new \Silex\Provider\DoctrineServiceProvider(), array(
0 ignored issues
show
introduced by unknown
Add a comma after each item in a multi-line array
Loading history...
425
            'dbs.options' => array(
0 ignored issues
show
introduced by chihiro-adachi
Add a comma after each item in a multi-line array
Loading history...
426
                'default' => $this['config']['database']
427
            )));
0 ignored issues
show
Coding Style introduced by Kiyoshi Yamamura
This line of the multi-line function call does not seem to be indented correctly. Expected 8 spaces, but found 12.
Loading history...
428
        $this->register(new \Saxulum\DoctrineOrmManagerRegistry\Silex\Provider\DoctrineOrmManagerRegistryProvider());
429
430
        // プラグインのmetadata定義を合わせて行う.
431 626
        $pluginConfigs = $this->getPluginConfigAll();
432
        $ormMappings = array();
433
        $ormMappings[] = array(
434 626
            'type' => 'yml',
435
            'namespace' => 'Eccube\Entity',
436
            'path' => array(
437 626
                __DIR__.'/Resource/doctrine',
438
                __DIR__.'/Resource/doctrine/master',
439 626
            ),
440
        );
441 626
442
        foreach ($pluginConfigs as $code) {
443
            $config = $code['config'];
444
            // Doctrine Extend
445
            if (isset($config['orm.path']) && is_array($config['orm.path'])) {
446 626
                $paths = array();
447
                foreach ($config['orm.path'] as $path) {
448
                    $paths[] = $this['config']['plugin_realdir'].'/'.$config['code'].$path;
449
                }
450
                $ormMappings[] = array(
451
                    'type' => 'yml',
452 626
                    'namespace' => 'Plugin\\'.$config['code'].'\\Entity',
453 626
                    'path' => $paths,
454 626
                );
455 626
            }
456 626
        }
457
458
        $options = array(
0 ignored issues
show
introduced by Kentaro Ohkouchi
Add a comma after each item in a multi-line array
Loading history...
459
            'mappings' => $ormMappings
460 626
        );
461
462 626
        if (!$this['debug']) {
463
            $cacheDrivers = array();
464
            if (array_key_exists('doctrine_cache', $this['config'])) {
465 626
                $cacheDrivers = $this['config']['doctrine_cache'];
466
            }
467
468
            if (array_key_exists('metadata_cache', $cacheDrivers)) {
469
                $options['metadata_cache'] = $cacheDrivers['metadata_cache'];
470
            }
471
            if (array_key_exists('query_cache', $cacheDrivers)) {
472
                $options['query_cache'] = $cacheDrivers['query_cache'];
473 626
            }
474
            if (array_key_exists('result_cache', $cacheDrivers)) {
475
                $options['result_cache'] = $cacheDrivers['result_cache'];
476
            }
477 626
            if (array_key_exists('hydration_cache', $cacheDrivers)) {
478
                $options['hydration_cache'] = $cacheDrivers['hydration_cache'];
479
            }
480 626
        }
481
482
        $this->register(new \Dflydev\Silex\Provider\DoctrineOrm\DoctrineOrmServiceProvider(), array(
483
            'orm.proxies_dir' => __DIR__.'/../../app/cache/doctrine/proxies',
484 626
            'orm.em.options' => $options,
485 626
            'orm.custom.functions.string' => array(
486 626
                'NORMALIZE' => 'Eccube\Doctrine\ORM\Query\Normalize',
487 626
            ),
488
            'orm.custom.functions.numeric' => array(
489
                'EXTRACT' => 'Eccube\Doctrine\ORM\Query\Extract',
490 626
            ),
491
        ));
492
493 626
        /**
494
         * YamlDriverのPHP7対応. Doctrine2.4で修正されれば不要.
495
         * @see https://github.com/EC-CUBE/ec-cube/issues/1338
496 626
         */
497 626
        $config = $this['orm.em']->getConfiguration();
498 626
        /** @var $driver \Doctrine\Common\Persistence\Mapping\Driver\MappingDriverChain */
499 626
        $chain = $config->getMetadataDriverImpl();
500
        // $ormMappingsの1要素ごとにDriverが生成されている.
501
        $drivers = $chain->getDrivers();
502
        foreach ($drivers as $namespace => $oldDriver) {
503
            /** @var $newDriver \Eccube\Doctrine\ORM\Mapping\Driver\YamlDriver */
504
            $newDriver = new YamlDriver($oldDriver->getLocator());
505
            // 修正したDriverに差し替える. メソッド名はaddだけど実際はsetしてる.
506 626
            $chain->addDriver($newDriver, $namespace);
507 626
        }
508
    }
509
510
    public function initSecurity()
0 ignored issues
show
introduced by Kiyoshi Yamamura
Missing function doc comment
Loading history...
511
    {
512
        $this->register(new \Silex\Provider\SecurityServiceProvider());
513
        $this->register(new \Silex\Provider\RememberMeServiceProvider());
514
515
        $this['security.firewalls'] = array(
516
            'admin' => array(
517
                'pattern' => "^/{$this['config']['admin_route']}/",
518
                'form' => array(
519
                    'login_path' => "/{$this['config']['admin_route']}/login",
520
                    'check_path' => "/{$this['config']['admin_route']}/login_check",
521 626
                    'username_parameter' => 'login_id',
522
                    'password_parameter' => 'password',
523
                    'with_csrf' => true,
524
                    'use_forward' => true,
525
                    'default_target_path' => "/{$this['config']['admin_route']}",
526
                ),
527
                'logout' => array(
528
                    'logout_path' => "/{$this['config']['admin_route']}/logout",
529
                    'target_url' => "/{$this['config']['admin_route']}/",
530
                ),
531
                'users' => $this['orm.em']->getRepository('Eccube\Entity\Member'),
532 389
                'anonymous' => true,
533
            ),
534
            'customer' => array(
535
                'pattern' => '^/',
536
                'form' => array(
537
                    'login_path' => '/mypage/login',
538
                    'check_path' => '/login_check',
539
                    'username_parameter' => 'login_email',
540
                    'password_parameter' => 'login_pass',
541
                    'with_csrf' => true,
542
                    'use_forward' => true,
543
                ),
544
                'logout' => array(
545
                    'logout_path' => '/logout',
546
                    'target_url' => '/',
547
                ),
548
                'remember_me' => array(
549
                    'key' => sha1($this['config']['auth_magic']),
550
                    'name' => $this['config']['cookie_name'].'_rememberme',
551
                    // lifetimeはデフォルトの1年間にする
552
                    // 'lifetime' => $this['config']['cookie_lifetime'],
0 ignored issues
show
Unused Code Comprehensibility introduced by Kiyoshi Yamamura
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...
553
                    'path' => $this['config']['root_urlpath'] ?: '/',
554
                    'secure' => $this['config']['force_ssl'],
555
                    'httponly' => true,
556
                    'always_remember_me' => false,
557
                    'remember_me_parameter' => 'login_memory',
558
                ),
559
                'users' => $this['orm.em']->getRepository('Eccube\Entity\Customer'),
560
                'anonymous' => true,
561
            ),
562
        );
563 389
564
        $channel = null;
565
        // 強制SSL
566
        if ($this['config']['force_ssl'] == \Eccube\Common\Constant::ENABLED) {
567
            $channel = "https";
568 389
        }
569
570
        $this['security.access_rules'] = array(
571
            array("^/{$this['config']['admin_route']}/login", 'IS_AUTHENTICATED_ANONYMOUSLY', $channel),
572
            array("^/{$this['config']['admin_route']}/", 'ROLE_ADMIN', $channel),
573
            array('^/mypage/login', 'IS_AUTHENTICATED_ANONYMOUSLY', $channel),
574
            array('^/mypage/withdraw_complete', 'IS_AUTHENTICATED_ANONYMOUSLY', $channel),
575
            array('^/mypage/change', 'IS_AUTHENTICATED_FULLY', $channel),
576
            array('^/mypage', 'ROLE_USER', $channel),
577
        );
578
579
        $this['eccube.password_encoder'] = $this->share(function ($app) {
580
            return new \Eccube\Security\Core\Encoder\PasswordEncoder($app['config']);
581
        });
582
        $this['security.encoder_factory'] = $this->share(function ($app) {
583
            return new \Symfony\Component\Security\Core\Encoder\EncoderFactory(array(
584
                'Eccube\Entity\Customer' => $app['eccube.password_encoder'],
585
                'Eccube\Entity\Member' => $app['eccube.password_encoder'],
586
            ));
587
        });
588
        $this['eccube.event_listner.security'] = $this->share(function ($app) {
589
            return new \Eccube\EventListener\SecurityEventListener($app['orm.em']);
590
        });
591
        $this['user'] = function ($app) {
592
            $token = $app['security']->getToken();
593
594
            return ($token !== null) ? $token->getUser() : null;
595
        };
596
597
        // ログイン時のイベントを設定.
598
        $this['dispatcher']->addListener(\Symfony\Component\Security\Http\SecurityEvents::INTERACTIVE_LOGIN, array($this['eccube.event_listner.security'], 'onInteractiveLogin'));
599
600
        // Voterの設定
601
        $app = $this;
602
        $this['authority_voter'] = $this->share(function ($app) {
603
            return new \Eccube\Security\Voter\AuthorityVoter($app);
604
        });
605
606
        $app['security.voters'] = $app->extend('security.voters', function ($voters) use ($app) {
607
            $voters[] = $app['authority_voter'];
608
609
            return $voters;
610
        });
611
612
        $this['security.access_manager'] = $this->share(function ($app) {
613
            return new \Symfony\Component\Security\Core\Authorization\AccessDecisionManager($app['security.voters'], 'unanimous');
614
        });
615
616
    }
617
618
    /**
619
     * ロードバランサー、プロキシサーバの設定を行う
620
     */
621
    public function initProxy()
622
    {
623
        $config = $this['config'];
624
        if (isset($config['trusted_proxies_connection_only']) && !empty($config['trusted_proxies_connection_only'])) {
625
            $this->on(KernelEvents::REQUEST, function (GetResponseEvent $event) use ($config) {
626
                // サブリクエストのREMOTE_ADDRも動的に設定を行う必要があるため、KernelEvents::REQUESTを使用する
627
                Request::setTrustedProxies(array_merge(array($event->getRequest()->server->get('REMOTE_ADDR')), $config['trusted_proxies']));
628
            }, self::EARLY_EVENT);
629 View Code Duplication
        } elseif (isset($config['trusted_proxies']) && !empty($config['trusted_proxies'])) {
630
            Request::setTrustedProxies($config['trusted_proxies']);
631
        }
632
    }
633
634
    public function initializePlugin()
0 ignored issues
show
introduced by Kiyoshi Yamamura
Missing function doc comment
Loading history...
635
    {
636
        if ($this->initializedPlugin) {
637
            return;
638
        }
639
640
        // setup event dispatcher
641
        $this->initPluginEventDispatcher();
642
643
        // load plugin
644
        $this->loadPlugin();
645
646
        $this->initializedPlugin = true;
647
    }
648
649
    public function initPluginEventDispatcher()
0 ignored issues
show
introduced by chihiro-adachi
Missing function doc comment
Loading history...
650
    {
651
        // EventDispatcher
652
        $this['eccube.event.dispatcher'] = $this->share(function () {
653
            return new EventDispatcher();
654
        });
655
656
        $app = $this;
657
658
        // hook point
659
        $this->on(KernelEvents::REQUEST, function (GetResponseEvent $event) use ($app) {
660
            if (!$event->isMasterRequest()) {
661
                return;
662
            }
663
            $hookpoint = 'eccube.event.app.before';
664
            $app['eccube.event.dispatcher']->dispatch($hookpoint, $event);
665
        }, self::EARLY_EVENT);
666
667 View Code Duplication
        $this->on(KernelEvents::REQUEST, function (GetResponseEvent $event) use ($app) {
668
            if (!$event->isMasterRequest()) {
669
                return;
670
            }
671
            $route = $event->getRequest()->attributes->get('_route');
672
            $hookpoint = "eccube.event.controller.$route.before";
673
            $app['eccube.event.dispatcher']->dispatch($hookpoint, $event);
674
        });
675
676 View Code Duplication
        $this->on(KernelEvents::RESPONSE, function (FilterResponseEvent $event) use ($app) {
677
            if (!$event->isMasterRequest()) {
678
                return;
679
            }
680
            $route = $event->getRequest()->attributes->get('_route');
681
            $hookpoint = "eccube.event.controller.$route.after";
682
            $app['eccube.event.dispatcher']->dispatch($hookpoint, $event);
683
        });
684
685
        $this->on(KernelEvents::RESPONSE, function (FilterResponseEvent $event) use ($app) {
686
            if (!$event->isMasterRequest()) {
687
                return;
688
            }
689
            $hookpoint = 'eccube.event.app.after';
690
            $app['eccube.event.dispatcher']->dispatch($hookpoint, $event);
691
        }, self::LATE_EVENT);
692
693
        $this->on(KernelEvents::TERMINATE, function (PostResponseEvent $event) use ($app) {
694
            $route = $event->getRequest()->attributes->get('_route');
695
            $hookpoint = "eccube.event.controller.$route.finish";
696
            $app['eccube.event.dispatcher']->dispatch($hookpoint, $event);
697
        });
698
699
        $this->on(\Symfony\Component\HttpKernel\KernelEvents::RESPONSE, function (\Symfony\Component\HttpKernel\Event\FilterResponseEvent $event) use ($app) {
700
            if (!$event->isMasterRequest()) {
701
                return;
702
            }
703
            $route = $event->getRequest()->attributes->get('_route');
704
            $app['eccube.event.dispatcher']->dispatch('eccube.event.render.'.$route.'.before', $event);
705
        });
706
707
        // Request Event
708 View Code Duplication
        $this->on(\Symfony\Component\HttpKernel\KernelEvents::REQUEST, function (\Symfony\Component\HttpKernel\Event\GetResponseEvent $event) use ($app) {
709
710
            if (!$event->isMasterRequest()) {
711
                return;
712
            }
713
714
            $route = $event->getRequest()->attributes->get('_route');
715
716
            if (is_null($route)) {
717
                return;
718
            }
719
720
            $app['monolog']->debug('KernelEvents::REQUEST '.$route);
721
722
            // 全体
723
            $app['eccube.event.dispatcher']->dispatch('eccube.event.app.request', $event);
724
725
            if (strpos($route, 'admin') === 0) {
726
                // 管理画面
727
                $app['eccube.event.dispatcher']->dispatch('eccube.event.admin.request', $event);
728
            } else {
729
                // フロント画面
730
                $app['eccube.event.dispatcher']->dispatch('eccube.event.front.request', $event);
731
            }
732
733
            // ルーティング単位
734
            $app['eccube.event.dispatcher']->dispatch("eccube.event.route.{$route}.request", $event);
735
736
        }, 30); // Routing(32)が解決しし, 認証判定(8)が実行される前のタイミング.
0 ignored issues
show
Unused Code Comprehensibility introduced by chihiro-adachi
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...
737
738
        // Controller Event
739 View Code Duplication
        $this->on(\Symfony\Component\HttpKernel\KernelEvents::CONTROLLER, function (\Symfony\Component\HttpKernel\Event\FilterControllerEvent $event) use ($app) {
740
741
            if (!$event->isMasterRequest()) {
742
                return;
743
            }
744
745
            $route = $event->getRequest()->attributes->get('_route');
746
747
            if (is_null($route)) {
748
                return;
749
            }
750
751
            $app['monolog']->debug('KernelEvents::CONTROLLER '.$route);
752
753
            // 全体
754
            $app['eccube.event.dispatcher']->dispatch('eccube.event.app.controller', $event);
755
756
            if (strpos($route, 'admin') === 0) {
757
                // 管理画面
758
                $app['eccube.event.dispatcher']->dispatch('eccube.event.admin.controller', $event);
759
            } else {
760
                // フロント画面
761
                $app['eccube.event.dispatcher']->dispatch('eccube.event.front.controller', $event);
762
            }
763
764
            // ルーティング単位
765
            $app['eccube.event.dispatcher']->dispatch("eccube.event.route.{$route}.controller", $event);
766
        });
767
768
        // Response Event
769 View Code Duplication
        $this->on(\Symfony\Component\HttpKernel\KernelEvents::RESPONSE, function (\Symfony\Component\HttpKernel\Event\FilterResponseEvent $event) use ($app) {
770
            if (!$event->isMasterRequest()) {
771
                return;
772
            }
773
774
            $route = $event->getRequest()->attributes->get('_route');
775
776
            if (is_null($route)) {
777
                return;
778
            }
779
780
            $app['monolog']->debug('KernelEvents::RESPONSE '.$route);
781
782
            // ルーティング単位
783
            $app['eccube.event.dispatcher']->dispatch("eccube.event.route.{$route}.response", $event);
784
785
            if (strpos($route, 'admin') === 0) {
786
                // 管理画面
787
                $app['eccube.event.dispatcher']->dispatch('eccube.event.admin.response', $event);
788
            } else {
789
                // フロント画面
790
                $app['eccube.event.dispatcher']->dispatch('eccube.event.front.response', $event);
791
            }
792
793
            // 全体
794
            $app['eccube.event.dispatcher']->dispatch('eccube.event.app.response', $event);
795
        });
796
797
        // Exception Event
798 View Code Duplication
        $this->on(\Symfony\Component\HttpKernel\KernelEvents::EXCEPTION, function (\Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent $event) use ($app) {
799
800
            if (!$event->isMasterRequest()) {
801
                return;
802
            }
803
804
            $route = $event->getRequest()->attributes->get('_route');
805
806
            if (is_null($route)) {
807
                return;
808
            }
809
810
            $app['monolog']->debug('KernelEvents::EXCEPTION '.$route);
811
812
            // ルーティング単位
813
            $app['eccube.event.dispatcher']->dispatch("eccube.event.route.{$route}.exception", $event);
814
815
            if (strpos($route, 'admin') === 0) {
816
                // 管理画面
817
                $app['eccube.event.dispatcher']->dispatch('eccube.event.admin.exception', $event);
818
            } else {
819
                // フロント画面
820
                $app['eccube.event.dispatcher']->dispatch('eccube.event.front.exception', $event);
821
            }
822
823
            // 全体
824
            $app['eccube.event.dispatcher']->dispatch('eccube.event.app.exception', $event);
825
        });
826
827
        // Terminate Event
828 View Code Duplication
        $this->on(\Symfony\Component\HttpKernel\KernelEvents::TERMINATE, function (\Symfony\Component\HttpKernel\Event\PostResponseEvent $event) use ($app) {
829
830
            $route = $event->getRequest()->attributes->get('_route');
831
832
            if (is_null($route)) {
833
                return;
834
            }
835
836
            $app['monolog']->debug('KernelEvents::TERMINATE '.$route);
837
838
            // ルーティング単位
839
            $app['eccube.event.dispatcher']->dispatch("eccube.event.route.{$route}.terminate", $event);
840
841
            if (strpos($route, 'admin') === 0) {
842
                // 管理画面
843
                $app['eccube.event.dispatcher']->dispatch('eccube.event.admin.terminate', $event);
844
            } else {
845
                // フロント画面
846
                $app['eccube.event.dispatcher']->dispatch('eccube.event.front.terminate', $event);
847
            }
848
849
            // 全体
850
            $app['eccube.event.dispatcher']->dispatch('eccube.event.app.terminate', $event);
851
        });
852
    }
853
854
    public function loadPlugin()
0 ignored issues
show
introduced by chihiro-adachi
Missing function doc comment
Loading history...
855
    {
856
        // プラグインディレクトリを探索.
857
        $basePath = $this['config']['plugin_realdir'];
858
        $pluginConfigs = $this->getPluginConfigAll();
859
860
        // ハンドラ優先順位をdbから持ってきてハッシュテーブルを作成
861
        $priorities = array();
862
        $handlers = $this['orm.em']
863
            ->getRepository('Eccube\Entity\PluginEventHandler')
864
            ->getHandlers();
865
866
        foreach ($handlers as $handler) {
867
            if ($handler->getPlugin()->getEnable() && !$handler->getPlugin()->getDelFlg()) {
0 ignored issues
show
Coding Style introduced by chihiro-adachi
Blank line found at start of control structure
Loading history...
868
869
                $priority = $handler->getPriority();
870
            } else {
871
                // Pluginがdisable、削除済みの場合、EventHandlerのPriorityを全て0とみなす
872
                $priority = \Eccube\Entity\PluginEventHandler::EVENT_PRIORITY_DISABLED;
873
            }
874
            $priorities[$handler->getPlugin()->getClassName()][$handler->getEvent()][$handler->getHandler()] = $priority;
875
        }
876
877
        // プラグインをロードする.
878
        // config.yml/event.ymlの定義に沿ってインスタンスの生成を行い, イベント設定を行う.
879
        foreach ($pluginConfigs as $code => $pluginConfig) {
880
            // 正しい形式の pluginConfig のみ読み込む
881
            $path = $basePath.'/'.$code;
882
            try {
883
                $this['eccube.service.plugin']->checkPluginArchiveContent($path, $pluginConfig['config']);
884
            } catch (\Eccube\Exception\PluginException $e) {
885
                $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...
886
                    'path' => $path,
887
                    'original-message' => $e->getMessage()
888
                ));
889
                continue;
890
            }
891
            $config = $pluginConfig['config'];
892
893
            $plugin = $this['orm.em']
894
                ->getRepository('Eccube\Entity\Plugin')
895
                ->findOneBy(array('code' => $config['code']));
896
897
            // const
898
            if (isset($config['const'])) {
899
                $this['config'] = $this->share($this->extend('config', function ($eccubeConfig) use ($config) {
900
                    $eccubeConfig[$config['code']] = array(
901
                        'const' => $config['const'],
902
                    );
903
904
                    return $eccubeConfig;
905
                }));
906
            }
907
908
            if ($plugin && $plugin->getEnable() == Constant::DISABLED) {
909
                // プラグインが無効化されていれば読み込まない
910
                continue;
911
            }
912
913
            // Type: Event
914
            if (isset($config['event'])) {
915
                $class = '\\Plugin\\'.$config['code'].'\\'.$config['event'];
916
                $eventExists = true;
917
918 View Code Duplication
                if (!class_exists($class)) {
919
                    $this['monolog']->warning("Event class for plugin {$code} not exists.", array(
920
                        'class' => $class,
921
                    ));
922
                    $eventExists = false;
923
                }
924
925
                if ($eventExists && isset($config['event'])) {
0 ignored issues
show
Coding Style introduced by Kentaro Ohkouchi
Blank line found at start of control structure
Loading history...
926
927
                    $subscriber = new $class($this);
928
929
                    foreach ($pluginConfig['event'] as $event => $handlers) {
930
                        foreach ($handlers as $handler) {
931
                            if (!isset($priorities[$config['event']][$event][$handler[0]])) { // ハンドラテーブルに登録されていない(ソースにしか記述されていない)ハンドラは一番後ろにする
932
                                $priority = \Eccube\Entity\PluginEventHandler::EVENT_PRIORITY_LATEST;
933
                            } else {
934
                                $priority = $priorities[$config['event']][$event][$handler[0]];
935
                            }
936
                            // 優先度が0のプラグインは登録しない