Failed Conditions
Pull Request — master (#2073)
by
unknown
55:18 queued 18:53
created

Application::__clone()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 4
ccs 0
cts 2
cp 0
rs 10
cc 1
eloc 2
nc 1
nop 0
crap 2
1
<?php
2
/*
3
 * This file is part of EC-CUBE
4
 *
5
 * Copyright(c) 2000-2015 LOCKON CO.,LTD. All Rights Reserved.
6
 *
7
 * http://www.lockon.co.jp/
8
 *
9
 * This program is free software; you can redistribute it and/or
10
 * modify it under the terms of the GNU General Public License
11
 * as published by the Free Software Foundation; either version 2
12
 * of the License, or (at your option) any later version.
13
 *
14
 * This program is distributed in the hope that it will be useful,
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
 * GNU General Public License for more details.
18
 *
19
 * You should have received a copy of the GNU General Public License
20
 * along with this program; if not, write to the Free Software
21
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22
 */
23
24
namespace Eccube;
25
26
use Binfo\Silex\MobileDetectServiceProvider;
27
use Eccube\Application\ApplicationTrait;
28
use Eccube\Common\Constant;
29
use Eccube\Doctrine\ORM\Mapping\Driver\YamlDriver;
30
use Eccube\EventListener\TransactionListener;
31
use Symfony\Component\EventDispatcher\EventDispatcher;
32
use Symfony\Component\Finder\Finder;
33
use Symfony\Component\HttpFoundation\Request;
34
use Symfony\Component\HttpFoundation\Response;
35
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
36
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
37
use Symfony\Component\HttpKernel\Event\PostResponseEvent;
38
use Symfony\Component\HttpKernel\KernelEvents;
39
use Symfony\Component\Yaml\Yaml;
40
41
class Application extends ApplicationTrait
0 ignored issues
show
introduced by
Missing class doc comment
Loading history...
42
{
43
    protected static $instance;
44
45
    protected $initialized = false;
46
    protected $initializedPlugin = false;
47
    protected $testMode = false;
48
49 1130
    public static function getInstance(array $values = array())
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
50
    {
51 1130
        if (!is_object(self::$instance)) {
52 1123
            self::$instance = new Application($values);
53
        }
54
55 1130
        return self::$instance;
56
    }
57
58 1124
    public static function clearInstance()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
59
    {
60 1124
        self::$instance = null;
61
    }
62
63
    final public function __clone()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
64
    {
65
        throw new \Exception('Clone is not allowed against '.get_class($this));
66
    }
67
68 1128
    public function __construct(array $values = array())
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
69
    {
70 1128
        parent::__construct($values);
71
72 1128
        if (is_null(self::$instance)) {
73 1124
            self::$instance = $this;
74
        }
75
76
        // load config
77 1128
        $this->initConfig();
78
79
        // init monolog
80 1128
        $this->initLogger();
81
    }
82
83
    /**
84
     * Application::runが実行されているか親クラスのプロパティから判定
85
     *
86
     * @return bool
87
     */
88 1129
    public function isBooted()
89
    {
90 1129
        return $this->booted;
91
    }
92
93 1128
    public function initConfig()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
94
    {
95
        // load config
96 1128
        $app = $this;
97
        $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...
98 1128
            $configAll = array();
99 1128
            $app->parseConfig('constant', $configAll)
100 1128
                ->parseConfig('path', $configAll)
101 1128
                ->parseConfig('config', $configAll)
102 1128
                ->parseConfig('database', $configAll)
103 1128
                ->parseConfig('mail', $configAll)
104 1128
                ->parseConfig('log', $configAll)
105 1128
                ->parseConfig('nav', $configAll, true)
106 1128
                ->parseConfig('doctrine_cache', $configAll)
107 1128
                ->parseConfig('http_cache', $configAll)
108 1128
                ->parseConfig('session_handler', $configAll);
109
110 1128
            return $configAll;
111 1128
        });
112
    }
113
114 1130
    public function initLogger()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
115
    {
116 1130
        $app = $this;
117 1130
        $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...
118
    }
119
120 1127
    public function initialize()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
