Completed
Push — master ( 69c079...087209 )
by Ryo
81:53
created

Application::initProxy()   B

Complexity

Conditions 5
Paths 3

Size

Total Lines 11
Code Lines 8

Duplication

Lines 3
Ratio 27.27 %

Code Coverage

Tests 4
CRAP Score 5

Importance

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