Completed
Pull Request — master (#1886)
by k-yamamura
261:28 queued 250:19
created

Application::initializePlugin()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 14
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 2

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 14
ccs 7
cts 7
cp 1
rs 9.4285
cc 2
eloc 6
nc 2
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 Eccube\Application\ApplicationTrait;
27
use Eccube\Common\Constant;
28
use Eccube\Doctrine\ORM\Mapping\Driver\YamlDriver;
29
use Eccube\EventListener\TransactionListener;
30
use Symfony\Component\EventDispatcher\EventDispatcher;
31
use Symfony\Component\Finder\Finder;
32
use Symfony\Component\HttpFoundation\Request;
33
use Symfony\Component\HttpFoundation\Response;
34
use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
35
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
36
use Symfony\Component\HttpKernel\Event\PostResponseEvent;
37
use Symfony\Component\HttpKernel\KernelEvents;
38
use Symfony\Component\Yaml\Yaml;
39
40
class Application extends ApplicationTrait
0 ignored issues
show
introduced by
Missing class doc comment
Loading history...
41
{
42
    protected static $instance;
43
44
    protected $initialized = false;
45
    protected $initializedPlugin = false;
46
    protected $testMode = false;
47
48 1067
    public static function getInstance(array $values = array())
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
49
    {
50 1067
        if (!is_object(self::$instance)) {
51 1066
            self::$instance = new Application($values);
52 1066
        }
53
54 1067
        return self::$instance;
55
    }
56
57 1071
    public static function clearInstance()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
58
    {
59 1071
        self::$instance = null;
60 1071
    }
61
62
    final public function __clone()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
63
    {
64
        throw new \Exception('Clone is not allowed against '.get_class($this));
65
    }
66
67 1071
    public function __construct(array $values = array())
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
68 1071
    {
69 1071
        parent::__construct($values);
70
71 1071
        if (is_null(self::$instance)) {
72 1071
            self::$instance = $this;
73 1071
        }
74
75
        // load config
76 1071
        $this->initConfig();
77
78
        // init monolog
79 1071
        $this->initLogger();
80 1071
    }
81
82
    /**
83
     * Application::runが実行されているか親クラスのプロパティから判定
84
     *
85
     * @return bool
86
     */
87 1071
    public function isBooted()
88
    {
89 1071
        return $this->booted;
90
    }
91
92 1071
    public function initConfig()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
93
    {
94
        // load config
95 1071
        $app = $this;
96
        $this['config'] = $this->share(function() use ($app) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
97 1071
            $configAll = array();
98 1071
            $app->parseConfig('constant', $configAll)
99 1071
                ->parseConfig('path', $configAll)
100 1071
                ->parseConfig('config', $configAll)
101 1071
                ->parseConfig('database', $configAll)
102 1071
                ->parseConfig('mail', $configAll)
103 1071
                ->parseConfig('log', $configAll)
104 1071
                ->parseConfig('nav', $configAll, true)
105 1071
                ->parseConfig('doctrine_cache', $configAll)
106 1071
                ->parseConfig('http_cache', $configAll)
107 1071
                ->parseConfig('session_handler', $configAll);
108
109 1071
            return $configAll;
110 1071
        });
111 1071
    }
112
113 1072
    public function initLogger()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
114
    {
115 1072
        $app = $this;
116 1072
        $this->register(new ServiceProvider\LogServiceProvider($app));
0 ignored issues
show
Unused Code introduced by
The call to LogServiceProvider::__construct() has too many arguments starting with $app.

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
117 1072
    }
118
119 1072
    public function initialize()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
120
    {
121 1071
        if ($this->initialized) {
122 1072
            return;
123
        }
124
125
        // init locale
126 1072
        $this->initLocale();
127
128
        // init session
129 1071
        if (!$this->isSessionStarted()) {
130 1072
            $this->initSession();
131 1071
        }
132
133
        // init twig
134 1071
        $this->initRendering();
135
136
        // init provider
137 1071
        $this->register(new \Silex\Provider\HttpCacheServiceProvider(), array(
138 1071
            'http_cache.cache_dir' => __DIR__.'/../../app/cache/http/',
139 1071
        ));
140 1071
        $this->register(new \Silex\Provider\HttpFragmentServiceProvider());
141 1071
        $this->register(new \Silex\Provider\UrlGeneratorServiceProvider());
142 1071
        $this->register(new \Silex\Provider\FormServiceProvider());
143 1071
        $this->register(new \Silex\Provider\SerializerServiceProvider());
144 1071
        $this->register(new \Silex\Provider\ValidatorServiceProvider());
145
146 1071
        $app = $this;
147
        $this->error(function (\Exception $e, $code) use ($app) {
148 19
            if ($app['debug']) {
149 1071
                return;
150
            }
151
152
            switch ($code) {
153 1071
                case 403:
154
                    $title = 'アクセスできません。';
155 1071
                    $message = 'お探しのページはアクセスができない状況にあるか、移動もしくは削除された可能性があります。';
156 1071
                    break;
157 1071
                case 404:
158 1071
                    $title = 'ページがみつかりません。';
159 1071
                    $message = 'URLに間違いがないかご確認ください。';
160 103
                    break;
161
                default:
162
                    $title = 'システムエラーが発生しました。';
163
                    $message = '大変お手数ですが、サイト管理者までご連絡ください。';
164
                    break;
165
            }
166
167
            return $app->render('error.twig', array(
168
                'error_title' => $title,
169
                'error_message' => $message,
170
            ));
171 1071
        });
172
173
        // init mailer
174 1071
        $this->initMailer();
175
176
        // init doctrine orm
177 1071
        $this->initDoctrine();
178
179
        // Set up the DBAL connection now to check for a proper connection to the database.
180 1071
        $this->checkDatabaseConnection();
181
182
        // init security
183 1071
        $this->initSecurity();
184
185
        // init ec-cube service provider
186 1071
        $this->register(new ServiceProvider\EccubeServiceProvider());
187
188
        // mount controllers
189 1071
        $this->register(new \Silex\Provider\ServiceControllerServiceProvider());
190 1071
        $this->mount('', new ControllerProvider\FrontControllerProvider());
191 1071
        $this->mount('/'.trim($this['config']['admin_route'], '/').'/', new ControllerProvider\AdminControllerProvider());
192 1071
        Request::enableHttpMethodParameterOverride(); // PUTやDELETEできるようにする
193
194
        // add transaction listener
195 1071
        $this['dispatcher']->addSubscriber(new TransactionListener($this));
196
197
        // init http cache
198 1071
        $this->initCacheRequest();
199
200 1071
        $this->initialized = true;
201 1071
    }
202
203 1071
    public function initLocale()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
204
    {
205
206
        // timezone
207 1071
        if (!empty($this['config']['timezone'])) {
208 1071
            date_default_timezone_set($this['config']['timezone']);
209 1071
        }
210
211 1071
        $this->register(new \Silex\Provider\TranslationServiceProvider(), array(
212 1071
            'locale' => $this['config']['locale'],
213 1071
            'translator.cache_dir' => $this['debug'] ? null : $this['config']['root_dir'].'/app/cache/translator',
214 1071
        ));
215
        $this['translator'] = $this->share($this->extend('translator', function ($translator, \Silex\Application $app) {
216 720
            $translator->addLoader('yaml', new \Symfony\Component\Translation\Loader\YamlFileLoader());
217
218 720
            $file = __DIR__.'/Resource/locale/validator.'.$app['locale'].'.yml';
219 720
            if (file_exists($file)) {
220 720
                $translator->addResource('yaml', $file, $app['locale'], 'validators');
221 720
            }
222
223 720
            $file = __DIR__.'/Resource/locale/message.'.$app['locale'].'.yml';
224 720
            if (file_exists($file)) {
225 720
                $translator->addResource('yaml', $file, $app['locale']);
226 720
            }
227
228 720
            return $translator;
229 1071
        }));
230 1071
    }
231
232 1071
    public function initSession()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
233
    {
234 1071
        $this->register(new \Silex\Provider\SessionServiceProvider(), array(
235 1071
            'session.storage.save_path' => $this['config']['root_dir'].'/app/cache/eccube/session',
236
            'session.storage.options' => array(
237 1071
                'name' => 'eccube',
238 1071
                'cookie_path' => $this['config']['root_urlpath'] ?: '/',
239 1071
                'cookie_secure' => $this['config']['force_ssl'],
240 1071
                'cookie_lifetime' => $this['config']['cookie_lifetime'],
241 1071
                'cookie_httponly' => true,
242
                // cookie_domainは指定しない
243
                // http://blog.tokumaru.org/2011/10/cookiedomain.html
244 1071
            ),
245 1071
        ));
246
247 1071
        $options = $this['config']['session_handler'];
248
249 1071
        if ($options['enabled']) {
250
            // @see http://silex.sensiolabs.org/doc/providers/session.html#custom-session-configurations
251
            $this['session.storage.handler'] = null;
252
            ini_set('session.save_handler', $options['save_handler']);
253
            ini_set('session.save_path', $options['save_path']);
254
        }
255 1071
    }
256
257 1071
    public function initRendering()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
258
    {
259 1071
        $this->register(new \Silex\Provider\TwigServiceProvider(), array(
260 1071
            'twig.form.templates' => array('Form/form_layout.twig'),
261 1071
        ));
262
        $this['twig'] = $this->share($this->extend('twig', function (\Twig_Environment $twig, \Silex\Application $app) {
263 473
            $twig->addExtension(new \Eccube\Twig\Extension\EccubeExtension($app));
264 473
            $twig->addExtension(new \Twig_Extension_StringLoader());
265
266 473
            return $twig;
267 1071
        }));
268
269
        $this->before(function (Request $request, \Silex\Application $app) {
270 461
            $app['admin'] = false;
271 461
            $app['front'] = false;
272 461
            $pathinfo = rawurldecode($request->getPathInfo());
273 461
            if (strpos($pathinfo, '/'.trim($app['config']['admin_route'], '/').'/') === 0) {
274 291
                $app['admin'] = true;
275 291
            } else {
276 172
                $app['front'] = true;
277
            }
278
279
            // フロント or 管理画面ごとにtwigの探索パスを切り替える.
280
            $app['twig'] = $app->share($app->extend('twig', function (\Twig_Environment $twig, \Silex\Application $app) {
281 459
                $paths = array();
282
283
                // 互換性がないのでprofiler とproduction 時のcacheを分離する
284 459
                if (isset($app['profiler'])) {
285
                    $cacheBaseDir = __DIR__.'/../../app/cache/twig/profiler/';
286
                } else {
287 459
                    $cacheBaseDir = __DIR__.'/../../app/cache/twig/production/';
288
                }
289
290 459
                if ($app->isAdminRequest()) {
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class Silex\Application as the method isAdminRequest() does only exist in the following sub-classes of Silex\Application: Eccube\Application, Eccube\Application\ApplicationTrait, Eccube\InstallApplication. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

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

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

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

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

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

Available Fixes

  1. Change the type-hint for the parameter:

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

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

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

Let’s take a look at an example:

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

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

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

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

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

Available Fixes

  1. Change the type-hint for the parameter:

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Loading history...
544 1071
                    'path' => $this['config']['root_urlpath'] ?: '/',
545 1071
                    'secure' => $this['config']['force_ssl'],
546 1071
                    'httponly' => true,
547 1071
                    'always_remember_me' => false,
548 1071
                    'remember_me_parameter' => 'login_memory',
549 1071
                ),
550 1071
                'users' => $this['orm.em']->getRepository('Eccube\Entity\Customer'),
551 1071
                'anonymous' => true,
552 1071
            ),
553
        );
554
555 1071
        $this['security.access_rules'] = array(
556 1071
            array("^/{$this['config']['admin_route']}/login", 'IS_AUTHENTICATED_ANONYMOUSLY'),
557 1071
            array("^/{$this['config']['admin_route']}/", 'ROLE_ADMIN'),
558 1071
            array('^/mypage/login', 'IS_AUTHENTICATED_ANONYMOUSLY'),
559 1071
            array('^/mypage/withdraw_complete', 'IS_AUTHENTICATED_ANONYMOUSLY'),
560 1071
            array('^/mypage/change', 'IS_AUTHENTICATED_FULLY'),
561 1071
            array('^/mypage', 'ROLE_USER'),
562
        );
563
564
        $this['eccube.password_encoder'] = $this->share(function ($app) {
565 1071
            return new \Eccube\Security\Core\Encoder\PasswordEncoder($app['config']);
566 1071
        });
567
        $this['security.encoder_factory'] = $this->share(function ($app) {
568 1071
            return new \Symfony\Component\Security\Core\Encoder\EncoderFactory(array(
569 1071
                'Eccube\Entity\Customer' => $app['eccube.password_encoder'],
570 1071
                'Eccube\Entity\Member' => $app['eccube.password_encoder'],
571 1071
            ));
572 1071
        });
573
        $this['eccube.event_listner.security'] = $this->share(function ($app) {
574 1071
            return new \Eccube\EventListener\SecurityEventListener($app['orm.em']);
575 1071
        });
576
        $this['user'] = function ($app) {
577 1071
            $token = $app['security']->getToken();
578
579 1071
            return ($token !== null) ? $token->getUser() : null;
580
        };
581
582
        // ログイン時のイベントを設定.
583 1071
        $this['dispatcher']->addListener(\Symfony\Component\Security\Http\SecurityEvents::INTERACTIVE_LOGIN, array($this['eccube.event_listner.security'], 'onInteractiveLogin'));
584
585
        // Voterの設定
586 1071
        $app = $this;
587
        $this['authority_voter'] = $this->share(function ($app) {
588 1071
            return new \Eccube\Security\Voter\AuthorityVoter($app);
589 1071
        });
590
591
        $app['security.voters'] = $app->extend('security.voters', function ($voters) use ($app) {
592 1071
            $voters[] = $app['authority_voter'];
593
594 1071
            return $voters;
595 1071
        });
596
597
        $this['security.access_manager'] = $this->share(function ($app) {
598 1071
            return new \Symfony\Component\Security\Core\Authorization\AccessDecisionManager($app['security.voters'], 'unanimous');
599 1071
        });
600
601 1071
    }
602
603 1071
    public function initializePlugin()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
604
    {
605 1071
        if ($this->initializedPlugin) {
606 6
            return;
607
        }
608
609
        // setup event dispatcher
610 1071
        $this->initPluginEventDispatcher();
611
612
        // load plugin
613 1071
        $this->loadPlugin();
614
615 1071
        $this->initializedPlugin = true;
616 1071
    }
617
618 1071
    public function initPluginEventDispatcher()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
619
    {
620
        // EventDispatcher
621
        $this['eccube.event.dispatcher'] = $this->share(function () {
622 475
            return new EventDispatcher();
623 1071
        });
624
625 1071
        $app = $this;
626
627
        // hook point
628
        $this->on(KernelEvents::REQUEST, function (GetResponseEvent $event) use ($app) {
629 461
            if (!$event->isMasterRequest()) {
630 72
                return;
631
            }
632 461
            $hookpoint = 'eccube.event.app.before';
633 461
            $app['eccube.event.dispatcher']->dispatch($hookpoint, $event);
634 1071
        }, self::EARLY_EVENT);
635
636 View Code Duplication
        $this->on(KernelEvents::REQUEST, function (GetResponseEvent $event) use ($app) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
637 460
            if (!$event->isMasterRequest()) {
638 72
                return;
639
            }
640 458
            $route = $event->getRequest()->attributes->get('_route');
641 458
            $hookpoint = "eccube.event.controller.$route.before";
642 458
            $app['eccube.event.dispatcher']->dispatch($hookpoint, $event);
643 1071
        });
644
645 View Code Duplication
        $this->on(KernelEvents::RESPONSE, function (FilterResponseEvent $event) use ($app) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
646 446
            if (!$event->isMasterRequest()) {
647 72
                return;
648
            }
649 446
            $route = $event->getRequest()->attributes->get('_route');
650 446
            $hookpoint = "eccube.event.controller.$route.after";
651 446
            $app['eccube.event.dispatcher']->dispatch($hookpoint, $event);
652 1071
        });
653
654
        $this->on(KernelEvents::RESPONSE, function (FilterResponseEvent $event) use ($app) {
655 446
            if (!$event->isMasterRequest()) {
656 72
                return;
657
            }
658 446
            $hookpoint = 'eccube.event.app.after';
659 446
            $app['eccube.event.dispatcher']->dispatch($hookpoint, $event);
660 1071
        }, self::LATE_EVENT);
661
662
        $this->on(KernelEvents::TERMINATE, function (PostResponseEvent $event) use ($app) {
663 446
            $route = $event->getRequest()->attributes->get('_route');
664 446
            $hookpoint = "eccube.event.controller.$route.finish";
665 446
            $app['eccube.event.dispatcher']->dispatch($hookpoint, $event);
666 1071
        });
667
668
        $this->on(\Symfony\Component\HttpKernel\KernelEvents::RESPONSE, function (\Symfony\Component\HttpKernel\Event\FilterResponseEvent $event) use ($app) {
669 446
            if (!$event->isMasterRequest()) {
670 72
                return;
671
            }
672 446
            $route = $event->getRequest()->attributes->get('_route');
673 446
            $app['eccube.event.dispatcher']->dispatch('eccube.event.render.'.$route.'.before', $event);
674 1071
        });
675
676
        // Request Event
677 View Code Duplication
        $this->on(\Symfony\Component\HttpKernel\KernelEvents::REQUEST, function (\Symfony\Component\HttpKernel\Event\GetResponseEvent $event) use ($app) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
678
679 460
            if (!$event->isMasterRequest()) {
680 72
                return;
681
            }
682
683 460
            $route = $event->getRequest()->attributes->get('_route');
684
685 460
            if (is_null($route)) {
686
                return;
687
            }
688
689 460
            $app['monolog']->debug('KernelEvents::REQUEST '.$route);
690
691
            // 全体
692 460
            $app['eccube.event.dispatcher']->dispatch('eccube.event.app.request', $event);
693
694 460
            if (strpos($route, 'admin') === 0) {
695
                // 管理画面
696 291
                $app['eccube.event.dispatcher']->dispatch('eccube.event.admin.request', $event);
697 291
            } else {
698
                // フロント画面
699 171
                $app['eccube.event.dispatcher']->dispatch('eccube.event.front.request', $event);
700
            }
701
702
            // ルーティング単位
703 460
            $app['eccube.event.dispatcher']->dispatch("eccube.event.route.{$route}.request", $event);
704
705 1071
        }, 30); // Routing(32)が解決しし, 認証判定(8)が実行される前のタイミング.
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

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

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

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

Loading history...
706
707
        // Controller Event
708 View Code Duplication
        $this->on(\Symfony\Component\HttpKernel\KernelEvents::CONTROLLER, function (\Symfony\Component\HttpKernel\Event\FilterControllerEvent $event) use ($app) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
709
710 459
            if (!$event->isMasterRequest()) {
711 72
                return;
712
            }
713
714 457
            $route = $event->getRequest()->attributes->get('_route');
715
716 457
            if (is_null($route)) {
717
                return;
718
            }
719
720 457
            $app['monolog']->debug('KernelEvents::CONTROLLER '.$route);
721
722
            // 全体
723 457
            $app['eccube.event.dispatcher']->dispatch('eccube.event.app.controller', $event);
724
725 457
            if (strpos($route, 'admin') === 0) {
726
                // 管理画面
727 289
                $app['eccube.event.dispatcher']->dispatch('eccube.event.admin.controller', $event);
728 289
            } else {
729
                // フロント画面
730 170
                $app['eccube.event.dispatcher']->dispatch('eccube.event.front.controller', $event);
731
            }
732
733
            // ルーティング単位
734 457
            $app['eccube.event.dispatcher']->dispatch("eccube.event.route.{$route}.controller", $event);
735 1071
        });
736
737
        // Response Event
738 View Code Duplication
        $this->on(\Symfony\Component\HttpKernel\KernelEvents::RESPONSE, function (\Symfony\Component\HttpKernel\Event\FilterResponseEvent $event) use ($app) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
739 446
            if (!$event->isMasterRequest()) {
740 72
                return;
741
            }
742
743 446
            $route = $event->getRequest()->attributes->get('_route');
744
745 446
            if (is_null($route)) {
746 1
                return;
747
            }
748
749 445
            $app['monolog']->debug('KernelEvents::RESPONSE '.$route);
750
751
            // ルーティング単位
752 445
            $app['eccube.event.dispatcher']->dispatch("eccube.event.route.{$route}.response", $event);
753
754 445
            if (strpos($route, 'admin') === 0) {
755
                // 管理画面
756 283
                $app['eccube.event.dispatcher']->dispatch('eccube.event.admin.response', $event);
757 283
            } else {
758
                // フロント画面
759 164
                $app['eccube.event.dispatcher']->dispatch('eccube.event.front.response', $event);
760
            }
761
762
            // 全体
763 445
            $app['eccube.event.dispatcher']->dispatch('eccube.event.app.response', $event);
764 1071
        });
