Failed Conditions
Push — experimental/3.1 ( 47a5a1...b65b3f )
by Yangsin
141:46 queued 135:28
created

Application::initialize()   D

Complexity

Conditions 13
Paths 3

Size

Total Lines 209
Code Lines 129

Duplication

Lines 22
Ratio 10.53 %

Code Coverage

Tests 106
CRAP Score 13.2685

Importance

Changes 0
Metric Value
cc 13
eloc 129
nc 3
nop 0
dl 22
loc 209
ccs 106
cts 120
cp 0.8833
crap 13.2685
rs 4.9922
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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 Doctrine\Common\Annotations\AnnotationReader;
27
use Doctrine\Common\Annotations\CachedReader;
28
use Doctrine\Common\Cache\ArrayCache;
29
use Doctrine\DBAL\Types\Type;
30
use Eccube\Doctrine\DBAL\Types\UTCDateTimeType;
31
use Eccube\Doctrine\DBAL\Types\UTCDateTimeTzType;
32
use Eccube\Doctrine\EventSubscriber\InitSubscriber;
33
use Eccube\Doctrine\ORM\Mapping\Driver\AnnotationDriver;
34
use Eccube\Entity\BaseInfo;
35
use Eccube\Plugin\ConfigManager as PluginConfigManager;
36
use Eccube\Routing\EccubeRouter;
37
use Eccube\ServiceProvider\CompatRepositoryProvider;
38
use Eccube\ServiceProvider\CompatServiceProvider;
39
use Eccube\ServiceProvider\DiServiceProvider;
40
use Eccube\ServiceProvider\EntityEventServiceProvider;
41
use Eccube\ServiceProvider\MobileDetectServiceProvider;
42
use Eccube\ServiceProvider\TwigLintServiceProvider;
43
use Sergiors\Silex\Routing\ChainUrlGenerator;
44
use Sergiors\Silex\Routing\ChainUrlMatcher;
45
use Symfony\Component\Dotenv\Dotenv;
46
use Symfony\Component\Finder\Finder;
47
use Symfony\Component\HttpFoundation\Request;
48
use Symfony\Component\HttpFoundation\Response;
49
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
50
use Symfony\Component\HttpKernel\KernelEvents;
51
use Symfony\Component\Yaml\Yaml;
52
53
class Application extends \Silex\Application
0 ignored issues
show
introduced by
Missing class doc comment
Loading history...
54
{
55
    use \Silex\Application\FormTrait;
56
    use \Silex\Application\UrlGeneratorTrait;
57
    use \Silex\Application\MonologTrait;
58
    use \Silex\Application\SwiftmailerTrait;
59
    use \Silex\Application\SecurityTrait;
60
    use \Silex\Application\TranslationTrait;
61
    use \Eccube\Application\ApplicationTrait;
62
    use \Eccube\Application\SecurityTrait;
63
    use \Eccube\Application\TwigTrait;
64
65
    protected static $instance;
66
67
    protected $initialized = false;
68
    protected $initializedPlugin = false;
69
    protected $testMode = false;
70
71 1101
    public static function getInstance(array $values = array())
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
72
    {
73 1101
        if (!is_object(self::$instance)) {
74 1101
            self::$instance = new Application($values);
75
        }
76
77 1101
        return self::$instance;
78
    }
79
80 1101
    public static function clearInstance()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
81
    {
82 1101
        self::$instance = null;
83
    }
84
85
    final public function __clone()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
86
    {
87
        throw new \Exception('Clone is not allowed against '.get_class($this));
88
    }
89
90 1102
    public function __construct(array $values = array())
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
91
    {
92 1102
        parent::__construct($values);
93
94 1102
        if (is_null(self::$instance)) {
95 1102
            self::$instance = $this;
96
        }
97
98
        // load config
99 1102
        $this->initConfig();
100
101
        // init monolog
102 1102
        $this->initLogger();
103
    }
104
105
    /**
106
     * Application::runが実行されているか親クラスのプロパティから判定
107
     *
108
     * @return bool
109
     */
110 1101
    public function isBooted()
111
    {
112 1101
        return $this->booted;
113
    }
114
115 1102
    public function initConfig()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
116
    {
117
        // load .env
118 1102
        $envFile = __DIR__.'/../../.env';
119 1102
        if (file_exists($envFile)) {
120
            (new Dotenv())->load($envFile);
121
        }
122
123
        // load config
124
        $this['config'] = function() {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
125 1102
            $configAll = array();
126 1102
            $this->parseConfig('constant', $configAll)
127 1102
                ->parseConfig('path', $configAll)
128 1102
                ->parseConfig('config', $configAll)
129 1102
                ->parseConfig('database', $configAll)
130 1102
                ->parseConfig('mail', $configAll)
131 1102
                ->parseConfig('log', $configAll)
132 1102
                ->parseConfig('nav', $configAll, true)
133 1102
                ->parseConfig('doctrine_cache', $configAll)
134 1102
                ->parseConfig('http_cache', $configAll)
135 1102
                ->parseConfig('session_handler', $configAll);
136
137 1102
            return $configAll;
138
        };
139
    }
140
141 1102
    public function initLogger()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
142
    {
143 1102
        $app = $this;
144 1102
        $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...
145
    }
146
147 1101
    public function initialize()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
148
    {
149 1101
        if ($this->initialized) {
150 2
            return;
151
        }
152
153
        // init locale
154 1101
        $this->initLocale();
155
156
        // init session
157 1101
        if (!$this->isSessionStarted()) {
158 1101
            $this->initSession();
159
        }
160
161
        // init twig
162 1101
        $this->initRendering();
163
164
        // init provider
165 1101
        $this->register(new \Silex\Provider\HttpCacheServiceProvider(), array(
166 1101
            'http_cache.cache_dir' => __DIR__.'/../../app/cache/http/',
167
        ));
168 1101
        $this->register(new \Silex\Provider\HttpFragmentServiceProvider());
169 1101
        $this->register(new \Silex\Provider\FormServiceProvider());
170 1101
        $this->register(new \Silex\Provider\SerializerServiceProvider());
171 1101
        $this->register(new \Silex\Provider\ValidatorServiceProvider());
172 1101
        $this->register(new \Saxulum\Validator\Provider\SaxulumValidatorProvider());
173 1101
        $this->register(new MobileDetectServiceProvider());
174 1101
        $this->register(new TwigLintServiceProvider());
175
176
        $this->error(function (\Exception $e, Request $request, $code) {
177 23
            if ($this['debug']) {
178 23
                return;
179
            }
180
181
            switch ($code) {
182
                case 403:
183
                    $title = 'アクセスできません。';
184
                    $message = 'お探しのページはアクセスができない状況にあるか、移動もしくは削除された可能性があります。';
185
                    break;
186
                case 404:
187
                    $title = 'ページがみつかりません。';
188
                    $message = 'URLに間違いがないかご確認ください。';
189
                    break;
190
                default:
191
                    $title = 'システムエラーが発生しました。';
192
                    $message = '大変お手数ですが、サイト管理者までご連絡ください。';
193
                    break;
194
            }
195
196
            return $this->render('error.twig', array(
197
                'error_title' => $title,
198
                'error_message' => $message,
199
            ));
200 1101
        });
201
202
        // init mailer
203 1101
        $this->initMailer();
204
205 1101
        $this->register(new \Sergiors\Silex\Provider\DoctrineCacheServiceProvider());
206 1101
        $this->register(new \Sergiors\Silex\Provider\AnnotationsServiceProvider(), [
0 ignored issues
show
introduced by
Add a comma after each item in a multi-line array
Loading history...
207 1101
            'annotations.debug' => $this['debug'],
208
            'annotations.options' => [
0 ignored issues
show
introduced by
Add a comma after each item in a multi-line array
Loading history...
209 1101
                'cache_driver' => $this['debug'] ? 'array' : 'filesystem',
210 1101
                'cache_dir' => $this['debug'] ? null : __DIR__.'/../../app/cache/annotation'
211
            ]
212
        ]);
213
214
        // init doctrine orm
215 1101
        $this->initDoctrine();
216
217
        // Set up the DBAL connection now to check for a proper connection to the database.
218 1101
        $this->checkDatabaseConnection();
219
220
        // init security
221 1101
        $this->initSecurity();
222
223 1101
        $this->register(new \Sergiors\Silex\Provider\RoutingServiceProvider(), [
0 ignored issues
show
introduced by
Add a comma after each item in a multi-line array
Loading history...
224 1101
            'routing.cache_dir' => $this['debug'] ? null : __DIR__.'/../../app/cache/routing'
225
        ]);
226 1101
        $this->register(new \Sergiors\Silex\Provider\TemplatingServiceProvider());
227 1101
        $this->register(new \Sergiors\Silex\Provider\SensioFrameworkExtraServiceProvider(), [
0 ignored issues
show
introduced by
Add a comma after each item in a multi-line array
Loading history...
228 1101
            'request' => [
0 ignored issues
show
introduced by
Add a comma after each item in a multi-line array
Loading history...
229
                'auto_convert' => true
230
            ]
231
        ]);
232
        // init proxy
233 1101
        $this->initProxy();
234
235
        // init ec-cube service provider
236 1101
        $this->register(new DiServiceProvider(), [
0 ignored issues
show
introduced by
Add a comma after each item in a multi-line array
Loading history...
237
            'eccube.di.dirs' => [
238 1101
                $this['config']['root_dir'].'/app/Acme/Controller',
239 1101
                $this['config']['root_dir'].'/src/Eccube/Repository',
240 1101
                $this['config']['root_dir'].'/src/Eccube/Form/Type',
241 1101
                $this['config']['root_dir'].'/src/Eccube/Form/Extension',
242 1101
                $this['config']['root_dir'].'/src/Eccube/Service',
243 1101
                $this['config']['root_dir'].'/src/Eccube/Controller',
244
            ],
245 1101
            'eccube.di.generator.dir' => $this['config']['root_dir'].'/app/cache/provider'
246
        ]);
247
248 1101
        $this->register(new CompatRepositoryProvider());
249 1101
        $this->register(new CompatServiceProvider());
250 1101
        $this->register(new ServiceProvider\EccubeServiceProvider());
251
252 1101
        $this->register(new \Silex\Provider\ServiceControllerServiceProvider());
253 1101
        Request::enableHttpMethodParameterOverride(); // PUTやDELETEできるようにする
254
255
        // ルーティングの設定
256
        // TODO EccubeRoutingServiceProviderに移植する.
257 1101
        $app = $this;
258
        $this['eccube.router'] = $this->protect(function($resoure, $cachePrefix) use ($app) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
259
            $options = [
0 ignored issues
show
introduced by
Add a comma after each item in a multi-line array
Loading history...
260 1101
                'debug' => $app['debug'],
261 1101
                'cache_dir' => $app['routing.cache_dir'],
262 1101
                'matcher_base_class' => $app['request_matcher_class'],
263 1101
                'matcher_class' => $app['request_matcher_class'],
264 1101
                'matcher_cache_class' => $cachePrefix.'UrlMatcher',
265 1101
                'generator_cache_class' => $cachePrefix.'UrlGenerator'
266
            ];
267 1101
            $router = new EccubeRouter(
268 1101
                $app['routing.loader'],
269 1101
                $resoure,
270 1101
                $options,
271 1101
                $app['request_context'],
272 1101
                $app['logger']
273
            );
274
275 1101
            $router->setAdminPrefix($app['config']['admin_route']);
276 1101
            $router->setUserDataPrefix($app['config']['user_data_route']);
277 1101
            $router->setRequireHttps($app['config']['force_ssl']);
278
279 1101
            return $router;
280 1101
        });
281
282
        $this['eccube.router.origin'] = function ($app) {
283 1101
            $resource = __DIR__.'/Controller';
284 1101
            $cachePrefix = 'Origin';
285
286 1101
            return $app['eccube.router']($resource, $cachePrefix);
287
        };
288
289
        $this['eccube.routers.plugin'] = function ($app) {
290
            // TODO 有効なプラグインを対象とする必要がある.
291 1101
            $dirs = Finder::create()
292 1101
                ->in($app['config']['root_dir'].'/app/Plugin')
293 1101
                ->name('Controller')
294 1101
                ->directories();
295
296 1101
            $routers = [];
297 1101
            foreach ($dirs as $dir) {
298 1101
                $realPath = $dir->getRealPath();
299 1101
                $pluginCode = basename(dirname($realPath));
300 1101
                $routers[] = $app['eccube.router']($realPath, 'Plugin'.$pluginCode);
301
            }
302
303 1101
            return $routers;
304
        };
305
306
        $this['eccube.router.extend'] = function ($app) {
307
            // TODO ディレクトリ名は暫定
308 1101
            $resource = $app['config']['root_dir'].'/app/Acme/Controller';
309 1101
            $cachePrefix = 'Extend';
310
311 1101
            $router = $app['eccube.router']($resource, $cachePrefix);
312
313 1101
            return $router;
314
        };
315
316 View Code Duplication
        $this->extend('request_matcher', function ($matcher, $app) {
317 1101
            $matchers = [];
318 1101
            $matchers[] = $app['eccube.router.extend'];
319 1101
            foreach ($app['eccube.routers.plugin'] as $router) {
320 1101
                $matchers[] = $router;
321
            };
322 1101
            $matchers[] = $app['eccube.router.origin'];
323 1101
            $matchers[] = $matcher;
324
325 1101
            return new ChainUrlMatcher($matchers, $app['request_context']);
326 1101
        });
327
328 View Code Duplication
        $this->extend('url_generator', function ($generator, $app) {
329 1101
            $generators = [];
330 1101
            $generators[] = $app['eccube.router.extend'];
331 1101
            foreach ($app['eccube.routers.plugin'] as $router) {
332 1101
                $generators[] = $router;
333
            };
334 1101
            $generators[] = $app['eccube.router.origin'];
335 1101
            $generators[] = $generator;
336
337 1101
            return new ChainUrlGenerator($generators, $app['request_context']);
338 1101
        });
339
340
        // Route CollectionにEC-CUBEで定義したルーティングを追加(debug tool barに出力するため)
341
        $this->extend('routes', function ($routes, $app) {
342 1101
            $routes->addCollection($app['eccube.router.extend']->getRouteCollection());
343 1101
            foreach ($app['eccube.routers.plugin'] as $router) {
344 1101
                $routes->addCollection($router->getRouteCollection());
345
            };
346 1101
            $routes->addCollection($app['eccube.router.origin']->getRouteCollection());
347
348 1101
            return $routes;
349 1101
        });
350
351
        // init http cache
352 1101
        $this->initCacheRequest();
353
354 1101
        $this->initialized = true;
355
    }
