Completed
Push — master ( a52817...705916 )
by Yangsin
30s
created

Application::parsePluginConfigs()   C

Complexity

Conditions 7
Paths 16

Size

Total Lines 45
Code Lines 31

Duplication

Lines 11
Ratio 24.44 %

Code Coverage

Tests 25
CRAP Score 7.1284

Importance

Changes 0
Metric Value
cc 7
eloc 31
nc 16
nop 0
dl 11
loc 45
ccs 25
cts 29
cp 0.8621
crap 7.1284
rs 6.7272
c 0
b 0
f 0
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 1079
    public static function getInstance(array $values = array())
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
49
    {
50 1079
        if (!is_object(self::$instance)) {
51 1075
            self::$instance = new Application($values);
52
        }
53
54 1079
        return self::$instance;
55
    }
56
57 1076
    public static function clearInstance()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
58
    {
59 1076
        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 1080
    public function __construct(array $values = array())
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
68
    {
69 1080
        parent::__construct($values);
70
71 1080
        if (is_null(self::$instance)) {
72 1076
            self::$instance = $this;
73
        }
74
75
        // load config
76 1080
        $this->initConfig();
77
78
        // init monolog
79 1080
        $this->initLogger();
80
    }
81
82
    /**
83
     * Application::runが実行されているか親クラスのプロパティから判定
84
     *
85
     * @return bool
86
     */
87 1079
    public function isBooted()
88
    {
89 1079
        return $this->booted;
90
    }
91
92 1080
    public function initConfig()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
93
    {
94
        // load config
95 1080
        $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 1080
            $configAll = array();
98 1080
            $app->parseConfig('constant', $configAll)
99 1080
                ->parseConfig('path', $configAll)
100 1080
                ->parseConfig('config', $configAll)
101 1080
                ->parseConfig('database', $configAll)
102 1080
                ->parseConfig('mail', $configAll)
103 1080
                ->parseConfig('log', $configAll)
104 1080
                ->parseConfig('nav', $configAll, true)
105 1080
                ->parseConfig('doctrine_cache', $configAll)
106 1080
                ->parseConfig('http_cache', $configAll)
107 1080
                ->parseConfig('session_handler', $configAll);
108
109 1080
            return $configAll;
110 1080
        });
111
    }
112
113 1081
    public function initLogger()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