765
766
        // Exception Event
767 View Code Duplication
        $this->on(\Symfony\Component\HttpKernel\KernelEvents::EXCEPTION, function (\Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent $event) use ($app) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
768
769 21
            if (!$event->isMasterRequest()) {
770
                return;
771
            }
772
773 21
            $route = $event->getRequest()->attributes->get('_route');
774
775 21
            if (is_null($route)) {
776
                return;
777
            }
778
779 21
            $app['monolog']->debug('KernelEvents::EXCEPTION '.$route);
780
781
            // ルーティング単位
782 21
            $app['eccube.event.dispatcher']->dispatch("eccube.event.route.{$route}.exception", $event);
783
784 21
            if (strpos($route, 'admin') === 0) {
785
                // 管理画面
786 10
                $app['eccube.event.dispatcher']->dispatch('eccube.event.admin.exception', $event);
787 10
            } else {
788
                // フロント画面
789 11
                $app['eccube.event.dispatcher']->dispatch('eccube.event.front.exception', $event);
790
            }
791
792
            // 全体
793 21
            $app['eccube.event.dispatcher']->dispatch('eccube.event.app.exception', $event);
794 1071
        });
795
796
        // Terminate Event
797 View Code Duplication
        $this->on(\Symfony\Component\HttpKernel\KernelEvents::TERMINATE, function (\Symfony\Component\HttpKernel\Event\PostResponseEvent $event) use ($app) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
798
799 446
            $route = $event->getRequest()->attributes->get('_route');
800
801 446
            if (is_null($route)) {
802 1
                return;
803
            }
804
805 445
            $app['monolog']->debug('KernelEvents::TERMINATE '.$route);
806
807
            // ルーティング単位
808 445
            $app['eccube.event.dispatcher']->dispatch("eccube.event.route.{$route}.terminate", $event);
809
810 445
            if (strpos($route, 'admin') === 0) {
811
                // 管理画面
812 283
                $app['eccube.event.dispatcher']->dispatch('eccube.event.admin.terminate', $event);
813 283
            } else {
814
                // フロント画面
815 164
                $app['eccube.event.dispatcher']->dispatch('eccube.event.front.terminate', $event);
816
            }
817
818
            // 全体
819 445
            $app['eccube.event.dispatcher']->dispatch('eccube.event.app.terminate', $event);
820 1071
        });
