Failed Conditions
Pull Request — experimental/3.1 (#2521)
by Kiyotaka
162:09 queued 154:25
created

Application::initialize()   C

Complexity

Conditions 12
Paths 3

Size

Total Lines 222
Code Lines 144

Duplication

Lines 22
Ratio 9.91 %

Code Coverage

Tests 115
CRAP Score 12.4105

Importance

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