Completed
Pull Request — master (#2028)
by
unknown
41:57
created

Application::parseConfig()   D

Complexity

Conditions 13
Paths 192

Size

Total Lines 41
Code Lines 29

Duplication

Lines 6
Ratio 14.63 %

Code Coverage

Tests 24
CRAP Score 13.0768

Importance

Changes 0
Metric Value
cc 13
eloc 29
nc 192
nop 5
dl 6
loc 41
ccs 24
cts 26
cp 0.9231
crap 13.0768
rs 4.8178
c 0
b 0
f 0

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

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

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

Loading history...
1238 146
                $config = Yaml::parse(file_get_contents($file));
1239
            } else {
1240
                $this['monolog']->warning("skip {$code} orm.path loading. config.yml not found.", array('path' => $file));
1241
                continue;
1242
            }
1243
1244 146
            $file = $dir->getRealPath().'/event.yml';
1245 146
            $event = null;
1246 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...
1247 142
                $event = Yaml::parse(file_get_contents($file));
1248
            } else {
1249 4
                $this['monolog']->info("skip {$code} event.yml not found.", array('path' => $file));
1250
            }
1251 146
            if (!is_null($config)) {
1252 146
                $pluginConfigs[$code] = array(
0 ignored issues
show
introduced by
Add a comma after each item in a multi-line array
Loading history...
1253 146
                    'config' => $config,
1254 146
                    'event' => $event
1255
                );
1256 1088
                $this['monolog']->debug("parse {$code} config", array($code => $pluginConfigs[$code]));
1257
            }
1258
        }
1259
1260 1088
        return $pluginConfigs;
1261
    }
1262
}
1263