821 1071
    }
822
823 1071
    public function loadPlugin()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
824
    {
825
        // プラグインディレクトリを探索.
826 1071
        $basePath = $this['config']['plugin_realdir'];
827 1071
        $pluginConfigs = $this->getPluginConfigAll();
828
829
        // ハンドラ優先順位をdbから持ってきてハッシュテーブルを作成
830 1071
        $priorities = array();
831 1071
        $handlers = $this['orm.em']
832 1071
            ->getRepository('Eccube\Entity\PluginEventHandler')
833 1071
            ->getHandlers();
834
835 1071
        foreach ($handlers as $handler) {
836 1
            if ($handler->getPlugin()->getEnable() && !$handler->getPlugin()->getDelFlg()) {
0 ignored issues
show
Coding Style introduced by
Blank line found at start of control structure
Loading history...
837
838
                $priority = $handler->getPriority();
839
            } else {
840
                // Pluginがdisable、削除済みの場合、EventHandlerのPriorityを全て0とみなす
841 1
                $priority = \Eccube\Entity\PluginEventHandler::EVENT_PRIORITY_DISABLED;
842
            }
843 1
            $priorities[$handler->getPlugin()->getClassName()][$handler->getEvent()][$handler->getHandler()] = $priority;
844 1071
        }
845
846
        // プラグインをロードする.
847
        // config.yml/event.ymlの定義に沿ってインスタンスの生成を行い, イベント設定を行う.
848 1071
        foreach ($pluginConfigs as $code => $pluginConfig) {
849
            // 正しい形式の pluginConfig のみ読み込む
850 141
            $path = $basePath.'/'.$code;
851
            try {
852 141
                $this['eccube.service.plugin']->checkPluginArchiveContent($path, $pluginConfig['config']);
853 141
            } catch (\Eccube\Exception\PluginException $e) {
854
                $this['monolog']->warning("skip {$code} config loading. config.yml not foud or invalid.", array(
0 ignored issues
show
introduced by
Add a comma after each item in a multi-line array
Loading history...
855
                    'path' => $path,
856
                    'original-message' => $e->getMessage()
857
                ));
858
                continue;
859
            }
860 141
            $config = $pluginConfig['config'];
861
862 141
            $plugin = $this['orm.em']
863 141
                ->getRepository('Eccube\Entity\Plugin')
864 141
                ->findOneBy(array('code' => $config['code']));
865
866
            // const
867 141
            if (isset($config['const'])) {
868
                $this['config'] = $this->share($this->extend('config', function ($eccubeConfig) use ($config) {
869 2
                    $eccubeConfig[$config['code']] = array(
870 2
                        'const' => $config['const'],
871
                    );
872
873 2
                    return $eccubeConfig;
874 2
                }));
875 2
            }
876
877 141
            if ($plugin && $plugin->getEnable() == Constant::DISABLED) {
878
                // プラグインが無効化されていれば読み込まない
879 2
                continue;
880
            }
881
882
            // Type: Event
883 139
            if (isset($config['event'])) {
884 139
                $class = '\\Plugin\\'.$config['code'].'\\'.$config['event'];
885 139
                $eventExists = true;
886
887 139 View Code Duplication
                if (!class_exists($class)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
888
                    $this['monolog']->warning("skip {$code} loading. event class not foud.", array(
889
                        'class' => $class,
890
                    ));
891
                    $eventExists = false;
892
                }
893
894 139
                if ($eventExists && isset($config['event'])) {
0 ignored issues
show
Coding Style introduced by
Blank line found at start of control structure
Loading history...
895
896 139
                    $subscriber = new $class($this);
897
898 139
                    foreach ($pluginConfig['event'] as $event => $handlers) {
899 139
                        foreach ($handlers as $handler) {
900 139
                            if (!isset($priorities[$config['event']][$event][$handler[0]])) { // ハンドラテーブルに登録されていない(ソースにしか記述されていない)ハンドラは一番後ろにする
901 139
                                $priority = \Eccube\Entity\PluginEventHandler::EVENT_PRIORITY_LATEST;
902 139
                            } else {
903
                                $priority = $priorities[$config['event']][$event][$handler[0]];
904
                            }
905
                            // 優先度が0のプラグインは登録しない
906 139
                            if (\Eccube\Entity\PluginEventHandler::EVENT_PRIORITY_DISABLED != $priority) {
907 139
                                $this['eccube.event.dispatcher']->addListener($event, array($subscriber, $handler[0]), $priority);
908 139
                            }
909 139
                        }
910 139
                    }
911 139
                }
912 139
            }
913
            // Type: ServiceProvider
914 139
            if (isset($config['service'])) {
915
                foreach ($config['service'] as $service) {
916
                    $class = '\\Plugin\\'.$config['code'].'\\ServiceProvider\\'.$service;
917 View Code Duplication
                    if (!class_exists($class)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
918
                        $this['monolog']->warning("skip {$code} loading. service provider class not foud.", array(
919
                            'class' => $class,
920
                        ));
921
                        continue;
922
                    }
923
                    $this->register(new $class($this));
924
                }
925
            }
926 1071
        }
927 1071
    }
