Failed Conditions
Pull Request — experimental/3.1 (#2521)
by Kiyotaka
83:08 queued 76:21
created

Application::initialize()   C

Complexity

Conditions 12
Paths 3

Size

Total Lines 216
Code Lines 138

Duplication

Lines 22
Ratio 10.19 %

Code Coverage

Tests 109
CRAP Score 12.4705

Importance

Changes 0
Metric Value
cc 12
eloc 138
nc 3
nop 0
dl 22
loc 216
ccs 109
cts 128
cp 0.8516
crap 12.4705
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\RepositoryScanner;
31
use Eccube\Di\Scanner\ServiceScanner;
32
use Eccube\Doctrine\DBAL\Types\UTCDateTimeType;
33
use Eccube\Doctrine\DBAL\Types\UTCDateTimeTzType;
34
use Eccube\Doctrine\EventSubscriber\InitSubscriber;
35
use Eccube\Doctrine\ORM\Mapping\Driver\AnnotationDriver;
36
use Eccube\Entity\BaseInfo;
37
use Eccube\Plugin\ConfigManager as PluginConfigManager;
38
use Eccube\Routing\EccubeRouter;
39
use Eccube\ServiceProvider\CompatRepositoryProvider;
40
use Eccube\ServiceProvider\CompatServiceProvider;
41
use Eccube\ServiceProvider\DiServiceProvider;
42
use Eccube\ServiceProvider\EntityEventServiceProvider;
43
use Eccube\ServiceProvider\MobileDetectServiceProvider;
44
use Eccube\ServiceProvider\TwigLintServiceProvider;
45
use Sergiors\Silex\Routing\ChainUrlGenerator;
46
use Sergiors\Silex\Routing\ChainUrlMatcher;
47
use Symfony\Component\Dotenv\Dotenv;
48
use Symfony\Component\HttpFoundation\Request;
49
use Symfony\Component\HttpFoundation\Response;
50
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
51
use Symfony\Component\HttpKernel\KernelEvents;
52
53
class Application extends \Silex\Application
0 ignored issues
show
introduced by
Missing class doc comment
Loading history...
54
{
55
    use \Silex\Application\FormTrait;
56
    use \Silex\Application\UrlGeneratorTrait;
57
    use \Silex\Application\MonologTrait;
58
    use \Silex\Application\SwiftmailerTrait;
59
    use \Silex\Application\SecurityTrait;
60
    use \Silex\Application\TranslationTrait;
61
    use \Eccube\Application\ApplicationTrait;
62
    use \Eccube\Application\SecurityTrait;
63
    use \Eccube\Application\TwigTrait;
64
65
    protected static $instance;
66
67
    protected $initialized = false;
68
    protected $initializedPlugin = false;
69
    protected $testMode = false;
70
71 1091
    public static function getInstance(array $values = array())
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
72
    {
73 1091
        if (!is_object(self::$instance)) {
74 1091
            self::$instance = new Application($values);
75
        }
76
77 1091
        return self::$instance;
78
    }
79
80 1091
    public static function clearInstance()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
81
    {
82 1091
        self::$instance = null;
83
    }
84
85
    final public function __clone()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
86
    {
87
        throw new \Exception('Clone is not allowed against '.get_class($this));
88
    }
89
90 1092
    public function __construct(array $values = array())
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
91
    {
92 1092
        parent::__construct($values);
93
94 1092
        if (is_null(self::$instance)) {
95 1092
            self::$instance = $this;
96
        }
97
98
        // load config
99 1092
        $this->initConfig();
100
101
        // init monolog
102 1092
        $this->initLogger();
103
    }
104
105
    /**
106
     * Application::runが実行されているか親クラスのプロパティから判定
107
     *
108
     * @return bool
109
     */
110 1091
    public function isBooted()
111
    {
112 1091
        return $this->booted;
113
    }
114
115 1092
    public function initConfig()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
116
    {
117
        // load .env
118 1092
        $envFile = __DIR__.'/../../.env';
119 1092
        if (file_exists($envFile)) {
120
            (new Dotenv())->load($envFile);
121
        }
122
123
        // load config
124
        $this['config'] = function() {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
125 1092
            $configAll = array();
126 1092
            $this->parseConfig('constant', $configAll)
127 1092
                ->parseConfig('path', $configAll)
128 1092
                ->parseConfig('config', $configAll)
129 1092
                ->parseConfig('database', $configAll)
130 1092
                ->parseConfig('mail', $configAll)
131 1092
                ->parseConfig('log', $configAll)
132 1092
                ->parseConfig('nav', $configAll, true)
133 1092
                ->parseConfig('doctrine_cache', $configAll)
134 1092
                ->parseConfig('http_cache', $configAll)
135 1092
                ->parseConfig('session_handler', $configAll);
136
137 1092
            return $configAll;
138
        };
139
    }
140
141 1092
    public function initLogger()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
142
    {
143 1092
        $app = $this;
144 1092
        $this->register(new ServiceProvider\LogServiceProvider($app));
0 ignored issues
show
Unused Code introduced by
The call to LogServiceProvider::__construct() has too many arguments starting with $app.

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

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

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

Loading history...
145
    }
146
147 1091
    public function initialize()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
148
    {
149 1091
        if ($this->initialized) {
150 2
            return;
151
        }
152
153
        // init locale
154 1091
        $this->initLocale();
155
156
        // init session
157 1091
        if (!$this->isSessionStarted()) {
158 1091
            $this->initSession();
159
        }
160
161
        // init twig
162 1091
        $this->initRendering();
163
164
        // init provider
165 1091
        $this->register(new \Silex\Provider\HttpCacheServiceProvider(), array(
166 1091
            'http_cache.cache_dir' => __DIR__.'/../../app/cache/http/',
167
        ));
168 1091
        $this->register(new \Silex\Provider\HttpFragmentServiceProvider());
169 1091
        $this->register(new \Silex\Provider\FormServiceProvider());
170 1091
        $this->register(new \Silex\Provider\SerializerServiceProvider());
171 1091
        $this->register(new \Silex\Provider\ValidatorServiceProvider());
172 1091
        $this->register(new \Saxulum\Validator\Provider\SaxulumValidatorProvider());
173 1091
        $this->register(new MobileDetectServiceProvider());
174 1091
        $this->register(new TwigLintServiceProvider());
175
176
        $this->error(function (\Exception $e, Request $request, $code) {
177 23
            if ($this['debug']) {
178 23
                return;
179
            }
180
181
            switch ($code) {
182
                case 403:
183
                    $title = 'アクセスできません。';
184
                    $message = 'お探しのページはアクセスができない状況にあるか、移動もしくは削除された可能性があります。';
185
                    break;
186
                case 404:
187
                    $title = 'ページがみつかりません。';
188
                    $message = 'URLに間違いがないかご確認ください。';
189
                    break;
190
                default:
191
                    $title = 'システムエラーが発生しました。';
192
                    $message = '大変お手数ですが、サイト管理者までご連絡ください。';
193
                    break;
194
            }
195
196
            return $this->render('error.twig', array(
197
                'error_title' => $title,
198
                'error_message' => $message,
199
            ));
200 1091
        });
201
202
        // init mailer
203 1091
        $this->initMailer();
204
205 1091
        $this->register(new \Sergiors\Silex\Provider\DoctrineCacheServiceProvider());
206 1091
        $this->register(new \Sergiors\Silex\Provider\AnnotationsServiceProvider(), [
0 ignored issues
show
introduced by
Add a comma after each item in a multi-line array
Loading history...
207 1091
            'annotations.debug' => $this['debug'],
208
            'annotations.options' => [
0 ignored issues
show
introduced by
Add a comma after each item in a multi-line array
Loading history...
209 1091
                'cache_driver' => $this['debug'] ? 'array' : 'filesystem',
210 1091
                'cache_dir' => $this['debug'] ? null : __DIR__.'/../../app/cache/annotation'
211
            ]
212
        ]);
213
214
        // init doctrine orm
215 1091
        $this->initDoctrine();
216
217
        // Set up the DBAL connection now to check for a proper connection to the database.
218 1091
        $this->checkDatabaseConnection();
219
220
        // init security
221 1091
        $this->initSecurity();
222
223 1091
        $this->register(new \Sergiors\Silex\Provider\RoutingServiceProvider(), [
0 ignored issues
show
introduced by
Add a comma after each item in a multi-line array
Loading history...
224 1091
            'routing.cache_dir' => $this['debug'] ? null : __DIR__.'/../../app/cache/routing'
225
        ]);
226 1091
        $this->register(new \Sergiors\Silex\Provider\TemplatingServiceProvider());
227 1091
        $this->register(new \Sergiors\Silex\Provider\SensioFrameworkExtraServiceProvider(), [
0 ignored issues
show
introduced by
Add a comma after each item in a multi-line array
Loading history...
228 1091
            'request' => [
0 ignored issues
show
introduced by
Add a comma after each item in a multi-line array
Loading history...
229
                'auto_convert' => true
230
            ]
231
        ]);
232
        // init proxy
233 1091
        $this->initProxy();
234
235 1091
        $enabledPlugins = $this['orm.em']->getRepository('Eccube\Entity\Plugin')->findAllEnabled();
236 1091
        $configRootDir = $this['config']['root_dir'];
237
        $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...
238
            return $configRootDir.'/app/Plugin/'.$plugin->getCode();
239 1091
        }, $enabledPlugins);
240
241
        $pluginSubDirs = (function($dirName) use ($enabledPluginDirs) {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
242
            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...
243
                return $pluginDir . '/' . $dirName;
0 ignored issues
show
Coding Style introduced by
Concat operator must not be surrounded by spaces
Loading history...
244 1091
            }, $enabledPluginDirs);
245 1091
        });
