Failed Conditions
Push — experimental/3.1 ( cb54a4...028283 )
by Kiyotaka
44:57
created

Application::__construct()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 14
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 2

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 14
ccs 6
cts 6
cp 1
rs 9.4285
cc 2
eloc 6
nc 2
nop 1
crap 2
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\EntityEventServiceProvider;
37
use Eccube\ServiceProvider\MobileDetectServiceProvider;
38
use Sergiors\Silex\Routing\ChainUrlGenerator;
39
use Sergiors\Silex\Routing\ChainUrlMatcher;
40
use Symfony\Component\Dotenv\Dotenv;
41
use Symfony\Component\Finder\Finder;
42
use Symfony\Component\HttpFoundation\Request;
43
use Symfony\Component\HttpFoundation\Response;
44
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
45
use Symfony\Component\HttpKernel\KernelEvents;
46
use Symfony\Component\Yaml\Yaml;
47
48
class Application extends \Silex\Application
0 ignored issues
show
introduced by
Missing class doc comment
Loading history...
49
{
50
    use \Silex\Application\FormTrait;
51
    use \Silex\Application\UrlGeneratorTrait;
52
    use \Silex\Application\MonologTrait;
53
    use \Silex\Application\SwiftmailerTrait;
54
    use \Silex\Application\SecurityTrait;
55
    use \Silex\Application\TranslationTrait;
56
    use \Eccube\Application\ApplicationTrait;
57
    use \Eccube\Application\SecurityTrait;
58
    use \Eccube\Application\TwigTrait;
59
60
    protected static $instance;
61
62
    protected $initialized = false;
63
    protected $initializedPlugin = false;
64
    protected $testMode = false;
65
66
    public static function getInstance(array $values = array())
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
67 1179
    {
68
        if (!is_object(self::$instance)) {
69 1179
            self::$instance = new Application($values);
70 1178
        }
71
72
        return self::$instance;
73 1179
    }
74
75
    public static function clearInstance()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
76 1179
    {
77
        self::$instance = null;
78 1179
    }
79
80
    final public function __clone()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
81
    {
82
        throw new \Exception('Clone is not allowed against '.get_class($this));
83
    }
84
85
    public function __construct(array $values = array())
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
86 1179
    {
87
        parent::__construct($values);
88 1179
89
        if (is_null(self::$instance)) {
90 1179
            self::$instance = $this;
91 1179
        }
92
93
        // load config
94
        $this->initConfig();
95 1179
96
        // init monolog
97
        $this->initLogger();
98 1179
    }
99
100
    /**
101
     * Application::runが実行されているか親クラスのプロパティから判定
102
     *
103
     * @return bool
104
     */
105
    public function isBooted()
106 1187
    {
107
        return $this->booted;
108 1187
    }
109
110
    public function initConfig()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
111 1179
    {
112
        // load .env
113
        $envFile = __DIR__.'/../../.env';
114
        if (file_exists($envFile)) {
115 1179
            (new Dotenv())->load($envFile);
116 1179
        }
117 1179
118 1179
        // load config
119 1179
        $this['config'] = function() {
0 ignored issues
show
Coding Style introduced by
Expected 1 space after FUNCTION keyword; 0 found
Loading history...
120 1179
            $configAll = array();
121 1179
            $this->parseConfig('constant', $configAll)
122 1179
                ->parseConfig('path', $configAll)
123 1179
                ->parseConfig('config', $configAll)
124 1179
                ->parseConfig('database', $configAll)
125 1179
                ->parseConfig('mail', $configAll)
126
                ->parseConfig('log', $configAll)
127 1179
                ->parseConfig('nav', $configAll, true)
128
                ->parseConfig('doctrine_cache', $configAll)
129
                ->parseConfig('http_cache', $configAll)
130
                ->parseConfig('session_handler', $configAll);
131 1179
132
            return $configAll;
133 1179
        };
134 1179
    }
135
136
    public function initLogger()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
137 1179
    {
138
        $app = $this;
139 1179
        $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...
140 4
    }
141
142
    public function initialize()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
143
    {
144 1179
        if ($this->initialized) {
145
            return;
146
        }
147 1179
148 1179
        // init locale
149
        $this->initLocale();
150
151
        // init session
152 1179
        if (!$this->isSessionStarted()) {
153
            $this->initSession();
154
        }
155 1179
156 1179
        // init twig
157
        $this->initRendering();
158 1179
159 1179
        // init provider
160 1179
        $this->register(new \Silex\Provider\HttpCacheServiceProvider(), array(
161 1179
            'http_cache.cache_dir' => __DIR__.'/../../app/cache/http/',
162
        ));
163
        $this->register(new \Silex\Provider\HttpFragmentServiceProvider());
164 33
        $this->register(new \Silex\Provider\FormServiceProvider());
165 33
        $this->register(new \Silex\Provider\SerializerServiceProvider());
166
        $this->register(new \Silex\Provider\ValidatorServiceProvider());
167
        $this->register(new \Saxulum\Validator\Provider\SaxulumValidatorProvider());
168
        $this->register(new MobileDetectServiceProvider());
169
170
        $this->error(function (\Exception $e, Request $request, $code) {
171
            if ($this['debug']) {
172
                return;
173
            }
174
175
            switch ($code) {
176
                case 403:
177
                    $title = 'アクセスできません。';
178
                    $message = 'お探しのページはアクセスができない状況にあるか、移動もしくは削除された可能性があります。';
179
                    break;
180
                case 404:
181
                    $title = 'ページがみつかりません。';
182
                    $message = 'URLに間違いがないかご確認ください。';
183
                    break;
184
                default:
185
                    $title = 'システムエラーが発生しました。';
186
                    $message = '大変お手数ですが、サイト管理者までご連絡ください。';
187 1179
                    break;
188
            }
189
190 1179
            return $this->render('error.twig', array(
191
                'error_title' => $title,
192
                'error_message' => $message,
193 1179
            ));
194
        });
195
196 1179
        // init mailer
197
        $this->initMailer();
198
199 1179
        // init doctrine orm
200
        $this->initDoctrine();
201 1179
202 1179
        // Set up the DBAL connection now to check for a proper connection to the database.
203 1179
        $this->checkDatabaseConnection();
204 1179
205 1179
        // init security
206 1179
        $this->initSecurity();
207 1179
208
        $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...
209 1179
            'routing.cache_dir' => $this['debug'] ? null : __DIR__.'/../../app/cache/routing'
210 1179
        ]);