928
929
    /**
930
     * PHPUnit を実行中かどうかを設定する.
931
     *
932
     * @param boolean $testMode PHPUnit を実行中の場合 true
933
     */
934 1061
    public function setTestMode($testMode)
935
    {
936 1061
        $this->testMode = $testMode;
937 1061
    }
938
939
    /**
940
     * PHPUnit を実行中かどうか.
941
     *
942
     * @return boolean PHPUnit を実行中の場合 true
943
     */
944 461
    public function isTestMode()
945
    {
946 461
        return $this->testMode;
947
    }
948
949
    /**
950
     *
951
     * データベースの接続を確認
952
     * 成功 : trueを返却
953
     * 失敗 : \Doctrine\DBAL\DBALExceptionエラーが発生( 接続に失敗した場合 )、エラー画面を表示しdie()
954
     * 備考 : app['debug']がtrueの際は処理を行わない
955
     *
956
     * @return boolean true
957
     *
958
     */
959 1071
    protected function checkDatabaseConnection()
960
    {
961 1071
        if ($this['debug']) {
962 1067
            return;
963
        }
964
        try {
965 4
            $this['db']->connect();
966 4
        } catch (\Doctrine\DBAL\DBALException $e) {
967
            $this['monolog']->error($e->getMessage());
968
            $this['twig.path'] = array(__DIR__.'/Resource/template/exception');
969
            $html = $this['twig']->render('error.twig', array(
970
                'error_title' => 'データーベース接続エラー',
971
                'error_message' => 'データーベースを確認してください',
972
            ));
973
            $response = new Response();
974
            $response->setContent($html);
975
            $response->setStatusCode('500');
976
            $response->headers->set('Content-Type', 'text/html');
977
            $response->send();
978
            die();
0 ignored issues
show
Coding Style Compatibility introduced by
The method checkDatabaseConnection() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
979
        }
980
981 4
        return true;
982
    }