246
247
        // init ec-cube service provider
248 1091
        $this->register(new DiServiceProvider(), [
0 ignored issues
show
introduced by
Add a comma after each item in a multi-line array
Loading history...
249
            'eccube.di.scanners' => [
0 ignored issues
show
introduced by
Add a comma after each item in a multi-line array
Loading history...
250 1091
                new ComponentScanner(array_merge([
0 ignored issues
show
introduced by
Add a comma after each item in a multi-line array
Loading history...
251 1091
                    $this['config']['root_dir'].'/app/Acme/Controller',
252 1091
                    $this['config']['root_dir'].'/src/Eccube/Controller'
253 1091
                ], $pluginSubDirs('Controller'))),
254 1091
                new FormTypeScanner(array_merge([
0 ignored issues
show
introduced by
Add a comma after each item in a multi-line array
Loading history...
255 1091
                    $this['config']['root_dir'].'/src/Eccube/Form/Type'
256 1091
                ], $pluginSubDirs('Form/Type'))),
257 1091
                new FormExtensionScanner(array_merge([
0 ignored issues
show
introduced by
Add a comma after each item in a multi-line array
Loading history...
258 1091
                    $this['config']['root_dir'].'/src/Eccube/Form/Extension'
259 1091
                ], $pluginSubDirs('Form/Extension'))),
260 1091
                new ServiceScanner(array_merge([
0 ignored issues
show
introduced by
Add a comma after each item in a multi-line array
Loading history...
261 1091
                    $this['config']['root_dir'].'/src/Eccube/Service'
262 1091
                ], $pluginSubDirs('Service'))),
263 1091
                new RepositoryScanner(array_merge([
0 ignored issues
show
introduced by
Add a comma after each item in a multi-line array
Loading history...
264 1091
                    $this['config']['root_dir'].'/src/Eccube/Repository'
265 1091
                ], $pluginSubDirs('Repository')))
266
            ],
267 1091
            'eccube.di.generator.dir' => $this['config']['root_dir'].'/app/cache/provider'
268
        ]);
269
270 1091
        $this->register(new CompatRepositoryProvider());
271 1091
        $this->register(new CompatServiceProvider());
272 1091
        $this->register(new ServiceProvider\EccubeServiceProvider());
273
274 1091
        $this->register(new \Silex\Provider\ServiceControllerServiceProvider());
275 1091
        Request::enableHttpMethodParameterOverride(); // PUTやDELETEできるようにする
276
277
        // ルーティングの設定
278
        // TODO EccubeRoutingServiceProviderに移植する.
