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