211
        $this->register(new \Sergiors\Silex\Provider\DoctrineCacheServiceProvider());
212
        $this->register(new \Sergiors\Silex\Provider\TemplatingServiceProvider());
213 1179
        $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...
214
            'annotations.debug' => $this['debug'],
215
            'annotations.options' => [
0 ignored issues
show
introduced by
Add a comma after each item in a multi-line array
Loading history...
216
                'cache_driver' => $this['debug'] ? 'array' : 'filesystem',
217 1179
                'cache_dir' => $this['debug'] ? null : __DIR__.'/../../app/cache/annotation'
218
            ]
219
        ]);
220 1179
        $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...
221
            'request' => [
0 ignored issues
show
introduced by
Add a comma after each item in a multi-line array
Loading history...
222
                'auto_convert' => true
223 1179
            ]
224 1179
        ]);
225 1179
        // init proxy
226 1179
        $this->initProxy();
227
228
        // init ec-cube service provider
229
        $this->register(new ServiceProvider\EccubeServiceProvider());
230 1179
231
        // mount controllers
232
        $this->register(new \Silex\Provider\ServiceControllerServiceProvider());
233 1178
        $this->mount('', new ControllerProvider\FrontControllerProvider());
0 ignored issues
show
Documentation introduced by
new \Eccube\ControllerPr...ontControllerProvider() is of type object<Eccube\Controller...rontControllerProvider>, but the function expects a callable.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
234 1178
        $this->mount('/'.trim($this['config']['admin_route'], '/').'/', new ControllerProvider\AdminControllerProvider());
0 ignored issues
show
Documentation introduced by
new \Eccube\ControllerPr...minControllerProvider() is of type object<Eccube\Controller...dminControllerProvider>, but the function expects a callable.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
235 1178
        Request::enableHttpMethodParameterOverride(); // PUTやDELETEできるようにする
236 1178
237 1178
        // ルーティングの設定