279 1091
        $app = $this;
280
        $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...
281
            $options = [
0 ignored issues
show
introduced by
Add a comma after each item in a multi-line array
Loading history...
282 1091
                'debug' => $app['debug'],
283 1091
                'cache_dir' => $app['routing.cache_dir'],
284 1091
                'matcher_base_class' => $app['request_matcher_class'],
285 1091
                'matcher_class' => $app['request_matcher_class'],
286 1091
                'matcher_cache_class' => $cachePrefix.'UrlMatcher',
287 1091
                'generator_cache_class' => $cachePrefix.'UrlGenerator'
288
            ];
289 1091
            $router = new EccubeRouter(
290 1091
                $app['routing.loader'],
291 1091
                $resoure,
292 1091
                $options,
293 1091
                $app['request_context'],
294 1091
                $app['logger']
295
            );
296
297 1091
            $router->setAdminPrefix($app['config']['admin_route']);
298 1091
            $router->setUserDataPrefix($app['config']['user_data_route']);
299 1091
            $router->setRequireHttps($app['config']['force_ssl']);
300
301 1091
            return $router;
302 1091
        });
303
304
        $this['eccube.router.origin'] = function ($app) {
305 1091
            $resource = __DIR__.'/Controller';
306 1091
            $cachePrefix = 'Origin';
307
308 1091
            return $app['eccube.router']($resource, $cachePrefix);
309
        };
310
311 1091
        $this['eccube.routers.plugin'] = [];
312
313
        $this['eccube.router.extend'] = function ($app) {
314
            // TODO ディレクトリ名は暫定
315 1091
            $resource = $app['config']['root_dir'].'/app/Acme/Controller';
316 1091
            $cachePrefix = 'Extend';
317
318 1091
            $router = $app['eccube.router']($resource, $cachePrefix);
319
320 1091
            return $router;
321
        };
322
323 View Code Duplication
        $this->extend('request_matcher', function ($matcher, $app) {
324 1091
            $matchers = [];
325 1091
            $matchers[] = $app['eccube.router.extend'];
326 1091
            foreach ($app['eccube.routers.plugin'] as $router) {
327
                $matchers[] = $router;
328
            };
329 1091
            $matchers[] = $app['eccube.router.origin'];
330 1091
            $matchers[] = $matcher;
331
332 1091
            return new ChainUrlMatcher($matchers, $app['request_context']);
333 1091
        });
334
335 View Code Duplication
        $this->extend('url_generator', function ($generator, $app) {
336 1091
            $generators = [];
337 1091
            $generators[] = $app['eccube.router.extend'];
338 1091
            foreach ($app['eccube.routers.plugin'] as $router) {
339
                $generators[] = $router;
340
            };
341 1091
            $generators[] = $app['eccube.router.origin'];
342 1091
            $generators[] = $generator;
343
344 1091
            return new ChainUrlGenerator($generators, $app['request_context']);
345 1091
        });
346
347
        // Route CollectionにEC-CUBEで定義したルーティングを追加(debug tool barに出力するため)
348
        $this->extend('routes', function ($routes, $app) {
349 1091
            $routes->addCollection($app['eccube.router.extend']->getRouteCollection());
350 1091
            foreach ($app['eccube.routers.plugin'] as $router) {
351
                $routes->addCollection($router->getRouteCollection());
352
            };
353 1091
            $routes->addCollection($app['eccube.router.origin']->getRouteCollection());
354
355 1091
            return $routes;
356 1091
        });
357
358
        // init http cache
359 1091
        $this->initCacheRequest();
360
361 1091
        $this->initialized = true;
362
    }
363
364 1091
    public function initLocale()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
365
    {
366
        // locale
367 1091
        if (!empty($this['config']['locale'])) {
368 1091
            \Locale::setDefault($this['config']['locale']);
369
        };
370
371
        // timezone
372 1091
        if (!empty($this['config']['timezone'])) {
373 1091
            date_default_timezone_set($this['config']['timezone']);
374
        }
375
376 1091
        $this->register(new \Silex\Provider\TranslationServiceProvider(), array(
377 1091
            'locale' => $this['config']['locale'],
378 1091
            'translator.cache_dir' => $this['debug'] ? null : $this['config']['root_dir'].'/app/cache/translator',
379
            'locale_fallbacks' => ['ja', 'en'],
380
        ));
381
        $this->extend('translator', function ($translator, \Silex\Application $app) {
382 1091
            $translator->addLoader('php', new \Symfony\Component\Translation\Loader\PhpFileLoader());
383
384 1091
            $file = __DIR__.'/Resource/locale/messages.'.$app['locale'].'.php';
385 1091
            if (file_exists($file)) {
386 1091
                $translator->addResource('php', $file, $app['locale']);
387 1091
                $translator->addResource('php', $file, $app['locale'], 'validators');
388
            }
389
390 1091
            return $translator;
391 1091
        });
392
    }
393
394 1091
    public function initSession()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
395
    {
396 1091
        $this->register(new \Silex\Provider\SessionServiceProvider(), array(
397 1091
            'session.storage.save_path' => $this['config']['root_dir'].'/app/cache/eccube/session',
398
            'session.storage.options' => array(
399 1091
                'name' => $this['config']['cookie_name'],
400 1091
                'cookie_path' => $this['config']['root_urlpath'] ?: '/',
401 1091
                'cookie_secure' => $this['config']['force_ssl'],
402 1091
                'cookie_lifetime' => $this['config']['cookie_lifetime'],
403
                'cookie_httponly' => true,
404
                // cookie_domainは指定しない
405
                // http://blog.tokumaru.org/2011/10/cookiedomain.html
406
            ),
407
        ));
408
409 1091
        $options = $this['config']['session_handler'];
410
411 1091
        if ($options['enabled']) {
412
            // @see http://silex.sensiolabs.org/doc/providers/session.html#custom-session-configurations
413
            $this['session.storage.handler'] = null;
414
            ini_set('session.save_handler', $options['save_handler']);
415
            ini_set('session.save_path', $options['save_path']);
416
        }
417
    }
418
419 1091
    public function initRendering()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