114
    {
115 1081
        $app = $this;
116 1081
        $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 1076
    public function initialize()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
120
    {
121 1076
        if ($this->initialized) {
122
            return;
123
        }
124
125
        // init locale
126 1076
        $this->initLocale();
127
128
        // init session
129 1076
        if (!$this->isSessionStarted()) {
130 1076
            $this->initSession();
131
        }
132
133
        // init twig
134 1076
        $this->initRendering();
135
136
        // init provider
137 1076
        $this->register(new \Silex\Provider\HttpCacheServiceProvider(), array(
138 1076
            'http_cache.cache_dir' => __DIR__.'/../../app/cache/http/',
139
        ));
140 1076
        $this->register(new \Silex\Provider\HttpFragmentServiceProvider());
141 1076
        $this->register(new \Silex\Provider\UrlGeneratorServiceProvider());
142 1076
        $this->register(new \Silex\Provider\FormServiceProvider());
143 1076
        $this->register(new \Silex\Provider\SerializerServiceProvider());
144 1076
        $this->register(new \Silex\Provider\ValidatorServiceProvider());
145
146 1076
        $app = $this;
147
        $this->error(function (\Exception $e, $code) use ($app) {
148 18
            if ($app['debug']) {
149 18
                return;
150
            }
151
152
            switch ($code) {
153
                case 403:
154
                    $title = 'アクセスできません。';
155
                    $message = 'お探しのページはアクセスができない状況にあるか、移動もしくは削除された可能性があります。';
156
                    break;
157
                case 404:
158
                    $title = 'ページがみつかりません。';
159
                    $message = 'URLに間違いがないかご確認ください。';
160
                    break;
161
                default:
162
                    $title = 'システムエラーが発生しました。';
163
                    $message = '大変お手数ですが、サイト管理者までご連絡ください。';
164
                    break;
165
            }
166
167
            return $app->render('error.twig', array(
168
                'error_title' => $title,
169
                'error_message' => $message,
170
            ));
171 1076
        });
172
173
        // init mailer
174 1076
        $this->initMailer();
175
176
        // init doctrine orm
177 1076
        $this->initDoctrine();
178
179
        // Set up the DBAL connection now to check for a proper connection to the database.
180 1076
        $this->checkDatabaseConnection();
181
182
        // init security
183 1076
        $this->initSecurity();
184
185
        // init ec-cube service provider
186 1076
        $this->register(new ServiceProvider\EccubeServiceProvider());
187
188
        // mount controllers
189 1076
        $this->register(new \Silex\Provider\ServiceControllerServiceProvider());
190 1076
        $this->mount('', new ControllerProvider\FrontControllerProvider());
191 1076
        $this->mount('/'.trim($this['config']['admin_route'], '/').'/', new ControllerProvider\AdminControllerProvider());
192 1076
        Request::enableHttpMethodParameterOverride(); // PUTやDELETEできるようにする
193
194
        // add transaction listener
195 1076
        $this['dispatcher']->addSubscriber(new TransactionListener($this));
196
197
        // init http cache
198 1076
        $this->initCacheRequest();
199
200 1076
        $this->initialized = true;
201
    }
202
203 1076
    public function initLocale()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
204
    {
205
206
        // timezone
207 1076
        if (!empty($this['config']['timezone'])) {
208 1076
            date_default_timezone_set($this['config']['timezone']);
209
        }
210
211 1076
        $this->register(new \Silex\Provider\TranslationServiceProvider(), array(
212 1076
            'locale' => $this['config']['locale'],
213 1076
            'translator.cache_dir' => $this['debug'] ? null : $this['config']['root_dir'].'/app/cache/translator',
214
        ));
215
        $this['translator'] = $this->share($this->extend('translator', function ($translator, \Silex\Application $app) {
216 719
            $translator->addLoader('yaml', new \Symfony\Component\Translation\Loader\YamlFileLoader());
217
218 719
            $file = __DIR__.'/Resource/locale/validator.'.$app['locale'].'.yml';
219 719
            if (file_exists($file)) {
220 719
                $translator->addResource('yaml', $file, $app['locale'], 'validators');
221
            }
222
223 719
            $file = __DIR__.'/Resource/locale/message.'.$app['locale'].'.yml';
224 719
            if (file_exists($file)) {
225 719
                $translator->addResource('yaml', $file, $app['locale']);
226
            }
227
228 719
            return $translator;
229 1076
        }));
230
    }
231
232 1076
    public function initSession()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
233
    {
234 1076
        $this->register(new \Silex\Provider\SessionServiceProvider(), array(
235 1076
            'session.storage.save_path' => $this['config']['root_dir'].'/app/cache/eccube/session',
236
            'session.storage.options' => array(
237 1076
                'name' => $this['config']['cookie_name'],
238 1076
                'cookie_path' => $this['config']['root_urlpath'] ?: '/',
239 1076
                'cookie_secure' => $this['config']['force_ssl'],
240 1076
                'cookie_lifetime' => $this['config']['cookie_lifetime'],
241
                'cookie_httponly' => true,
242
                // cookie_domainは指定しない
243
                // http://blog.tokumaru.org/2011/10/cookiedomain.html
244
            ),
245
        ));
246
247 1076
        $options = $this['config']['session_handler'];
248
249 1076
        if ($options['enabled']) {
250
            // @see http://silex.sensiolabs.org/doc/providers/session.html#custom-session-configurations
251
            $this['session.storage.handler'] = null;
252
            ini_set('session.save_handler', $options['save_handler']);
253
            ini_set('session.save_path', $options['save_path']);
254
        }
255
    }
256
257 1076
    public function initRendering()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
258
    {
259 1076
        $this->register(new \Silex\Provider\TwigServiceProvider(), array(
260 1076
            'twig.form.templates' => array('Form/form_layout.twig'),
261
        ));
262
        $this['twig'] = $this->share($this->extend('twig', function (\Twig_Environment $twig, \Silex\Application $app) {
263 472
            $twig->addExtension(new \Eccube\Twig\Extension\EccubeExtension($app));
264 472
            $twig->addExtension(new \Twig_Extension_StringLoader());
265
266 472
            return $twig;
267 1076
        }));
268
269
        $this->before(function (Request $request, \Silex\Application $app) {
270 461
            $app['admin'] = false;
271 461
            $app['front'] = false;
272 461
            $pathinfo = rawurldecode($request->getPathInfo());
273 461
            if (strpos($pathinfo, '/'.trim($app['config']['admin_route'], '/').'/') === 0) {
274 289
                $app['admin'] = true;
275
            } else {
276 174
                $app['front'] = true;
277
            }
278
279
            // フロント or 管理画面ごとにtwigの探索パスを切り替える.
280
            $app['twig'] = $app->share($app->extend('twig', function (\Twig_Environment $twig, \Silex\Application $app) {
281 459
                $paths = array();
282
283
                // 互換性がないのでprofiler とproduction 時のcacheを分離する
284 459
                if (isset($app['profiler'])) {
285
                    $cacheBaseDir = __DIR__.'/../../app/cache/twig/profiler/';
286
                } else {
287 459
                    $cacheBaseDir = __DIR__.'/../../app/cache/twig/production/';
288
                }
289
290 459
                if ($app->isAdminRequest()) {
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class Silex\Application as the method isAdminRequest() does only exist in the following sub-classes of Silex\Application: Eccube\Application, Eccube\Application\ApplicationTrait, Eccube\InstallApplication. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

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

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

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

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

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

Available Fixes

  1. Change the type-hint for the parameter:

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

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

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

Let’s take a look at an example:

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

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

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

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

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

Available Fixes

  1. Change the type-hint for the parameter:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Loading history...
547 1076
                    'path' => $this['config']['root_urlpath'] ?: '/',
548 1076
                    'secure' => $this['config']['force_ssl'],
549
                    'httponly' => true,
550
                    'always_remember_me' => false,
551 1076
                    'remember_me_parameter' => 'login_memory',
552
                ),
553 1076
                'users' => $this['orm.em']->getRepository('Eccube\Entity\Customer'),
554
                'anonymous' => true,
555
            ),
556
        );
557
558 1076
        $this['security.access_rules'] = array(
559 1076
            array("^/{$this['config']['admin_route']}/login", 'IS_AUTHENTICATED_ANONYMOUSLY'),
560 1076
            array("^/{$this['config']['admin_route']}/", 'ROLE_ADMIN'),
561
            array('^/mypage/login', 'IS_AUTHENTICATED_ANONYMOUSLY'),
562
            array('^/mypage/withdraw_complete', 'IS_AUTHENTICATED_ANONYMOUSLY'),
563
            array('^/mypage/change', 'IS_AUTHENTICATED_FULLY'),
564
            array('^/mypage', 'ROLE_USER'),
565
        );
566
567
        $this['eccube.password_encoder'] = $this->share(function ($app) {
568 1076
            return new \Eccube\Security\Core\Encoder\PasswordEncoder($app['config']);
569 1076
        });
570
        $this['security.encoder_factory'] = $this->share(function ($app) {
571 1076
            return new \Symfony\Component\Security\Core\Encoder\EncoderFactory(array(
572 1076
                'Eccube\Entity\Customer' => $app['eccube.password_encoder'],
573 1076
                'Eccube\Entity\Member' => $app['eccube.password_encoder'],
574
            ));
575 1076
        });
576
        $this['eccube.event_listner.security'] = $this->share(function ($app) {
577 1076
            return new \Eccube\EventListener\SecurityEventListener($app['orm.em']);
578 1076
        });
579
        $this['user'] = function ($app) {
580 1076
            $token = $app['security']->getToken();
581
582 1076
            return ($token !== null) ? $token->getUser() : null;
583
        };
584
585
        // ログイン時のイベントを設定.
586 1076
        $this['dispatcher']->addListener(\Symfony\Component\Security\Http\SecurityEvents::INTERACTIVE_LOGIN, array($this['eccube.event_listner.security'], 'onInteractiveLogin'));
587
588
        // Voterの設定
589 1076
        $app = $this;
590
        $this['authority_voter'] = $this->share(function ($app) {
591 1076
            return new \Eccube\Security\Voter\AuthorityVoter($app);
592 1076
        });
593
594
        $app['security.voters'] = $app->extend('security.voters', function ($voters) use ($app) {
595 1076
            $voters[] = $app['authority_voter'];
596
597 1076
            return $voters;
598 1076
        });
599
600
        $this['security.access_manager'] = $this->share(function ($app) {
601 1076
            return new \Symfony\Component\Security\Core\Authorization\AccessDecisionManager($app['security.voters'], 'unanimous');
602 1076
        });
603
604
    }
605
606 1076
    public function initializePlugin()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
607
    {
608 1076
        if ($this->initializedPlugin) {
609
            return;
610
        }
611
612
        // setup event dispatcher
613 1076
        $this->initPluginEventDispatcher();
614
615
        // load plugin
616 1076
        $this->loadPlugin();
617
618 1076
        $this->initializedPlugin = true;
619
    }
620
621 1076
    public function initPluginEventDispatcher()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
622
    {
623
        // EventDispatcher
624
        $this['eccube.event.dispatcher'] = $this->share(function () {
625 474
            return new EventDispatcher();
626 1076
        });
627
628 1076
        $app = $this;
629
630
        // hook point
631
        $this->on(KernelEvents::REQUEST, function (GetResponseEvent $event) use ($app) {
632 461
            if (!$event->isMasterRequest()) {
633 72
                return;
634
            }
635 461
            $hookpoint = 'eccube.event.app.before';
636 461
            $app['eccube.event.dispatcher']->dispatch($hookpoint, $event);
637 1076
        }, self::EARLY_EVENT);
638
639 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...
640 460
            if (!$event->isMasterRequest()) {
641 72
                return;
642
            }
643 458
            $route = $event->getRequest()->attributes->get('_route');
644 458
            $hookpoint = "eccube.event.controller.$route.before";
645 458
            $app['eccube.event.dispatcher']->dispatch($hookpoint, $event);
646 1076
        });
647
648 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...
649 447
            if (!$event->isMasterRequest()) {
650 72
                return;
651
            }
652 447
            $route = $event->getRequest()->attributes->get('_route');
653 447
            $hookpoint = "eccube.event.controller.$route.after";
654 447
            $app['eccube.event.dispatcher']->dispatch($hookpoint, $event);
655 1076
        });
656
657
        $this->on(KernelEvents::RESPONSE, function (FilterResponseEvent $event) use ($app) {
658 447
            if (!$event->isMasterRequest()) {
659 72
                return;
660
            }
661 447
            $hookpoint = 'eccube.event.app.after';
662 447
            $app['eccube.event.dispatcher']->dispatch($hookpoint, $event);
663 1076
        }, self::LATE_EVENT);
664
665
        $this->on(KernelEvents::TERMINATE, function (PostResponseEvent $event) use ($app) {
666 447
            $route = $event->getRequest()->attributes->get('_route');
667 447
            $hookpoint = "eccube.event.controller.$route.finish";
668 447
            $app['eccube.event.dispatcher']->dispatch($hookpoint, $event);
669 1076
        });
670
671
        $this->on(\Symfony\Component\HttpKernel\KernelEvents::RESPONSE, function (\Symfony\Component\HttpKernel\Event\FilterResponseEvent $event) use ($app) {
672 447
            if (!$event->isMasterRequest()) {
673 72
                return;
674
            }
675 447
            $route = $event->getRequest()->attributes->get('_route');
676 447
            $app['eccube.event.dispatcher']->dispatch('eccube.event.render.'.$route.'.before', $event);
677 1076
        });
678
679
        // Request Event
680 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...
681
682 460
            if (!$event->isMasterRequest()) {
683 72
                return;
684
            }
685
686 460
            $route = $event->getRequest()->attributes->get('_route');
687
688 460
            if (is_null($route)) {
689
                return;
690
            }
691
692 460
            $app['monolog']->debug('KernelEvents::REQUEST '.$route);
693
694
            // 全体
695 460
            $app['eccube.event.dispatcher']->dispatch('eccube.event.app.request', $event);
696
697 460
            if (strpos($route, 'admin') === 0) {
698
                // 管理画面
699 289
                $app['eccube.event.dispatcher']->dispatch('eccube.event.admin.request', $event);
700
            } else {
701
                // フロント画面
702 173
                $app['eccube.event.dispatcher']->dispatch('eccube.event.front.request', $event);
703
            }
704
705
            // ルーティング単位
706 460
            $app['eccube.event.dispatcher']->dispatch("eccube.event.route.{$route}.request", $event);
707
708 1076
        }, 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...