121
    {
122 1127
        if ($this->initialized) {
123 4
            return;
124
        }
125
126
        // init locale
127 1124
        $this->initLocale();
128
129
        // init session
130 1124
        if (!$this->isSessionStarted()) {
131 1124
            $this->initSession();
132
        }
133
134
        // init twig
135 1124
        $this->initRendering();
136
137
        // init provider
138 1124
        $this->register(new \Silex\Provider\HttpCacheServiceProvider(), array(
139 1124
            'http_cache.cache_dir' => __DIR__.'/../../app/cache/http/',
140
        ));
141 1124
        $this->register(new \Silex\Provider\HttpFragmentServiceProvider());
142 1124
        $this->register(new \Silex\Provider\UrlGeneratorServiceProvider());
143 1124
        $this->register(new \Silex\Provider\FormServiceProvider());
144 1124
        $this->register(new \Silex\Provider\SerializerServiceProvider());
145 1124
        $this->register(new \Silex\Provider\ValidatorServiceProvider());
146 1124
        $this->register(new MobileDetectServiceProvider());
147
148 1124
        $app = $this;
149
        $this->error(function (\Exception $e, $code) use ($app) {
150 18
            if ($app['debug']) {
151 18
                return;
152
            }
153
154
            switch ($code) {
155
                case 403:
156
                    $title = 'アクセスできません。';
157
                    $message = 'お探しのページはアクセスができない状況にあるか、移動もしくは削除された可能性があります。';
158
                    break;
159
                case 404:
160
                    $title = 'ページがみつかりません。';
161
                    $message = 'URLに間違いがないかご確認ください。';
162
                    break;
163
                default:
164
                    $title = 'システムエラーが発生しました。';
165
                    $message = '大変お手数ですが、サイト管理者までご連絡ください。';
166
                    break;
167
            }
168
169
            return $app->render('error.twig', array(
170
                'error_title' => $title,
171
                'error_message' => $message,
172
            ));
173 1124
        });
174
175
        // init mailer
176 1124
        $this->initMailer();
177
178
        // init doctrine orm
179 1124
        $this->initDoctrine();
180
181
        // Set up the DBAL connection now to check for a proper connection to the database.
182 1124
        $this->checkDatabaseConnection();
183
184
        // init security
185 1124
        $this->initSecurity();
186
187
        // init ec-cube service provider
188 1124
        $this->register(new ServiceProvider\EccubeServiceProvider());
189
190
        // mount controllers
191 1124
        $this->register(new \Silex\Provider\ServiceControllerServiceProvider());
192 1124
        $this->mount('', new ControllerProvider\FrontControllerProvider());
193 1124
        $this->mount('/'.trim($this['config']['admin_route'], '/').'/', new ControllerProvider\AdminControllerProvider());
194 1124
        Request::enableHttpMethodParameterOverride(); // PUTやDELETEできるようにする
195
196
        // add transaction listener
197 1124
        $this['dispatcher']->addSubscriber(new TransactionListener($this));
198
199
        // init http cache
200 1124
        $this->initCacheRequest();
201
202 1124
        $this->initialized = true;
203
    }
204
205 1124
    public function initLocale()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
206
    {
207
208
        // timezone
209 1124
        if (!empty($this['config']['timezone'])) {
210 1124
            date_default_timezone_set($this['config']['timezone']);
211
        }
212
213 1124
        $this->register(new \Silex\Provider\TranslationServiceProvider(), array(
214 1124
            'locale' => $this['config']['locale'],
215 1124
            'translator.cache_dir' => $this['debug'] ? null : $this['config']['root_dir'].'/app/cache/translator',
216
        ));
217
        $this['translator'] = $this->share($this->extend('translator', function ($translator, \Silex\Application $app) {
218 767
            $translator->addLoader('yaml', new \Symfony\Component\Translation\Loader\YamlFileLoader());
219
220 767
            $file = __DIR__.'/Resource/locale/validator.'.$app['locale'].'.yml';
221 767
            if (file_exists($file)) {
222 767
                $translator->addResource('yaml', $file, $app['locale'], 'validators');
223
            }
224
225 767
            $file = __DIR__.'/Resource/locale/message.'.$app['locale'].'.yml';
226 767
            if (file_exists($file)) {
227 767
                $translator->addResource('yaml', $file, $app['locale']);
228
            }
229
230 767
            return $translator;
231 1124
        }));
232
    }