356
357 1101
    public function initLocale()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
358
    {
359
        // locale
360 1101
        if (!empty($this['config']['locale'])) {
361 1101
            \Locale::setDefault($this['config']['locale']);
362
        };
363
364
        // timezone
365 1101
        if (!empty($this['config']['timezone'])) {
366 1101
            date_default_timezone_set($this['config']['timezone']);
367
        }
368
369 1101
        $this->register(new \Silex\Provider\TranslationServiceProvider(), array(
370 1101
            'locale' => $this['config']['locale'],
371 1101
            'translator.cache_dir' => $this['debug'] ? null : $this['config']['root_dir'].'/app/cache/translator',
372
            'locale_fallbacks' => ['ja', 'en'],
373
        ));
374
        $this->extend('translator', function ($translator, \Silex\Application $app) {
375 1101
            $translator->addLoader('php', new \Symfony\Component\Translation\Loader\PhpFileLoader());
376
377 1101
            $file = __DIR__.'/Resource/locale/messages.'.$app['locale'].'.php';
378 1101
            if (file_exists($file)) {
379 1101
                $translator->addResource('php', $file, $app['locale']);
380 1101
                $translator->addResource('php', $file, $app['locale'], 'validators');
381
            }
382
383 1101
            return $translator;
384 1101
        });
385
    }
