Completed
Push — experimental/3.1 ( a17b3e...f391d2 )
by Kiyotaka
50:54
created

Application::isBooted()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

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