Completed
Pull Request — experimental/3.1 (#2484)
by Kentaro
57:08 queued 35:11
created

Application::initRendering()   D

Complexity

Conditions 20
Paths 1

Size

Total Lines 139
Code Lines 85

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 73
CRAP Score 20.2679

Importance

Changes 0
Metric Value
cc 20
eloc 85
nc 1
nop 0
dl 0
loc 139
ccs 73
cts 80
cp 0.9125
crap 20.2679
rs 4.7294
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 Sergiors\Silex\Routing\ChainUrlGenerator;
43
use Sergiors\Silex\Routing\ChainUrlMatcher;
44
use Symfony\Component\Dotenv\Dotenv;
45
use Symfony\Component\Finder\Finder;
46
use Symfony\Component\HttpFoundation\Request;
47
use Symfony\Component\HttpFoundation\Response;
48
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
49
use Symfony\Component\HttpKernel\KernelEvents;
50
use Symfony\Component\Yaml\Yaml;
51
52
class Application extends \Silex\Application
0 ignored issues
show
introduced by
Missing class doc comment
Loading history...
53
{
54
    use \Silex\Application\FormTrait;
55
    use \Silex\Application\UrlGeneratorTrait;
56
    use \Silex\Application\MonologTrait;
57
    use \Silex\Application\SwiftmailerTrait;
58
    use \Silex\Application\SecurityTrait;
59
    use \Silex\Application\TranslationTrait;
60
    use \Eccube\Application\ApplicationTrait;
61
    use \Eccube\Application\SecurityTrait;
62
    use \Eccube\Application\TwigTrait;
63
64
    protected static $instance;
65
66
    protected $initialized = false;
67
    protected $initializedPlugin = false;
68
    protected $testMode = false;
69
70 1104
    public static function getInstance(array $values = array())
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
71
    {
72 1104
        if (!is_object(self::$instance)) {
73 1104
            self::$instance = new Application($values);
74
        }
75
76 1104
        return self::$instance;
77
    }
78
79 1104
    public static function clearInstance()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
80
    {
81 1104
        self::$instance = null;
82
    }
83
84
    final public function __clone()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
85
    {
86
        throw new \Exception('Clone is not allowed against '.get_class($this));
87
    }
88
89 1105
    public function __construct(array $values = array())
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
90
    {
91 1105
        parent::__construct($values);
92
93 1105
        if (is_null(self::$instance)) {
94 1105
            self::$instance = $this;
95
        }
96
97
        // load config
98 1105
        $this->initConfig();
99
100
        // init monolog
101 1105
        $this->initLogger();
102
    }
103
104
    /**
105
     * Application::runが実行されているか親クラスのプロパティから判定
106
     *
107
     * @return bool
108
     */
109 1104
    public function isBooted()
110
    {
111 1104
        return $this->booted;
112
    }
113
114 1105
    public function initConfig()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
115
    {
116
        // load .env
117 1105
        $envFile = __DIR__.'/../../.env';
118 1105
        if (file_exists($envFile)) {
119
            (new Dotenv())->load($envFile);
120
        }
121
122
        // load config
123
        $this['config'] = function() {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
124 1105
            $configAll = array();
125 1105
            $this->parseConfig('constant', $configAll)
126 1105
                ->parseConfig('path', $configAll)
127 1105
                ->parseConfig('config', $configAll)
128 1105
                ->parseConfig('database', $configAll)
129 1105
                ->parseConfig('mail', $configAll)
130 1105
                ->parseConfig('log', $configAll)
131 1105
                ->parseConfig('nav', $configAll, true)
132 1105
                ->parseConfig('doctrine_cache', $configAll)
133 1105
                ->parseConfig('http_cache', $configAll)
134 1105
                ->parseConfig('session_handler', $configAll);
135
136 1105
            return $configAll;
137
        };
138
    }
139
140 1105
    public function initLogger()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
141
    {
142 1105
        $app = $this;
143 1105
        $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...
144
    }
145
146 1104
    public function initialize()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
147
    {
148 1104
        if ($this->initialized) {
149 2
            return;
150
        }
151
152
        // init locale
153 1104
        $this->initLocale();
154
155
        // init session
156 1104
        if (!$this->isSessionStarted()) {
157 1104
            $this->initSession();
158
        }
159
160
        // init twig
161 1104
        $this->initRendering();
162
163
        // init provider
164 1104
        $this->register(new \Silex\Provider\HttpCacheServiceProvider(), array(
165 1104
            'http_cache.cache_dir' => __DIR__.'/../../app/cache/http/',
166
        ));
167 1104
        $this->register(new \Silex\Provider\HttpFragmentServiceProvider());
168 1104
        $this->register(new \Silex\Provider\FormServiceProvider());
169 1104
        $this->register(new \Silex\Provider\SerializerServiceProvider());
170 1104
        $this->register(new \Silex\Provider\ValidatorServiceProvider());
171 1104
        $this->register(new \Saxulum\Validator\Provider\SaxulumValidatorProvider());
172 1104
        $this->register(new MobileDetectServiceProvider());
173
174
        $this->error(function (\Exception $e, Request $request, $code) {
175 23
            if ($this['debug']) {
176 23
                return;
177
            }
178
179
            switch ($code) {
180
                case 403:
181
                    $title = 'アクセスできません。';
182
                    $message = 'お探しのページはアクセスができない状況にあるか、移動もしくは削除された可能性があります。';
183
                    break;
184
                case 404:
185
                    $title = 'ページがみつかりません。';
186
                    $message = 'URLに間違いがないかご確認ください。';
187
                    break;
188
                default:
189
                    $title = 'システムエラーが発生しました。';
190
                    $message = '大変お手数ですが、サイト管理者までご連絡ください。';
191
                    break;
192
            }
193
194
            return $this->render('error.twig', array(
195
                'error_title' => $title,
196
                'error_message' => $message,
197
            ));
198 1104
        });
199
200
        // init mailer
201 1104
        $this->initMailer();
202
203 1104
        $this->register(new \Sergiors\Silex\Provider\DoctrineCacheServiceProvider());
204 1104
        $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...
205 1104
            'annotations.debug' => $this['debug'],
206
            'annotations.options' => [
0 ignored issues
show
introduced by
Add a comma after each item in a multi-line array
Loading history...
207 1104
                'cache_driver' => $this['debug'] ? 'array' : 'filesystem',
208 1104
                'cache_dir' => $this['debug'] ? null : __DIR__.'/../../app/cache/annotation'
209
            ]
210
        ]);
211
212
        // init doctrine orm
213 1104
        $this->initDoctrine();
214
215
        // Set up the DBAL connection now to check for a proper connection to the database.
216 1104
        $this->checkDatabaseConnection();
217
218
        // init security
219 1104
        $this->initSecurity();
220
221 1104
        $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...
222 1104
            'routing.cache_dir' => $this['debug'] ? null : __DIR__.'/../../app/cache/routing'
223
        ]);
