Failed Conditions
Push — experimental/3.1 ( 36d064...2457e2 )
by Kiyotaka
128:07 queued 120:55
created

InstallController::createTables()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 0
Metric Value
cc 1
eloc 4
nc 1
nop 1
dl 0
loc 6
rs 9.4285
c 0
b 0
f 0
ccs 0
cts 4
cp 0
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\Controller\Install;
25
26
use Doctrine\DBAL\Connection;
27
use Doctrine\DBAL\DriverManager;
28
use Doctrine\DBAL\Migrations\Configuration\Configuration;
29
use Doctrine\DBAL\Migrations\Migration;
30
use Doctrine\DBAL\Migrations\MigrationException;
31
use Doctrine\DBAL\Types\Type;
32
use Doctrine\ORM\EntityManager;
33
use Doctrine\ORM\Tools\SchemaTool;
34
use Doctrine\ORM\Tools\Setup;
35
use Eccube\Common\Constant;
36
use Eccube\Form\Type\Install\Step1Type;
37
use Eccube\Form\Type\Install\Step3Type;
38
use Eccube\Form\Type\Install\Step4Type;
39
use Eccube\Form\Type\Install\Step5Type;
40
use Eccube\InstallApplication;
41
use Eccube\Security\Core\Encoder\PasswordEncoder;
42
use Eccube\Util\Str;
43
use Symfony\Component\Dotenv\Dotenv;
44
use Symfony\Component\Filesystem\Filesystem;
45
use Symfony\Component\Finder\Finder;
46
use Symfony\Component\HttpFoundation\Request;
47
use Symfony\Component\HttpFoundation\Response;
48
use Symfony\Component\HttpFoundation\Session\Session;
49
50
class InstallController
0 ignored issues
show
introduced by
Missing class doc comment
Loading history...
51
{
52
    protected $requiredModules = [
0 ignored issues
show
introduced by
Add a comma after each item in a multi-line array
Loading history...
53
        'pdo',
54
        'phar',
55
        'mbstring',
56
        'zlib',
57
        'ctype',
58
        'session',
59
        'JSON',
60
        'xml',
61
        'libxml',
62
        'OpenSSL',
63
        'zip',
64
        'cURL',
65
        'fileinfo',
66
        'intl'
67
    ];
68
69
    protected $recommendedModules = [
0 ignored issues
show
introduced by
Add a comma after each item in a multi-line array
Loading history...
70
        'hash',
71
        'mcrypt'
72
    ];
73
74
    protected $writableDirs = [
75
        '/html',
76
        '/app',
77
        '/app/template',
78
        '/app/cache',
79
        '/app/config',
80
        '/app/config/eccube',
81
        '/app/log',
82
        '/app/Plugin',
83
        '/app/proxy',
84
        '/app/proxy/entity',
85
    ];
86
87
    protected $rootDir;
88
    protected $configDir;
89
    protected $configDistDir;
90
    protected $cacheDir;
91
92 7
    public function __construct()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
93
    {
94 7
        $this->rootDir = realpath(__DIR__.'/../../../..');
95 7
        $this->configDir = realpath($this->rootDir.'/app/config/eccube');
96 7
        $this->configDistDir = realpath($this->rootDir.'/src/Eccube/Resource/config');
97 7
        $this->cacheDir = realpath($this->rootDir.'/app/cache');
98
    }
99
100
    /**
101
     * 最初からやり直す場合、SESSION情報をクリア.
102
     *
103
     * @param InstallApplication $app
104
     * @param Request $request
0 ignored issues
show
introduced by
Expected 12 spaces after parameter type; 1 found
Loading history...
105
     * @param Session $session
0 ignored issues
show
introduced by
Expected 12 spaces after parameter type; 1 found
Loading history...
106
     * @return Response
107
     */
108 1
    public function index(InstallApplication $app, Request $request, Session $session)
0 ignored issues
show
Unused Code introduced by
The parameter $request 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...
109
    {
110 1
        $this->removeSessionData($session);
111
112 1
        return $app->redirect($app->path('install_step1'));
113
    }
114
115
    /**
0 ignored issues
show
introduced by
Doc comment for parameter "$session" missing
Loading history...
116
     * ようこそ.
117
     *
118
     * @param InstallApplication $app
119
     * @param Request $request
0 ignored issues
show
introduced by
Expected 12 spaces after parameter type; 1 found
Loading history...
120
     * @return Response
121
     */
122 1
    public function step1(InstallApplication $app, Request $request, Session $session)
123
    {
124 1
        $form = $app['form.factory']
125 1
            ->createBuilder(Step1Type::class)
126 1
            ->getForm();
127
128 1
        $form->setData($this->getSessionData($session));
129 1
        $form->handleRequest($request);
130
131 1
        if ($form->isSubmitted() && $form->isValid()) {
132
            $this->setSessionData($session, $form->getData());
133
134
            return $app->redirect($app->path('install_step2'));
135
        }
136
137 1
        $this->checkModules($app);
138
139 1
        return $app['twig']->render('step1.twig', [
140 1
            'form' => $form->createView(),
141 1
            'publicPath' => '..'.RELATIVE_PUBLIC_DIR_PATH.'/',
142
        ]);
143
    }
144
145
    /**
146
     * ディレクトリの書き込み権限をチェック.
147
     *
148
     * @param InstallApplication $app
149
     * @param Request $request
0 ignored issues
show
introduced by
Expected 12 spaces after parameter type; 1 found
Loading history...
150
     * @param Session $session
0 ignored issues
show
introduced by
Expected 12 spaces after parameter type; 1 found
Loading history...
151
     * @return Response
152
     */
153 1
    public function step2(InstallApplication $app, Request $request, Session $session)
0 ignored issues
show
Unused Code introduced by
The parameter $request 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...
Unused Code introduced by
The parameter $session 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...
154
    {
155 1
        $protectedDirs = [];
156 1
        foreach ($this->writableDirs as $dir) {
157 1
            if (!is_writable($this->rootDir.$dir)) {
158 1
                $protectedDirs[] = $dir;
159
            }
160
        }
161
162
        // 権限がある場合, キャッシュディレクトリをクリア
163 1
        if (empty($protectedDirs)) {
164 1
            $finder = Finder::create()
165 1
                ->in($this->cacheDir)
166 1
                ->notName('.gitkeep')
167 1
                ->files();
168 1
            $fs = new Filesystem();
169 1
            $fs->remove($finder);
170
        }
171
172 1
        return $app['twig']->render('step2.twig', [
173 1
            'protectedDirs' => $protectedDirs,
174 1
            'publicPath' => '..'.RELATIVE_PUBLIC_DIR_PATH.'/',
175
        ]);
176
    }
177
178
    /**
179
     * サイトの設定.
180
     *
181
     * @param InstallApplication $app
182
     * @param Request $request
0 ignored issues
show
introduced by
Expected 12 spaces after parameter type; 1 found
Loading history...
183
     * @param Session $session
0 ignored issues
show
introduced by
Expected 12 spaces after parameter type; 1 found
Loading history...
184
     * @return Response
185
     */
186 1
    public function step3(InstallApplication $app, Request $request, Session $session)
187
    {
188 1
        $sessionData = $this->getSessionData($session);
189
190 1
        if (empty($sessionData['shop_name'])) {
191
            // 再インストールの場合は設定ファイルから復旧
192 1
            if (file_exists($this->configDir.'/config.php')) {
193 1
                (new Dotenv())->load($this->configDir.'/.env');
194
                // ショップ名/メールアドレス
195 1
                $config = require $this->configDir.'/database.php';
196 1
                $conn = $this->createConnection($config['database'][$config['database']['default']]);
197 1
                $stmt = $conn->query("SELECT shop_name, email01 FROM dtb_base_info WHERE id = 1;");
198 1
                $row = $stmt->fetch();
199 1
                $sessionData['shop_name'] = $row['shop_name'];
200 1
                $sessionData['email'] = $row['email01'];
201
202
                // 管理画面ルーティング
203 1
                $config = require $this->configDir.'/path.php';
204 1
                $sessionData['admin_dir'] = $config['admin_route'];
205
206
                // 管理画面許可IP
207 1
                $config = require $this->configDir.'/config.php';
208 1 View Code Duplication
                if (!empty($config['admin_allow_hosts'])) {
209
                    $sessionData['admin_allow_hosts']
210
                        = Str::convertLineFeed(implode("\n", $config['admin_allow_hosts']));
211
                }
212
                // 強制SSL
213 1
                $sessionData['admin_force_ssl'] = $config['force_ssl'];
214
215
                // ロードバランサ, プロキシサーバ
216 1
                if (!empty($config['trusted_proxies_connection_only'])) {
217
                    $sessionData['trusted_proxies_connection_only'] = (bool)$config['trusted_proxies_connection_only'];
0 ignored issues
show
Coding Style introduced by
As per coding-style, a cast statement should be followed by a single space.
Loading history...
218
                }
219 1 View Code Duplication
                if (!empty($config['trusted_proxies'])) {
220
                    $sessionData['trusted_proxies'] = Str::convertLineFeed(implode("\n",
221
                        $sessionData['trusted_proxies']));
0 ignored issues
show
Coding Style introduced by
This line of the multi-line function call does not seem to be indented correctly. Expected 20 spaces, but found 24.
Loading history...
222
                }
223
                // メール
224 1
                $file = $this->configDir.'/mail.php';
225 1
                $config = require $file;
226 1
                $sessionData['mail_backend'] = $config['mail']['transport'];
227 1
                $sessionData['smtp_host'] = $config['mail']['host'];
228 1
                $sessionData['smtp_port'] = $config['mail']['port'];
229 1
                $sessionData['smtp_username'] = $config['mail']['username'];
230 1
                $sessionData['smtp_password'] = $config['mail']['password'];
231
            } else {
232
                // 初期値にmailを設定.
233
                $sessionData['mail_backend'] = 'mail';
234
            }
235
        }
236
237 1
        $form = $app['form.factory']
238 1
            ->createBuilder(Step3Type::class)
239 1
            ->getForm();
240
241 1
        $form->setData($sessionData);
242 1
        $form->handleRequest($request);
243
244 1
        if ($form->isSubmitted() && $form->isValid()) {
245
            $this->setSessionData($session, $form->getData());
246
247
            return $app->redirect($app->path('install_step4'));
248
        }
249
250 1
        return $app['twig']->render('step3.twig', [
251 1
            'form' => $form->createView(),
252 1
            'publicPath' => '..'.RELATIVE_PUBLIC_DIR_PATH.'/',
253
        ]);
254
    }
255
256
    /**
257
     * データベースの設定.
258
     *
259
     * @param InstallApplication $app
260
     * @param Request $request
0 ignored issues
show
introduced by
Expected 12 spaces after parameter type; 1 found
Loading history...
261
     * @param Session $session
0 ignored issues
show
introduced by
Expected 12 spaces after parameter type; 1 found
Loading history...
262
     * @return Response
263
     */
264 1
    public function step4(InstallApplication $app, Request $request, Session $session)
265
    {
266 1
        $sessionData = $this->getSessionData($session);
267
268 1
        if (empty($sessionData['database'])) {
269
            // 再インストールの場合は設定ファイルから復旧.
270 1
            $file = $this->configDir.'/database.php';
271 1
            if (file_exists($file)) {
272 1
                (new Dotenv())->load($this->configDir.'/.env');
273
                // データベース設定
274 1
                $config = require $file;
275 1
                $database = $config['database'][$config['database']['default']];
276 1
                $sessionData['database'] = $database['driver'];
277 1
                if ($database['driver'] === 'pdo_sqlite') {
278
                    $sessionData['database_name'] = $this->configDir.'/eccube.db';
279
                } else {
280 1
                    $sessionData['database_host'] = $database['host'];
281 1
                    $sessionData['database_port'] = $database['port'];
282 1
                    $sessionData['database_name'] = $database['dbname'];
283 1
                    $sessionData['database_user'] = $database['user'];
284 1
                    $sessionData['database_password'] = $database['password'];
285
                }
286
            }
287
        }
288
289 1
        $form = $app['form.factory']
290 1
            ->createBuilder(Step4Type::class)
291 1
            ->getForm();
292
293 1
        $form->setData($sessionData);
294 1
        $form->handleRequest($request);
295
296 1
        if ($form->isSubmitted() && $form->isValid()) {
297
            $this->setSessionData($session, $form->getData());
298
299
            return $app->redirect($app->path('install_step5'));
300
        }
301
302 1
        return $app['twig']->render('step4.twig', [
303 1
            'form' => $form->createView(),
304 1
            'publicPath' => '..'.RELATIVE_PUBLIC_DIR_PATH.'/',
305
        ]);
306
    }
307
308
    /**
309
     * データベースの初期化.
310
     *
311
     * @param InstallApplication $app
312
     * @param Request $request
0 ignored issues
show
introduced by
Expected 12 spaces after parameter type; 1 found
Loading history...
313
     * @param Session $session
0 ignored issues
show
introduced by
Expected 12 spaces after parameter type; 1 found
Loading history...
314
     * @return Response
315
     */
316 1
    public function step5(InstallApplication $app, Request $request, Session $session)
317
    {
318 1
        $form = $app['form.factory']
319 1
            ->createBuilder(Step5Type::class)
320 1
            ->getForm();
321
322 1
        $sessionData = $this->getSessionData($session);
323 1
        $form->setData($sessionData);
324 1
        $form->handleRequest($request);
325
326 1
        if ($form->isSubmitted() && $form->isValid()) {
327
            $noUpdate = $form['no_update']->getData();
328
329
            $this->copyConfigFiles();
330
            $data = array_merge(['root_urlpath' => $request->getBasePath()], $sessionData);
331
            $this->createEnvFile($data, !$noUpdate);
332
333
            (new Dotenv())->load($this->configDir.'/.env');
334
335
            $params = require $this->configDir.'/database.php';
336
            $conn = $this->createConnection($params['database'][$params['database']['default']]);
337
            $em = $this->createEntityManager($conn);
338
            $migration = $this->createMigration($conn);
339
340
            $config = require $this->configDir.'/config.php';
341
            if ($noUpdate) {
342
                $this->update($conn, [
343
                    'auth_magic' => $config['auth_magic'],
344
                    'login_id' => $sessionData['login_id'],
345
                    'login_pass' => $sessionData['login_pass'],
346
                    'shop_name' => $sessionData['shop_name'],
347
                    'email' => $sessionData['email'],
348
                ]);
349
            } else {
350
                $this->dropTables($em);
351
                $this->createTables($em);
352
                $this->importCsv($em);
353
                $this->migrate($migration);
354
                $this->insert($conn, [
355
                    'auth_magic' => $config['auth_magic'],
356
                    'login_id' => $sessionData['login_id'],
357
                    'login_pass' => $sessionData['login_pass'],
358
                    'shop_name' => $sessionData['shop_name'],
359
                    'email' => $sessionData['email'],
360
                ]);
361
            }
362
363
            if (isset($sessionData['agree']) && $sessionData['agree']) {
364
                $host = $request->getSchemeAndHttpHost();
365
                $basePath = $request->getBasePath();
366
                $params = array(
367
                    'http_url' => $host.$basePath,
368
                    'shop_name' => $sessionData['shop_name'],
369
                );
370
                $this->sendAppData($params);
371
            }
372
373
            $this->removeSessionData($session);
374
375
            return $app->redirect($app->path('install_complete'));
376
        }
377
378 1
        return $app['twig']->render('step5.twig', [
379 1
            'form' => $form->createView(),
380 1
            'publicPath' => '..'.RELATIVE_PUBLIC_DIR_PATH.'/',
381
        ]);
382
    }
383
384
    //    インストール完了
385 1
    public function complete(InstallApplication $app, Request $request)
0 ignored issues
show
introduced by
You must use "/**" style comments for a function comment
Loading history...
386
    {
387 1
        (new Dotenv())->load($this->configDir.'/.env');
388 1
        $config = require $this->configDir.'/config.php';
389 1
        if (isset($config['trusted_proxies_connection_only']) && !empty($config['trusted_proxies_connection_only'])) {
390
            Request::setTrustedProxies(array_merge(array($request->server->get('REMOTE_ADDR')),
391
                $config['trusted_proxies']));
0 ignored issues
show
Coding Style introduced by
This line of the multi-line function call does not seem to be indented correctly. Expected 12 spaces, but found 16.
Loading history...
392 1 View Code Duplication
        } elseif (isset($config['trusted_proxies']) && !empty($config['trusted_proxies'])) {
393
            Request::setTrustedProxies($config['trusted_proxies']);
394
        }
395
396 1
        $pathConfig = require $this->configDir.'/path.php';
397 1
        $host = $request->getSchemeAndHttpHost();
398 1
        $basePath = $request->getBasePath();
399 1
        $adminUrl = $host.$basePath.'/'.$pathConfig['admin_route'];
400
401 1
        return $app['twig']->render('complete.twig', [
402 1
            'admin_url' => $adminUrl,
403 1
            'publicPath' => '..'.RELATIVE_PUBLIC_DIR_PATH.'/',
404
        ]);
405
    }
406
407 4
    private function getSessionData(Session $session)
408
    {
409 4
        return $session->get('eccube.session.install', []);
410
    }
411
412 1
    private function removeSessionData(Session $session)
413
    {
414 1
        $session->remove('eccube.session.install');
415
    }
416
417
    private function setSessionData(Session $session, $data = [])
418
    {
419
        $data = array_replace_recursive($this->getSessionData($session), $data);
420
        $session->set('eccube.session.install', $data);
421
    }
422
423 1
    private function checkModules($app)
0 ignored issues
show
Coding Style introduced by
checkModules uses the super-global variable $_SERVER which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
424
    {
425 1
        foreach ($this->requiredModules as $module) {
426 1
            if (!extension_loaded($module)) {
427 1
                $app->addDanger('[必須] '.$module.' 拡張モジュールが有効になっていません。', 'install');
428
            }
429
        }
430 1
        if (!extension_loaded('pdo_mysql') && !extension_loaded('pdo_pgsql')) {
431
            $app->addDanger('[必須] '.'pdo_pgsql又はpdo_mysql 拡張モジュールを有効にしてください。', 'install');
432
        }
433 1
        foreach ($this->recommendedModules as $module) {
434 1
            if (!extension_loaded($module)) {
435
                if ($module == 'mcrypt' && PHP_VERSION_ID >= 70100) {
436
                    //The mcrypt extension has been deprecated in PHP 7.1.x
437
                    //http://php.net/manual/en/migration71.deprecated.php
438
                    continue;
439
                }
440 1
                $app->addInfo('[推奨] '.$module.' 拡張モジュールが有効になっていません。', 'install');
441
            }
442
        }
443 1
        if ('\\' === DIRECTORY_SEPARATOR) { // for Windows
444
            if (!extension_loaded('wincache')) {
445
                $app->addInfo('[推奨] WinCache 拡張モジュールが有効になっていません。', 'install');
446
            }
447
        } else {
448 1
            if (!extension_loaded('apc')) {
449 1
                $app->addInfo('[推奨] APC 拡張モジュールが有効になっていません。', 'install');
450
            }
451
        }
452 1
        if (isset($_SERVER['SERVER_SOFTWARE']) && strpos('Apache', $_SERVER['SERVER_SOFTWARE']) !== false) {
453
            if (!function_exists('apache_get_modules')) {
454
                $app->addWarning('mod_rewrite が有効になっているか不明です。', 'install');
455
            } elseif (!in_array('mod_rewrite', apache_get_modules())) {
456
                $app->addDanger('[必須] '.'mod_rewriteを有効にしてください。', 'install');
457
            }
458 1
        } elseif (isset($_SERVER['SERVER_SOFTWARE']) && strpos('Microsoft-IIS',
0 ignored issues
show
Unused Code introduced by
This elseif statement is empty, and could be removed.

This check looks for the bodies of elseif statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These elseif bodies can be removed. If you have an empty elseif but statements in the else branch, consider inverting the condition.

Loading history...
459 1
                $_SERVER['SERVER_SOFTWARE']) !== false
460
        ) {
461
            // iis
462 1
        } elseif (isset($_SERVER['SERVER_SOFTWARE']) && strpos('nginx', $_SERVER['SERVER_SOFTWARE']) !== false) {
0 ignored issues
show
Unused Code introduced by
This elseif statement is empty, and could be removed.

This check looks for the bodies of elseif statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These elseif bodies can be removed. If you have an empty elseif but statements in the else branch, consider inverting the condition.

Loading history...
463
            // nginx
464
        }
465
    }
466
467 1
    private function createConnection(array $params)
468
    {
469 1
        $conn = DriverManager::getConnection($params);
470 1
        $conn->ping();
471
472 1
        return $conn;
473
    }
474
475
    private function createEntityManager(Connection $conn)
476
    {
477
        $paths = [
478
            $this->rootDir.'/src/Eccube/Entity',
479
            $this->rootDir.'/app/Acme/Entity',
480
        ];
481
        $config = Setup::createAnnotationMetadataConfiguration($paths, true, null, null, false);
482
        $em = EntityManager::create($conn, $config);
483
484
        return $em;
485
    }
486
487 View Code Duplication
    private function createMigration(Connection $conn)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
488
    {
489
        $config = new Configuration($conn);
490
        $config->setMigrationsNamespace('DoctrineMigrations');
491
        $migrationDir = $this->rootDir.'/src/Eccube/Resource/doctrine/migration';
492
        $config->setMigrationsDirectory($migrationDir);
493
        $config->registerMigrationsFromDirectory($migrationDir);
494
495
        $migration = new Migration($config);
496
        $migration->setNoMigrationException(true);
497
498
        return $migration;
499
    }
500
501
    private function dropTables(EntityManager $em)
502
    {
503
        $metadatas = $em->getMetadataFactory()->getAllMetadata();
504
        $schemaTool = new SchemaTool($em);
505
        $schemaTool->dropSchema($metadatas);
506
        $em->getConnection()->executeQuery('DROP TABLE IF EXISTS doctrine_migration_versions');
507
    }
508
509
    private function createTables(EntityManager $em)
510
    {
511
        $metadatas = $em->getMetadataFactory()->getAllMetadata();
512
        $schemaTool = new SchemaTool($em);
513
        $schemaTool->createSchema($metadatas);
514
    }
515
516
    private function importCsv(EntityManager $em)
517
    {
518
        $loader = new \Eccube\Doctrine\Common\CsvDataFixtures\Loader();
519
        $loader->loadFromDirectory($this->rootDir.'/src/Eccube/Resource/doctrine/import_csv');
520
        $executer = new \Eccube\Doctrine\Common\CsvDataFixtures\Executor\DbalExecutor($em);
521
        $fixtures = $loader->getFixtures();
522
        $executer->execute($fixtures);
523
    }
524
525
    private function insert(Connection $conn, array $data)
526
    {
527
        $conn->beginTransaction();
528
        try {
529
            $config = array(
530
                'auth_type' => '',
531
                'auth_magic' => $data['auth_magic'],
532
                'password_hash_algos' => 'sha256',
533
            );
534
            $encoder = new PasswordEncoder($config);
535
            $salt = Str::random(32);
536
            $password = $encoder->encodePassword($data['login_pass'], $salt);
537
538
            $id = ('postgresql' === $conn->getDatabasePlatform()->getName())
539
                ? $conn->fetchColumn("select nextval('dtb_base_info_id_seq')")
540
                : null;
541
542
            $conn->insert('dtb_base_info', [
0 ignored issues
show
introduced by
Add a comma after each item in a multi-line array
Loading history...
543
                'id' => $id,
544
                'shop_name' => $data['shop_name'],
545
                'email01' => $data['email'],
546
                'email02' => $data['email'],
547
                'email03' => $data['email'],
548
                'email04' => $data['email'],
549
                'update_date' => new \DateTime(),
550
                'discriminator_type' => 'baseinfo'
551
            ], [
0 ignored issues
show
Coding Style introduced by
This line of the multi-line function call does not seem to be indented correctly. Expected 16 spaces, but found 12.
Loading history...
introduced by
Add a comma after each item in a multi-line array
Loading history...
552
                'update_date' => \Doctrine\DBAL\Types\Type::DATETIME
553
            ]);
554
555
            $member_id = ('postgresql' === $conn->getDatabasePlatform()->getName())
556
                ? $conn->fetchColumn("select nextval('dtb_member_member_id_seq')")
557
                : null;
558
559
            $conn->insert('dtb_member', [
0 ignored issues
show
introduced by
Add a comma after each item in a multi-line array
Loading history...
560
                'member_id' => $member_id,
561
                'login_id' => $data['login_id'],
562
                'password' => $password,
563
                'salt' => $salt,
564
                'work' => 1,
565
                'authority' => 0,
566
                'creator_id' => 1,
567
                'rank' => 1,
568
                'update_date' => new \DateTime(),
569
                'create_date' => new \DateTime(),
570
                'name' => '管理者',
571
                'department' => 'EC-CUBE SHOP',
572
                'discriminator_type' => 'member'
573
            ], [
0 ignored issues
show
Coding Style introduced by
This line of the multi-line function call does not seem to be indented correctly. Expected 16 spaces, but found 12.
Loading history...
574
                'update_date' => Type::DATETIME,
575
                'create_date' => Type::DATETIME,
576
            ]);
577
            $conn->commit();
578
        } catch (\Exception $e) {
579
            $conn->rollback();
580
            throw $e;
581
        }
582
    }
583
584
    private function update(Connection $conn, array $data)
585
    {
586
        $conn->beginTransaction();
587
        try {
588
            $config = array(
589
                'auth_type' => '',
590
                'auth_magic' => $data['auth_magic'],
591
                'password_hash_algos' => 'sha256',
592
            );
593
            $encoder = new PasswordEncoder($config);
594
            $salt = Str::random(32);
595
            $stmt = $conn->prepare("SELECT member_id FROM dtb_member WHERE login_id = :login_id;");
596
            $stmt->execute([':login_id' => $data['login_id']]);
597
            $row = $stmt->fetch();
598
            $password = $encoder->encodePassword($data['login_pass'], $salt);
599
            if ($row) {
600
                // 同一の管理者IDであればパスワードのみ更新
601
                $sth = $conn->prepare("UPDATE dtb_member set password = :password, salt = :salt, update_date = current_timestamp WHERE login_id = :login_id;");
602
                $sth->execute([
603
                    ':password' => $password,
604
                    ':salt' => $salt,
605
                    ':login_id' => $data['login_id'],
606
                ]);
607
            } else {
608
                // 新しい管理者IDが入力されたらinsert
609
                $sth = $conn->prepare("INSERT INTO dtb_member (login_id, password, salt, work, del_flg, authority, creator_id, rank, update_date, create_date,name,department,discriminator_type) VALUES (:login_id, :password , :salt , '1', '0', '0', '1', '1', current_timestamp, current_timestamp,'管理者','EC-CUBE SHOP', 'member');");
610
                $sth->execute([
611
                    ':login_id' => $data['login_id'],
612
                    ':password' => $password,
613
                    ':salt' => $salt,
614
                ]);
615
            }
616
            $stmt = $conn->prepare('UPDATE dtb_base_info set
617
                shop_name = :shop_name,
618
                email01 = :admin_mail,
619
                email02 = :admin_mail,
620
                email03 = :admin_mail,
621
                email04 = :admin_mail,
622
                update_date = current_timestamp
623
            WHERE id = 1;');
624
            $stmt->execute(array(
625
                ':shop_name' => $data['shop_name'],
626
                ':admin_mail' => $data['email'],
627
            ));
628
            $stmt->commit();
0 ignored issues
show
Bug introduced by
The method commit() does not seem to exist on object<Doctrine\DBAL\Driver\Statement>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
629
        } catch (\Exception $e) {
630
            $stmt->rollback();
0 ignored issues
show
Bug introduced by
The variable $stmt 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...
Bug introduced by
The method rollback() does not seem to exist on object<Doctrine\DBAL\Driver\Statement>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
631
            throw $e;
632
        }
633
    }
634
635
    private function migrate(Migration $migration)
636
    {
637
        try {
638
            // nullを渡すと最新バージョンまでマイグレートする
639
            $migration->migrate(null, false);
640
        } catch (MigrationException $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
Coding Style introduced by
Blank line found at start of control structure
Loading history...
641
642
        }
643
    }
644
645
    private function copyConfigFiles()
646
    {
647
        $src = $this->rootDir.'/src/Eccube/Resource/config';
648
        $dist = $this->configDir;
649
        $fs = new \Symfony\Component\Filesystem\Filesystem();
650
        $fs->mirror($src, $dist, null, ['override' => true]);
651
    }
652
653
    private function createEnvFile(array $data, $updateAuthMagic = true)
654
    {
655
        $values = [];
656
        $path = $this->configDir.'/.env';
657
        if (file_exists($path)) {
658
            $values = (new Dotenv())->parse(file_get_contents($path), $path);
659
        }
660
661
        $values['ECCUBE_INSTALL'] = 1;
662
        $values['ROOT_URLPATH'] = $data['root_urlpath'];
663
664
        if ($updateAuthMagic) {
665
            $values['AUTH_MAGIC'] = Str::random(32);
666
        } else {
667
            if (empty($values['AUTH_MAGIC'])) {
668
                $values['AUTH_MAGIC'] = Str::random(32);
669
            }
670
        }
671
        if (isset($data['force_ssl'])) {
672
            $values['FORCE_SSL'] = $data['force_ssl'];
673
        }
674
        if (isset($data['admin_dir'])) {
675
            $values['ADMIN_ROUTE'] = $data['admin_dir'];
676
        }
677
        if (isset($data['database'])) {
678
            $values['DB_DEFAULT'] = str_replace('pdo_', '', $data['database']);
679
        }
680
        if (isset($data['database_host'])) {
681
            $values['DB_HOST'] = $data['database_host'];
682
        }
683
        if (isset($data['database_port'])) {
684
            $values['DB_PORT'] = $data['database_port'];
685
        }
686
        if (isset($data['database_name'])) {
687
            $values['DB_DATABASE'] = $data['database_name'];
688
        }
689
        if (isset($data['database_user'])) {
690
            $values['DB_USERNAME'] = $data['database_user'];
691
        }
692
        if (isset($data['database_password'])) {
693
            $values['DB_PASSWORD'] = $data['database_password'];
694
        }
695
        if (isset($data['mail_backend'])) {
696
            $values['MAIL_TRANSPORT'] = $data['mail_backend'];
697
        }
698
        if (isset($data['smtp_host'])) {
699
            $values['MAIL_HOST'] = $data['smtp_host'];
700
        }
701
        if (isset($data['smtp_port'])) {
702
            $values['MAIL_PORT'] = $data['smtp_port'];
703
        }
704
        if (isset($data['smtp_username'])) {
705
            $values['MAIL_USERNAME'] = $data['smtp_username'];
706
        }
707
        if (isset($data['smtp_password'])) {
708
            $values['MAIL_PASSWORD'] = $data['smtp_password'];
709
        }
710
        if (isset($data['admin_allow_hosts'])) {
711
            $values['ADMIN_ALLOW_HOSTS'] = $data['admin_allow_hosts'];
712
        }
713
        if (isset($data['admin_allow_hosts'])) {
714
            $hosts = Str::convertLineFeed($data['admin_allow_hosts']);
715
            if ($hosts) {
716
                $values['ADMIN_ALLOW_HOSTS'] = explode("\n", $hosts);
717
            }
718
        }
719
        if (isset($data['trusted_proxies'])) {
720
            $proxies = Str::convertLineFeed($data['trusted_proxies']);
721
            if ($proxies) {
722
                $proxies = explode("\n", $proxies);
723
                // ループバックアドレスを含める
724
                $values['TRUSTED_PROXIES'] = array_merge($proxies, ['127.0.0.1/8', '::1']);
725
            }
726
        }
727
        if (isset($data['trusted_proxies_connection_only']) && $data['trusted_proxies_connection_only']) {
728
            // ループバックアドレスを含める
729
            $values['TRUSTED_PROXIES'] = array_merge($proxies, ['127.0.0.1/8', '::1']);
0 ignored issues
show
Bug introduced by
The variable $proxies 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...
730
        }
731
732
        $content = '';
733
        $format = '%s=%s'.PHP_EOL;
734
        foreach ($values as $key => $value) {
735
            if ($value === true) {
736
                $value = 'true';
737
            }
738
            if ($value === false) {
739
                $value = 'false';
740
            }
741
            if ($value === null) {
742
                $value = 'null';
743
            }
744
            if (is_array($value)) {
745
                $value = implode(',', $value);
746
            }
747
            $content .= sprintf($format, $key, $value);
748
        }
749
750
        file_put_contents($path, $content);
751
    }
752
753
    private function sendAppData($params)
754
    {
755
        $config = require $this->configDir.'/database.php';
756
        $conn = $this->createConnection($config['database']);
757
        $stmt = $conn->query('select version() as v');
758
        $version = '';
759
760
        foreach ($stmt as $row) {
761
            $version = $row['v'];
762
        }
763
764
        if ($config['database']['driver'] === 'pdo_mysql') {
765
            $db_ver = 'MySQL:'.$version;
766
        } else {
767
            $db_ver = $version;
768
        }
769
770
        $data = http_build_query(
771
            array(
772
                'site_url' => $params['http_url'],
773
                'shop_name' => $params['shop_name'],
774
                'cube_ver' => Constant::VERSION,
775
                'php_ver' => phpversion(),
776
                'db_ver' => $db_ver,
777
                'os_type' => php_uname(),
778
            )
779
        );
780
        $header = array(
781
            'Content-Type: application/x-www-form-urlencoded',
782
            'Content-Length: '.strlen($data),
783
        );
784
        $context = stream_context_create(
785
            array(
786
                'http' => array(
787
                    'method' => 'POST',
788
                    'header' => $header,
789
                    'content' => $data,
790
                ),
791
            )
792
        );
793
        file_get_contents('http://www.ec-cube.net/mall/use_site.php', false, $context);
794
795
        return $this;
796
    }
797
798
    /**
799
     * マイグレーション画面を表示する.
800
     *
801
     * @param InstallApplication $app
802
     * @param Request $request
0 ignored issues
show
introduced by
Expected 12 spaces after parameter type; 1 found
Loading history...
803
     *
804
     * @return \Symfony\Component\HttpFoundation\Response
805
     */
806
    public function migration(InstallApplication $app, Request $request)
0 ignored issues
show
Unused Code introduced by
The parameter $request 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...
introduced by
Declare public methods first, then protected ones and finally private ones
Loading history...
807
    {
808
        return $app['twig']->render('migration.twig', array(
809
            'publicPath' => '..'.RELATIVE_PUBLIC_DIR_PATH.'/',
810
        ));
811
    }
812
813
    /**
814
     * インストール済プラグインの一覧を表示する.
815
     * プラグインがインストールされていない場合は, マイグレーション実行画面へリダイレクトする.
816
     *
817
     * @param InstallApplication $app
818
     * @param Request $request
0 ignored issues
show
introduced by
Expected 12 spaces after parameter type; 1 found
Loading history...
819
     *
820
     * @return \Symfony\Component\HttpFoundation\Response
821
     */
822
    public function migration_plugin(InstallApplication $app, Request $request)
0 ignored issues
show
Unused Code introduced by
The parameter $request 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...
Coding Style introduced by
Method name "InstallController::migration_plugin" is not in camel caps format
Loading history...
823
    {
824
        $eccube = \Eccube\Application::getInstance();
825
        $eccube->initialize();
826
        $eccube->boot();
827
        $pluginRepository = $eccube['orm.em']->getRepository('Eccube\Entity\Plugin');
828
        $Plugins = $pluginRepository->findBy(array('del_flg' => Constant::DISABLED));
829
        if (empty($Plugins)) {
830
            // インストール済プラグインがない場合はマイグレーション実行画面へリダイレクト.
831
            return $app->redirect($app->path('migration_end'));
832
        } else {
833
            return $app['twig']->render('migration_plugin.twig', array(
834
                'Plugins' => $Plugins,
835
                'version' => Constant::VERSION,
836
                'publicPath' => '..'.RELATIVE_PUBLIC_DIR_PATH.'/',
837
            ));
838
        }
839
    }
840
841
    /**
842
     * マイグレーションを実行し, 完了画面を表示させる
843
     *
844
     * @param InstallApplication $app
845
     * @param Request $request
0 ignored issues
show
introduced by
Expected 12 spaces after parameter type; 1 found
Loading history...
846
     *
847
     * @return \Symfony\Component\HttpFoundation\Response
848
     */
849
    public function migration_end(InstallApplication $app, Request $request)
0 ignored issues
show
Unused Code introduced by
The parameter $request 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...
Coding Style introduced by
Method name "InstallController::migration_end" is not in camel caps format
Loading history...
850
    {
851
        $this->doMigrate();
0 ignored issues
show
Bug introduced by
The method doMigrate() does not exist on Eccube\Controller\Install\InstallController. Did you maybe mean migrate()?

This check marks calls to methods that do not seem to exist on an object.

This is most likely the result of a method being renamed without all references to it being renamed likewise.

Loading history...
852
        $config_app = new \Eccube\Application(); // install用のappだとconfigが取れないので
853
        $config_app->initialize();
854
        $config_app->boot();
855
        \Eccube\Util\Cache::clear($config_app, true);
856
857
        return $app['twig']->render('migration_end.twig', array(
858
            'publicPath' => '..'.RELATIVE_PUBLIC_DIR_PATH.'/',
859
        ));
860
    }
861
}