709
710
        // Controller Event
711 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...
712
713 459
            if (!$event->isMasterRequest()) {
714 72
                return;
715
            }
716
717 457
            $route = $event->getRequest()->attributes->get('_route');
718
719 457
            if (is_null($route)) {
720
                return;
721
            }
722
723 457
            $app['monolog']->debug('KernelEvents::CONTROLLER '.$route);
724
725
            // 全体
726 457
            $app['eccube.event.dispatcher']->dispatch('eccube.event.app.controller', $event);
727
728 457
            if (strpos($route, 'admin') === 0) {
729
                // 管理画面
730 287
                $app['eccube.event.dispatcher']->dispatch('eccube.event.admin.controller', $event);
731
            } else {
732
                // フロント画面
733 172
                $app['eccube.event.dispatcher']->dispatch('eccube.event.front.controller', $event);
734
            }
735
736
            // ルーティング単位
737 457
            $app['eccube.event.dispatcher']->dispatch("eccube.event.route.{$route}.controller", $event);
738 1076
        });
739
740
        // Response Event
741 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...
742 447
            if (!$event->isMasterRequest()) {
743 72
                return;
744
            }
745
746 447
            $route = $event->getRequest()->attributes->get('_route');
747
748 447
            if (is_null($route)) {
749 1
                return;
750
            }