224 1104
        $this->register(new \Sergiors\Silex\Provider\TemplatingServiceProvider());
225 1104
        $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...
226 1104
            'request' => [
0 ignored issues
show
introduced by
Add a comma after each item in a multi-line array
Loading history...
227
                'auto_convert' => true
228
            ]
229
        ]);
230
        // init proxy
231 1104
        $this->initProxy();
232
233
        // init ec-cube service provider
234 1104
        $this->register(new DiServiceProvider(), [
0 ignored issues
show
introduced by
Add a comma after each item in a multi-line array
Loading history...
235
            'eccube.di.dirs' => [
236 1104
                $this['config']['root_dir'].'/app/Acme/Controller',
237 1104
                $this['config']['root_dir'].'/src/Eccube/Repository',
238 1104
                $this['config']['root_dir'].'/src/Eccube/Form/Type',
239 1104
                $this['config']['root_dir'].'/src/Eccube/Form/Extension',
240 1104
                $this['config']['root_dir'].'/src/Eccube/Service',
241 1104
                $this['config']['root_dir'].'/src/Eccube/Controller',
242
            ],
243 1104
            'eccube.di.generator.dir' => $this['config']['root_dir'].'/app/cache/provider'
244
        ]);
245
246 1104
        $this->register(new CompatRepositoryProvider());
247 1104
        $this->register(new CompatServiceProvider());
248 1104
        $this->register(new ServiceProvider\EccubeServiceProvider());
249
250 1104
        $this->register(new \Silex\Provider\ServiceControllerServiceProvider());
251 1104
        Request::enableHttpMethodParameterOverride(); // PUTやDELETEできるようにする
252
253
        // ルーティングの設定
254
        // TODO EccubeRoutingServiceProviderに移植する.
255 1104
        $app = $this;
256
        $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...
257
            $options = [
0 ignored issues
show
introduced by
Add a comma after each item in a multi-line array
Loading history...
258 1104
                'debug' => $app['debug'],
259 1104
                'cache_dir' => $app['routing.cache_dir'],
260 1104
                'matcher_base_class' => $app['request_matcher_class'],
261 1104
                'matcher_class' => $app['request_matcher_class'],
262 1104
                'matcher_cache_class' => $cachePrefix.'UrlMatcher',
263 1104
                'generator_cache_class' => $cachePrefix.'UrlGenerator'
264
            ];
265 1104
            $router = new EccubeRouter(
266 1104
                $app['routing.loader'],
267 1104
                $resoure,
268 1104
                $options,
269 1104
                $app['request_context'],
270 1104
                $app['logger']
271
            );
272
273 1104
            $router->setAdminPrefix($app['config']['admin_route']);
274 1104
            $router->setUserDataPrefix($app['config']['user_data_route']);
275 1104
            $router->setRequireHttps($app['config']['force_ssl']);
276
277 1104
            return $router;
278 1104
        });
279
280
        $this['eccube.router.origin'] = function ($app) {
281 1104
            $resource = __DIR__.'/Controller';
282 1104
            $cachePrefix = 'Origin';
283
284 1104
            return $app['eccube.router']($resource, $cachePrefix);
285
        };
286
287
        $this['eccube.routers.plugin'] = function ($app) {
288
            // TODO 有効なプラグインを対象とする必要がある.
289 1104
            $dirs = Finder::create()
290 1104
                ->in($app['config']['root_dir'].'/app/Plugin')
291 1104
                ->name('Controller')
292 1104
                ->directories();
293
294 1104
            $routers = [];
295 1104
            foreach ($dirs as $dir) {
296 1104
                $realPath = $dir->getRealPath();
297 1104
                $pluginCode = basename(dirname($realPath));
298 1104
                $routers[] = $app['eccube.router']($realPath, 'Plugin'.$pluginCode);
299
            }
300
301 1104
            return $routers;
302
        };
303
304
        $this['eccube.router.extend'] = function ($app) {
305
            // TODO ディレクトリ名は暫定
306 1104
            $resource = $app['config']['root_dir'].'/app/Acme/Controller';
307 1104
            $cachePrefix = 'Extend';
308
309 1104
            $router = $app['eccube.router']($resource, $cachePrefix);
310
311 1104
            return $router;
312
        };
313
314 View Code Duplication
        $this->extend('request_matcher', function ($matcher, $app) {
315 1104
            $matchers = [];
316 1104
            $matchers[] = $app['eccube.router.extend'];
317 1104
            foreach ($app['eccube.routers.plugin'] as $router) {
318 1104
                $matchers[] = $router;
319
            };
320 1104
            $matchers[] = $app['eccube.router.origin'];
321 1104
            $matchers[] = $matcher;
322
323 1104
            return new ChainUrlMatcher($matchers, $app['request_context']);
324 1104
        });