386
387 1101
    public function initSession()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
388
    {
389 1101
        $this->register(new \Silex\Provider\SessionServiceProvider(), array(
390 1101
            'session.storage.save_path' => $this['config']['root_dir'].'/app/cache/eccube/session',
391
            'session.storage.options' => array(
392 1101
                'name' => $this['config']['cookie_name'],
393 1101
                'cookie_path' => $this['config']['root_urlpath'] ?: '/',
394 1101
                'cookie_secure' => $this['config']['force_ssl'],
395 1101
                'cookie_lifetime' => $this['config']['cookie_lifetime'],
396
                'cookie_httponly' => true,
397
                // cookie_domainは指定しない
398
                // http://blog.tokumaru.org/2011/10/cookiedomain.html
399
            ),
400
        ));
401
402 1101
        $options = $this['config']['session_handler'];
403
404 1101
        if ($options['enabled']) {
405
            // @see http://silex.sensiolabs.org/doc/providers/session.html#custom-session-configurations
406
            $this['session.storage.handler'] = null;
407
            ini_set('session.save_handler', $options['save_handler']);
408
            ini_set('session.save_path', $options['save_path']);
409
        }
410
    }
411
412 1101
    public function initRendering()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
413
    {
414 1101
        $this->register(new \Silex\Provider\TwigServiceProvider(), array(
415 1101
            'twig.form.templates' => array('Form/form_layout.twig'),
416
        ));
417
        $this->extend('twig', function (\Twig_Environment $twig, \Silex\Application $app) {
418 1101
            $twig->addExtension(new \Eccube\Twig\Extension\EccubeExtension($app));
419 1101
            $twig->addExtension(new \Twig_Extension_StringLoader());
420
421 1101
            return $twig;
422 1101
        });
423
424
        $this->before(function (Request $request, \Silex\Application $app) {
425 317
            $app['admin'] = $app['front'] = false;
426 317
            $pathinfo = rawurldecode($request->getPathInfo());
427 317
            if (strpos($pathinfo, '/'.trim($app['config']['admin_route'], '/').'/') === 0) {
428 220
                $app['admin'] = true;
429
            } else {
430 97
                $app['front'] = true;
431
            }
432
433
            // フロント or 管理画面ごとにtwigの探索パスを切り替える.
434 317
            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\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...
435 220
                if (file_exists(__DIR__.'/../../app/template/admin')) {
436 220
                    $paths[] = __DIR__.'/../../app/template/admin';
0 ignored issues
show
Coding Style Comprehensibility introduced by
$paths was never initialized. Although not strictly required by PHP, it is generally a good practice to add $paths = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
437
                }
438 220
                $paths[] = $app['config']['template_admin_realdir'];
0 ignored issues
show
Bug introduced by
The variable $paths does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
439 220
                $paths[] = __DIR__.'/../../app/Plugin';
440 220
                $cacheDir =  __DIR__.'/../../app/cache/twig/admin';
441
            } else {
442
                // モバイル端末時、smartphoneディレクトリを探索パスに追加する.
443 97
                if ($app['mobile_detect.device_type'] == \Eccube\Entity\Master\DeviceType::DEVICE_TYPE_SP) {
444
                    if (file_exists(__DIR__.'/../../app/template/smartphone')) {
445
                        $paths[] = __DIR__.'/../../app/template/smartphone';
446
                    }
447
                    $paths[] = __DIR__.'/Resource/template/smartphone';
448
                }
449
450 97
                if (file_exists($app['config']['template_realdir'])) {
451 97
                    $paths[] = $app['config']['template_realdir'];
452
                }
453 97
                $paths[] = $app['config']['template_default_realdir'];
454 97
                $paths[] = __DIR__.'/../../app/Plugin';
455 97
                $cacheDir =  __DIR__.'/../../app/cache/twig/'.$app['config']['template_code'];
456
            }
457 317
            $app['twig']->setCache($app['debug'] ? null : $cacheDir);
458 317
            $app['twig.loader']->addLoader(new \Twig_Loader_Filesystem($paths));
459
460
            // 管理画面のIP制限チェック.
461 317
            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\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...
462
                // IP制限チェック
463 220
                $allowHost = $app['config']['admin_allow_host'];
464 220
                if (count($allowHost) > 0) {
465
                    if (array_search($app['request_stack']->getCurrentRequest()->getClientIp(), $allowHost) === false) {
466
                        throw new \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException();
467
                    }
468
                }
469
            }
470 1101
        }, self::EARLY_EVENT);