983
984
    /**
985
     * Config ファイルをパースし、連想配列を返します.
986
     *
987
     * $config_name.yml ファイルをパースし、連想配列を返します.
988
     * $config_name.php が存在する場合は、 PHP ファイルに記述された連想配列を使用します。
989
     *
990
     * @param string $config_name Config 名称
0 ignored issues
show
introduced by
Expected 2 spaces after parameter type; 1 found
Loading history...
991
     * @param array $configAll Config の連想配列
0 ignored issues
show
introduced by
Expected 3 spaces after parameter type; 1 found
Loading history...
introduced by
Expected 3 spaces after parameter name; 1 found
Loading history...
992
     * @param boolean $wrap_key Config の連想配列に config_name のキーを生成する場合 true, デフォルト false
0 ignored issues
show
introduced by
Expected 4 spaces after parameter name; 1 found
Loading history...
993
     * @param string $ymlPath config yaml を格納したディレクトリ
0 ignored issues
show
introduced by
Expected 2 spaces after parameter type; 1 found
Loading history...
introduced by
Expected 5 spaces after parameter name; 1 found
Loading history...
994
     * @param string $distPath config yaml dist を格納したディレクトリ
0 ignored issues
show
introduced by
Expected 2 spaces after parameter type; 1 found
Loading history...
introduced by
Expected 4 spaces after parameter name; 1 found
Loading history...
995
     * @return Application
996
     */
