Issues (3006)

Security Analysis    not enabled

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

src/Eccube/Application.php (64 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

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

Let’s take a look at an example:

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

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

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

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

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

Available Fixes

  1. Change the type-hint for the parameter:

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

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

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

Let’s take a look at an example:

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

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

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

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

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

Available Fixes

  1. Change the type-hint for the parameter:

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

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

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

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

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

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

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

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

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

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

Loading history...
393 1088
        if (isset($this['config']['mail']['charset_iso_2022_jp']) && is_bool($this['config']['mail']['charset_iso_2022_jp'])) {
394 1088
            if ($this['config']['mail']['charset_iso_2022_jp'] === true) {
395
                \Swift::init(function () {
396
                    \Swift_DependencyContainer::getInstance()
397
                        ->register('mime.qpheaderencoder')
398
                        ->asAliasOf('mime.base64headerencoder');
399
                    \Swift_Preferences::getInstance()->setCharset('iso-2022-jp');
400
                });
401
            }
402
        }
403
404 1088
        $this->register(new \Silex\Provider\SwiftmailerServiceProvider());
405 1088
        $this['swiftmailer.options'] = $this['config']['mail'];
406
407 1088
        if (isset($this['config']['mail']['spool']) && is_bool($this['config']['mail']['spool'])) {
408
            $this['swiftmailer.use_spool'] = $this['config']['mail']['spool'];
409
        }
410
        // デフォルトはsmtpを使用
411 1088
        $transport = $this['config']['mail']['transport'];
412 1088
        if ($transport == 'sendmail') {
413
            $this['swiftmailer.transport'] = \Swift_SendmailTransport::newInstance();
414 1088
        } elseif ($transport == 'mail') {
415
            $this['swiftmailer.transport'] = \Swift_MailTransport::newInstance();
416
        }
417
    }
418
419 1088
    public function initDoctrine()
0 ignored issues
show
Missing function doc comment
Loading history...
420
    {
421 1088
        $this->register(new \Silex\Provider\DoctrineServiceProvider(), array(
0 ignored issues
show
Add a comma after each item in a multi-line array
Loading history...
422
            'dbs.options' => array(
0 ignored issues
show
Add a comma after each item in a multi-line array
Loading history...
423 1088
                'default' => $this['config']['database']
424
            )));
0 ignored issues
show
This line of the multi-line function call does not seem to be indented correctly. Expected 8 spaces, but found 12.
Loading history...
425 1088
        $this->register(new \Saxulum\DoctrineOrmManagerRegistry\Silex\Provider\DoctrineOrmManagerRegistryProvider());
426
427
        // プラグインのmetadata定義を合わせて行う.
428 1088
        $pluginConfigs = $this->getPluginConfigAll();
429 1088
        $ormMappings = array();
430 1088
        $ormMappings[] = array(
431
            'type' => 'yml',
432
            'namespace' => 'Eccube\Entity',
433
            'path' => array(
434
                __DIR__.'/Resource/doctrine',
435
                __DIR__.'/Resource/doctrine/master',
436
            ),
437
        );
438
439 1088
        foreach ($pluginConfigs as $code) {
440 140
            $config = $code['config'];
441
            // Doctrine Extend
442 140
            if (isset($config['orm.path']) && is_array($config['orm.path'])) {
443
                $paths = array();
444
                foreach ($config['orm.path'] as $path) {
445
                    $paths[] = $this['config']['plugin_realdir'].'/'.$config['code'].$path;
446
                }
447
                $ormMappings[] = array(
448
                    'type' => 'yml',
449
                    'namespace' => 'Plugin\\'.$config['code'].'\\Entity',
450 1088
                    'path' => $paths,
451
                );
452
            }
453
        }
454
455
        $options = array(
0 ignored issues
show
Add a comma after each item in a multi-line array
Loading history...
456 1088
            'mappings' => $ormMappings
457
        );
458
459 1088
        if (!$this['debug']) {
460 1
            $cacheDrivers = array();
461 1
            if (array_key_exists('doctrine_cache', $this['config'])) {
462 1
                $cacheDrivers = $this['config']['doctrine_cache'];
463
            }
464
465 1
            if (array_key_exists('metadata_cache', $cacheDrivers)) {
466 1
                $options['metadata_cache'] = $cacheDrivers['metadata_cache'];
467
            }
468 1
            if (array_key_exists('query_cache', $cacheDrivers)) {
469 1
                $options['query_cache'] = $cacheDrivers['query_cache'];
470
            }
471 1
            if (array_key_exists('result_cache', $cacheDrivers)) {
472 1
                $options['result_cache'] = $cacheDrivers['result_cache'];
473
            }
474 1
            if (array_key_exists('hydration_cache', $cacheDrivers)) {
475 1
                $options['hydration_cache'] = $cacheDrivers['hydration_cache'];
476
            }
477
        }
478
479 1088
        $this->register(new \Dflydev\Silex\Provider\DoctrineOrm\DoctrineOrmServiceProvider(), array(
480 1088
            'orm.proxies_dir' => __DIR__.'/../../app/cache/doctrine/proxies',
481 1088
            'orm.em.options' => $options,
482
            'orm.custom.functions.string' => array(
483
                'NORMALIZE' => 'Eccube\Doctrine\ORM\Query\Normalize',
484
            ),
485
            'orm.custom.functions.numeric' => array(
486
                'EXTRACT' => 'Eccube\Doctrine\ORM\Query\Extract',
487
            ),
488
        ));
489
490
        /**
491
         * YamlDriverのPHP7対応. Doctrine2.4で修正されれば不要.
492
         * @see https://github.com/EC-CUBE/ec-cube/issues/1338
493
         */
494 1088
        $config = $this['orm.em']->getConfiguration();
495
        /** @var $driver \Doctrine\Common\Persistence\Mapping\Driver\MappingDriverChain */
496 1088
        $chain = $config->getMetadataDriverImpl();
497
        // $ormMappingsの1要素ごとにDriverが生成されている.
498 1088
        $drivers = $chain->getDrivers();
499 1088
        foreach ($drivers as $namespace => $oldDriver) {
500
            /** @var $newDriver \Eccube\Doctrine\ORM\Mapping\Driver\YamlDriver */
501 1088
            $newDriver = new YamlDriver($oldDriver->getLocator());
502
            // 修正したDriverに差し替える. メソッド名はaddだけど実際はsetしてる.
503 1088
            $chain->addDriver($newDriver, $namespace);
504
        }
505
    }