471
472
        // twigのグローバル変数を定義.
473
        $this->on(\Symfony\Component\HttpKernel\KernelEvents::CONTROLLER, function (\Symfony\Component\HttpKernel\Event\FilterControllerEvent $event) {
474
            // 未ログイン時にマイページや管理画面以下にアクセスするとSubRequestで実行されるため,
475
            // $event->isMasterRequest()ではなく、グローバル変数が初期化済かどうかの判定を行う
476 315
            if (isset($this['twig_global_initialized']) && $this['twig_global_initialized'] === true) {
477 71
                return;
478
            }
479
            // ショップ基本情報
480 315
            $this['twig']->addGlobal('BaseInfo', $this[BaseInfo::class]);
481
482 315
            if ($this->isAdminRequest()) {
483
                // 管理画面
484
                // 管理画面メニュー
485 220
                $menus = array('', '', '');
486 220
                $this['twig']->addGlobal('menus', $menus);
487
488 220
                $Member = $this->user();
489 220
                if (is_object($Member)) {
490
                    // ログインしていれば管理者のロールを取得
491 217
                    $AuthorityRoles = $this['eccube.repository.authority_role']->findBy(array('Authority' => $Member->getAuthority()));
492
493 217
                    $roles = array();
494 217
                    $request = $event->getRequest();
495 217
                    foreach ($AuthorityRoles as $AuthorityRole) {
496
                        // 管理画面でメニュー制御するため相対パス全てをセット
497 3
                        $roles[] = $request->getBaseUrl().'/'.$this['config']['admin_route'].$AuthorityRole->getDenyUrl();
498
                    }
499
500 220
                    $this['twig']->addGlobal('AuthorityRoles', $roles);
501
                }
502
0 ignored issues
show
Coding Style introduced by
Blank line found at end of control structure
Loading history...
503
            } else {
504
                // フロント画面
505 95
                $request = $event->getRequest();
506 95
                $route = $request->attributes->get('_route');
507
508
                // ユーザ作成画面
509 95
                if ($route === 'user_data') {
510 2
                    $params = $request->attributes->get('_route_params');
511 2
                    $route = $params['route'];
512
                    // プレビュー画面
513 93
                } elseif ($request->get('preview')) {
514
                    $route = 'preview';
515
                }
516
517
                try {
518 95
                    $device_type_id = $this['mobile_detect.device_type'];
519
520
                    // TODO デバッグ用
521 95
                    if ($request->query->has('device_type_id')) {
522
                        $device_type_id = $request->get('device_type_id', \Eccube\Entity\Master\DeviceType::DEVICE_TYPE_PC);
523
                    }
524
525 95
                    $DeviceType = $this['eccube.repository.master.device_type']
526 95
                        ->find($device_type_id);
527 95
                    $qb = $this['eccube.repository.page_layout']->createQueryBuilder('p');
528 95
                    $PageLayout = $qb->select('p, pll,l, bp, b')
529 95
                        ->leftJoin('p.PageLayoutLayouts', 'pll')
530 95
                        ->leftJoin('pll.Layout', 'l')
531 95
                        ->leftJoin('l.BlockPositions', 'bp')
532 95
                        ->leftJoin('bp.Block', 'b')
533 95
                        ->where('p.url = :route')
534 95
                        ->andWhere('l.DeviceType = :DeviceType')
535 95
                        ->orderBy('bp.block_row', 'ASC')
536 95
                        ->setParameter('route', $route)
537 95
                        ->setParameter('DeviceType', $DeviceType)
538 95
                        ->getQuery()
539 95
                        ->getSingleResult();
540 33
                } catch (\Doctrine\ORM\NoResultException $e) {
541 33
                    $PageLayout = $this['eccube.repository.page_layout']->newPageLayout($DeviceType);
0 ignored issues
show
Bug introduced by
The variable $DeviceType does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
542
                }
543
544 95
                $this['twig']->addGlobal('PageLayout', $PageLayout);
545 95
                $this['twig']->addGlobal('title', $PageLayout->getName());
546
            }
547
548 315
            $this['twig_global_initialized'] = true;
549 1101
        });