997 1071
    public function parseConfig($config_name, array &$configAll, $wrap_key = false, $ymlPath = null, $distPath = null)
0 ignored issues
show
introduced by
Declare public methods first, then protected ones and finally private ones
Loading history...
998
    {
999 1071
        $ymlPath = $ymlPath ? $ymlPath : __DIR__.'/../../app/config/eccube';
1000 1071
        $distPath = $distPath ? $distPath : __DIR__.'/../../src/Eccube/Resource/config';
1001 1071
        $config = array();
1002 1071
        $config_php = $ymlPath.'/'.$config_name.'.php';
1003 1071
        if (!file_exists($config_php)) {
1004 1071
            $config_yml = $ymlPath.'/'.$config_name.'.yml';
1005 1071
            if (file_exists($config_yml)) {
1006 1071
                $config = Yaml::parse(file_get_contents($config_yml));
1007 1071
                $config = empty($config) ? array() : $config;
1008 1071 View Code Duplication
                if (isset($this['output_config_php']) && $this['output_config_php']) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
1009
                    file_put_contents($config_php, sprintf('<?php return %s', var_export($config, true)).';');
1010
                }
1011 1071
            }
1012 1071
        } else {
1013
            $config = require $config_php;
1014
        }
1015
1016 1071
        $config_dist = array();