420
    {
421 1091
        $this->register(new \Silex\Provider\TwigServiceProvider(), array(
422 1091
            'twig.form.templates' => array('Form/form_layout.twig'),
423
        ));
424
        $this->extend('twig', function (\Twig_Environment $twig, \Silex\Application $app) {
425 1091
            $twig->addExtension(new \Eccube\Twig\Extension\EccubeExtension($app));
426 1091
            $twig->addExtension(new \Twig_Extension_StringLoader());
427
428 1091
            return $twig;
429 1091
        });
430
431
        $this->before(function (Request $request, \Silex\Application $app) {
432 315
            $app['admin'] = $app['front'] = false;
433 315
            $pathinfo = rawurldecode($request->getPathInfo());
434 315
            if (strpos($pathinfo, '/'.trim($app['config']['admin_route'], '/').'/') === 0) {
435 218
                $app['admin'] = true;
436
            } else {
437 97
                $app['front'] = true;
438
            }
439
440
            // フロント or 管理画面ごとにtwigの探索パスを切り替える.
441 315
            if ($app->isAdminRequest()) {
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class Silex\Application as the method isAdminRequest() does only exist in the following sub-classes of Silex\Application: Eccube\Application, Eccube\InstallApplication. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
442 218
                if (file_exists(__DIR__.'/../../app/template/admin')) {
443 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...
444
                }
445 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...
446 218
                $paths[] = __DIR__.'/../../app/Plugin';
447 218
                $cacheDir =  __DIR__.'/../../app/cache/twig/admin';
448
            } else {
449
                // モバイル端末時、smartphoneディレクトリを探索パスに追加する.
450 97
                if ($app['mobile_detect.device_type'] == \Eccube\Entity\Master\DeviceType::DEVICE_TYPE_SP) {
451
                    if (file_exists(__DIR__.'/../../app/template/smartphone')) {
452
                        $paths[] = __DIR__.'/../../app/template/smartphone';
453
                    }
454
                    $paths[] = __DIR__.'/Resource/template/smartphone';
455
                }
456
457 97
                if (file_exists($app['config']['template_realdir'])) {
458 97
                    $paths[] = $app['config']['template_realdir'];
459
                }
460 97
                $paths[] = $app['config']['template_default_realdir'];
461 97
                $paths[] = __DIR__.'/../../app/Plugin';
462 97
                $cacheDir =  __DIR__.'/../../app/cache/twig/'.$app['config']['template_code'];
463
            }
464 315
            $app['twig']->setCache($app['debug'] ? null : $cacheDir);
465 315
            $app['twig.loader']->addLoader(new \Twig_Loader_Filesystem($paths));
466
467
            // 管理画面のIP制限チェック.
468 315
            if ($app->isAdminRequest()) {
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class Silex\Application as the method isAdminRequest() does only exist in the following sub-classes of Silex\Application: Eccube\Application, Eccube\InstallApplication. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
469
                // IP制限チェック
470 218
                $allowHost = $app['config']['admin_allow_host'];
471 218
                if (count($allowHost) > 0) {
472
                    if (array_search($app['request_stack']->getCurrentRequest()->getClientIp(), $allowHost) === false) {
473
                        throw new \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException();
474
                    }
475
                }
476
            }
477 1091
        }, self::EARLY_EVENT);
478
479
        // twigのグローバル変数を定義.
480
        $this->on(\Symfony\Component\HttpKernel\KernelEvents::CONTROLLER, function (\Symfony\Component\HttpKernel\Event\FilterControllerEvent $event) {
481
            // 未ログイン時にマイページや管理画面以下にアクセスするとSubRequestで実行されるため,
482
            // $event->isMasterRequest()ではなく、グローバル変数が初期化済かどうかの判定を行う
483 313
            if (isset($this['twig_global_initialized']) && $this['twig_global_initialized'] === true) {
484 71
                return;
485
            }
486
            // ショップ基本情報
487 313
            $this['twig']->addGlobal('BaseInfo', $this[BaseInfo::class]);
488
489 313
            if ($this->isAdminRequest()) {
490
                // 管理画面
491
                // 管理画面メニュー
492 218
                $menus = array('', '', '');
493 218
                $this['twig']->addGlobal('menus', $menus);
494
495 218
                $Member = $this->user();
496 218
                if (is_object($Member)) {
497
                    // ログインしていれば管理者のロールを取得
498 215
                    $AuthorityRoles = $this['eccube.repository.authority_role']->findBy(array('Authority' => $Member->getAuthority()));
499
500 215
                    $roles = array();
501 215
                    $request = $event->getRequest();
502 215
                    foreach ($AuthorityRoles as $AuthorityRole) {
503
                        // 管理画面でメニュー制御するため相対パス全てをセット
504 3
                        $roles[] = $request->getBaseUrl().'/'.$this['config']['admin_route'].$AuthorityRole->getDenyUrl();
505
                    }
506
507 218
                    $this['twig']->addGlobal('AuthorityRoles', $roles);
508
                }
509
0 ignored issues
show
Coding Style introduced by
Blank line found at end of control structure
Loading history...
510
            } else {
511
                // フロント画面
512 95
                $request = $event->getRequest();
513 95
                $route = $request->attributes->get('_route');
514
515
                // ユーザ作成画面
516 95
                if ($route === 'user_data') {
517 2
                    $params = $request->attributes->get('_route_params');
518 2
                    $route = $params['route'];
519
                    // プレビュー画面
520 93
                } elseif ($request->get('preview')) {
521
                    $route = 'preview';
522
                }
523
524
                try {
525 95
                    $device_type_id = $this['mobile_detect.device_type'];
526
527
                    // TODO デバッグ用
528 95
                    if ($request->query->has('device_type_id')) {
529
                        $device_type_id = $request->get('device_type_id', \Eccube\Entity\Master\DeviceType::DEVICE_TYPE_PC);
530
                    }
531
532 95
                    $DeviceType = $this['eccube.repository.master.device_type']
533 95
                        ->find($device_type_id);
534 95
                    $qb = $this['eccube.repository.page_layout']->createQueryBuilder('p');
535 95
                    $PageLayout = $qb->select('p, pll,l, bp, b')
536 95
                        ->leftJoin('p.PageLayoutLayouts', 'pll')
537 95
                        ->leftJoin('pll.Layout', 'l')
538 95
                        ->leftJoin('l.BlockPositions', 'bp')
539 95
                        ->leftJoin('bp.Block', 'b')
540 95
                        ->where('p.url = :route')
541 95
                        ->andWhere('l.DeviceType = :DeviceType')
542 95
                        ->orderBy('bp.block_row', 'ASC')
543 95
                        ->setParameter('route', $route)
544 95
                        ->setParameter('DeviceType', $DeviceType)
545 95
                        ->getQuery()
546 95
                        ->getSingleResult();
547 33
                } catch (\Doctrine\ORM\NoResultException $e) {
548 33
                    $PageLayout = $this['eccube.repository.page_layout']->newPageLayout($DeviceType);
0 ignored issues
show
Bug introduced by
The variable $DeviceType does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
549
                }
550
551 95
                $this['twig']->addGlobal('PageLayout', $PageLayout);
552 95
                $this['twig']->addGlobal('title', $PageLayout->getName());
553
            }
554
555 313
            $this['twig_global_initialized'] = true;
556 1091
        });
557
    }