506
507 1090
    public function initSecurity()
0 ignored issues
show
Missing function doc comment
Loading history...
508
    {
509 1088
        $this->register(new \Silex\Provider\SecurityServiceProvider());
510 1088
        $this->register(new \Silex\Provider\RememberMeServiceProvider());
511
512 1088
        $this['security.firewalls'] = array(
513
            'admin' => array(
514 1088
                'pattern' => "^/{$this['config']['admin_route']}/",
515
                'form' => array(
516 1088
                    'login_path' => "/{$this['config']['admin_route']}/login",
517 1088
                    'check_path' => "/{$this['config']['admin_route']}/login_check",
518 1088
                    'username_parameter' => 'login_id',
519 1088
                    'password_parameter' => 'password',
520
                    'with_csrf' => true,
521
                    'use_forward' => true,
522
                ),
523
                'logout' => array(
524 1088
                    'logout_path' => "/{$this['config']['admin_route']}/logout",
525 1088
                    'target_url' => "/{$this['config']['admin_route']}/",
526
                ),
527 1088
                'users' => $this['orm.em']->getRepository('Eccube\Entity\Member'),
528
                'anonymous' => true,
529 1088
            ),
530
            'customer' => array(
531 1088
                'pattern' => '^/',
532
                'form' => array(
533
                    'login_path' => '/mypage/login',
534
                    'check_path' => '/login_check',
535
                    'username_parameter' => 'login_email',
536
                    'password_parameter' => 'login_pass',
537
                    'with_csrf' => true,
538
                    'use_forward' => true,
539
                ),
540
                'logout' => array(
541
                    'logout_path' => '/logout',
542
                    'target_url' => '/',
543
                ),
544
                'remember_me' => array(
545 1088
                    'key' => sha1($this['config']['auth_magic']),
546 1088
                    'name' => $this['config']['cookie_name'].'_rememberme',
547
                    // lifetimeはデフォルトの1年間にする
548
                    // '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...
549 1088
                    'path' => $this['config']['root_urlpath'] ?: '/',
550 1088
                    'secure' => $this['config']['force_ssl'],
551
                    'httponly' => true,
552
                    'always_remember_me' => false,
553 1088
                    'remember_me_parameter' => 'login_memory',
554
                ),
555 1088
                'users' => $this['orm.em']->getRepository('Eccube\Entity\Customer'),
556
                'anonymous' => true,
557
            ),
558
        );
559
560 1088
        $channel = null;
561
        // 強制SSL
562 1088
        if ($this['config']['force_ssl'] == \Eccube\Common\Constant::ENABLED) {
563
            $channel = "https";
564
        }
565
566 1088
        $this['security.access_rules'] = array(
567 1088
            array("^/{$this['config']['admin_route']}/login", 'IS_AUTHENTICATED_ANONYMOUSLY', $channel),
568 1088
            array("^/{$this['config']['admin_route']}/", 'ROLE_ADMIN', $channel),
569 1088
            array('^/mypage/login', 'IS_AUTHENTICATED_ANONYMOUSLY', $channel),
570 1088
            array('^/mypage/withdraw_complete', 'IS_AUTHENTICATED_ANONYMOUSLY', $channel),
571 1088
            array('^/mypage/change', 'IS_AUTHENTICATED_FULLY', $channel),
572 1088
            array('^/mypage', 'ROLE_USER', $channel),
573
        );
574
575
        $this['eccube.password_encoder'] = $this->share(function ($app) {
576 1088
            return new \Eccube\Security\Core\Encoder\PasswordEncoder($app['config']);
577 1088
        });
578
        $this['security.encoder_factory'] = $this->share(function ($app) {
579 1088
            return new \Symfony\Component\Security\Core\Encoder\EncoderFactory(array(
580 1088
                'Eccube\Entity\Customer' => $app['eccube.password_encoder'],
581 1088
                'Eccube\Entity\Member' => $app['eccube.password_encoder'],
582
            ));
583 1088
        });
584
        $this['eccube.event_listner.security'] = $this->share(function ($app) {
585 1088
            return new \Eccube\EventListener\SecurityEventListener($app['orm.em']);
586 1088
        });
587
        $this['user'] = function ($app) {
588 1090
            $token = $app['security']->getToken();
589
590 1090
            return ($token !== null) ? $token->getUser() : null;
591
        };
592
593
        // ログイン時のイベントを設定.
594 1088
        $this['dispatcher']->addListener(\Symfony\Component\Security\Http\SecurityEvents::INTERACTIVE_LOGIN, array($this['eccube.event_listner.security'], 'onInteractiveLogin'));
595
596
        // Voterの設定
597 1088
        $app = $this;
598
        $this['authority_voter'] = $this->share(function ($app) {
599 1088
            return new \Eccube\Security\Voter\AuthorityVoter($app);
600 1088
        });
601
602
        $app['security.voters'] = $app->extend('security.voters', function ($voters) use ($app) {
603 1088
            $voters[] = $app['authority_voter'];
604
605 1088
            return $voters;
606 1088
        });
607
608
        $this['security.access_manager'] = $this->share(function ($app) {
609 1088
            return new \Symfony\Component\Security\Core\Authorization\AccessDecisionManager($app['security.voters'], 'unanimous');
610 1088
        });
611
612
    }
