Failed Conditions
Pull Request — experimental/3.1 (#2521)
by Kiyotaka
34:19
created

Application::initialize()   C

Complexity

Conditions 12
Paths 3

Size

Total Lines 219
Code Lines 141

Duplication

Lines 22
Ratio 10.05 %

Code Coverage

Tests 112
CRAP Score 12.439

Importance

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