238 1178
        // TODO EccubeRoutingServiceProviderに移植する.
239
        $app = $this;
240 1178
        $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...
241 1178
            $options = [
0 ignored issues
show
introduced by
Add a comma after each item in a multi-line array
Loading history...
242
                'debug' => $app['debug'],
243
                'cache_dir' => $app['routing.cache_dir'],
244 1178
                'matcher_base_class' => $app['request_matcher_class'],
245 1178
                'matcher_class' => $app['request_matcher_class'],
246
                'matcher_cache_class' => $cachePrefix.'UrlMatcher',
247
                'generator_cache_class' => $cachePrefix.'UrlGenerator'
248 1178
            ];
249 1178
            $router = new EccubeRouter(
250 1178
                $app['routing.loader'],
251
                $resoure,
252 1178
                $options,
253 1179
                $app['request_context'],
254
                $app['logger']
255
            );
256 1178
257 1178
            $router->setAdminPrefix($app['config']['admin_route']);
258
            $router->setUserDataPrefix($app['config']['user_data_route']);
259 1178
            $router->setRequireHttps($app['config']['force_ssl']);
260
261
            return $router;
262
        });
263
264 1178
        $this['eccube.router.origin'] = function ($app) {
265 1178
            $resource = __DIR__.'/Controller';
266 1178
            $cachePrefix = 'Origin';
267 1178
268
            return $app['eccube.router']($resource, $cachePrefix);
269 1178
        };
270 1178
271 1178
        $this['eccube.routers.plugin'] = function ($app) {
272 1178
            // TODO 有効なプラグインを対象とする必要がある.
273 1178
            $dirs = Finder::create()
274
                ->in($app['config']['root_dir'].'/app/Plugin')
275
                ->name('Controller')
276 1178
                ->directories();
277
278
            $routers = [];
279
            foreach ($dirs as $dir) {
280
                $realPath = $dir->getRealPath();
281 1178
                $pluginCode = basename(dirname($realPath));
282 1178
                $routers[] = $app['eccube.router']($realPath, 'Plugin'.$pluginCode);
283
            }
284 1178
285
            return $routers;
286 1178
        };
287
288
        $this['eccube.router.extend'] = function ($app) {
289
            // TODO ディレクトリ名は暫定
290 1178
            $resource = $app['config']['root_dir'].'/app/Acme/Controller';
291 1178
            $cachePrefix = 'Extend';
292 1178
293 1178
            $router = $app['eccube.router']($resource, $cachePrefix);
294
295 1178
            return $router;
296 1178
        };
297
298 1178 View Code Duplication
        $this->extend('request_matcher', function ($matcher, $app) {
299 1179
            $matchers = [];
300
            $matchers[] = $app['eccube.router.extend'];
301
            foreach ($app['eccube.routers.plugin'] as $router) {
302 1178
                $matchers[] = $router;
303 1178
            };
304 1178
            $matchers[] = $app['eccube.router.origin'];
305 1178
            $matchers[] = $matcher;
306
307 1178
            return new ChainUrlMatcher($matchers, $app['request_context']);
308 1178
        });
309
310 1178 View Code Duplication
        $this->extend('url_generator', function ($generator, $app) {
311 1179
            $generators = [];
312
            $generators[] = $app['eccube.router.extend'];
313
            foreach ($app['eccube.routers.plugin'] as $router) {
314 1179
                $generators[] = $router;
315
            };
316 1179
            $generators[] = $app['eccube.router.origin'];
317
            $generators[] = $generator;
318
319 1179
            return new ChainUrlGenerator($generators, $app['request_context']);
320
        });
321
322
        // Route CollectionにEC-CUBEで定義したルーティングを追加(debug tool barに出力するため)
323 1179
        $this->extend('routes', function ($routes, $app) {
324 1179
            $routes->addCollection($app['eccube.router.extend']->getRouteCollection());
325
            foreach ($app['eccube.routers.plugin'] as $router) {
326
                $routes->addCollection($router->getRouteCollection());
327 1179
            };
328 1179
            $routes->addCollection($app['eccube.router.origin']->getRouteCollection());
329 1179
330
            return $routes;
331
        });
332
333 1178
        // init http cache
334
        $this->initCacheRequest();