550
    }
551
552 1101
    public function initMailer()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
553
    {
554
555
        // メール送信時の文字エンコード指定(デフォルトはUTF-8)
556 1101
        if (isset($this['config']['mail']['charset_iso_2022_jp']) && is_bool($this['config']['mail']['charset_iso_2022_jp'])) {
557
            if ($this['config']['mail']['charset_iso_2022_jp'] === true) {
558
                \Swift::init(function () {
559
                    \Swift_DependencyContainer::getInstance()
560
                        ->register('mime.qpheaderencoder')
561
                        ->asAliasOf('mime.base64headerencoder');
562
                    \Swift_Preferences::getInstance()->setCharset('iso-2022-jp');
563
                });
564
            }
565
        }
566
567 1101
        $this->register(new \Silex\Provider\SwiftmailerServiceProvider());
568 1101
        $this['swiftmailer.options'] = $this['config']['mail'];
569
570 1101
        if (isset($this['config']['mail']['spool']) && is_bool($this['config']['mail']['spool'])) {
571 1101
            $this['swiftmailer.use_spool'] = $this['config']['mail']['spool'];
572
        }
573
        // デフォルトはsmtpを使用
574 1101
        $transport = $this['config']['mail']['transport'];
575 1101
        if ($transport == 'sendmail') {
576
            $this['swiftmailer.transport'] = \Swift_SendmailTransport::newInstance();
577 1101
        } elseif ($transport == 'mail') {
578
            $this['swiftmailer.transport'] = \Swift_MailTransport::newInstance();
579
        }
580
    }
581
582 1101
    public function initDoctrine()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
583
    {
584 1101
        $this->register(new EntityEventServiceProvider());
585 1101
        $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...
586
            'dbs.options' => array(
0 ignored issues
show
introduced by
Add a comma after each item in a multi-line array
Loading history...
587 1101
                'default' => $this['config']['database']
588
            )
589
        ));
590 1101
        $this->register(new \Saxulum\DoctrineOrmManagerRegistry\Provider\DoctrineOrmManagerRegistryProvider());
591
592 1101
        $app = $this;
593
        $this->extend('db.event_manager', function ($evm) use ($app) {
594 1101
            $initSubscriber = new InitSubscriber($app);
595 1101
            $evm->addEventSubscriber($initSubscriber);
596
597 1101
            return $evm;
598 1101
        });
599
600
        // UTCで保存
601
        // @see http://doctrine-orm.readthedocs.org/projects/doctrine-orm/en/latest/cookbook/working-with-datetime.html
602 1101
        UTCDateTimeType::setTimeZone($this['config']['timezone']);
603 1101
        UTCDateTimeTzType::setTimeZone($this['config']['timezone']);
604 1101
        Type::overrideType('datetime', UTCDateTimeType::class);
605 1101
        Type::overrideType('datetimetz', UTCDateTimeTzType::class);
606
607
        // プラグインのmetadata定義を合わせて行う.
608 1101
        $pluginConfigs = PluginConfigManager::getPluginConfigAll($this['debug']);
609 1101
        $ormMappings = array();
610 1101
        $ormMappings[] = array(
611
             'type' => 'annotation',
612
             'namespace' => 'Eccube\Entity',
613
             'path' => array(
0 ignored issues
show
introduced by
Add a comma after each item in a multi-line array
Loading history...
614
                 __DIR__.'/Entity'
615
             ),
616
             'use_simple_annotation_reader' => false,
617
         );
618
619
        // TODO namespace は暫定
620 1101
        $ormMappings[] = array(
621
            'type' => 'annotation',
622
            'namespace' => 'Acme\Entity',
623
            'path' => array(
624
                __DIR__.'/../../app/Acme/Entity',
625
            ),
626
            'use_simple_annotation_reader' => false,
627
        );
628
629 1101
        foreach ($pluginConfigs as $code) {
630 1101
            $config = $code['config'];
631
            // Doctrine Extend
632 1101
            if (isset($config['orm.path']) && is_array($config['orm.path'])) {
633
                $paths = array();
634 View Code Duplication
                foreach ($config['orm.path'] as $path) {
635
                    $paths[] = $this['config']['plugin_realdir'].'/'.$config['code'].$path;
636
                }
637
                $ormMappings[] = array(
638
                    'type' => 'yml',
639
                    'namespace' => 'Plugin\\'.$config['code'].'\\Entity',
640
                    'path' => $paths,
641
                );
642
                $ormMappings[] = array(
643 1101
                    'type' => 'annotation',
644
                    'namespace' => 'Plugin\\'.$config['code'].'\\Entity',
645
                    'path' => $paths,
646
                    'use_simple_annotation_reader' => false,
647
                );
648
            }
649
        }
650
651
        $options = array(
0 ignored issues
show
introduced by
Add a comma after each item in a multi-line array
Loading history...
652 1101
            'mappings' => $ormMappings
653
        );
654
655 1101
        if (!$this['debug']) {
656
            $cacheDrivers = array();
657
            if (array_key_exists('doctrine_cache', $this['config'])) {
658
                $cacheDrivers = $this['config']['doctrine_cache'];
659
            }
660
661
            if (array_key_exists('metadata_cache', $cacheDrivers)) {
662
                $options['metadata_cache'] = $cacheDrivers['metadata_cache'];
663
            }
664
            if (array_key_exists('query_cache', $cacheDrivers)) {
665
                $options['query_cache'] = $cacheDrivers['query_cache'];
666
            }
667
            if (array_key_exists('result_cache', $cacheDrivers)) {
668
                $options['result_cache'] = $cacheDrivers['result_cache'];
669
            }
670
            if (array_key_exists('hydration_cache', $cacheDrivers)) {
671
                $options['hydration_cache'] = $cacheDrivers['hydration_cache'];
672
            }
673
        }
674
675 1101
        $this->register(new \Dflydev\Provider\DoctrineOrm\DoctrineOrmServiceProvider(), array(
676 1101
            'orm.proxies_dir' => __DIR__.'/../../app/cache/doctrine/proxies',
677 1101
            'orm.em.options' => $options,
678
            'orm.custom.functions.string' => array(
679
                'NORMALIZE' => 'Eccube\Doctrine\ORM\Query\Normalize',
680
            ),
681
            'orm.custom.functions.numeric' => array(
682
                'EXTRACT' => 'Eccube\Doctrine\ORM\Query\Extract',
683
            ),
684
        ));