233
234 1124
    public function initSession()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
235
    {
236 1124
        $this->register(new \Silex\Provider\SessionServiceProvider(), array(
237 1124
            'session.storage.save_path' => $this['config']['root_dir'].'/app/cache/eccube/session',
238
            'session.storage.options' => array(
239 1124
                'name' => $this['config']['cookie_name'],
240 1124
                'cookie_path' => $this['config']['root_urlpath'] ?: '/',
241 1124
                'cookie_secure' => $this['config']['force_ssl'],
242 1124
                'cookie_lifetime' => $this['config']['cookie_lifetime'],
243
                'cookie_httponly' => true,
244
                // cookie_domainは指定しない
245
                // http://blog.tokumaru.org/2011/10/cookiedomain.html
246
            ),
247
        ));
248
249 1124
        $options = $this['config']['session_handler'];
250
251 1124
        if ($options['enabled']) {
252
            // @see http://silex.sensiolabs.org/doc/providers/session.html#custom-session-configurations
253
            $this['session.storage.handler'] = null;
254
            ini_set('session.save_handler', $options['save_handler']);
255
            ini_set('session.save_path', $options['save_path']);
256
        }
257
    }
258
259 1124
    public function initRendering()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
260
    {
261 1124
        $this->register(new \Silex\Provider\TwigServiceProvider(), array(
262 1124
            'twig.form.templates' => array('Form/form_layout.twig'),
263
        ));
264
        $this['twig'] = $this->share($this->extend('twig', function (\Twig_Environment $twig, \Silex\Application $app) {
265 520
            $twig->addExtension(new \Eccube\Twig\Extension\EccubeExtension($app));
266 520
            $twig->addExtension(new \Twig_Extension_StringLoader());
267
268 520
            return $twig;
269 1124
        }));
270
271
        $this->before(function (Request $request, \Silex\Application $app) {
272 509
            $app['admin'] = false;
273 509
            $app['front'] = false;
274 509
            $pathinfo = rawurldecode($request->getPathInfo());
275 509
            if (strpos($pathinfo, '/'.trim($app['config']['admin_route'], '/').'/') === 0) {
276 301
                $app['admin'] = true;
277
            } else {
278 210
                $app['front'] = true;
279
            }
280
281
            // フロント or 管理画面ごとにtwigの探索パスを切り替える.
282
            $app['twig'] = $app->share($app->extend('twig', function (\Twig_Environment $twig, \Silex\Application $app) {
283 507
                $paths = array();
284
285
                // 互換性がないのでprofiler とproduction 時のcacheを分離する
286 507
                if (isset($app['profiler'])) {
287
                    $cacheBaseDir = __DIR__.'/../../app/cache/twig/profiler/';
288
                } else {
289 507
                    $cacheBaseDir = __DIR__.'/../../app/cache/twig/production/';
290
                }
291
292 507
                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...
293 301
                    if (file_exists(__DIR__.'/../../app/template/admin')) {
294 301
                        $paths[] = __DIR__.'/../../app/template/admin';
295
                    }
296 301
                    $paths[] = $app['config']['template_admin_realdir'];
297 301
                    $paths[] = __DIR__.'/../../app/Plugin';
298 301
                    $cache = $cacheBaseDir.'admin';
299
0 ignored issues
show
Coding Style introduced by
Blank line found at end of control structure
Loading history...
300
                } else {
301 208
                    if (file_exists($app['config']['template_realdir'])) {
302 208
                        $paths[] = $app['config']['template_realdir'];
303
                    }
304 208
                    $paths[] = $app['config']['template_default_realdir'];
305 208
                    $paths[] = __DIR__.'/../../app/Plugin';
306 208
                    $cache = $cacheBaseDir.$app['config']['template_code'];
307 208
                    $app['front'] = true;
308
                }
309 507
                $twig->setCache($cache);
310 507
                $app['twig.loader']->addLoader(new \Twig_Loader_Filesystem($paths));
311
312 507
                return $twig;
313 509
            }));
314
315
            // 管理画面のIP制限チェック.
316 509
            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...
317
                // IP制限チェック
318 301
                $allowHost = $app['config']['admin_allow_host'];
319 301
                if (count($allowHost) > 0) {
320
                    if (array_search($app['request']->getClientIp(), $allowHost) === false) {
321
                        throw new \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException();
322
                    }
323
                }
324
            }
325 1124
        }, self::EARLY_EVENT);