1017 1071
        $config_php_dist = $distPath.'/'.$config_name.'.dist.php';
1018 1071
        if (!file_exists($config_php_dist)) {
1019 1071
            $config_yml_dist = $distPath.'/'.$config_name.'.yml.dist';
1020 1071
            if (file_exists($config_yml_dist)) {
1021 1071
                $config_dist = Yaml::parse(file_get_contents($config_yml_dist));
1022 1071 View Code Duplication
                if (isset($this['output_config_php']) && $this['output_config_php']) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
1023
                    file_put_contents($config_php_dist, sprintf('<?php return %s', var_export($config_dist, true)).';');
1024
                }
1025 1071
            }
1026 1071
        } else {
1027
            $config_dist = require $config_php_dist;
1028
        }
1029
1030 1071
        if ($wrap_key) {
1031 1071
            $configAll = array_replace_recursive($configAll, array($config_name => $config_dist), array($config_name => $config));
1032 1071
        } else {
1033 1071
            $configAll = array_replace_recursive($configAll, $config_dist, $config);
1034
        }
1035
1036 1071
        return $this;
1037
    }
1038
1039
    /**
1040
     * セッションが開始されているかどうか.
1041
     *
1042
     * @return boolean セッションが開始済みの場合 true
1043
     * @link http://php.net/manual/ja/function.session-status.php#113468
1044
     */
1045 1071
    protected function isSessionStarted()
1046
    {
1047 1071
        if (php_sapi_name() !== 'cli') {
1048
            if (version_compare(phpversion(), '5.4.0', '>=')) {
1049
                return session_status() === PHP_SESSION_ACTIVE ? true : false;
1050
            } else {
1051
                return session_id() === '' ? false : true;
1052
            }
1053
        }
1054
1055 1071
        return false;
1056
    }
1057
1058
    /**
1059
     * Http Cache対応
1060
     */
1061 1071
    protected function initCacheRequest()
1062
    {
1063
        // httpキャッシュが無効の場合はイベント設定を行わない.
1064 1071
        if (!$this['config']['http_cache']['enabled']) {
1065 1071
            return;
1066
        }
1067
1068
        $app = $this;
1069
1070
        // Response Event(http cache対応、event実行は一番遅く設定)
1071
        $this->on(\Symfony\Component\HttpKernel\KernelEvents::RESPONSE, function (\Symfony\Component\HttpKernel\Event\FilterResponseEvent $event) use ($app) {
1072
1073
            if (!$event->isMasterRequest()) {
1074
                return;
1075
            }
1076
1077
            $request = $event->getRequest();
1078
            $response = $event->getResponse();
1079
1080
            $route = $request->attributes->get('_route');
1081
1082
            $etag = md5($response->getContent());
1083
1084
            if (strpos($route, 'admin') === 0) {
1085
                // 管理画面
1086
1087
                // 管理画面ではコンテンツの中身が変更された時点でキャッシュを更新し、キャッシュの適用範囲はprivateに設定
1088
                $response->setCache(array(
1089
                    'etag' => $etag,
1090
                    'private' => true,
1091
                ));
1092
1093
                if ($response->isNotModified($request)) {
1094
                    return $response;
1095
                }
1096
0 ignored issues
show
Coding Style introduced by
Blank line found at end of control structure
Loading history...
1097
            } else {
1098
                // フロント画面
1099
                $cacheRoute = $app['config']['http_cache']['route'];
1100
1101
                if (in_array($route, $cacheRoute) === true) {
1102
                    // キャッシュ対象となる画面lが含まれていた場合、キャッシュ化
1103
                    // max-ageを設定しているためExpiresは不要
1104
                    // Last-Modifiedだと比較する項目がないためETagで対応
1105
                    // max-ageを設定していた場合、contentの中身が変更されても変更されない
1106
1107
                    $age = $app['config']['http_cache']['age'];
1108
1109
                    $response->setCache(array(
1110
                        'etag' => $etag,
1111
                        'max_age' => $age,
1112
                        's_maxage' => $age,
1113
                        'public' => true,
1114
                    ));
1115
1116
                    if ($response->isNotModified($request)) {
1117
                        return $response;
1118
                    }
1119
                }
1120
            }
1121
1122
        }, -1024);
1123
    }