335 1178
336 1178
        $this->initialized = true;
337 1178
    }
338
339
    public function initLocale()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
340 1178
    {
341 1178
342 1178
        // timezone
343
        if (!empty($this['config']['timezone'])) {
344
            date_default_timezone_set($this['config']['timezone']);
345 1178
        }
346 1179
347
        $this->register(new \Silex\Provider\TranslationServiceProvider(), array(
348
            'locale' => $this['config']['locale'],
349 1179
            'translator.cache_dir' => $this['debug'] ? null : $this['config']['root_dir'].'/app/cache/translator',
350
            'locale_fallbacks' => ['ja', 'en'],
351 1179
        ));
352 1179
        $this->extend('translator', function ($translator, \Silex\Application $app) {
353
            $translator->addLoader('yaml', new \Symfony\Component\Translation\Loader\YamlFileLoader());
354 1179
355 1179
            $file = __DIR__.'/Resource/locale/validator.'.$app['locale'].'.yml';
356 1179
            if (file_exists($file)) {
357 1179
                $translator->addResource('yaml', $file, $app['locale'], 'validators');
358
            }
359
360
            $file = __DIR__.'/Resource/locale/message.'.$app['locale'].'.yml';
361
            if (file_exists($file)) {
362
                $translator->addResource('yaml', $file, $app['locale']);
363
            }
364 1179
365
            return $translator;
366 1179
        });
367
    }
368
369
    public function initSession()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
370
    {
371
        $this->register(new \Silex\Provider\SessionServiceProvider(), array(
372
            'session.storage.save_path' => $this['config']['root_dir'].'/app/cache/eccube/session',
373
            'session.storage.options' => array(
374 1179
                'name' => $this['config']['cookie_name'],
375
                'cookie_path' => $this['config']['root_urlpath'] ?: '/',
376 1179
                'cookie_secure' => $this['config']['force_ssl'],
377 1179
                'cookie_lifetime' => $this['config']['cookie_lifetime'],
378
                'cookie_httponly' => true,
379
                // cookie_domainは指定しない
380 1178
                // http://blog.tokumaru.org/2011/10/cookiedomain.html
381 1178
            ),
382
        ));
383 1178
384 1179
        $options = $this['config']['session_handler'];
385
386
        if ($options['enabled']) {
387 475
            // @see http://silex.sensiolabs.org/doc/providers/session.html#custom-session-configurations
388 475
            $this['session.storage.handler'] = null;
389 475
            ini_set('session.save_handler', $options['save_handler']);
390 475
            ini_set('session.save_path', $options['save_path']);
391 300
        }
392
    }
393 177
394
    public function initRendering()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
395 475
    {
396 300
        $this->register(new \Silex\Provider\TwigServiceProvider(), array(
397 300
            'twig.form.templates' => array('Form/form_layout.twig'),
398
        ));
399 300
        $this->extend('twig', function (\Twig_Environment $twig, \Silex\Application $app) {
400 300
            $twig->addExtension(new \Eccube\Twig\Extension\EccubeExtension($app));
401
            $twig->addExtension(new \Twig_Extension_StringLoader());
402
403
            return $twig;
404 177
        });
405 177
406
        $this->before(function (Request $request, \Silex\Application $app) {
407 177
            $app['admin'] = $app['front'] = false;
408 177
            $pathinfo = rawurldecode($request->getPathInfo());
409
            if (strpos($pathinfo, '/'.trim($app['config']['admin_route'], '/').'/') === 0) {
410 177
                $app['admin'] = true;
411
            } else {
412
                $app['front'] = true;
413 475
            }
414
415
            // フロント or 管理画面ごとにtwigの探索パスを切り替える.
416 475
            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...
417
                if (file_exists(__DIR__.'/../../app/template/admin')) {
418
                    $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...
419
                }
420
                $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...
421
                $paths[] = __DIR__.'/../../app/Plugin';
422
                $cacheDir =  __DIR__.'/../../app/cache/twig/admin';
423
            } else {
424
                // モバイル端末時、smartphoneディレクトリを探索パスに追加する.
425
                if ($app['mobile_detect.device_type'] == \Eccube\Entity\Master\DeviceType::DEVICE_TYPE_SP) {
426
                    if (file_exists(__DIR__.'/../../app/template/smartphone')) {
427
                        $paths[] = __DIR__.'/../../app/template/smartphone';
428
                    }
429
                    $paths[] = __DIR__.'/Resource/template/smartphone';
430
                }
431
432
                if (file_exists($app['config']['template_realdir'])) {
433
                    $paths[] = $app['config']['template_realdir'];
434
                }
435
                $paths[] = $app['config']['template_default_realdir'];
436
                $paths[] = __DIR__.'/../../app/Plugin';
437
                $cacheDir =  __DIR__.'/../../app/cache/twig/'.$app['config']['template_code'];
438
            }
439
            $app['twig']->setCache($app['debug'] ? null : $cacheDir);
440
            $app['twig.loader']->addLoader(new \Twig_Loader_Filesystem($paths));
441
442
            // 管理画面のIP制限チェック.
443
            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...
444
                // IP制限チェック
445
                $allowHost = $app['config']['admin_allow_host'];
446
                if (count($allowHost) > 0) {
447
                    if (array_search($app['request_stack']->getCurrentRequest()->getClientIp(), $allowHost) === false) {
448
                        throw new \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException();
449
                    }
450
                }
451
            }
452
        }, self::EARLY_EVENT);