326
327
        // twigのグローバル変数を定義.
328 1124
        $app = $this;
329
        $this->on(\Symfony\Component\HttpKernel\KernelEvents::CONTROLLER, function (\Symfony\Component\HttpKernel\Event\FilterControllerEvent $event) use ($app) {
330
            // 未ログイン時にマイページや管理画面以下にアクセスするとSubRequestで実行されるため,
331
            // $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...
332 507
            if (isset($app['twig_global_initialized']) && $app['twig_global_initialized'] === true) {
333 157
                return;
334
            }
335
            // ショップ基本情報
336 507
            $BaseInfo = $app['eccube.repository.base_info']->get();
337 507
            $app['twig']->addGlobal('BaseInfo', $BaseInfo);
338
339 507
            if ($app->isAdminRequest()) {
340
                // 管理画面
341
                // 管理画面メニュー
342 301
                $menus = array('', '', '');
343 301
                $app['twig']->addGlobal('menus', $menus);
344
345 301
                $Member = $app->user();
346 301
                if (is_object($Member)) {
347
                    // ログインしていれば管理者のロールを取得
348 295
                    $AuthorityRoles = $app['eccube.repository.authority_role']->findBy(array('Authority' => $Member->getAuthority()));
349
350 295
                    $roles = array();
351 295
                    foreach ($AuthorityRoles as $AuthorityRole) {
352
                        // 管理画面でメニュー制御するため相対パス全てをセット
353 295
                        $roles[] = $app['request']->getBaseUrl().'/'.$app['config']['admin_route'].$AuthorityRole->getDenyUrl();
354
                    }
355
356 301
                    $app['twig']->addGlobal('AuthorityRoles', $roles);
357
                }
358
0 ignored issues
show
Coding Style introduced by
Blank line found at end of control structure
Loading history...
359
            } else {
360
                // フロント画面
361 206
                $request = $event->getRequest();
362 206
                $route = $request->attributes->get('_route');
363
364
                // ユーザ作成画面
365 206
                if ($route === 'user_data') {
366 2
                    $params = $request->attributes->get('_route_params');
367 2
                    $route = $params['route'];
368
                    // プレビュー画面
369 204
                } elseif ($request->get('preview')) {
370
                    $route = 'preview';
371
                }
372
373
                try {
374 206
                    $DeviceType = $app['eccube.repository.master.device_type']
375 206
                        ->find(\Eccube\Entity\Master\DeviceType::DEVICE_TYPE_PC);
376 206
                    $PageLayout = $app['eccube.repository.page_layout']->getByUrl($DeviceType, $route);
377 103
                } catch (\Doctrine\ORM\NoResultException $e) {
378 103
                    $PageLayout = $app['eccube.repository.page_layout']->newPageLayout($DeviceType);
379
                }
380
381 206
                $app['twig']->addGlobal('PageLayout', $PageLayout);
382 206
                $app['twig']->addGlobal('title', $PageLayout->getName());
383
            }
384
385 507
            $app['twig_global_initialized'] = true;
386 1124
        });
387
    }
388
389 1124
    public function initMailer()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
