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