453 475
454
        // twigのグローバル変数を定義.
455 300
        $this->on(\Symfony\Component\HttpKernel\KernelEvents::CONTROLLER, function (\Symfony\Component\HttpKernel\Event\FilterControllerEvent $event) {
456 300
            // 未ログイン時にマイページや管理画面以下にアクセスするとSubRequestで実行されるため,
457
            // $event->isMasterRequest()ではなく、グローバル変数が初期化済かどうかの判定を行う
458
            if (isset($this['twig_global_initialized']) && $this['twig_global_initialized'] === true) {
459
                return;
460
            }
461
            // ショップ基本情報
462 1179
            $BaseInfo = $this['eccube.repository.base_info']->get();
463
            $this['twig']->addGlobal('BaseInfo', $BaseInfo);
464
465
            if ($this->isAdminRequest()) {
466
                // 管理画面
467
                // 管理画面メニュー
468 470
                $menus = array('', '', '');
469 122
                $this['twig']->addGlobal('menus', $menus);
470
471
                $Member = $this->user();
472 470
                if (is_object($Member)) {
473 470
                    // ログインしていれば管理者のロールを取得
474
                    $AuthorityRoles = $this['eccube.repository.authority_role']->findBy(array('Authority' => $Member->getAuthority()));
475 470
476
                    $roles = array();
477
                    $request = $event->getRequest();
478 300
                    foreach ($AuthorityRoles as $AuthorityRole) {
479 300
                        // 管理画面でメニュー制御するため相対パス全てをセット
480
                        $roles[] = $request->getBaseUrl().'/'.$this['config']['admin_route'].$AuthorityRole->getDenyUrl();
481 300
                    }
482 300
483
                    $this['twig']->addGlobal('AuthorityRoles', $roles);
484 294
                }
485
0 ignored issues
show
Coding Style introduced by
Blank line found at end of control structure
Loading history...
486 294
            } else {
487 294
                // フロント画面
488 294
                $request = $event->getRequest();
489
                $route = $request->attributes->get('_route');
490 294
491
                // ユーザ作成画面
492
                if ($route === 'user_data') {
493 300
                    $params = $request->attributes->get('_route_params');
494
                    $route = $params['route'];
495
                    // プレビュー画面
496
                } elseif ($request->get('preview')) {
497
                    $route = 'preview';
498 170
                }
499 170
500
                try {
501
                    $device_type_id = $this['mobile_detect.device_type'];
502 170
503 2
                    // TODO デバッグ用
504 2
                    if ($request->query->has('device_type_id')) {
505
                        $device_type_id = $request->get('device_type_id', \Eccube\Entity\Master\DeviceType::DEVICE_TYPE_PC);
506 168
                    }
507
508
                    $DeviceType = $this['eccube.repository.master.device_type']
509
                        ->find($device_type_id);
510
                    $qb = $this['eccube.repository.page_layout']->createQueryBuilder('p');
511 170
                    $PageLayout = $qb->select('p, pll,l, bp, b')
512 170
                        ->leftJoin('p.PageLayoutLayouts', 'pll')
513 170
                        ->leftJoin('pll.Layout', 'l')
514 69
                        ->leftJoin('l.BlockPositions', 'bp')
515 69
                        ->leftJoin('bp.Block', 'b')
516
                        ->where('p.url = :route')
517
                        ->andWhere('l.DeviceType = :DeviceType')
518 170
                        ->orderBy('bp.block_row', 'ASC')
519 170
                        ->setParameter('route', $route)
520
                        ->setParameter('DeviceType', $DeviceType)
521
                        ->getQuery()
522 470
                        ->getSingleResult();
523 1179
                } catch (\Doctrine\ORM\NoResultException $e) {
524
                    $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...
525
                }
526 1179
527
                $this['twig']->addGlobal('PageLayout', $PageLayout);
528
                $this['twig']->addGlobal('title', $PageLayout->getName());
529
            }
530 1179
531 1179
            $this['twig_global_initialized'] = true;
532
        });