558
559 1091
    public function initMailer()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
560
    {
561
562
        // メール送信時の文字エンコード指定(デフォルトはUTF-8)
563 1091
        if (isset($this['config']['mail']['charset_iso_2022_jp']) && is_bool($this['config']['mail']['charset_iso_2022_jp'])) {
564
            if ($this['config']['mail']['charset_iso_2022_jp'] === true) {
565
                \Swift::init(function () {
566
                    \Swift_DependencyContainer::getInstance()
567
                        ->register('mime.qpheaderencoder')
568
                        ->asAliasOf('mime.base64headerencoder');
569
                    \Swift_Preferences::getInstance()->setCharset('iso-2022-jp');
570
                });
571
            }
572
        }
573
574 1091
        $this->register(new \Silex\Provider\SwiftmailerServiceProvider());
575 1091
        $this['swiftmailer.options'] = $this['config']['mail'];
576
577 1091
        if (isset($this['config']['mail']['spool']) && is_bool($this['config']['mail']['spool'])) {
578 1091
            $this['swiftmailer.use_spool'] = $this['config']['mail']['spool'];
579
        }
580
        // デフォルトはsmtpを使用
581 1091
        $transport = $this['config']['mail']['transport'];
582 1091
        if ($transport == 'sendmail') {
583
            $this['swiftmailer.transport'] = \Swift_SendmailTransport::newInstance();
584 1091
        } elseif ($transport == 'mail') {
585
            $this['swiftmailer.transport'] = \Swift_MailTransport::newInstance();
586
        }
587
    }
588
589 1091
    public function initDoctrine()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