1124
1125
    /**
1126
     * すべてのプラグインの設定情報を返す.
1127
     *
1128
     * すべてのプラグインの config.yml 及び event.yml を読み込み、連想配列で返す.
1129
     * キャッシュファイルが存在する場合は、キャッシュを利用する.
1130
     * キャッシュファイルが存在しない場合は、キャッシュを生成する.
1131
     * $app['debug'] = true の場合は、キャッシュを利用しない.
1132
     *
1133
     * @return array
1134
     */
1135 1071
    public function getPluginConfigAll()
0 ignored issues
show
introduced by
Declare public methods first, then protected ones and finally private ones
Loading history...
1136
    {
1137 1071
        if ($this['debug']) {
1138 1067
            return $this->parsePluginConfigs();
1139
        }
1140 5
        $pluginConfigCache = $this->getPluginConfigCacheFile();
1141 5
        if (file_exists($pluginConfigCache)) {
1142 5
            return require $pluginConfigCache;
1143
        }
1144 2
        if ($this->writePluginConfigCache($pluginConfigCache) === false) {
1145
            return $this->parsePluginConfigs();
1146
        } else {
1147 2
            return require $pluginConfigCache;
1148
        }
1149
    }
1150
1151
    /**
1152
     * プラグイン設定情報のキャッシュを書き込む.
1153
     *
1154
     * @param string $cacheFile
1155
     * @return int|boolean file_put_contents() の結果
1156
     */
1157 7
    public function writePluginConfigCache($cacheFile = null)
1158
    {
1159 7
        if (is_null($cacheFile)) {
1160 6
            $cacheFile = $this->getPluginConfigCacheFile();
1161 6
        }
1162 7
        $pluginConfigs = $this->parsePluginConfigs();
1163 7
        if (!file_exists($this['config']['plugin_temp_realdir'])) {
1164 1
            @mkdir($this['config']['plugin_temp_realdir']);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
1165 1
        }
1166 7
        $this['monolog']->debug("write plugin config cache", array($pluginConfigs));
1167 7
        return file_put_contents($cacheFile, sprintf('<?php return %s', var_export($pluginConfigs, true)).';');
0 ignored issues
show
introduced by
Missing blank line before return statement
Loading history...
1168
    }
1169
1170
    /**
1171
     * プラグイン設定情報のキャッシュファイルを削除する.
1172
     *
1173
     * @return boolean
1174
     */
1175 9
    public function removePluginConfigCache()
1176
    {
1177 9
        $cacheFile = $this->getPluginConfigCacheFile();
1178 9
        if (file_exists($cacheFile)) {
1179 8
            $this['monolog']->debug("remove plugin config cache");
1180 8
            return unlink($cacheFile);
0 ignored issues
show
introduced by
Missing blank line before return statement
Loading history...
1181
        }
1182 5
        return false;
0 ignored issues
show
introduced by
Missing blank line before return statement
Loading history...
1183
    }
1184
1185
    /**
1186
     * プラグイン設定情報のキャッシュファイルパスを返す.
1187
     *
1188
     * @return string
1189
     */
1190 13
    public function getPluginConfigCacheFile()
1191
    {
1192 13
        return $this['config']['plugin_temp_realdir'].'/config_cache.php';
1193
    }
1194
1195
    /**
1196
     * プラグイン設定情報をパースし, 連想配列で返す.
1197
     *
1198
     * すべてのプラグインを探索し、 config.yml 及び event.yml をパースする.
1199
     * パースした情報を連想配列で返す.
1200
     *
1201
     * @return array
1202
     */
1203 1068
    public function parsePluginConfigs()
1204
    {
1205
1206 1068
        $finder = Finder::create()
1207 1068
            ->in($this['config']['plugin_realdir'])
1208 1068
            ->directories()
1209 1068
            ->depth(0);
1210 1068
        $finder->sortByName();
1211
1212 1068
        $pluginConfigs = array();
1213 1068
        foreach ($finder as $dir) {
1214 145
            $code = $dir->getBaseName();
1215 145
            $file = $dir->getRealPath().'/config.yml';
1216 145
            $config = null;
0 ignored issues
show
Unused Code introduced by
$config is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
1217 145 View Code Duplication
            if (file_exists($file)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
1218 145
                $config = Yaml::parse(file_get_contents($file));
1219 145
            } else {
1220
                $this['monolog']->warning("skip {$code} orm.path loading. config.yml not found.", array('path' => $file));
1221
                continue;
1222
            }
1223
1224 145
            $file = $dir->getRealPath().'/event.yml';
1225 145
            $event = null;
1226 145 View Code Duplication
            if (file_exists($file)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

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

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

Loading history...
1227 141
                $event = Yaml::parse(file_get_contents($file));
1228 141
            } else {
1229 4
                $this['monolog']->info("skip {$code} event.yml not found.", array('path' => $file));
1230
            }
1231 145
            if (!is_null($config)) {
1232 145
                $pluginConfigs[$code] = array(
0 ignored issues
show
introduced by
Add a comma after each item in a multi-line array
Loading history...
1233 145
                    'config' => $config,
1234
                    'event' => $event
1235 145
                );
1236 145
                $this['monolog']->debug("parse {$code} config", array($code => $pluginConfigs[$code]));
1237 145
            }
1238 1068
        }
1239
1240 1068
        return $pluginConfigs;
1241
    }
1242
}
1243