390
    {
391
392
        // メール送信時の文字エンコード指定(デフォルトは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...
393 1124
        if (isset($this['config']['mail']['charset_iso_2022_jp']) && is_bool($this['config']['mail']['charset_iso_2022_jp'])) {
394 1124
            if ($this['config']['mail']['charset_iso_2022_jp'] === true) {
395
                \Swift::init(function () {
396
                    \Swift_DependencyContainer::getInstance()
397
                        ->register('mime.qpheaderencoder')
398
                        ->asAliasOf('mime.base64headerencoder');
399
                    \Swift_Preferences::getInstance()->setCharset('iso-2022-jp');
400
                });
401
            }
402
        }
403
404 1124
        $this->register(new \Silex\Provider\SwiftmailerServiceProvider());
405 1124
        $this['swiftmailer.options'] = $this['config']['mail'];
406
407 1124
        if (isset($this['config']['mail']['spool']) && is_bool($this['config']['mail']['spool'])) {
408
            $this['swiftmailer.use_spool'] = $this['config']['mail']['spool'];
409
        }
410
        // デフォルトはsmtpを使用
411 1124
        $transport = $this['config']['mail']['transport'];
412 1124
        if ($transport == 'sendmail') {
413
            $this['swiftmailer.transport'] = \Swift_SendmailTransport::newInstance();
414 1124
        } elseif ($transport == 'mail') {
415
            $this['swiftmailer.transport'] = \Swift_MailTransport::newInstance();
416
        }
417
    }
418
419 1124
    public function initDoctrine()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
420
    {
421 1124
        $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...
422
            'dbs.options' => array(
0 ignored issues
show
introduced by
Add a comma after each item in a multi-line array
Loading history...
423 1124
                'default' => $this['config']['database']
424
            )));
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...
425 1124
        $this->register(new \Saxulum\DoctrineOrmManagerRegistry\Silex\Provider\DoctrineOrmManagerRegistryProvider());
426
427
        // プラグインのmetadata定義を合わせて行う.
428 1124
        $pluginConfigs = $this->getPluginConfigAll();
429 1124
        $ormMappings = array();
430 1124
        $ormMappings[] = array(
431
            'type' => 'yml',
432
            'namespace' => 'Eccube\Entity',
433
            'path' => array(
434
                __DIR__.'/Resource/doctrine',
435
                __DIR__.'/Resource/doctrine/master',
436
            ),
437
        );
438
439 1124
        foreach ($pluginConfigs as $code) {
440 140
            $config = $code['config'];
441
            // Doctrine Extend
442 140
            if (isset($config['orm.path']) && is_array($config['orm.path'])) {
443
                $paths = array();
444
                foreach ($config['orm.path'] as $path) {
445
                    $paths[] = $this['config']['plugin_realdir'].'/'.$config['code'].$path;
446
                }
447
                $ormMappings[] = array(
448
                    'type' => 'yml',
449
                    'namespace' => 'Plugin\\'.$config['code'].'\\Entity',
450 1124
                    'path' => $paths,
451
                );
452
            }
453
        }
454
455
        $options = array(
0 ignored issues
show
introduced by
Add a comma after each item in a multi-line array
Loading history...
456 1124
            'mappings' => $ormMappings
457
        );
458
459 1124
        if (!$this['debug']) {
460 1
            $cacheDrivers = array();
461 1
            if (array_key_exists('doctrine_cache', $this['config'])) {
462 1
                $cacheDrivers = $this['config']['doctrine_cache'];
463
            }
464
465 1
            if (array_key_exists('metadata_cache', $cacheDrivers)) {
466 1
                $options['metadata_cache'] = $cacheDrivers['metadata_cache'];
467
            }
468 1
            if (array_key_exists('query_cache', $cacheDrivers)) {
469 1
                $options['query_cache'] = $cacheDrivers['query_cache'];
470
            }
471 1
            if (array_key_exists('result_cache', $cacheDrivers)) {
472 1
                $options['result_cache'] = $cacheDrivers['result_cache'];
473
            }
474 1
            if (array_key_exists('hydration_cache', $cacheDrivers)) {
475 1
                $options['hydration_cache'] = $cacheDrivers['hydration_cache'];
476
            }
477
        }
478
479 1124
        $this->register(new \Dflydev\Silex\Provider\DoctrineOrm\DoctrineOrmServiceProvider(), array(
480 1124
            'orm.proxies_dir' => __DIR__.'/../../app/cache/doctrine/proxies',
481 1124
            'orm.em.options' => $options,
482
            'orm.custom.functions.string' => array(
483
                'NORMALIZE' => 'Eccube\Doctrine\ORM\Query\Normalize',
484
            ),
485
            'orm.custom.functions.numeric' => array(
486
                'EXTRACT' => 'Eccube\Doctrine\ORM\Query\Extract',
487
            ),
488
        ));