325
326 View Code Duplication
        $this->extend('url_generator', function ($generator, $app) {
327 1104
            $generators = [];
328 1104
            $generators[] = $app['eccube.router.extend'];
329 1104
            foreach ($app['eccube.routers.plugin'] as $router) {
330 1104
                $generators[] = $router;
331
            };
332 1104
            $generators[] = $app['eccube.router.origin'];
333 1104
            $generators[] = $generator;
334
335 1104
            return new ChainUrlGenerator($generators, $app['request_context']);
336 1104
        });
337
338
        // Route CollectionにEC-CUBEで定義したルーティングを追加(debug tool barに出力するため)
339
        $this->extend('routes', function ($routes, $app) {
340 1104
            $routes->addCollection($app['eccube.router.extend']->getRouteCollection());
341 1104
            foreach ($app['eccube.routers.plugin'] as $router) {
342 1104
                $routes->addCollection($router->getRouteCollection());
343
            };
344 1104
            $routes->addCollection($app['eccube.router.origin']->getRouteCollection());
345
346 1104
            return $routes;
347 1104
        });
348
349
        // init http cache
350 1104
        $this->initCacheRequest();
351
352 1104
        $this->initialized = true;
353
    }
354
355 1104
    public function initLocale()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
356
    {
357
        // locale
358 1104
        if (!empty($this['config']['locale'])) {
359 1104
            \Locale::setDefault($this['config']['locale']);
360
        };
361
362
        // timezone
363 1104
        if (!empty($this['config']['timezone'])) {
364 1104
            date_default_timezone_set($this['config']['timezone']);
365
        }
366
367 1104
        $this->register(new \Silex\Provider\TranslationServiceProvider(), array(
368 1104
            'locale' => $this['config']['locale'],
369 1104
            'translator.cache_dir' => $this['debug'] ? null : $this['config']['root_dir'].'/app/cache/translator',
370
            'locale_fallbacks' => ['ja', 'en'],
371
        ));
372
        $this->extend('translator', function ($translator, \Silex\Application $app) {
373 1104
            $translator->addLoader('yaml', new \Symfony\Component\Translation\Loader\YamlFileLoader());
374
375 1104
            $file = __DIR__.'/Resource/locale/validator.'.$app['locale'].'.yml';
376 1104
            if (file_exists($file)) {
377 1104
                $translator->addResource('yaml', $file, $app['locale'], 'validators');
378
            }
379
380 1104
            $file = __DIR__.'/Resource/locale/message.'.$app['locale'].'.yml';
381 1104
            if (file_exists($file)) {
382 1104
                $translator->addResource('yaml', $file, $app['locale']);
383
            }
384
385 1104
            return $translator;
386 1104
        });
387
    }
388
389 1104
    public function initSession()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
390
    {
391 1104
        $this->register(new \Silex\Provider\SessionServiceProvider(), array(
392 1104
            'session.storage.save_path' => $this['config']['root_dir'].'/app/cache/eccube/session',
393
            'session.storage.options' => array(
394 1104
                'name' => $this['config']['cookie_name'],
395 1104
                'cookie_path' => $this['config']['root_urlpath'] ?: '/',
396 1104
                'cookie_secure' => $this['config']['force_ssl'],
397 1104
                'cookie_lifetime' => $this['config']['cookie_lifetime'],
398
                'cookie_httponly' => true,
399
                // cookie_domainは指定しない
400
                // http://blog.tokumaru.org/2011/10/cookiedomain.html
401
            ),
402
        ));
403
404 1104
        $options = $this['config']['session_handler'];
405
406 1104
        if ($options['enabled']) {
407
            // @see http://silex.sensiolabs.org/doc/providers/session.html#custom-session-configurations
408
            $this['session.storage.handler'] = null;
409
            ini_set('session.save_handler', $options['save_handler']);
410
            ini_set('session.save_path', $options['save_path']);
411
        }
412
    }
413
414 1104
    public function initRendering()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
415
    {
416 1104
        $this->register(new \Silex\Provider\TwigServiceProvider(), array(
417 1104
            'twig.form.templates' => array('Form/form_layout.twig'),
418
        ));
419
        $this->extend('twig', function (\Twig_Environment $twig, \Silex\Application $app) {
420 1104
            $twig->addExtension(new \Eccube\Twig\Extension\EccubeExtension($app));
421 1104
            $twig->addExtension(new \Twig_Extension_StringLoader());
422
423 1104
            return $twig;
424 1104
        });
425
426
        $this->before(function (Request $request, \Silex\Application $app) {
427 317
            $app['admin'] = $app['front'] = false;
428 317
            $pathinfo = rawurldecode($request->getPathInfo());
429 317
            if (strpos($pathinfo, '/'.trim($app['config']['admin_route'], '/').'/') === 0) {
430 220
                $app['admin'] = true;
431
            } else {
432 97
                $app['front'] = true;
433
            }
434
435
            // フロント or 管理画面ごとにtwigの探索パスを切り替える.
436 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...
437 220
                if (file_exists(__DIR__.'/../../app/template/admin')) {
438 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...
439
                }
440 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...
441 220
                $paths[] = __DIR__.'/../../app/Plugin';
442 220
                $cacheDir =  __DIR__.'/../../app/cache/twig/admin';
443
            } else {
444
                // モバイル端末時、smartphoneディレクトリを探索パスに追加する.
445 97
                if ($app['mobile_detect.device_type'] == \Eccube\Entity\Master\DeviceType::DEVICE_TYPE_SP) {
446
                    if (file_exists(__DIR__.'/../../app/template/smartphone')) {
447
                        $paths[] = __DIR__.'/../../app/template/smartphone';
448
                    }
449
                    $paths[] = __DIR__.'/Resource/template/smartphone';
450
                }
451
452 97
                if (file_exists($app['config']['template_realdir'])) {
453 97
                    $paths[] = $app['config']['template_realdir'];
454
                }
455 97
                $paths[] = $app['config']['template_default_realdir'];
456 97
                $paths[] = __DIR__.'/../../app/Plugin';
457 97
                $cacheDir =  __DIR__.'/../../app/cache/twig/'.$app['config']['template_code'];
458
            }
459 317
            $app['twig']->setCache($app['debug'] ? null : $cacheDir);
460 317
            $app['twig.loader']->addLoader(new \Twig_Loader_Filesystem($paths));
461
462
            // 管理画面のIP制限チェック.
463 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...
464
                // IP制限チェック
465 220
                $allowHost = $app['config']['admin_allow_host'];
466 220
                if (count($allowHost) > 0) {
467
                    if (array_search($app['request_stack']->getCurrentRequest()->getClientIp(), $allowHost) === false) {
468
                        throw new \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException();
469
                    }
470
                }
471
            }
472 1104
        }, self::EARLY_EVENT);