533
    }
534
535
    public function initMailer()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
536
    {
537
538
        // メール送信時の文字エンコード指定(デフォルトはUTF-8)
539
        if (isset($this['config']['mail']['charset_iso_2022_jp']) && is_bool($this['config']['mail']['charset_iso_2022_jp'])) {
540
            if ($this['config']['mail']['charset_iso_2022_jp'] === true) {
541 1179
                \Swift::init(function () {
542 1179
                    \Swift_DependencyContainer::getInstance()
543
                        ->register('mime.qpheaderencoder')
544 1179
                        ->asAliasOf('mime.base64headerencoder');
545 1179
                    \Swift_Preferences::getInstance()->setCharset('iso-2022-jp');
546
                });
547
            }
548 1179
        }
549 1179
550
        $this->register(new \Silex\Provider\SwiftmailerServiceProvider());
551 1179
        $this['swiftmailer.options'] = $this['config']['mail'];
552
553
        if (isset($this['config']['mail']['spool']) && is_bool($this['config']['mail']['spool'])) {
554
            $this['swiftmailer.use_spool'] = $this['config']['mail']['spool'];
555
        }
556 1179
        // デフォルトはsmtpを使用
557
        $transport = $this['config']['mail']['transport'];
558 1179
        if ($transport == 'sendmail') {
559 1179
            $this['swiftmailer.transport'] = \Swift_SendmailTransport::newInstance();
560
        } elseif ($transport == 'mail') {
561 1179
            $this['swiftmailer.transport'] = \Swift_MailTransport::newInstance();
562
        }
563
    }
564
565 1179
    public function initDoctrine()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
566 1179
    {
567
        $this->register(new EntityEventServiceProvider());
568
        $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...
569
            'dbs.options' => array(
0 ignored issues
show
introduced by
Add a comma after each item in a multi-line array
Loading history...
570 1179
                'default' => $this['config']['database']
571 1179
            )
572 1179
        ));
573
        $this->register(new \Saxulum\DoctrineOrmManagerRegistry\Provider\DoctrineOrmManagerRegistryProvider());
574
575
        $app = $this;
576
        $this->extend('db.event_manager', function ($evm) use ($app) {
577
            $initSubscriber = new InitSubscriber($app);
578
            $evm->addEventSubscriber($initSubscriber);
579
580
            return $evm;
581
        });
582
583
        // UTCで保存
584
        // @see http://doctrine-orm.readthedocs.org/projects/doctrine-orm/en/latest/cookbook/working-with-datetime.html
585
        UTCDateTimeType::setTimeZone($this['config']['timezone']);
586
        UTCDateTimeTzType::setTimeZone($this['config']['timezone']);
587
        Type::overrideType('datetime', UTCDateTimeType::class);
588
        Type::overrideType('datetimetz', UTCDateTimeTzType::class);
589
590
        // プラグインのmetadata定義を合わせて行う.
591
        $pluginConfigs = PluginConfigManager::getPluginConfigAll($this['debug']);
592
        $ormMappings = array();