751
752 446
            $app['monolog']->debug('KernelEvents::RESPONSE '.$route);
753
754
            // ルーティング単位
755 446
            $app['eccube.event.dispatcher']->dispatch("eccube.event.route.{$route}.response", $event);
756
757 446
            if (strpos($route, 'admin') === 0) {
758
                // 管理画面
759 282
                $app['eccube.event.dispatcher']->dispatch('eccube.event.admin.response', $event);
760
            } else {
761
                // フロント画面
762 166
                $app['eccube.event.dispatcher']->dispatch('eccube.event.front.response', $event);
763
            }
764
765
            // 全体
766 446
            $app['eccube.event.dispatcher']->dispatch('eccube.event.app.response', $event);
767 1076
        });
768
769
        // Exception Event
770 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...
771
772 20
            if (!$event->isMasterRequest()) {
773
                return;
774
            }
775
776 20
            $route = $event->getRequest()->attributes->get('_route');
777
778 20
            if (is_null($route)) {
779
                return;
780
            }
781
782 20
            $app['monolog']->debug('KernelEvents::EXCEPTION '.$route);
783
784
            // ルーティング単位
785 20
            $app['eccube.event.dispatcher']->dispatch("eccube.event.route.{$route}.exception", $event);
786
787 20
            if (strpos($route, 'admin') === 0) {
788
                // 管理画面
789 9
                $app['eccube.event.dispatcher']->dispatch('eccube.event.admin.exception', $event);
790
            } else {
791
                // フロント画面
792 11
                $app['eccube.event.dispatcher']->dispatch('eccube.event.front.exception', $event);
793
            }
