Failed Conditions
Push — experimental/3.1 ( 94d0cd...3ded70 )
by chihiro
23s
created

Application::parseConfig()   B

Complexity

Conditions 5
Paths 16

Size

Total Lines 28
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 17
CRAP Score 5.0042

Importance

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