473
474
        // twigのグローバル変数を定義.
475
        $this->on(\Symfony\Component\HttpKernel\KernelEvents::CONTROLLER, function (\Symfony\Component\HttpKernel\Event\FilterControllerEvent $event) {
476
            // 未ログイン時にマイページや管理画面以下にアクセスするとSubRequestで実行されるため,
477
            // $event->isMasterRequest()ではなく、グローバル変数が初期化済かどうかの判定を行う
478 315
            if (isset($this['twig_global_initialized']) && $this['twig_global_initialized'] === true) {
479 45
                return;
480
            }
481
            // ショップ基本情報
482 315
            $this['twig']->addGlobal('BaseInfo', $this[BaseInfo::class]);
483
484 315
            if ($this->isAdminRequest()) {
485
                // 管理画面
486
                // 管理画面メニュー
487 220
                $menus = array('', '', '');
488 220
                $this['twig']->addGlobal('menus', $menus);
489
490 220
                $Member = $this->user();
491 220
                if (is_object($Member)) {
492
                    // ログインしていれば管理者のロールを取得
493 217
                    $AuthorityRoles = $this['eccube.repository.authority_role']->findBy(array('Authority' => $Member->getAuthority()));
494
495 217
                    $roles = array();
496 217
                    $request = $event->getRequest();
497 217
                    foreach ($AuthorityRoles as $AuthorityRole) {
498
                        // 管理画面でメニュー制御するため相対パス全てをセット
499 3
                        $roles[] = $request->getBaseUrl().'/'.$this['config']['admin_route'].$AuthorityRole->getDenyUrl();
500
                    }
501
502 220
                    $this['twig']->addGlobal('AuthorityRoles', $roles);
503
                }
504
0 ignored issues
show
Coding Style introduced by
Blank line found at end of control structure
Loading history...
505
            } else {
506
                // フロント画面
507 95
                $request = $event->getRequest();
508 95
                $route = $request->attributes->get('_route');
509
510
                // ユーザ作成画面
511 95
                if ($route === 'user_data') {
512 2
                    $params = $request->attributes->get('_route_params');
513 2
                    $route = $params['route'];
514
                    // プレビュー画面
515 93
                } elseif ($request->get('preview')) {
516
                    $route = 'preview';
517
                }
518
519
                try {
520 95
                    $device_type_id = $this['mobile_detect.device_type'];
521
522
                    // TODO デバッグ用
523 95
                    if ($request->query->has('device_type_id')) {
524
                        $device_type_id = $request->get('device_type_id', \Eccube\Entity\Master\DeviceType::DEVICE_TYPE_PC);
525
                    }
526
527 95
                    $DeviceType = $this['eccube.repository.master.device_type']
528 95
                        ->find($device_type_id);
529 95
                    $qb = $this['eccube.repository.page_layout']->createQueryBuilder('p');
530 95
                    $PageLayout = $qb->select('p, pll,l, bp, b')
531 95
                        ->leftJoin('p.PageLayoutLayouts', 'pll')
532 95
                        ->leftJoin('pll.Layout', 'l')
533 95
                        ->leftJoin('l.BlockPositions', 'bp')
534 95
                        ->leftJoin('bp.Block', 'b')
535 95
                        ->where('p.url = :route')
536 95
                        ->andWhere('l.DeviceType = :DeviceType')
537 95
                        ->orderBy('bp.block_row', 'ASC')
538 95
                        ->setParameter('route', $route)
539 95
                        ->setParameter('DeviceType', $DeviceType)
540 95
                        ->getQuery()
541 95
                        ->getSingleResult();
542 33
                } catch (\Doctrine\ORM\NoResultException $e) {
543 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...
544
                }
545
546 95
                $this['twig']->addGlobal('PageLayout', $PageLayout);
547 95
                $this['twig']->addGlobal('title', $PageLayout->getName());
548
            }
549
550 315
            $this['twig_global_initialized'] = true;
551 1104
        });
552
    }
553
554 1104
    public function initMailer()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