794
795
            // 全体
796 20
            $app['eccube.event.dispatcher']->dispatch('eccube.event.app.exception', $event);
797 1076
        });
798
799
        // Terminate Event
800 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...
801
802 447
            $route = $event->getRequest()->attributes->get('_route');
803
804 447
            if (is_null($route)) {
805 1
                return;
806
            }
807
808 446
            $app['monolog']->debug('KernelEvents::TERMINATE '.$route);
809
810
            // ルーティング単位
811 446
            $app['eccube.event.dispatcher']->dispatch("eccube.event.route.{$route}.terminate", $event);
812
813 446
            if (strpos($route, 'admin') === 0) {
814
                // 管理画面
815 282
                $app['eccube.event.dispatcher']->dispatch('eccube.event.admin.terminate', $event);
816
            } else {
817
                // フロント画面
818 166
                $app['eccube.event.dispatcher']->dispatch('eccube.event.front.terminate', $event);
819
            }
820
821
            // 全体
822 446
            $app['eccube.event.dispatcher']->dispatch('eccube.event.app.terminate', $event);
823 1076
        });
824
    }
825
826 1076
    public function loadPlugin()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
827
    {
828
        // プラグインディレクトリを探索.
829 1076
        $basePath = $this['config']['plugin_realdir'];
830 1076
        $pluginConfigs = $this->getPluginConfigAll();
831
832
        // ハンドラ優先順位をdbから持ってきてハッシュテーブルを作成
833 1076
        $priorities = array();
834 1076
        $handlers = $this['orm.em']
835 1076
            ->getRepository('Eccube\Entity\PluginEventHandler')
836 1076
            ->getHandlers();
837
838 1076
        foreach ($handlers as $handler) {
839 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...
840
841
                $priority = $handler->getPriority();
842
            } else {
843
                // Pluginがdisable、削除済みの場合、EventHandlerのPriorityを全て0とみなす
844 1
                $priority = \Eccube\Entity\PluginEventHandler::EVENT_PRIORITY_DISABLED;
845
            }
846 1076
            $priorities[$handler->getPlugin()->getClassName()][$handler->getEvent()][$handler->getHandler()] = $priority;
847
        }
848
849
        // プラグインをロードする.
850
        // config.yml/event.ymlの定義に沿ってインスタンスの生成を行い, イベント設定を行う.
851 1076
        foreach ($pluginConfigs as $code => $pluginConfig) {
852
            // 正しい形式の pluginConfig のみ読み込む
853 142
            $path = $basePath.'/'.$code;
854
            try {
855 142
                $this['eccube.service.plugin']->checkPluginArchiveContent($path, $pluginConfig['config']);
856
            } catch (\Eccube\Exception\PluginException $e) {
857
                $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...
858
                    'path' => $path,
859
                    'original-message' => $e->getMessage()
860
                ));
861
                continue;
862
            }
863 142
            $config = $pluginConfig['config'];
864
865 142
            $plugin = $this['orm.em']
866 142
                ->getRepository('Eccube\Entity\Plugin')
867 142
                ->findOneBy(array('code' => $config['code']));
868
869
            // const
870 142
            if (isset($config['const'])) {
871
                $this['config'] = $this->share($this->extend('config', function ($eccubeConfig) use ($config) {
872 2
                    $eccubeConfig[$config['code']] = array(
873 2
                        'const' => $config['const'],
874
                    );
875
876 2
                    return $eccubeConfig;
877 2
                }));
878
            }
879
880 142
            if ($plugin && $plugin->getEnable() == Constant::DISABLED) {
881
                // プラグインが無効化されていれば読み込まない
882 2
                continue;
883
            }
884
885
            // Type: Event
886 140
            if (isset($config['event'])) {
887 140
                $class = '\\Plugin\\'.$config['code'].'\\'.$config['event'];
888 140
                $eventExists = true;
889
890 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...
891
                    $this['monolog']->warning("Event class for plugin {$code} not exists.", array(
892
                        'class' => $class,
893
                    ));
894
                    $eventExists = false;
895
                }