685
686 1101
        $this->extend(
687 1101
            'orm.em.config',
688
            function (\Doctrine\ORM\Configuration $config, \Silex\Application $app) {
689
690
                /** @var $chain \Doctrine\Common\Persistence\Mapping\Driver\MappingDriverChain */
691 1101
                $chain = $config->getMetadataDriverImpl();
692 1101
                $drivers = $chain->getDrivers();
693 1101
                foreach ($drivers as $namespace => $oldDriver) {
694 1101
                    if ('Eccube\Entity' === $namespace) {
695 1101
                        $newDriver = new AnnotationDriver(
696 1101
                            $app['annotations'],
697 1101
                            $oldDriver->getPaths());
698 1101
                        $newDriver->setFileExtension($oldDriver->getFileExtension());
699 1101
                        $newDriver->addExcludePaths($oldDriver->getExcludePaths());
700 1101
                        $newDriver->setTraitProxiesDirectory(
701 1101
                            realpath(__DIR__.'/../../app/proxy/entity'));
702 1101
                        $chain->addDriver($newDriver, $namespace);
703
                    }
704
                }
705
706 1101
                return $config;
707 1101
            }
708
        );
709
710
        $this->extend('orm.em', function (\Doctrine\ORM\EntityManager $em, \Silex\Application $app) {
711
            // save
712 1101
            $saveEventSubscriber = new \Eccube\Doctrine\EventSubscriber\SaveEventSubscriber($app);
0 ignored issues
show
Compatibility introduced by
$app of type object<Silex\Application> is not a sub-type of object<Eccube\Application>. It seems like you assume a child class of the class Silex\Application to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
713 1101
            $em->getEventManager()->addEventSubscriber($saveEventSubscriber);
714
715
            // clear cache
716 1101
            $clearCacheEventSubscriber = new \Eccube\Doctrine\EventSubscriber\ClearCacheEventSubscriber($app);
0 ignored issues
show
Compatibility introduced by
$app of type object<Silex\Application> is not a sub-type of object<Eccube\Application>. It seems like you assume a child class of the class Silex\Application to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
717 1101
            $em->getEventManager()->addEventSubscriber($clearCacheEventSubscriber);
718
719
            // filters
720 1101
            $config = $em->getConfiguration();
721 1101
            $config->addFilter("soft_delete", '\Eccube\Doctrine\Filter\SoftDeleteFilter');
722 1101
            $config->addFilter("nostock_hidden", '\Eccube\Doctrine\Filter\NoStockHiddenFilter');
723 1101
            $config->addFilter("incomplete_order_status_hidden", '\Eccube\Doctrine\Filter\OrderStatusFilter');
724 1101
            $em->getFilters()->enable('soft_delete');
725
726 1101
            return $em;
727 1101
        });
728
729 1101
        if (!$this['debug']) {
730
            // second level cacheの設定.
731
            $this->extend(
732
                'orm.em.config',
733
                function (\Doctrine\ORM\Configuration $config, \Silex\Application $app) {
0 ignored issues
show
Unused Code introduced by
The parameter $app is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
734
                    $config->setSecondLevelCacheEnabled();
735
                    $cacheConfig = $config->getSecondLevelCacheConfiguration();
736
                    $regionConfig = $cacheConfig->getRegionsConfiguration();
737
                    // TODO キャッシュ先は設定で切り替えられるように
738
                    $cache = $this['orm.cache.factory'](
739
                        'filesystem',
740
                        [
0 ignored issues
show
introduced by
Add a comma after each item in a multi-line array
Loading history...
741
                            'path' => __DIR__.'/../../app/cache/doctrine/second'
742
                        ]
743
                    );
744
                    $factory = new \Doctrine\ORM\Cache\DefaultCacheFactory($regionConfig, $cache);
745
                    $cacheConfig->setCacheFactory($factory);
746
747
                    return $config;
748
                }
749
            );
750
        }
751
    }
752
753 1101
    public function initSecurity()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