555
    {
556
557
        // メール送信時の文字エンコード指定(デフォルトはUTF-8)
558 1104
        if (isset($this['config']['mail']['charset_iso_2022_jp']) && is_bool($this['config']['mail']['charset_iso_2022_jp'])) {
559
            if ($this['config']['mail']['charset_iso_2022_jp'] === true) {
560
                \Swift::init(function () {
561
                    \Swift_DependencyContainer::getInstance()
562
                        ->register('mime.qpheaderencoder')
563
                        ->asAliasOf('mime.base64headerencoder');
564
                    \Swift_Preferences::getInstance()->setCharset('iso-2022-jp');
565
                });
566
            }
567
        }
568
569 1104
        $this->register(new \Silex\Provider\SwiftmailerServiceProvider());
570 1104
        $this['swiftmailer.options'] = $this['config']['mail'];
571
572 1104
        if (isset($this['config']['mail']['spool']) && is_bool($this['config']['mail']['spool'])) {
573 1104
            $this['swiftmailer.use_spool'] = $this['config']['mail']['spool'];
574
        }
575
        // デフォルトはsmtpを使用
576 1104
        $transport = $this['config']['mail']['transport'];
577 1104
        if ($transport == 'sendmail') {
578
            $this['swiftmailer.transport'] = \Swift_SendmailTransport::newInstance();
579 1104
        } elseif ($transport == 'mail') {
580
            $this['swiftmailer.transport'] = \Swift_MailTransport::newInstance();
581
        }
582
    }
583
584 1104
    public function initDoctrine()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
585
    {
586 1104
        $this->register(new EntityEventServiceProvider());
587 1104
        $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...
588
            'dbs.options' => array(
0 ignored issues
show
introduced by
Add a comma after each item in a multi-line array
Loading history...
589 1104
                'default' => $this['config']['database']
590
            )
591
        ));
592 1104
        $this->register(new \Saxulum\DoctrineOrmManagerRegistry\Provider\DoctrineOrmManagerRegistryProvider());
593
594 1104
        $app = $this;
595
        $this->extend('db.event_manager', function ($evm) use ($app) {
596 1104
            $initSubscriber = new InitSubscriber($app);
597 1104
            $evm->addEventSubscriber($initSubscriber);
598
599 1104
            return $evm;
600 1104
        });
601
602
        // UTCで保存
603
        // @see http://doctrine-orm.readthedocs.org/projects/doctrine-orm/en/latest/cookbook/working-with-datetime.html
604 1104
        UTCDateTimeType::setTimeZone($this['config']['timezone']);
605 1104
        UTCDateTimeTzType::setTimeZone($this['config']['timezone']);
606 1104
        Type::overrideType('datetime', UTCDateTimeType::class);
607 1104
        Type::overrideType('datetimetz', UTCDateTimeTzType::class);
608
609
        // プラグインのmetadata定義を合わせて行う.
610 1104
        $pluginConfigs = PluginConfigManager::getPluginConfigAll($this['debug']);
611 1104
        $ormMappings = array();
612 1104
        $ormMappings[] = array(
613
             'type' => 'annotation',
614
             'namespace' => 'Eccube\Entity',
615
             'path' => array(
0 ignored issues
show
introduced by
Add a comma after each item in a multi-line array
Loading history...
616
                 __DIR__.'/Entity'
617
             ),
618
             'use_simple_annotation_reader' => false,
619
         );
620
621
        // TODO namespace は暫定
622 1104
        $ormMappings[] = array(
623
            'type' => 'annotation',
624
            'namespace' => 'Acme\Entity',
625
            'path' => array(
626
                __DIR__.'/../../app/Acme/Entity',
627
            ),
628
            'use_simple_annotation_reader' => false,
629
        );
630
631 1104
        foreach ($pluginConfigs as $code) {
632 1104
            $config = $code['config'];
633
            // Doctrine Extend
634 1104
            if (isset($config['orm.path']) && is_array($config['orm.path'])) {
635
                $paths = array();
636 View Code Duplication
                foreach ($config['orm.path'] as $path) {
637
                    $paths[] = $this['config']['plugin_realdir'].'/'.$config['code'].$path;
638
                }
639
                $ormMappings[] = array(
640
                    'type' => 'yml',
641
                    'namespace' => 'Plugin\\'.$config['code'].'\\Entity',
642
                    'path' => $paths,
643
                );
644
                $ormMappings[] = array(
645 1104
                    'type' => 'annotation',
646
                    'namespace' => 'Plugin\\'.$config['code'].'\\Entity',
647
                    'path' => $paths,
648
                    'use_simple_annotation_reader' => false,
649
                );
650
            }
651
        }
652
653
        $options = array(
0 ignored issues
show
introduced by
Add a comma after each item in a multi-line array
Loading history...
654 1104
            'mappings' => $ormMappings
655
        );
656
657 1104
        if (!$this['debug']) {
658
            $cacheDrivers = array();
659
            if (array_key_exists('doctrine_cache', $this['config'])) {
660
                $cacheDrivers = $this['config']['doctrine_cache'];
661
            }
662
663
            if (array_key_exists('metadata_cache', $cacheDrivers)) {
664
                $options['metadata_cache'] = $cacheDrivers['metadata_cache'];
665
            }
666
            if (array_key_exists('query_cache', $cacheDrivers)) {
667
                $options['query_cache'] = $cacheDrivers['query_cache'];
668
            }
669
            if (array_key_exists('result_cache', $cacheDrivers)) {
670
                $options['result_cache'] = $cacheDrivers['result_cache'];
671
            }
672
            if (array_key_exists('hydration_cache', $cacheDrivers)) {
673
                $options['hydration_cache'] = $cacheDrivers['hydration_cache'];
674
            }
675
        }
676
677 1104
        $this->register(new \Dflydev\Provider\DoctrineOrm\DoctrineOrmServiceProvider(), array(
678 1104
            'orm.proxies_dir' => __DIR__.'/../../app/cache/doctrine/proxies',
679 1104
            'orm.em.options' => $options,
680
            'orm.custom.functions.string' => array(
681
                'NORMALIZE' => 'Eccube\Doctrine\ORM\Query\Normalize',
682
            ),
683
            'orm.custom.functions.numeric' => array(
684
                'EXTRACT' => 'Eccube\Doctrine\ORM\Query\Extract',
685
            ),
686
        ));
