Failed Conditions
Pull Request — experimental/3.1 (#2479)
by chihiro
121:04 queued 113:52
created

Application::initLocale()   B

Complexity

Conditions 6
Paths 4

Size

Total Lines 33
Code Lines 18

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 17
CRAP Score 6

Importance

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