590
    {
591 1091
        $this->register(new EntityEventServiceProvider());
592 1091
        $this->register(new \Silex\Provider\DoctrineServiceProvider(), array(
0 ignored issues
show
introduced by
Add a comma after each item in a multi-line array
Loading history...
593
            'dbs.options' => array(
0 ignored issues
show
introduced by
Add a comma after each item in a multi-line array
Loading history...
594 1091
                'default' => $this['config']['database']
595
            )
596
        ));
597 1091
        $this->register(new \Saxulum\DoctrineOrmManagerRegistry\Provider\DoctrineOrmManagerRegistryProvider());
598
599 1091
        $app = $this;
600
        $this->extend('db.event_manager', function ($evm) use ($app) {
601 1091
            $initSubscriber = new InitSubscriber($app);
602 1091
            $evm->addEventSubscriber($initSubscriber);
603
604 1091
            return $evm;
605 1091
        });
606
607
        // UTCで保存
608
        // @see http://doctrine-orm.readthedocs.org/projects/doctrine-orm/en/latest/cookbook/working-with-datetime.html
609 1091
        UTCDateTimeType::setTimeZone($this['config']['timezone']);
610 1091
        UTCDateTimeTzType::setTimeZone($this['config']['timezone']);
611 1091
        Type::overrideType('datetime', UTCDateTimeType::class);
612 1091
        Type::overrideType('datetimetz', UTCDateTimeTzType::class);
613
614
        // プラグインのmetadata定義を合わせて行う.
615 1091
        $pluginConfigs = PluginConfigManager::getPluginConfigAll($this['debug']);
616 1091
        $ormMappings = array();
617 1091
        $ormMappings[] = array(
618
             'type' => 'annotation',
619
             'namespace' => 'Eccube\Entity',
620
             'path' => array(
0 ignored issues
show
introduced by
Add a comma after each item in a multi-line array
Loading history...
621
                 __DIR__.'/Entity'
622
             ),
623
             'use_simple_annotation_reader' => false,
624
         );
625
626
        // TODO namespace は暫定
627 1091
        $ormMappings[] = array(
628
            'type' => 'annotation',
629
            'namespace' => 'Acme\Entity',
630
            'path' => array(
631
                __DIR__.'/../../app/Acme/Entity',
632
            ),
633
            'use_simple_annotation_reader' => false,
634
        );
635
636 1091
        foreach ($pluginConfigs as $code) {
637 1091
            $config = $code['config'];
638
            // Doctrine Extend
639 1091
            if (isset($config['orm.path']) && is_array($config['orm.path'])) {
640
                $paths = array();
641 View Code Duplication
                foreach ($config['orm.path'] as $path) {
642
                    $paths[] = $this['config']['plugin_realdir'].'/'.$config['code'].$path;
643
                }
644
                $ormMappings[] = array(
645
                    'type' => 'yml',
646
                    'namespace' => 'Plugin\\'.$config['code'].'\\Entity',
647
                    'path' => $paths,
648
                );
649
                $ormMappings[] = array(
650 1091
                    'type' => 'annotation',
651
                    'namespace' => 'Plugin\\'.$config['code'].'\\Entity',
652
                    'path' => $paths,
653
                    'use_simple_annotation_reader' => false,
654
                );
655
            }
656
        }
657
658
        $options = array(
0 ignored issues
show
introduced by
Add a comma after each item in a multi-line array
Loading history...
659 1091
            'mappings' => $ormMappings
660
        );
661
662 1091
        if (!$this['debug']) {
663
            $cacheDrivers = array();
664
            if (array_key_exists('doctrine_cache', $this['config'])) {
665
                $cacheDrivers = $this['config']['doctrine_cache'];
666
            }
667
668
            if (array_key_exists('metadata_cache', $cacheDrivers)) {
669
                $options['metadata_cache'] = $cacheDrivers['metadata_cache'];
670
            }
671
            if (array_key_exists('query_cache', $cacheDrivers)) {
672
                $options['query_cache'] = $cacheDrivers['query_cache'];
673
            }
674
            if (array_key_exists('result_cache', $cacheDrivers)) {
675
                $options['result_cache'] = $cacheDrivers['result_cache'];
676
            }
677
            if (array_key_exists('hydration_cache', $cacheDrivers)) {
678
                $options['hydration_cache'] = $cacheDrivers['hydration_cache'];
679
            }
680
        }
681
682 1091
        $this->register(new \Dflydev\Provider\DoctrineOrm\DoctrineOrmServiceProvider(), array(
683 1091
            'orm.proxies_dir' => __DIR__.'/../../app/cache/doctrine/proxies',
684 1091
            'orm.em.options' => $options,
685
            'orm.custom.functions.string' => array(
686
                'NORMALIZE' => 'Eccube\Doctrine\ORM\Query\Normalize',
687
            ),
688
            'orm.custom.functions.numeric' => array(
689
                'EXTRACT' => 'Eccube\Doctrine\ORM\Query\Extract',
690
            ),
691
        ));
692
693 1091
        $this->extend(
694 1091
            'orm.em.config',
695
            function (\Doctrine\ORM\Configuration $config, \Silex\Application $app) {
696
697
                /** @var $chain \Doctrine\Common\Persistence\Mapping\Driver\MappingDriverChain */
698 1091
                $chain = $config->getMetadataDriverImpl();
699 1091
                $drivers = $chain->getDrivers();
700 1091
                foreach ($drivers as $namespace => $oldDriver) {
701 1091
                    if ('Eccube\Entity' === $namespace) {
702 1091
                        $newDriver = new AnnotationDriver(
703 1091
                            $app['annotations'],
704 1091
                            $oldDriver->getPaths());
705 1091
                        $newDriver->setFileExtension($oldDriver->getFileExtension());
706 1091
                        $newDriver->addExcludePaths($oldDriver->getExcludePaths());
707 1091
                        $newDriver->setTraitProxiesDirectory(
708 1091
                            realpath(__DIR__.'/../../app/proxy/entity'));
709 1091
                        $chain->addDriver($newDriver, $namespace);
710
                    }
711
                }
712
713 1091
                return $config;
714 1091
            }
715
        );
716
717
        $this->extend('orm.em', function (\Doctrine\ORM\EntityManager $em, \Silex\Application $app) {
718
            // save
719 1091
            $saveEventSubscriber = new \Eccube\Doctrine\EventSubscriber\SaveEventSubscriber($app);
0 ignored issues
show
Compatibility introduced by
$app of type object<Silex\Application> is not a sub-type of object<Eccube\Application>. It seems like you assume a child class of the class Silex\Application to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
720 1091
            $em->getEventManager()->addEventSubscriber($saveEventSubscriber);
721
722
            // clear cache
723 1091
            $clearCacheEventSubscriber = new \Eccube\Doctrine\EventSubscriber\ClearCacheEventSubscriber($app);
0 ignored issues
show
Compatibility introduced by
$app of type object<Silex\Application> is not a sub-type of object<Eccube\Application>. It seems like you assume a child class of the class Silex\Application to be always present.

This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.

Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.

Loading history...
724 1091
            $em->getEventManager()->addEventSubscriber($clearCacheEventSubscriber);
725
726
            // filters
727 1091
            $config = $em->getConfiguration();
728 1091
            $config->addFilter("nostock_hidden", '\Eccube\Doctrine\Filter\NoStockHiddenFilter');
729 1091
            $config->addFilter("incomplete_order_status_hidden", '\Eccube\Doctrine\Filter\OrderStatusFilter');
730
731 1091
            return $em;
732 1091
        });
733
734 1091
        if (!$this['debug']) {
735
            // second level cacheの設定.
736
            $this->extend(
737
                'orm.em.config',
738
                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...
739
                    $config->setSecondLevelCacheEnabled();
740
                    $cacheConfig = $config->getSecondLevelCacheConfiguration();
741
                    $regionConfig = $cacheConfig->getRegionsConfiguration();
742
                    // TODO キャッシュ先は設定で切り替えられるように
743
                    $cache = $this['orm.cache.factory'](
744
                        'filesystem',
745
                        [
0 ignored issues
show
introduced by
Add a comma after each item in a multi-line array
Loading history...
746
                            'path' => __DIR__.'/../../app/cache/doctrine/second'
747
                        ]
748
                    );
749
                    $factory = new \Doctrine\ORM\Cache\DefaultCacheFactory($regionConfig, $cache);
750
                    $cacheConfig->setCacheFactory($factory);
751
752
                    return $config;
753
                }
754
            );
755
        }
756
    }
757
758 1091
    public function initSecurity()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