593 1179
        $ormMappings[] = array(
594
             'type' => 'annotation',
595
             'namespace' => 'Eccube\Entity',
596
             'path' => array(
0 ignored issues
show
introduced by
Add a comma after each item in a multi-line array
Loading history...
597
                 __DIR__.'/Entity'
598
             ),
599
             'use_simple_annotation_reader' => false,
600
         );
601
602 1179
        // TODO namespace は暫定
603 1179
        $ormMappings[] = array(
604
            'type' => 'annotation',
605 1179
            'namespace' => 'Acme\Entity',
606 1179
            'path' => array(
607 1179
                __DIR__.'/../../app/Acme/Entity',
608 1179
            ),
609
            'use_simple_annotation_reader' => false,
610 1179
        );
611 1179
612 1179
        foreach ($pluginConfigs as $code) {
613 1179
            $config = $code['config'];
614
            // Doctrine Extend
615 1179
            if (isset($config['orm.path']) && is_array($config['orm.path'])) {
616 1179
                $paths = array();
617 1179 View Code Duplication
                foreach ($config['orm.path'] as $path) {
618 1179
                    $paths[] = $this['config']['plugin_realdir'].'/'.$config['code'].$path;
619
                }
620
                $ormMappings[] = array(
621
                    'type' => 'yml',
622
                    'namespace' => 'Plugin\\'.$config['code'].'\\Entity',
623
                    'path' => $paths,
624
                );
625 1179
                $ormMappings[] = array(
626
                    'type' => 'annotation',
627
                    'namespace' => 'Plugin\\'.$config['code'].'\\Entity',
628 1179
                    'path' => $paths,
629
                    'use_simple_annotation_reader' => false,
630
                );
631
            }
632
        }
633
634
        $options = array(
0 ignored issues
show
introduced by
Add a comma after each item in a multi-line array
Loading history...
635
            'mappings' => $ormMappings
636
        );
637
638
        if (!$this['debug']) {
639
            $cacheDrivers = array();
640
            if (array_key_exists('doctrine_cache', $this['config'])) {
641
                $cacheDrivers = $this['config']['doctrine_cache'];
642
            }
643
644
            if (array_key_exists('metadata_cache', $cacheDrivers)) {
645
                $options['metadata_cache'] = $cacheDrivers['metadata_cache'];
646
            }
647
            if (array_key_exists('query_cache', $cacheDrivers)) {
648 1179
                $options['query_cache'] = $cacheDrivers['query_cache'];
649 1179
            }
650 1179
            if (array_key_exists('result_cache', $cacheDrivers)) {
651 1179
                $options['result_cache'] = $cacheDrivers['result_cache'];
652
            }
653
            if (array_key_exists('hydration_cache', $cacheDrivers)) {
654
                $options['hydration_cache'] = $cacheDrivers['hydration_cache'];
655
            }
656
        }
657
658
        $this->register(new \Dflydev\Provider\DoctrineOrm\DoctrineOrmServiceProvider(), array(
659
            'orm.proxies_dir' => __DIR__.'/../../app/cache/doctrine/proxies',
660
            'orm.em.options' => $options,
661 1179
            'orm.custom.functions.string' => array(
662 1179
                'NORMALIZE' => 'Eccube\Doctrine\ORM\Query\Normalize',
663 1179
            ),
664 1179
            'orm.custom.functions.numeric' => array(
665
                'EXTRACT' => 'Eccube\Doctrine\ORM\Query\Extract',
666
            ),
667 1179
        ));
668 1179
669
        $this->extend(
670
            'orm.em.config',
671 1179
            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...
672 1179
673
                /** @var $chain \Doctrine\Common\Persistence\Mapping\Driver\MappingDriverChain */
674
                $chain = $config->getMetadataDriverImpl();
675 1179
                $drivers = $chain->getDrivers();
676 1179
                foreach ($drivers as $namespace => $oldDriver) {
677 1179
                    if ('Eccube\Entity' === $namespace) {
678 1179
                        $newDriver = new AnnotationDriver(
679 1179
                            new CachedReader(new AnnotationReader(), new ArrayCache()),
0 ignored issues
show
Documentation introduced by
new \Doctrine\Common\Ann...mon\Cache\ArrayCache()) is of type object<Doctrine\Common\Annotations\CachedReader>, but the function expects a object<Doctrine\Common\A...tions\AnnotationReader>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

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