754
    {
755 1101
        $this->register(new \Silex\Provider\SecurityServiceProvider());
756 1101
        $this->register(new \Silex\Provider\CsrfServiceProvider());
757 1101
        $this->register(new \Silex\Provider\RememberMeServiceProvider());
758
759 1101
        $this['security.firewalls'] = array(
760 1101
            'admin' => array(
761 1101
                'pattern' => "^/{$this['config']['admin_route']}/",
762
                'form' => array(
763 1101
                    'login_path' => "/{$this['config']['admin_route']}/login",
764 1101
                    'check_path' => "/{$this['config']['admin_route']}/login_check",
765 1101
                    'username_parameter' => 'login_id',
766 1101
                    'password_parameter' => 'password',
767
                    'with_csrf' => true,
768
                    'use_forward' => true,
769
                ),
770
                'logout' => array(
771 1101
                    'logout_path' => "/{$this['config']['admin_route']}/logout",
772 1101
                    'target_url' => "/{$this['config']['admin_route']}/",
773
                ),
774 1101
                'users' => $this['orm.em']->getRepository('Eccube\Entity\Member'),
775
                'anonymous' => true,
776
            ),
777
            'customer' => array(
778 1101
                'pattern' => '^/',
779
                'form' => array(
780
                    'login_path' => '/mypage/login',
781
                    'check_path' => '/login_check',
782
                    'username_parameter' => 'login_email',
783
                    'password_parameter' => 'login_pass',
784
                    'with_csrf' => true,
785
                    'use_forward' => true,
786
                ),
787
                'logout' => array(
788
                    'logout_path' => '/logout',
789
                    'target_url' => '/',
790
                ),
791
                'remember_me' => array(
792 1101
                    'key' => sha1($this['config']['auth_magic']),
793 1101
                    'name' => $this['config']['cookie_name'].'_rememberme',
794
                    // lifetimeはデフォルトの1年間にする
795
                    // 'lifetime' => $this['config']['cookie_lifetime'],
796 1101
                    'path' => $this['config']['root_urlpath'] ?: '/',
797 1101
                    'secure' => $this['config']['force_ssl'],
798
                    'httponly' => true,
799
                    'always_remember_me' => false,
800 1101
                    'remember_me_parameter' => 'login_memory',
801
                ),
802 1101
                'users' => $this['orm.em']->getRepository('Eccube\Entity\Customer'),
803
                'anonymous' => true,
804
            ),
805
        );
806
807 1101
        $channel = null;
808
        // 強制SSL
809 1101
        if ($this['config']['force_ssl'] == \Eccube\Common\Constant::ENABLED) {
810
            $channel = "https";
811
        }
812
813 1101
        $this['security.access_rules'] = array(
814 1101
            array("^/{$this['config']['admin_route']}/login", 'IS_AUTHENTICATED_ANONYMOUSLY', $channel),
815 1101
            array("^/{$this['config']['admin_route']}/", 'ROLE_ADMIN', $channel),
816 1101
            array('^/mypage/login', 'IS_AUTHENTICATED_ANONYMOUSLY', $channel),
817 1101
            array('^/mypage/withdraw_complete', 'IS_AUTHENTICATED_ANONYMOUSLY', $channel),
818 1101
            array('^/mypage/change', 'IS_AUTHENTICATED_FULLY', $channel),
819 1101
            array('^/mypage', 'ROLE_USER', $channel),
820
        );
821
822
        $this['eccube.password_encoder'] = function ($app) {
823 1099
            return new \Eccube\Security\Core\Encoder\PasswordEncoder($app['config']);
824
        };
825
        $this['security.encoder_factory'] = function ($app) {
826 1099
            return new \Symfony\Component\Security\Core\Encoder\EncoderFactory(array(
827 1099
                'Eccube\Entity\Customer' => $app['eccube.password_encoder'],
828 1099
                'Eccube\Entity\Member' => $app['eccube.password_encoder'],
829
            ));
830
        };
831
        $this['eccube.event_listner.security'] = function ($app) {
832 1101
            return new \Eccube\EventListener\SecurityEventListener($app['orm.em']);
833
        };
834
835
        // Voterの設定
836
        $this['authority_voter'] = function ($app) {
837 1099
            return new \Eccube\Security\Voter\AuthorityVoter($app);
838
        };
839
840
        $this->extend('security.voters', function ($voters, \Silex\Application $app) {
841 1099
            $voters[] = $app['authority_voter'];
842
843 1099
            return $voters;
844 1101
        });
845
846
        $this['security.access_manager'] = function ($app) {
847 1099
            return new \Symfony\Component\Security\Core\Authorization\AccessDecisionManager($app['security.voters'], 'unanimous');
848
        };
849
850 1101
        $this->on(\Symfony\Component\Security\Http\SecurityEvents::INTERACTIVE_LOGIN, array($this['eccube.event_listner.security'], 'onInteractiveLogin'));
851
    }
852
853
    /**
854
     * ロードバランサー、プロキシサーバの設定を行う
855
     */
856 1101
    public function initProxy()
857
    {
858 1101
        $config = $this['config'];
859 1101
        if (isset($config['trusted_proxies_connection_only']) && !empty($config['trusted_proxies_connection_only'])) {
860
            $this->on(KernelEvents::REQUEST, function (GetResponseEvent $event) use ($config) {
861
                // サブリクエストのREMOTE_ADDRも動的に設定を行う必要があるため、KernelEvents::REQUESTを使用する
862
                Request::setTrustedProxies(array_merge(array($event->getRequest()->server->get('REMOTE_ADDR')), $config['trusted_proxies']));
863
            }, self::EARLY_EVENT);
864 1101 View Code Duplication
        } elseif (isset($config['trusted_proxies']) && !empty($config['trusted_proxies'])) {
865
            Request::setTrustedProxies($config['trusted_proxies']);
866
        }
867
    }
868
869 1099
    public function initializePlugin()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
870
    {
871 1099
        if ($this->initializedPlugin) {
872
            return;
873
        }
874 1099
        $this->register(new ServiceProvider\EccubePluginServiceProvider());
875
876
        // TODO Acme\ServiceProvider の初期化はここで OK?
877 1099
        if (array_key_exists('service',$this['config'])) {
0 ignored issues
show
introduced by
Add a single space after each comma delimiter
Loading history...
878
            foreach ($this['config']['service'] as $service) {
879
                $this->register(new $service);
0 ignored issues
show
introduced by
Use parentheses when instantiating classes
Loading history...
880
            }
881
        }
882 1099
        $this->initializedPlugin = true;
883
    }
884
885
    /**
886
     * PHPUnit を実行中かどうかを設定する.
887
     *
888
     * @param boolean $testMode PHPUnit を実行中の場合 true
889
     */
890 1091
    public function setTestMode($testMode)
891
    {
892 1091
        $this->testMode = $testMode;
893
    }
894
895
    /**
896
     * PHPUnit を実行中かどうか.
897
     *
898
     * @return boolean PHPUnit を実行中の場合 true
899
     */
900 317
    public function isTestMode()
901
    {
902 317
        return $this->testMode;
903
    }
904
905
    /**
906
     *
907
     * データベースの接続を確認
908
     * 成功 : trueを返却
909
     * 失敗 : \Doctrine\DBAL\DBALExceptionエラーが発生( 接続に失敗した場合 )、エラー画面を表示しdie()
910
     * 備考 : app['debug']がtrueの際は処理を行わない
911
     *
912
     * @return boolean true
913
     *
914
     */
915 1101
    protected function checkDatabaseConnection()
916
    {
917 1101
        if ($this['debug']) {
918 1101
            return;
919
        }
920
        try {
921
            $this['db']->connect();
922
        } catch (\Doctrine\DBAL\DBALException $e) {
923
            $this['monolog']->error($e->getMessage());
924
            $this['twig.path'] = array(__DIR__.'/Resource/template/exception');
925
            $html = $this['twig']->render('error.twig', array(
926
                'error_title' => 'データーベース接続エラー',
927
                'error_message' => 'データーベースを確認してください',
928
            ));
929
            $response = new Response();
930
            $response->setContent($html);
931
            $response->setStatusCode('500');
932
            $response->headers->set('Content-Type', 'text/html');
933
            $response->send();
934
            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...
935
        }
936
937
        return true;
938
    }