759
    {
760 1091
        $this->register(new \Silex\Provider\SecurityServiceProvider());
761 1091
        $this->register(new \Silex\Provider\CsrfServiceProvider());
762 1091
        $this->register(new \Silex\Provider\RememberMeServiceProvider());
763
764 1091
        $this['security.firewalls'] = array(
765 1091
            'admin' => array(
766 1091
                'pattern' => "^/{$this['config']['admin_route']}/",
767
                'form' => array(
768 1091
                    'login_path' => "/{$this['config']['admin_route']}/login",
769 1091
                    'check_path' => "/{$this['config']['admin_route']}/login_check",
770 1091
                    'username_parameter' => 'login_id',
771 1091
                    'password_parameter' => 'password',
772
                    'with_csrf' => true,
773
                    'use_forward' => true,
774
                ),
775
                'logout' => array(
776 1091
                    'logout_path' => "/{$this['config']['admin_route']}/logout",
777 1091
                    'target_url' => "/{$this['config']['admin_route']}/",
778
                ),
779 1091
                'users' => $this['orm.em']->getRepository('Eccube\Entity\Member'),
780
                'anonymous' => true,
781
            ),
782
            'customer' => array(
783 1091
                'pattern' => '^/',
784
                'form' => array(
785
                    'login_path' => '/mypage/login',
786
                    'check_path' => '/login_check',
787
                    'username_parameter' => 'login_email',
788
                    'password_parameter' => 'login_pass',
789
                    'with_csrf' => true,
790
                    'use_forward' => true,
791
                ),
792
                'logout' => array(
793
                    'logout_path' => '/logout',
794
                    'target_url' => '/',
795
                ),
796
                'remember_me' => array(
797 1091
                    'key' => sha1($this['config']['auth_magic']),
798 1091
                    'name' => $this['config']['cookie_name'].'_rememberme',
799
                    // lifetimeはデフォルトの1年間にする
800
                    // 'lifetime' => $this['config']['cookie_lifetime'],
801 1091
                    'path' => $this['config']['root_urlpath'] ?: '/',
802 1091
                    'secure' => $this['config']['force_ssl'],
803
                    'httponly' => true,
804
                    'always_remember_me' => false,
805 1091
                    'remember_me_parameter' => 'login_memory',
806
                ),
807 1091
                'users' => $this['orm.em']->getRepository('Eccube\Entity\Customer'),
808
                'anonymous' => true,
809
            ),
810
        );
811
812 1091
        $channel = null;
813
        // 強制SSL
814 1091
        if ($this['config']['force_ssl'] == \Eccube\Common\Constant::ENABLED) {
815
            $channel = "https";
816
        }
817
818 1091
        $this['security.access_rules'] = array(
819 1091
            array("^/{$this['config']['admin_route']}/login", 'IS_AUTHENTICATED_ANONYMOUSLY', $channel),
820 1091
            array("^/{$this['config']['admin_route']}/", 'ROLE_ADMIN', $channel),
821 1091
            array('^/mypage/login', 'IS_AUTHENTICATED_ANONYMOUSLY', $channel),
822 1091
            array('^/mypage/withdraw_complete', 'IS_AUTHENTICATED_ANONYMOUSLY', $channel),
823 1091
            array('^/mypage/change', 'IS_AUTHENTICATED_FULLY', $channel),
824 1091
            array('^/mypage', 'ROLE_USER', $channel),
825
        );
826
827
        $this['eccube.password_encoder'] = function ($app) {
828 1089
            return new \Eccube\Security\Core\Encoder\PasswordEncoder($app['config']);
829
        };
830
        $this['security.encoder_factory'] = function ($app) {
831 1089
            return new \Symfony\Component\Security\Core\Encoder\EncoderFactory(array(
832 1089
                'Eccube\Entity\Customer' => $app['eccube.password_encoder'],
833 1089
                'Eccube\Entity\Member' => $app['eccube.password_encoder'],
834
            ));
835
        };
836
        $this['eccube.event_listner.security'] = function ($app) {
837 1091
            return new \Eccube\EventListener\SecurityEventListener($app['orm.em']);
838
        };
839
840
        // Voterの設定
841
        $this['authority_voter'] = function ($app) {
842 1089
            return new \Eccube\Security\Voter\AuthorityVoter($app);
843
        };
844
845
        $this->extend('security.voters', function ($voters, \Silex\Application $app) {
846 1089
            $voters[] = $app['authority_voter'];
847
848 1089
            return $voters;
849 1091
        });
850
851
        $this['security.access_manager'] = function ($app) {
852 1089
            return new \Symfony\Component\Security\Core\Authorization\AccessDecisionManager($app['security.voters'], 'unanimous');
853
        };
854
855 1091
        $this->on(\Symfony\Component\Security\Http\SecurityEvents::INTERACTIVE_LOGIN, array($this['eccube.event_listner.security'], 'onInteractiveLogin'));
856
    }
857
858
    /**
859
     * ロードバランサー、プロキシサーバの設定を行う
860
     */
861 1091
    public function initProxy()
862
    {
863 1091
        $config = $this['config'];
864 1091
        if (isset($config['trusted_proxies_connection_only']) && !empty($config['trusted_proxies_connection_only'])) {
865
            $this->on(KernelEvents::REQUEST, function (GetResponseEvent $event) use ($config) {
866
                // サブリクエストのREMOTE_ADDRも動的に設定を行う必要があるため、KernelEvents::REQUESTを使用する
867
                Request::setTrustedProxies(array_merge(array($event->getRequest()->server->get('REMOTE_ADDR')), $config['trusted_proxies']));
868
            }, self::EARLY_EVENT);
869 1091 View Code Duplication
        } elseif (isset($config['trusted_proxies']) && !empty($config['trusted_proxies'])) {
870
            Request::setTrustedProxies($config['trusted_proxies']);
871
        }
872
    }
873
874 1089
    public function initializePlugin()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
875
    {
876 1089
        if ($this->initializedPlugin) {
877
            return;
878
        }
879 1089
        $this->register(new ServiceProvider\EccubePluginServiceProvider());
880
881
        // TODO Acme\ServiceProvider の初期化はここで OK?
882 1089
        if (array_key_exists('service',$this['config'])) {
0 ignored issues
show
introduced by
Add a single space after each comma delimiter
Loading history...
883
            foreach ($this['config']['service'] as $service) {
884
                $this->register(new $service);
0 ignored issues
show
introduced by
Use parentheses when instantiating classes
Loading history...
885
            }
886
        }
887 1089
        $this->initializedPlugin = true;
888
    }
889
890
    /**
891
     * PHPUnit を実行中かどうかを設定する.
892
     *
893
     * @param boolean $testMode PHPUnit を実行中の場合 true
894
     */
895 1081
    public function setTestMode($testMode)
896
    {
897 1081
        $this->testMode = $testMode;
898
    }
899
900
    /**
901
     * PHPUnit を実行中かどうか.
902
     *
903
     * @return boolean PHPUnit を実行中の場合 true
904
     */
905 315
    public function isTestMode()
906
    {
907 315
        return $this->testMode;
908
    }