896
897 140
                if ($eventExists && isset($config['event'])) {
0 ignored issues
show
Coding Style introduced by
Blank line found at start of control structure
Loading history...
898
899 140
                    $subscriber = new $class($this);
900
901 140
                    foreach ($pluginConfig['event'] as $event => $handlers) {
902 140
                        foreach ($handlers as $handler) {
903 140
                            if (!isset($priorities[$config['event']][$event][$handler[0]])) { // ハンドラテーブルに登録されていない(ソースにしか記述されていない)ハンドラは一番後ろにする
904 140
                                $priority = \Eccube\Entity\PluginEventHandler::EVENT_PRIORITY_LATEST;
905
                            } else {
906
                                $priority = $priorities[$config['event']][$event][$handler[0]];
907
                            }
908
                            // 優先度が0のプラグインは登録しない
909 140
                            if (\Eccube\Entity\PluginEventHandler::EVENT_PRIORITY_DISABLED != $priority) {
910 140
                                $this['eccube.event.dispatcher']->addListener($event, array($subscriber, $handler[0]), $priority);
911
                            }
912
                        }
913
                    }
914
                }
915
            }
916
            // Type: ServiceProvider
917 140
            if (isset($config['service'])) {
918
                foreach ($config['service'] as $service) {
919
                    $class = '\\Plugin\\'.$config['code'].'\\ServiceProvider\\'.$service;
920 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...
921
                        $this['monolog']->warning("Service provider class for plugin {$code} not exists.", array(
922
                            'class' => $class,
923
                        ));
924
                        continue;
925
                    }
926 1076
                    $this->register(new $class($this));
927
                }
928
            }
929
        }
930
    }
931
932
    /**
933
     * PHPUnit を実行中かどうかを設定する.
934
     *
935
     * @param boolean $testMode PHPUnit を実行中の場合 true
936
     */
937 1066
    public function setTestMode($testMode)
938
    {
939 1066
        $this->testMode = $testMode;
940
    }
941
942
    /**
943
     * PHPUnit を実行中かどうか.
944
     *
945
     * @return boolean PHPUnit を実行中の場合 true
946
     */
947 461
    public function isTestMode()
948
    {
949 461
        return $this->testMode;
950
    }
951
952
    /**
953
     *
954
     * データベースの接続を確認
955
     * 成功 : trueを返却
956
     * 失敗 : \Doctrine\DBAL\DBALExceptionエラーが発生( 接続に失敗した場合 )、エラー画面を表示しdie()
957
     * 備考 : app['debug']がtrueの際は処理を行わない
958
     *
959
     * @return boolean true
960
     *
961
     */
962 1076
    protected function checkDatabaseConnection()
963
    {
964 1076
        if ($this['debug']) {
965 1076
            return;
966
        }
967
        try {
968
            $this['db']->connect();
969
        } catch (\Doctrine\DBAL\DBALException $e) {
970
            $this['monolog']->error($e->getMessage());
971
            $this['twig.path'] = array(__DIR__.'/Resource/template/exception');
972
            $html = $this['twig']->render('error.twig', array(
973
                'error_title' => 'データーベース接続エラー',
974
                'error_message' => 'データーベースを確認してください',
975
            ));
976
            $response = new Response();
977
            $response->setContent($html);
978
            $response->setStatusCode('500');
979
            $response->headers->set('Content-Type', 'text/html');
980
            $response->send();
981
            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...
982
        }
983
984
        return true;
985
    }
986
987
    /**
988
     * Config ファイルをパースし、連想配列を返します.
989
     *
990
     * $config_name.yml ファイルをパースし、連想配列を返します.
991
     * $config_name.php が存在する場合は、 PHP ファイルに記述された連想配列を使用します。
992
     *
993
     * @param string $config_name Config 名称
0 ignored issues
show
introduced by
Expected 2 spaces after parameter type; 1 found
Loading history...
994
     * @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...
995
     * @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...
996
     * @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...
997
     * @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...
998
     * @return Application
999
     */
1000 1080
    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...
1001
    {
1002 1080
        $ymlPath = $ymlPath ? $ymlPath : __DIR__.'/../../app/config/eccube';
1003 1080
        $distPath = $distPath ? $distPath : __DIR__.'/../../src/Eccube/Resource/config';
1004 1080
        $config = array();
1005 1080
        $config_php = $ymlPath.'/'.$config_name.'.php';
1006 1080
        if (!file_exists($config_php)) {
1007 1080
            $config_yml = $ymlPath.'/'.$config_name.'.yml';
1008 1080
            if (file_exists($config_yml)) {
1009 1080
                $config = Yaml::parse(file_get_contents($config_yml));
1010 1080
                $config = empty($config) ? array() : $config;
1011 1080 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...
1012 1080
                    file_put_contents($config_php, sprintf('<?php return %s', var_export($config, true)).';');
1013
                }
1014
            }
1015
        } else {
1016
            $config = require $config_php;
1017
        }
