Completed
Pull Request — experimental/3.1 (#2518)
by Kiyotaka
76:23 queued 70:09
created

Application::initialize()   D

Complexity

Conditions 13
Paths 3

Size

Total Lines 225
Code Lines 138

Duplication

Lines 22
Ratio 9.78 %

Code Coverage

Tests 115
CRAP Score 13.2158

Importance

Changes 0
Metric Value
cc 13
eloc 138
nc 3
nop 0
dl 22
loc 225
ccs 115
cts 129
cp 0.8915
crap 13.2158
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 1071
    public static function getInstance(array $values = array())
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
68
    {
69 1071
        if (!is_object(self::$instance)) {
70 1071
            self::$instance = new Application($values);
71
        }
72
73 1071
        return self::$instance;
74
    }
75
76 1071
    public static function clearInstance()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
77
    {
78 1071
        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 1072
    public function __construct(array $values = array())
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
87
    {
88 1072
        parent::__construct($values);
89
90 1072
        if (is_null(self::$instance)) {
91 1072
            self::$instance = $this;
92
        }
93
94
        // load config
95 1072
        $this->initConfig();
96
97
        // init monolog
98 1072
        $this->initLogger();
99
    }
100
101
    /**
102
     * Application::runが実行されているか親クラスのプロパティから判定
103
     *
104
     * @return bool
105
     */
106 1071
    public function isBooted()
107
    {
108 1071
        return $this->booted;
109
    }
110
111 1072
    public function initConfig()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
112
    {
113
        // load .env
114 1072
        $envFile = __DIR__.'/../../.env';
115 1072
        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 1072
            $configAll = array();
122 1072
            $this->parseConfig('constant', $configAll)
123 1072
                ->parseConfig('path', $configAll)
124 1072
                ->parseConfig('config', $configAll)
125 1072
                ->parseConfig('database', $configAll)
126 1072
                ->parseConfig('mail', $configAll)
127 1072
                ->parseConfig('log', $configAll)
128 1072
                ->parseConfig('nav', $configAll, true)
129 1072
                ->parseConfig('doctrine_cache', $configAll)
130 1072
                ->parseConfig('http_cache', $configAll)
131 1072
                ->parseConfig('session_handler', $configAll);
132
133 1072
            return $configAll;
134
        };
135
    }
136
137 1072
    public function initLogger()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
138
    {
139 1072
        $app = $this;
140 1072
        $this->register(new ServiceProvider\LogServiceProvider($app));
0 ignored issues
show
Unused Code introduced by
The call to LogServiceProvider::__construct() has too many arguments starting with $app.

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

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

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

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