687
688 1104
        $this->extend(
689 1104
            'orm.em.config',
690
            function (\Doctrine\ORM\Configuration $config, \Silex\Application $app) {
691
692
                /** @var $chain \Doctrine\Common\Persistence\Mapping\Driver\MappingDriverChain */
693 1104
                $chain = $config->getMetadataDriverImpl();
694 1104
                $drivers = $chain->getDrivers();
695 1104
                foreach ($drivers as $namespace => $oldDriver) {
696 1104
                    if ('Eccube\Entity' === $namespace) {
697 1104
                        $newDriver = new AnnotationDriver(
698 1104
                            $app['annotations'],
699 1104
                            $oldDriver->getPaths());
700 1104
                        $newDriver->setFileExtension($oldDriver->getFileExtension());
701 1104
                        $newDriver->addExcludePaths($oldDriver->getExcludePaths());
702 1104
                        $newDriver->setTraitProxiesDirectory(
703 1104
                            realpath(__DIR__.'/../../app/proxy/entity'));
704 1104
                        $chain->addDriver($newDriver, $namespace);
705
                    }
706
                }
707
708 1104
                return $config;
709 1104
            }
710
        );
711
712
        $this->extend('orm.em', function (\Doctrine\ORM\EntityManager $em, \Silex\Application $app) {
713
            // save
714 1104
            $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...
715 1104
            $em->getEventManager()->addEventSubscriber($saveEventSubscriber);
716
717
            // clear cache
718 1104
            $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...
719 1104
            $em->getEventManager()->addEventSubscriber($clearCacheEventSubscriber);
720
721
            // filters
722 1104
            $config = $em->getConfiguration();
723 1104
            $config->addFilter("soft_delete", '\Eccube\Doctrine\Filter\SoftDeleteFilter');
724 1104
            $config->addFilter("nostock_hidden", '\Eccube\Doctrine\Filter\NoStockHiddenFilter');
725 1104
            $config->addFilter("incomplete_order_status_hidden", '\Eccube\Doctrine\Filter\OrderStatusFilter');
726 1104
            $em->getFilters()->enable('soft_delete');
727
728 1104
            return $em;
729 1104
        });
730
731 1104
        if (!$this['debug']) {
732
            // second level cacheの設定.
733
            $this->extend(
734
                'orm.em.config',
735
                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...
736
                    $config->setSecondLevelCacheEnabled();
737
                    $cacheConfig = $config->getSecondLevelCacheConfiguration();
738
                    $regionConfig = $cacheConfig->getRegionsConfiguration();
739
                    // TODO キャッシュ先は設定で切り替えられるように
740
                    $cache = $this['orm.cache.factory'](
741
                        'filesystem',
742
                        [
0 ignored issues
show
introduced by
Add a comma after each item in a multi-line array
Loading history...
743
                            'path' => __DIR__.'/../../app/cache/doctrine/second'
744
                        ]
745
                    );
746
                    $factory = new \Doctrine\ORM\Cache\DefaultCacheFactory($regionConfig, $cache);
747
                    $cacheConfig->setCacheFactory($factory);
748
749
                    return $config;
750
                }
751
            );
752
        }
753
    }
754
755 1104
    public function initSecurity()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
756
    {
757 1104
        $this->register(new \Silex\Provider\SecurityServiceProvider());
758 1104
        $this->register(new \Silex\Provider\CsrfServiceProvider());
759 1104
        $this->register(new \Silex\Provider\RememberMeServiceProvider());
760
761 1104
        $this['security.firewalls'] = array(
762 1104
            'admin' => array(
763 1104
                'pattern' => "^/{$this['config']['admin_route']}/",
764
                'form' => array(
765 1104
                    'login_path' => "/{$this['config']['admin_route']}/login",
766 1104
                    'check_path' => "/{$this['config']['admin_route']}/login_check",
767 1104
                    'username_parameter' => 'login_id',
768 1104
                    'password_parameter' => 'password',
769
                    'with_csrf' => true,
770
                    'use_forward' => true,
771
                ),
772
                'logout' => array(
773 1104
                    'logout_path' => "/{$this['config']['admin_route']}/logout",
774 1104
                    'target_url' => "/{$this['config']['admin_route']}/",
775
                ),
776 1104
                'users' => $this['orm.em']->getRepository('Eccube\Entity\Member'),
777
                'anonymous' => true,
778
            ),
779
            'customer' => array(
780 1104
                'pattern' => '^/',
781
                'form' => array(
782
                    'login_path' => '/mypage/login',
783
                    'check_path' => '/login_check',
784
                    'username_parameter' => 'login_email',
785
                    'password_parameter' => 'login_pass',
786
                    'with_csrf' => true,
787
                    'use_forward' => true,
788
                ),
789
                'logout' => array(
790
                    'logout_path' => '/logout',
791
                    'target_url' => '/',
792
                ),
793
                'remember_me' => array(
794 1104
                    'key' => sha1($this['config']['auth_magic']),
795 1104
                    'name' => $this['config']['cookie_name'].'_rememberme',
796
                    // lifetimeはデフォルトの1年間にする
797
                    // 'lifetime' => $this['config']['cookie_lifetime'],
798 1104
                    'path' => $this['config']['root_urlpath'] ?: '/',
799 1104
                    'secure' => $this['config']['force_ssl'],
800
                    'httponly' => true,
801
                    'always_remember_me' => false,
802 1104
                    'remember_me_parameter' => 'login_memory',
803
                ),
804 1104
                'users' => $this['orm.em']->getRepository('Eccube\Entity\Customer'),
805
                'anonymous' => true,
806
            ),
807
        );
808
809 1104
        $channel = null;
810
        // 強制SSL
811 1104
        if ($this['config']['force_ssl'] == \Eccube\Common\Constant::ENABLED) {
812
            $channel = "https";
813
        }
814
815 1104
        $this['security.access_rules'] = array(
816 1104
            array("^/{$this['config']['admin_route']}/login", 'IS_AUTHENTICATED_ANONYMOUSLY', $channel),
817 1104
            array("^/{$this['config']['admin_route']}/", 'ROLE_ADMIN', $channel),
818 1104
            array('^/mypage/login', 'IS_AUTHENTICATED_ANONYMOUSLY', $channel),
819 1104
            array('^/mypage/withdraw_complete', 'IS_AUTHENTICATED_ANONYMOUSLY', $channel),
820 1104
            array('^/mypage/change', 'IS_AUTHENTICATED_FULLY', $channel),
821 1104
            array('^/mypage', 'ROLE_USER', $channel),
822
        );
823
824
        $this['eccube.password_encoder'] = function ($app) {
825 1102
            return new \Eccube\Security\Core\Encoder\PasswordEncoder($app['config']);
826
        };
827
        $this['security.encoder_factory'] = function ($app) {
828 1102
            return new \Symfony\Component\Security\Core\Encoder\EncoderFactory(array(
829 1102
                'Eccube\Entity\Customer' => $app['eccube.password_encoder'],
830 1102
                'Eccube\Entity\Member' => $app['eccube.password_encoder'],
831
            ));
832
        };
833
        $this['eccube.event_listner.security'] = function ($app) {
834 1104
            return new \Eccube\EventListener\SecurityEventListener($app['orm.em']);
835
        };
836
837
        // Voterの設定
838
        $this['authority_voter'] = function ($app) {
839 1102
            return new \Eccube\Security\Voter\AuthorityVoter($app);
840
        };
841
842
        $this->extend('security.voters', function ($voters, \Silex\Application $app) {
843 1102
            $voters[] = $app['authority_voter'];
844
845 1102
            return $voters;
846 1104
        });
847
848
        $this['security.access_manager'] = function ($app) {
849 1102
            return new \Symfony\Component\Security\Core\Authorization\AccessDecisionManager($app['security.voters'], 'unanimous');
850
        };
851
852 1104
        $this->on(\Symfony\Component\Security\Http\SecurityEvents::INTERACTIVE_LOGIN, array($this['eccube.event_listner.security'], 'onInteractiveLogin'));
853
    }