1018
1019 1080
        $config_dist = array();
1020 1080
        $config_php_dist = $distPath.'/'.$config_name.'.dist.php';
1021 1080
        if (!file_exists($config_php_dist)) {
1022 1080
            $config_yml_dist = $distPath.'/'.$config_name.'.yml.dist';
1023 1080
            if (file_exists($config_yml_dist)) {
1024 1080
                $config_dist = Yaml::parse(file_get_contents($config_yml_dist));
1025 1080 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...
1026 1080
                    file_put_contents($config_php_dist, sprintf('<?php return %s', var_export($config_dist, true)).';');
1027
                }
1028
            }
1029
        } else {
1030
            $config_dist = require $config_php_dist;
1031
        }
1032
1033 1080
        if ($wrap_key) {
1034 1080
            $configAll = array_replace_recursive($configAll, array($config_name => $config_dist), array($config_name => $config));
1035
        } else {
1036 1080
            $configAll = array_replace_recursive($configAll, $config_dist, $config);
1037
        }
1038
1039 1080
        return $this;
1040
    }
1041
1042
    /**
1043
     * セッションが開始されているかどうか.
1044
     *
1045
     * @return boolean セッションが開始済みの場合 true
1046
     * @link http://php.net/manual/ja/function.session-status.php#113468
1047
     */
1048 1076
    protected function isSessionStarted()
1049
    {
1050 1076
        if (php_sapi_name() !== 'cli') {
1051 1076
            if (version_compare(phpversion(), '5.4.0', '>=')) {
1052 1076
                return session_status() === PHP_SESSION_ACTIVE ? true : false;
1053
            } else {
1054
                return session_id() === '' ? false : true;
1055
            }
1056
        }
1057
1058
        return false;
1059
    }
1060
1061
    /**
1062
     * Http Cache対応
1063
     */
1064 1076
    protected function initCacheRequest()
1065
    {
1066
        // httpキャッシュが無効の場合はイベント設定を行わない.
1067 1076
        if (!$this['config']['http_cache']['enabled']) {
1068 1076
            return;
1069
        }
1070
1071
        $app = $this;
1072
1073
        // Response Event(http cache対応、event実行は一番遅く設定)
1074
        $this->on(\Symfony\Component\HttpKernel\KernelEvents::RESPONSE, function (\Symfony\Component\HttpKernel\Event\FilterResponseEvent $event) use ($app) {
1075
1076
            if (!$event->isMasterRequest()) {
1077
                return;
1078
            }
1079
1080
            $request = $event->getRequest();
1081
            $response = $event->getResponse();
1082
1083
            $route = $request->attributes->get('_route');
1084
1085
            $etag = md5($response->getContent());
1086
1087
            if (strpos($route, 'admin') === 0) {
1088
                // 管理画面
1089
1090
                // 管理画面ではコンテンツの中身が変更された時点でキャッシュを更新し、キャッシュの適用範囲はprivateに設定
1091
                $response->setCache(array(
1092
                    'etag' => $etag,
1093
                    'private' => true,
1094
                ));
1095
1096
                if ($response->isNotModified($request)) {
1097
                    return $response;
1098
                }
1099
0 ignored issues
show
Coding Style introduced by
Blank line found at end of control structure
Loading history...
1100
            } else {
1101
                // フロント画面
1102
                $cacheRoute = $app['config']['http_cache']['route'];
1103
1104
                if (in_array($route, $cacheRoute) === true) {
1105
                    // キャッシュ対象となる画面lが含まれていた場合、キャッシュ化
1106
                    // max-ageを設定しているためExpiresは不要
1107
                    // Last-Modifiedだと比較する項目がないためETagで対応
1108
                    // max-ageを設定していた場合、contentの中身が変更されても変更されない
1109
1110
                    $age = $app['config']['http_cache']['age'];
1111
1112
                    $response->setCache(array(
1113
                        'etag' => $etag,
1114
                        'max_age' => $age,
1115
                        's_maxage' => $age,
1116
                        'public' => true,
1117
                    ));
1118
1119
                    if ($response->isNotModified($request)) {
1120
                        return $response;
1121
                    }
1122
                }
1123
            }
1124
1125
        }, -1024);
1126
    }
1127
1128
    /**
1129
     * すべてのプラグインの設定情報を返す.
1130
     *
1131
     * すべてのプラグインの config.yml 及び event.yml を読み込み、連想配列で返す.
1132
     * キャッシュファイルが存在する場合は、キャッシュを利用する.
1133
     * キャッシュファイルが存在しない場合は、キャッシュを生成する.
1134
     * $app['debug'] = true の場合は、キャッシュを利用しない.
1135
     *
1136
     * @return array
1137
     */