489
490
        /**
491
         * YamlDriverのPHP7対応. Doctrine2.4で修正されれば不要.
492
         * @see https://github.com/EC-CUBE/ec-cube/issues/1338
493
         */
494 1124
        $config = $this['orm.em']->getConfiguration();
495
        /** @var $driver \Doctrine\Common\Persistence\Mapping\Driver\MappingDriverChain */
496 1124
        $chain = $config->getMetadataDriverImpl();
497
        // $ormMappingsの1要素ごとにDriverが生成されている.
498 1124
        $drivers = $chain->getDrivers();
499 1124
        foreach ($drivers as $namespace => $oldDriver) {
500
            /** @var $newDriver \Eccube\Doctrine\ORM\Mapping\Driver\YamlDriver */
501 1124
            $newDriver = new YamlDriver($oldDriver->getLocator());
502
            // 修正したDriverに差し替える. メソッド名はaddだけど実際はsetしてる.
503 1124
            $chain->addDriver($newDriver, $namespace);
504
        }
505
    }
506
507 1126
    public function initSecurity()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
508
    {
509
510
        // ロードバランサー、プロキシサーバの設定を行う
511
        // 設定 config.yml --> trusted_proxies:
512
        // リクエストヘッダーに[ X_Forwarded_Proto ]が必要です。
513 1124
        if (isset($this['config']['trusted_proxies']) && is_array($this['config']['trusted_proxies']) && !empty($this['config']['trusted_proxies'])) {
514
            var_dump($this['config']['trusted_proxies']);
0 ignored issues
show
Security Debugging Code introduced by
var_dump($this['config']['trusted_proxies']); looks like debug code. Are you sure you do not want to remove it? This might expose sensitive data.
Loading history...
515
            Request::setTrustedProxies($this['config']['trusted_proxies']);
516
        }
517
518 1124
        $this->register(new \Silex\Provider\SecurityServiceProvider());
519 1124
        $this->register(new \Silex\Provider\RememberMeServiceProvider());
520
521 1124
        $this['security.firewalls'] = array(
522
            'admin' => array(
523 1124
                'pattern' => "^/{$this['config']['admin_route']}/",
524
                'form' => array(
525 1124
                    'login_path' => "/{$this['config']['admin_route']}/login",
526 1124
                    'check_path' => "/{$this['config']['admin_route']}/login_check",
527 1124
                    'username_parameter' => 'login_id',
528 1124
                    'password_parameter' => 'password',
529
                    'with_csrf' => true,
530
                    'use_forward' => true,
531
                ),
532
                'logout' => array(
533 1124
                    'logout_path' => "/{$this['config']['admin_route']}/logout",
534 1124
                    'target_url' => "/{$this['config']['admin_route']}/",
535
                ),
536 1124
                'users' => $this['orm.em']->getRepository('Eccube\Entity\Member'),
537
                'anonymous' => true,
538 1124
            ),
539
            'customer' => array(
540 1124
                'pattern' => '^/',
541
                'form' => array(
542
                    'login_path' => '/mypage/login',
543
                    'check_path' => '/login_check',
544
                    'username_parameter' => 'login_email',
545
                    'password_parameter' => 'login_pass',
546
                    'with_csrf' => true,
547
                    'use_forward' => true,
548
                ),
549
                'logout' => array(
550
                    'logout_path' => '/logout',
551
                    'target_url' => '/',
552
                ),
553
                'remember_me' => array(
554 1124
                    'key' => sha1($this['config']['auth_magic']),
555 1124
                    'name' => $this['config']['cookie_name'].'_rememberme',
556
                    // lifetimeはデフォルトの1年間にする
557
                    // 'lifetime' => $this['config']['cookie_lifetime'],
0 ignored issues
show
Unused Code Comprehensibility introduced by
77% of this comment could be valid code. Did you maybe forget this after debugging?

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

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

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

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