854
855
    /**
856
     * ロードバランサー、プロキシサーバの設定を行う
857
     */
858 1104
    public function initProxy()
859
    {
860 1104
        $config = $this['config'];
861 1104
        if (isset($config['trusted_proxies_connection_only']) && !empty($config['trusted_proxies_connection_only'])) {
862
            $this->on(KernelEvents::REQUEST, function (GetResponseEvent $event) use ($config) {
863
                // サブリクエストのREMOTE_ADDRも動的に設定を行う必要があるため、KernelEvents::REQUESTを使用する
864
                Request::setTrustedProxies(array_merge(array($event->getRequest()->server->get('REMOTE_ADDR')), $config['trusted_proxies']));
865
            }, self::EARLY_EVENT);
866 1104 View Code Duplication
        } elseif (isset($config['trusted_proxies']) && !empty($config['trusted_proxies'])) {
867
            Request::setTrustedProxies($config['trusted_proxies']);
868
        }
869
    }
870
871 1102
    public function initializePlugin()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
872
    {
873 1102
        if ($this->initializedPlugin) {
874
            return;
875
        }
876 1102
        $this->register(new ServiceProvider\EccubePluginServiceProvider());
877
878
        // TODO Acme\ServiceProvider の初期化はここで OK?
879 1102
        if (array_key_exists('service',$this['config'])) {
0 ignored issues
show
introduced by
Add a single space after each comma delimiter
Loading history...
880
            foreach ($this['config']['service'] as $service) {
881
                $this->register(new $service);
0 ignored issues
show
introduced by
Use parentheses when instantiating classes
Loading history...
882
            }
883
        }
884 1102
        $this->initializedPlugin = true;
885
    }
886
887
    /**
888
     * PHPUnit を実行中かどうかを設定する.
889
     *
890
     * @param boolean $testMode PHPUnit を実行中の場合 true
891
     */
892 1094
    public function setTestMode($testMode)
893
    {
894 1094
        $this->testMode = $testMode;
895
    }
896
897
    /**
898
     * PHPUnit を実行中かどうか.
899
     *
900
     * @return boolean PHPUnit を実行中の場合 true
901
     */
902 317
    public function isTestMode()
903
    {
904 317
        return $this->testMode;
905
    }
906
907
    /**
908
     *
909
     * データベースの接続を確認
910
     * 成功 : trueを返却
911
     * 失敗 : \Doctrine\DBAL\DBALExceptionエラーが発生( 接続に失敗した場合 )、エラー画面を表示しdie()
912
     * 備考 : app['debug']がtrueの際は処理を行わない
913
     *
914
     * @return boolean true
915
     *
916
     */
917 1104
    protected function checkDatabaseConnection()
918
    {
919 1104
        if ($this['debug']) {
920 1104
            return;
921
        }
922
        try {
923
            $this['db']->connect();
924
        } catch (\Doctrine\DBAL\DBALException $e) {
925
            $this['monolog']->error($e->getMessage());
926
            $this['twig.path'] = array(__DIR__.'/Resource/template/exception');
927
            $html = $this['twig']->render('error.twig', array(
928
                'error_title' => 'データーベース接続エラー',
929
                'error_message' => 'データーベースを確認してください',
930
            ));
931
            $response = new Response();
932
            $response->setContent($html);
933
            $response->setStatusCode('500');
934
            $response->headers->set('Content-Type', 'text/html');
935
            $response->send();
936
            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...
937
        }
938
939
        return true;
940
    }