909
910
    /**
911
     *
912
     * データベースの接続を確認
913
     * 成功 : trueを返却
914
     * 失敗 : \Doctrine\DBAL\DBALExceptionエラーが発生( 接続に失敗した場合 )、エラー画面を表示しdie()
915
     * 備考 : app['debug']がtrueの際は処理を行わない
916
     *
917
     * @return boolean true
918
     *
919
     */
920 1091
    protected function checkDatabaseConnection()
921
    {
922 1091
        if ($this['debug']) {
923 1091
            return;
924
        }
925
        try {
926
            $this['db']->connect();
927
        } catch (\Doctrine\DBAL\DBALException $e) {
928
            $this['monolog']->error($e->getMessage());
929
            $this['twig.path'] = array(__DIR__.'/Resource/template/exception');
930
            $html = $this['twig']->render('error.twig', array(
931
                'error_title' => 'データーベース接続エラー',
932
                'error_message' => 'データーベースを確認してください',
933
            ));
934
            $response = new Response();
935
            $response->setContent($html);
936
            $response->setStatusCode('500');
937
            $response->headers->set('Content-Type', 'text/html');
938
            $response->send();
939
            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...
940
        }
941
942
        return true;
943
    }
944
945
    /**
946
     * Config ファイルをパースし、連想配列を返します.
947
     *
948
     * $config_name.yml ファイルをパースし、連想配列を返します.
949
     * $config_name.php が存在する場合は、 PHP ファイルに記述された連想配列を使用します。
950
     *
951
     * @param string $config_name Config 名称
0 ignored issues
show
introduced by
Expected 2 spaces after parameter type; 1 found
Loading history...
952
     * @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...
953
     * @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...
954
     * @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...
955
     * @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...
956
     * @return Application
957
     */
958 1092
    public function parseConfig($config_name, array &$configAll, $wrap_key = false, $ymlPath = null, $distPath = null)
0 ignored issues
show
introduced by
Declare public methods first, then protected ones and finally private ones
Loading history...
959
    {
960 1092
        $ymlPath = $ymlPath ? $ymlPath : __DIR__.'/../../app/config/eccube';
961 1092
        $distPath = $distPath ? $distPath : __DIR__.'/../../src/Eccube/Resource/config';
962
963 1092
        $config = [];
964 1092
        $config_php = $ymlPath.'/'.$config_name.'.php';
965 1092
        if (file_exists($config_php)) {
966 1092
            $config = require $config_php;
967
        }
968
969
        // `%ROOT_DIR%`を絶対パスに変換
970 1092
        $rootDir = realpath(__DIR__.'/../../');
971
        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...
972 1092
            $value = str_replace('%ROOT_DIR%', $rootDir, $value);
973 1092
        });
974
975 1092
        $config_php_dist = $distPath.'/'.$config_name.'.php';
976 1092
        $config_dist = require $config_php_dist;
977
978 1092
        if ($wrap_key) {
979 1092
            $configAll = array_replace_recursive($configAll, array($config_name => $config_dist), array($config_name => $config));
980
        } else {
981 1092
            $configAll = array_replace_recursive($configAll, $config_dist, $config);
982
        }
983
984 1092
        return $this;
985
    }
986
987
    /**
988
     * セッションが開始されているかどうか.
989
     *
990
     * @return boolean セッションが開始済みの場合 true
991
     * @link http://php.net/manual/ja/function.session-status.php#113468
992
     */
993 1091
    protected function isSessionStarted()
994
    {
995 1091
        if (php_sapi_name() !== 'cli') {
996 1091
            if (version_compare(phpversion(), '5.4.0', '>=')) {
997 1091
                return session_status() === PHP_SESSION_ACTIVE ? true : false;
998
            } else {
999
                return session_id() === '' ? false : true;
1000
            }
1001
        }
1002
1003
        return false;
1004
    }
1005
1006
    /**
1007
     * Http Cache対応
1008
     */
1009 1091
    protected function initCacheRequest()
1010
    {
1011
        // httpキャッシュが無効の場合はイベント設定を行わない.
1012 1091
        if (!$this['config']['http_cache']['enabled']) {
1013 1091
            return;
1014
        }
1015
1016
        $app = $this;
1017
1018
        // Response Event(http cache対応、event実行は一番遅く設定)
1019
        $this->on(\Symfony\Component\HttpKernel\KernelEvents::RESPONSE, function (\Symfony\Component\HttpKernel\Event\FilterResponseEvent $event) use ($app) {
1020
1021
            if (!$event->isMasterRequest()) {
1022
                return;
1023
            }
1024
1025
            $request = $event->getRequest();
1026
            $response = $event->getResponse();
1027
1028
            $route = $request->attributes->get('_route');
1029
1030
            $etag = md5($response->getContent());
1031
1032
            if (strpos($route, 'admin') === 0) {
1033
                // 管理画面
1034
1035
                // 管理画面ではコンテンツの中身が変更された時点でキャッシュを更新し、キャッシュの適用範囲はprivateに設定
1036
                $response->setCache(array(
1037
                    'etag' => $etag,
1038
                    'private' => true,
1039
                ));
1040
1041
                if ($response->isNotModified($request)) {
1042
                    return $response;
1043
                }
1044
0 ignored issues
show
Coding Style introduced by
Blank line found at end of control structure
Loading history...
1045
            } else {
1046
                // フロント画面
1047
                $cacheRoute = $app['config']['http_cache']['route'];
1048
1049
                if (in_array($route, $cacheRoute) === true) {
1050
                    // キャッシュ対象となる画面lが含まれていた場合、キャッシュ化
1051
                    // max-ageを設定しているためExpiresは不要
1052
                    // Last-Modifiedだと比較する項目がないためETagで対応
1053
                    // max-ageを設定していた場合、contentの中身が変更されても変更されない
1054
1055
                    $age = $app['config']['http_cache']['age'];
1056
1057
                    $response->setCache(array(
1058
                        'etag' => $etag,
1059
                        'max_age' => $age,
1060
                        's_maxage' => $age,
1061
                        'public' => true,
1062
                    ));
1063
1064
                    if ($response->isNotModified($request)) {
1065
                        return $response;
1066
                    }
1067
                }
1068
            }
1069
1070
        }, -1024);
1071
    }
1072
}
1073