Failed Conditions
Push — master ( 9ed6ac...d1d972 )
by chihiro
493:16 queued 481:52
created

Application::isBooted()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

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