941
942
    /**
943
     * Config ファイルをパースし、連想配列を返します.
944
     *
945
     * $config_name.yml ファイルをパースし、連想配列を返します.
946
     * $config_name.php が存在する場合は、 PHP ファイルに記述された連想配列を使用します。
947
     *
948
     * @param string $config_name Config 名称
0 ignored issues
show
introduced by
Expected 2 spaces after parameter type; 1 found
Loading history...
949
     * @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...
950
     * @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...
951
     * @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...
952
     * @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...
953
     * @return Application
954
     */
955 1105
    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...
956
    {
957 1105
        $ymlPath = $ymlPath ? $ymlPath : __DIR__.'/../../app/config/eccube';
958 1105
        $distPath = $distPath ? $distPath : __DIR__.'/../../src/Eccube/Resource/config';
959 1105
        $config = array();
960 1105
        $config_php = $ymlPath.'/'.$config_name.'.php';
961 1105
        if (!file_exists($config_php)) {
962 1105
            $config_yml = $ymlPath.'/'.$config_name.'.yml';
963 1105
            if (file_exists($config_yml)) {
964 1105
                $config = Yaml::parse(file_get_contents($config_yml));
965 1105
                $config = empty($config) ? array() : $config;
966 1105 View Code Duplication
                if (isset($this['output_config_php']) && $this['output_config_php']) {
967 1105
                    file_put_contents($config_php, sprintf('<?php return %s', var_export($config, true)).';');
968
                }
969
            }
970
        } else {
971
            $config = require $config_php;
972
        }
973
974
        // `%ROOT_DIR%`を絶対パスに変換
975 1105
        $rootDir = realpath(__DIR__.'/../../');
976
        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...
977 1105
            $value = str_replace('%ROOT_DIR%', $rootDir, $value);
978 1105
        });
979
980 1105
        $config_dist = array();
981 1105
        $config_php_dist = $distPath.'/'.$config_name.'.dist.php';
982 1105
        if (!file_exists($config_php_dist)) {
983 1105
            $config_yml_dist = $distPath.'/'.$config_name.'.yml.dist';
984 1105
            if (file_exists($config_yml_dist)) {
985 1105
                $config_dist = Yaml::parse(file_get_contents($config_yml_dist));
986 1105 View Code Duplication
                if (isset($this['output_config_php']) && $this['output_config_php']) {
987 1105
                    file_put_contents($config_php_dist, sprintf('<?php return %s', var_export($config_dist, true)).';');
988
                }
989
            }
990
        } else {
991
            $config_dist = require $config_php_dist;
992
        }
993
994 1105
        if ($wrap_key) {
995 1105
            $configAll = array_replace_recursive($configAll, array($config_name => $config_dist), array($config_name => $config));
996
        } else {
997 1105
            $configAll = array_replace_recursive($configAll, $config_dist, $config);
998
        }
999
1000 1105
        return $this;
1001
    }
1002
1003
    /**
1004
     * セッションが開始されているかどうか.
1005
     *
1006
     * @return boolean セッションが開始済みの場合 true
1007
     * @link http://php.net/manual/ja/function.session-status.php#113468
1008
     */
1009 1104
    protected function isSessionStarted()
1010
    {
1011 1104
        if (php_sapi_name() !== 'cli') {
1012 1104
            if (version_compare(phpversion(), '5.4.0', '>=')) {
1013 1104
                return session_status() === PHP_SESSION_ACTIVE ? true : false;
1014
            } else {
1015
                return session_id() === '' ? false : true;
1016
            }
1017
        }
1018
1019
        return false;
1020
    }
1021
1022
    /**
1023
     * Http Cache対応
1024
     */
1025 1104
    protected function initCacheRequest()
1026
    {
1027
        // httpキャッシュが無効の場合はイベント設定を行わない.
1028 1104
        if (!$this['config']['http_cache']['enabled']) {
1029 1104
            return;
1030
        }
1031
1032
        $app = $this;
1033
1034
        // Response Event(http cache対応、event実行は一番遅く設定)
1035
        $this->on(\Symfony\Component\HttpKernel\KernelEvents::RESPONSE, function (\Symfony\Component\HttpKernel\Event\FilterResponseEvent $event) use ($app) {
1036
1037
            if (!$event->isMasterRequest()) {
1038
                return;
1039
            }
1040
1041
            $request = $event->getRequest();
1042
            $response = $event->getResponse();
1043
1044
            $route = $request->attributes->get('_route');
1045
1046
            $etag = md5($response->getContent());
1047
1048
            if (strpos($route, 'admin') === 0) {
1049
                // 管理画面
1050
1051
                // 管理画面ではコンテンツの中身が変更された時点でキャッシュを更新し、キャッシュの適用範囲はprivateに設定
1052
                $response->setCache(array(
1053
                    'etag' => $etag,
1054
                    'private' => true,
1055
                ));
1056
1057
                if ($response->isNotModified($request)) {
1058
                    return $response;
1059
                }
1060
0 ignored issues
show
Coding Style introduced by
Blank line found at end of control structure
Loading history...
1061
            } else {
1062
                // フロント画面
1063
                $cacheRoute = $app['config']['http_cache']['route'];
1064
1065
                if (in_array($route, $cacheRoute) === true) {
1066
                    // キャッシュ対象となる画面lが含まれていた場合、キャッシュ化
1067
                    // max-ageを設定しているためExpiresは不要
1068
                    // Last-Modifiedだと比較する項目がないためETagで対応
1069
                    // max-ageを設定していた場合、contentの中身が変更されても変更されない
1070
1071
                    $age = $app['config']['http_cache']['age'];
1072
1073
                    $response->setCache(array(
1074
                        'etag' => $etag,
1075
                        'max_age' => $age,
1076
                        's_maxage' => $age,
1077
                        'public' => true,
1078
                    ));
1079
1080
                    if ($response->isNotModified($request)) {
1081
                        return $response;
1082
                    }
1083
                }
1084
            }
1085
1086
        }, -1024);
1087
    }
1088
}
1089