1138 1076
    public function getPluginConfigAll()
0 ignored issues
show
introduced by
Declare public methods first, then protected ones and finally private ones
Loading history...
1139
    {
1140 1076
        if ($this['debug']) {
1141 1076
            return $this->parsePluginConfigs();
1142
        }
1143 1
        $pluginConfigCache = $this->getPluginConfigCacheFile();
1144 1
        if (file_exists($pluginConfigCache)) {
1145 1
            return require $pluginConfigCache;
1146
        }
1147 1
        if ($this->writePluginConfigCache($pluginConfigCache) === false) {
1148
            return $this->parsePluginConfigs();
1149
        } else {
1150 1
            return require $pluginConfigCache;
1151
        }
1152
    }
1153
1154
    /**
1155
     * プラグイン設定情報のキャッシュを書き込む.
1156
     *
1157
     * @param string $cacheFile
1158
     * @return int|boolean file_put_contents() の結果
1159
     */
1160 6
    public function writePluginConfigCache($cacheFile = null)
1161
    {
1162 6
        if (is_null($cacheFile)) {
1163 6
            $cacheFile = $this->getPluginConfigCacheFile();
1164
        }
1165 6
        $pluginConfigs = $this->parsePluginConfigs();
1166 6
        if (!file_exists($this['config']['plugin_temp_realdir'])) {
1167
            @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...
1168
        }
1169 6
        $this['monolog']->debug("write plugin config cache", array($pluginConfigs));
1170 6
        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...
1171
    }
1172
1173
    /**
1174
     * プラグイン設定情報のキャッシュファイルを削除する.
1175
     *
1176
     * @return boolean
1177
     */
1178 9
    public function removePluginConfigCache()
1179
    {
1180 9
        $cacheFile = $this->getPluginConfigCacheFile();
1181 9
        if (file_exists($cacheFile)) {
1182 8
            $this['monolog']->debug("remove plugin config cache");
1183 8
            return unlink($cacheFile);
0 ignored issues
show
introduced by
Missing blank line before return statement
Loading history...
1184
        }
1185 5
        return false;
0 ignored issues
show
introduced by
Missing blank line before return statement
Loading history...
1186
    }
1187
1188
    /**
1189
     * プラグイン設定情報のキャッシュファイルパスを返す.
1190
     *
1191
     * @return string
1192
     */
1193 9
    public function getPluginConfigCacheFile()
1194
    {
1195 9
        return $this['config']['plugin_temp_realdir'].'/config_cache.php';
1196
    }
1197
1198
    /**
1199
     * プラグイン設定情報をパースし, 連想配列で返す.
1200
     *
1201
     * すべてのプラグインを探索し、 config.yml 及び event.yml をパースする.
1202
     * パースした情報を連想配列で返す.
1203
     *
1204
     * @return array
1205
     */
1206 1076
    public function parsePluginConfigs()
1207
    {
1208
1209 1076
        $finder = Finder::create()
1210 1076
            ->in($this['config']['plugin_realdir'])
1211 1076
            ->directories()
1212 1076
            ->depth(0);
1213 1076
        $finder->sortByName();
1214
1215 1076
        $pluginConfigs = array();
1216 1076
        foreach ($finder as $dir) {
1217 146
            $code = $dir->getBaseName();
1218 146
            if (!$code) {
1219
                //PHP5.3のgetBaseNameバグ対応
1220
                if (PHP_VERSION_ID < 50400) {
1221
                    $code = $dir->getFilename();
1222
                }
1223
            }
1224 146
            $file = $dir->getRealPath().'/config.yml';
1225 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...
1226 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...
1227 146
                $config = Yaml::parse(file_get_contents($file));
1228
            } else {
1229
                $this['monolog']->warning("skip {$code} orm.path loading. config.yml not found.", array('path' => $file));
1230
                continue;
1231
            }
1232
1233 146
            $file = $dir->getRealPath().'/event.yml';
1234 146
            $event = null;
1235 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...
1236 142
                $event = Yaml::parse(file_get_contents($file));
1237
            } else {
1238 4
                $this['monolog']->info("skip {$code} event.yml not found.", array('path' => $file));
1239
            }
1240 146
            if (!is_null($config)) {
1241 146
                $pluginConfigs[$code] = array(
0 ignored issues
show
introduced by
Add a comma after each item in a multi-line array
Loading history...
1242 146
                    'config' => $config,
1243 146
                    'event' => $event
1244
                );
1245 1076
                $this['monolog']->debug("parse {$code} config", array($code => $pluginConfigs[$code]));
1246
            }
1247
        }
1248
1249 1076
        return $pluginConfigs;
1250
    }
1251
}
1252