939
940
    /**
941
     * Config ファイルをパースし、連想配列を返します.
942
     *
943
     * $config_name.yml ファイルをパースし、連想配列を返します.
944
     * $config_name.php が存在する場合は、 PHP ファイルに記述された連想配列を使用します。
945
     *
946
     * @param string $config_name Config 名称
0 ignored issues
show
introduced by
Expected 2 spaces after parameter type; 1 found
Loading history...
947
     * @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...
948
     * @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...
949
     * @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...
950
     * @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...
951
     * @return Application
952
     */
953 1102
    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...
954
    {
955 1102
        $ymlPath = $ymlPath ? $ymlPath : __DIR__.'/../../app/config/eccube';
956 1102
        $distPath = $distPath ? $distPath : __DIR__.'/../../src/Eccube/Resource/config';
957 1102
        $config = array();
958 1102
        $config_php = $ymlPath.'/'.$config_name.'.php';
959 1102
        if (!file_exists($config_php)) {
960 1102
            $config_yml = $ymlPath.'/'.$config_name.'.yml';
961 1102
            if (file_exists($config_yml)) {
962 1102
                $config = Yaml::parse(file_get_contents($config_yml));
963 1102
                $config = empty($config) ? array() : $config;
964 1102 View Code Duplication
                if (isset($this['output_config_php']) && $this['output_config_php']) {
965 1102
                    file_put_contents($config_php, sprintf('<?php return %s', var_export($config, true)).';');
966
                }
967
            }
968
        } else {
969
            $config = require $config_php;
970
        }
971
972
        // `%ROOT_DIR%`を絶対パスに変換
973 1102
        $rootDir = realpath(__DIR__.'/../../');
974
        array_walk($config, function(&$value) use ($rootDir) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
975 1102
            $value = str_replace('%ROOT_DIR%', $rootDir, $value);
976 1102
        });
977
978 1102
        $config_dist = array();
979 1102
        $config_php_dist = $distPath.'/'.$config_name.'.dist.php';
980 1102
        if (!file_exists($config_php_dist)) {
981 1102
            $config_yml_dist = $distPath.'/'.$config_name.'.yml.dist';
982 1102
            if (file_exists($config_yml_dist)) {
983 1102
                $config_dist = Yaml::parse(file_get_contents($config_yml_dist));
984 1102 View Code Duplication
                if (isset($this['output_config_php']) && $this['output_config_php']) {
985 1102
                    file_put_contents($config_php_dist, sprintf('<?php return %s', var_export($config_dist, true)).';');
986
                }
987
            }
988
        } else {
989
            $config_dist = require $config_php_dist;
990
        }
991
992 1102
        if ($wrap_key) {
993 1102
            $configAll = array_replace_recursive($configAll, array($config_name => $config_dist), array($config_name => $config));
994
        } else {
995 1102
            $configAll = array_replace_recursive($configAll, $config_dist, $config);
996
        }
997
998 1102
        return $this;
999
    }
1000
1001
    /**
1002
     * セッションが開始されているかどうか.
1003
     *
1004
     * @return boolean セッションが開始済みの場合 true
1005
     * @link http://php.net/manual/ja/function.session-status.php#113468
1006
     */
1007 1101
    protected function isSessionStarted()
1008
    {
1009 1101
        if (php_sapi_name() !== 'cli') {
1010 1101
            if (version_compare(phpversion(), '5.4.0', '>=')) {
1011 1101
                return session_status() === PHP_SESSION_ACTIVE ? true : false;
1012
            } else {
1013
                return session_id() === '' ? false : true;
1014
            }
1015
        }
1016
1017
        return false;
1018
    }
1019
1020
    /**
1021
     * Http Cache対応
1022
     */
1023 1101
    protected function initCacheRequest()
1024
    {
1025
        // httpキャッシュが無効の場合はイベント設定を行わない.
1026 1101
        if (!$this['config']['http_cache']['enabled']) {
1027 1101
            return;
1028
        }
1029
1030
        $app = $this;
1031
1032
        // Response Event(http cache対応、event実行は一番遅く設定)
1033
        $this->on(\Symfony\Component\HttpKernel\KernelEvents::RESPONSE, function (\Symfony\Component\HttpKernel\Event\FilterResponseEvent $event) use ($app) {
1034
1035
            if (!$event->isMasterRequest()) {
1036
                return;
1037
            }
1038
1039
            $request = $event->getRequest();
1040
            $response = $event->getResponse();
1041
1042
            $route = $request->attributes->get('_route');
1043
1044
            $etag = md5($response->getContent());
1045
1046
            if (strpos($route, 'admin') === 0) {
1047
                // 管理画面
1048
1049
                // 管理画面ではコンテンツの中身が変更された時点でキャッシュを更新し、キャッシュの適用範囲はprivateに設定
1050
                $response->setCache(array(
1051
                    'etag' => $etag,
1052
                    'private' => true,
1053
                ));
1054
1055
                if ($response->isNotModified($request)) {
1056
                    return $response;
1057
                }
1058
0 ignored issues
show
Coding Style introduced by
Blank line found at end of control structure
Loading history...
1059
            } else {
1060
                // フロント画面
1061
                $cacheRoute = $app['config']['http_cache']['route'];
1062
1063
                if (in_array($route, $cacheRoute) === true) {
1064
                    // キャッシュ対象となる画面lが含まれていた場合、キャッシュ化
1065
                    // max-ageを設定しているためExpiresは不要
1066
                    // Last-Modifiedだと比較する項目がないためETagで対応
1067
                    // max-ageを設定していた場合、contentの中身が変更されても変更されない
1068
1069
                    $age = $app['config']['http_cache']['age'];
1070
1071
                    $response->setCache(array(
1072
                        'etag' => $etag,
1073
                        'max_age' => $age,
1074
                        's_maxage' => $age,
1075
                        'public' => true,
1076
                    ));
1077
1078
                    if ($response->isNotModified($request)) {
1079
                        return $response;
1080
                    }
1081
                }
1082
            }
1083
1084
        }, -1024);
1085
    }
1086
}
1087