613
614 1088
    public function initializePlugin()
0 ignored issues
show
Missing function doc comment
Loading history...
615
    {
616 1088
        if ($this->initializedPlugin) {
617
            return;
618
        }
619
620
        // setup event dispatcher
621 1088
        $this->initPluginEventDispatcher();
622
623
        // load plugin
624 1088
        $this->loadPlugin();
625
626 1088
        $this->initializedPlugin = true;
627
    }
628
629 1088
    public function initPluginEventDispatcher()
0 ignored issues
show
Missing function doc comment
Loading history...
630
    {
631
        // EventDispatcher
632
        $this['eccube.event.dispatcher'] = $this->share(function () {
633 486
            return new EventDispatcher();
634 1088
        });
635
636 1088
        $app = $this;
637
638
        // hook point
639
        $this->on(KernelEvents::REQUEST, function (GetResponseEvent $event) use ($app) {
640 473
            if (!$event->isMasterRequest()) {
641 71
                return;
642
            }
643 473
            $hookpoint = 'eccube.event.app.before';
644 473
            $app['eccube.event.dispatcher']->dispatch($hookpoint, $event);
645 1088
        }, self::EARLY_EVENT);
646
647 View Code Duplication
        $this->on(KernelEvents::REQUEST, function (GetResponseEvent $event) use ($app) {
0 ignored issues
show
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...
648 472
            if (!$event->isMasterRequest()) {
649 71
                return;
650
            }
651 470
            $route = $event->getRequest()->attributes->get('_route');
652 470
            $hookpoint = "eccube.event.controller.$route.before";
653 470
            $app['eccube.event.dispatcher']->dispatch($hookpoint, $event);
654 1088
        });
655
656 View Code Duplication
        $this->on(KernelEvents::RESPONSE, function (FilterResponseEvent $event) use ($app) {
0 ignored issues
show
This code seems to be duplicated across your project.

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

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

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

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

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

Loading history...
1244 142
                $event = Yaml::parse(file_get_contents($file));
1245
            } else {
1246 4
                $this['monolog']->info("skip {$code} event.yml not found.", array('path' => $file));
1247
            }
1248 146
            if (!is_null($config)) {
1249 146
                $pluginConfigs[$code] = array(
0 ignored issues
show
Add a comma after each item in a multi-line array
Loading history...
1250 146
                    'config' => $config,
1251 146
                    'event' => $event
1252
                );
1253 1089
                $this['monolog']->debug("parse {$code} config", array($code => $pluginConfigs[$code]));
1254
            }
1255
        }
1256
1257 1089
        return $pluginConfigs;
1258
    }
1259
}
1260