Completed
Pull Request — 4.0 (#3993)
by
unknown
05:49
created

InstallController::step2()   B

Complexity

Conditions 6
Paths 10

Size

Total Lines 32

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 42

Importance

Changes 0
Metric Value
cc 6
nc 10
nop 0
dl 0
loc 32
ccs 0
cts 8
cp 0
crap 42
rs 8.7857
c 0
b 0
f 0
1
<?php
2
3
/*
4
 * This file is part of EC-CUBE
5
 *
6
 * Copyright(c) LOCKON CO.,LTD. All Rights Reserved.
7
 *
8
 * http://www.lockon.co.jp/
9
 *
10
 * For the full copyright and license information, please view the LICENSE
11
 * file that was distributed with this source code.
12
 */
13
14
namespace Eccube\Controller\Install;
15
16
use Doctrine\Common\Annotations\AnnotationReader;
17
use Doctrine\Common\Annotations\CachedReader;
18
use Doctrine\Common\Cache\ArrayCache;
19
use Doctrine\DBAL\Connection;
20
use Doctrine\DBAL\DriverManager;
21
use Doctrine\DBAL\Migrations\Configuration\Configuration;
22
use Doctrine\DBAL\Migrations\Migration;
23
use Doctrine\DBAL\Migrations\MigrationException;
24
use Doctrine\DBAL\Types\Type;
25
use Doctrine\ORM\EntityManager;
26
use Doctrine\ORM\Tools\SchemaTool;
27
use Doctrine\ORM\Tools\Setup;
28
use Eccube\Common\Constant;
29
use Eccube\Controller\AbstractController;
30
use Eccube\Doctrine\DBAL\Types\UTCDateTimeType;
31
use Eccube\Doctrine\DBAL\Types\UTCDateTimeTzType;
32
use Eccube\Doctrine\ORM\Mapping\Driver\AnnotationDriver;
33
use Eccube\Form\Type\Install\Step1Type;
34
use Eccube\Form\Type\Install\Step3Type;
35
use Eccube\Form\Type\Install\Step4Type;
36
use Eccube\Form\Type\Install\Step5Type;
37
use Eccube\Security\Core\Encoder\PasswordEncoder;
38
use Eccube\Util\CacheUtil;
39
use Eccube\Util\StringUtil;
40
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
41
use Symfony\Component\Finder\Finder;
42
use Symfony\Component\HttpFoundation\Request;
43
use Symfony\Component\HttpFoundation\Session\SessionInterface;
44
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
45
use Symfony\Component\Routing\Annotation\Route;
46
47
class InstallController extends AbstractController
48
{
49
    /**
50
     * default value of auth magic
51
     */
52
    const DEFAULT_AUTH_MAGIC = '<change.me>';
53
54
    protected $requiredModules = [
55
        'pdo',
56
        'phar',
57
        'mbstring',
58
        'zlib',
59
        'ctype',
60
        'session',
61
        'JSON',
62
        'xml',
63
        'libxml',
64
        'OpenSSL',
65
        'zip',
66
        'cURL',
67
        'fileinfo',
68
        'intl',
69
    ];
70
71
    protected $recommendedModules = [
72
        'hash',
73
        'mcrypt',
74
    ];
75
76
    /**
77
     * @var PasswordEncoder
78
     */
79
    protected $encoder;
80
81
    /**
82
     * @var CacheUtil
83
     */
84
    protected $cacheUtil;
85
86
    public function __construct(PasswordEncoder $encoder, CacheUtil $cacheUtil)
87
    {
88
        $this->encoder = $encoder;
89
        $this->cacheUtil = $cacheUtil;
90
    }
91
92
    /**
93
     * 最初からやり直す場合、SESSION情報をクリア.
94
     *
95
     * @Route("/", name="homepage")
96
     * @Route("/install", name="install")
97
     *
98
     * @Template("index.twig")
99
     *
100
     * @return \Symfony\Component\HttpFoundation\RedirectResponse
101
     */
102
    public function index()
103
    {
104
        if (!$this->isInstallEnv()) {
105
            throw new NotFoundHttpException();
106
        }
107
108
        $this->removeSessionData($this->session);
109
110
        return $this->redirectToRoute('install_step1');
111
    }
112
113
    /**
114
     * ようこそ.
115
     *
116
     * @Route("/install/step1", name="install_step1")
117
     * @Template("step1.twig")
118
     *
119
     * @param Request $request
120
     *
121
     * @return array|\Symfony\Component\HttpFoundation\RedirectResponse
122
     */
123
    public function step1(Request $request)
124
    {
125
        if (!$this->isInstallEnv()) {
126
            throw new NotFoundHttpException();
127
        }
128
129
        $form = $this->formFactory
130
            ->createBuilder(Step1Type::class)
131
            ->getForm();
132
133
        $form->setData($this->getSessionData($this->session));
134
        $form->handleRequest($request);
135
136 View Code Duplication
        if ($form->isSubmitted() && $form->isValid()) {
137
            $this->setSessionData($this->session, $form->getData());
138
139
            return $this->redirectToRoute('install_step2');
140
        }
141
142
        $this->checkModules();
143
144
        $authmagic = $this->getParameter('eccube_auth_magic');
145
        if ($authmagic === self::DEFAULT_AUTH_MAGIC) {
146
            $authmagic = StringUtil::random(32);
147
        }
148
        $this->setSessionData($this->session, ['authmagic' => $authmagic]);
149
150
        return [
151
            'form' => $form->createView(),
152
        ];
153
    }
154
155
    /**
156
     * ディレクトリとファイルの書き込み権限をチェック.
157
     *
158
     * @Route("/install/step2", name="install_step2")
159
     * @Template("step2.twig")
160
     *
161
     * @return array
162
     */
163
    public function step2()
164
    {
165
        if (!$this->isInstallEnv()) {
166
            throw new NotFoundHttpException();
167
        }
168
169
        $noWritePermissions = [];
170
171
        // ディレクトリの書き込み権限をチェック
172
        $targetDirs = Finder::create()
173
            ->in($this->getParameter('kernel.project_dir'))
174
            ->directories();
175
        foreach ($targetDirs as $targetDir) {
176
            if (!is_writable($targetDir->getRealPath())) {
177
                $noWritePermissions[] = $targetDir;
178
            }
179
        }
180
181
        // ファイルの書き込み権限をチェック
182
        $targetFiles = Finder::create()
183
            ->in($this->getParameter('kernel.project_dir'))
184
            ->files();
185
        foreach ($targetFiles as $targetFile) {
186
            if (!is_writable($targetFile->getRealPath())) {
187
                $noWritePermissions[] = $targetFile;
188
            }
189
        }
190
191
        return [
192
            'noWritePermissions' => $noWritePermissions,
193
        ];
194
    }
195
196
    /**
197
     * サイトの設定.
198
     *
199
     * @Route("/install/step3", name="install_step3")
200
     * @Template("step3.twig")
201
     *
202
     * @param Request $request
203
     *
204
     * @return array|\Symfony\Component\HttpFoundation\RedirectResponse
205
     *
206
     * @throws \Doctrine\DBAL\DBALException
207
     * @throws \Exception
208
     */
209
    public function step3(Request $request)
210
    {
211
        if (!$this->isInstallEnv()) {
212
            throw new NotFoundHttpException();
213
        }
214
215
        $sessionData = $this->getSessionData($this->session);
216
217
        // 再インストールの場合は環境変数から復旧
218
        if ($this->isInstalled()) {
219
            // ショップ名/メールアドレス
220
            $conn = $this->entityManager->getConnection();
221
            $stmt = $conn->query('SELECT shop_name, email01 FROM dtb_base_info WHERE id = 1;');
222
            $row = $stmt->fetch();
223
            $sessionData['shop_name'] = $row['shop_name'];
224
            $sessionData['email'] = $row['email01'];
225
226
            $databaseUrl = $this->getParameter('eccube_database_url');
227
            $sessionData = array_merge($sessionData, $this->extractDatabaseUrl($databaseUrl));
228
229
            // 管理画面ルーティング
230
            $sessionData['admin_dir'] = $this->getParameter('eccube_admin_route');
231
232
            // 管理画面許可IP
233
            $sessionData['admin_allow_hosts'] = implode($this->getParameter('eccube_admin_allow_hosts'));
234
235
            // 強制SSL
236
            $sessionData['admin_force_ssl'] = $this->getParameter('eccube_force_ssl');
237
238
            // メール
239
            $mailerUrl = $this->getParameter('eccube_mailer_url');
240
            $sessionData = array_merge($sessionData, $this->extractMailerUrl($mailerUrl));
241
        } else {
242
            // 初期値設定
243
            if (!isset($sessionData['admin_allow_hosts'])) {
244
                $sessionData['admin_allow_hosts'] = '';
245
            }
246
            if (!isset($sessionData['smtp_host'])) {
247
                $sessionData = array_merge($sessionData, $this->extractMailerUrl('smtp://localhost:25'));
248
            }
249
        }
250
251
        $form = $this->formFactory
252
            ->createBuilder(Step3Type::class)
253
            ->getForm();
254
255
        $form->setData($sessionData);
256
        $form->handleRequest($request);
257
258 View Code Duplication
        if ($form->isSubmitted() && $form->isValid()) {
259
            $this->setSessionData($this->session, $form->getData());
260
261
            return $this->redirectToRoute('install_step4');
262
        }
263
264
        return [
265
            'form' => $form->createView(),
266
            'request' => $request,
267
        ];
268
    }
269
270
    /**
271
     * データベースの設定.
272
     *
273
     * @Route("/install/step4", name="install_step4")
274
     * @Template("step4.twig")
275
     *
276
     * @param Request $request
277
     *
278
     * @return array|\Symfony\Component\HttpFoundation\RedirectResponse
279
     *
280
     * @throws \Exception
281
     */
282
    public function step4(Request $request)
283
    {
284
        if (!$this->isInstallEnv()) {
285
            throw new NotFoundHttpException();
286
        }
287
288
        $sessionData = $this->getSessionData($this->session);
289
290
        if (empty($sessionData['database'])) {
291
            // 再インストールの場合は環境変数から復旧.
292
            if ($this->isInstalled()) {
293
                $databaseUrl = $this->getParameter('eccube_database_url');
294
                $sessionData = array_merge($sessionData, $this->extractDatabaseUrl($databaseUrl));
295
            }
296
        }
297
298
        $form = $this->formFactory
299
            ->createBuilder(Step4Type::class)
300
            ->getForm();
301
302
        $form->setData($sessionData);
303
        $form->handleRequest($request);
304
305
        if ($form->isSubmitted() && $form->isValid()) {
306
            $data = $form->getData();
307
            if ($data['database'] === 'pdo_sqlite') {
308
                $data['database_name'] = '/%kernel.project_dir%/var/eccube.db';
309
            }
310
311
            $this->setSessionData($this->session, $data);
312
313
            return $this->redirectToRoute('install_step5');
314
        }
315
316
        return [
317
            'form' => $form->createView(),
318
        ];
319
    }
320
321
    /**
322
     * データベースの初期化.
323
     *
324
     * @Route("/install/step5", name="install_step5")
325
     * @Template("step5.twig")
326
     *
327
     * @param Request $request
328
     *
329
     * @return array|\Symfony\Component\HttpFoundation\RedirectResponse
330
     *
331
     * @throws \Exception
332
     */
333
    public function step5(Request $request)
334
    {
335
        if (!$this->isInstallEnv()) {
336
            throw new NotFoundHttpException();
337
        }
338
339
        $form = $this->formFactory
340
            ->createBuilder(Step5Type::class)
341
            ->getForm();
342
343
        $sessionData = $this->getSessionData($this->session);
344
        $form->setData($sessionData);
345
        $form->handleRequest($request);
346
347
        if ($form->isSubmitted() && $form->isValid()) {
348
            $noUpdate = $form['no_update']->getData();
349
350
            $url = $this->createDatabaseUrl($sessionData);
351
            // for sqlite, resolve %kernel.project_dir% paramter.
352
            $url = $this->container->getParameterBag()->resolveValue($url);
0 ignored issues
show
Bug introduced by
The method getParameterBag() does not exist on Symfony\Component\Depend...tion\ContainerInterface. Did you maybe mean getParameter()?

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...
353
354
            try {
355
                $conn = $this->createConnection(['url' => $url]);
356
                $em = $this->createEntityManager($conn);
357
                $migration = $this->createMigration($conn);
358
359
                if ($noUpdate) {
360
                    $this->update($conn, [
361
                        'auth_magic' => $sessionData['authmagic'],
362
                        'login_id' => $sessionData['login_id'],
363
                        'login_pass' => $sessionData['login_pass'],
364
                        'shop_name' => $sessionData['shop_name'],
365
                        'email' => $sessionData['email'],
366
                    ]);
367
                } else {
368
                    $this->dropTables($em);
369
                    $this->createTables($em);
370
                    $this->importCsv($em);
371
                    $this->migrate($migration);
372
                    $this->insert($conn, [
373
                        'auth_magic' => $sessionData['authmagic'],
374
                        'login_id' => $sessionData['login_id'],
375
                        'login_pass' => $sessionData['login_pass'],
376
                        'shop_name' => $sessionData['shop_name'],
377
                        'email' => $sessionData['email'],
378
                    ]);
379
                }
380
            } catch (\Exception $e) {
381
                log_error($e->getMessage());
382
                $this->addError($e->getMessage());
383
384
                return [
385
                    'form' => $form->createView(),
386
                ];
387
            }
388
389
            if (isset($sessionData['agree']) && $sessionData['agree']) {
390
                $host = $request->getSchemeAndHttpHost();
391
                $basePath = $request->getBasePath();
392
                $params = [
393
                    'http_url' => $host.$basePath,
394
                    'shop_name' => $sessionData['shop_name'],
395
                ];
396
                $this->sendAppData($params, $em);
397
            }
398
            $version = $this->getDatabaseVersion($em);
399
            $this->setSessionData($this->session, ['database_version' => $version]);
400
401
            return $this->redirectToRoute('install_complete');
402
        }
403
404
        return [
405
            'form' => $form->createView(),
406
        ];
407
    }
408
409
    /**
410
     * インストール完了
411
     *
412
     * @Route("/install/complete", name="install_complete")
413
     * @Template("complete.twig")
414
     */
415
    public function complete(Request $request)
416
    {
417
        if (!$this->isInstallEnv()) {
418
            throw new NotFoundHttpException();
419
        }
420
421
        $sessionData = $this->getSessionData($this->session);
422
        $databaseUrl = $this->createDatabaseUrl($sessionData);
423
        $mailerUrl = $this->createMailerUrl($sessionData);
424
        $forceSSL = isset($sessionData['admin_force_ssl']) ? (bool) $sessionData['admin_force_ssl'] : false;
425 View Code Duplication
        if ($forceSSL === false) {
426
            $forceSSL = 'false';
427
        } elseif ($forceSSL === true) {
428
            $forceSSL = 'true';
429
        }
430
        $env = file_get_contents(__DIR__.'/../../../../.env.dist');
431
        $replacement = [
432
            'APP_ENV' => 'prod',
433
            'APP_DEBUG' => '0',
434
            'DATABASE_URL' => $databaseUrl,
435
            'MAILER_URL' => $mailerUrl,
436
            'ECCUBE_AUTH_MAGIC' => $sessionData['authmagic'],
437
            'DATABASE_SERVER_VERSION' => isset($sessionData['database_version']) ? $sessionData['database_version'] : '3',
438
            'ECCUBE_ADMIN_ALLOW_HOSTS' => $this->convertAdminAllowHosts($sessionData['admin_allow_hosts']),
439
            'ECCUBE_FORCE_SSL' => $forceSSL,
440
            'ECCUBE_ADMIN_ROUTE' => isset($sessionData['admin_dir']) ? $sessionData['admin_dir'] : 'admin',
441
            'ECCUBE_COOKIE_PATH' => $request->getBasePath() ? $request->getBasePath() : '/',
442
        ];
443
444
        $env = StringUtil::replaceOrAddEnv($env, $replacement);
445
446
        if ($this->getParameter('kernel.environment') === 'install') {
447
            file_put_contents(__DIR__.'/../../../../.env', $env);
448
        }
449
        $host = $request->getSchemeAndHttpHost();
450
        $basePath = $request->getBasePath();
451
        $adminUrl = $host.$basePath.'/'.$replacement['ECCUBE_ADMIN_ROUTE'];
452
453
        $this->removeSessionData($this->session);
454
455
        $this->cacheUtil->clearCache('prod');
456
457
        return [
458
            'admin_url' => $adminUrl,
459
        ];
460
    }
461
462
    protected function getSessionData(SessionInterface $session)
463
    {
464
        return $session->get('eccube.session.install', []);
465
    }
466
467
    protected function removeSessionData(SessionInterface $session)
468
    {
469
        $session->clear();
470
    }
471
472
    protected function setSessionData(SessionInterface $session, $data = [])
473
    {
474
        $data = array_replace_recursive($this->getSessionData($session), $data);
475
        $session->set('eccube.session.install', $data);
476
    }
477
478
    protected function checkModules()
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...
479
    {
480
        foreach ($this->requiredModules as $module) {
481
            if (!extension_loaded($module)) {
482
                $this->addDanger(trans('install.required_extension_disabled', ['%module%' => $module]), 'install');
483
            }
484
        }
485
        if (!extension_loaded('pdo_mysql') && !extension_loaded('pdo_pgsql')) {
486
            $this->addDanger(trans('install.required_database_extension_disabled'), 'install');
487
        }
488
        foreach ($this->recommendedModules as $module) {
489
            if (!extension_loaded($module)) {
490
                if ($module == 'mcrypt' && PHP_VERSION_ID >= 70100) {
491
                    //The mcrypt extension has been deprecated in PHP 7.1.x
492
                    //http://php.net/manual/en/migration71.deprecated.php
493
                    continue;
494
                }
495
                $this->addInfo(trans('install.recommend_extension_disabled', ['%module%' => $module]), 'install');
496
            }
497
        }
498
        if ('\\' === DIRECTORY_SEPARATOR) { // for Windows
499
            if (!extension_loaded('wincache')) {
500
                $this->addInfo(trans('install.recommend_extension_disabled', ['%module%' => 'wincache']), 'install');
501
            }
502
        } else {
503
            if (!extension_loaded('apc')) {
504
                $this->addInfo(trans('install.recommend_extension_disabled', ['%module%' => 'apc']), 'install');
505
            }
506
        }
507
        if (isset($_SERVER['SERVER_SOFTWARE']) && strpos($_SERVER['SERVER_SOFTWARE'], 'Apache') !== false) {
508
            if (!function_exists('apache_get_modules')) {
509
                $this->addWarning(trans('install.mod_rewrite_unknown'), 'install');
510
            } elseif (!in_array('mod_rewrite', apache_get_modules())) {
511
                $this->addDanger(trans('install.mod_rewrite_disabled'), 'install');
512
            }
513
        } elseif (isset($_SERVER['SERVER_SOFTWARE']) && strpos($_SERVER['SERVER_SOFTWARE'], 'Microsoft-IIS') !== false) {
514
            // iis
515
        } elseif (isset($_SERVER['SERVER_SOFTWARE']) && strpos($_SERVER['SERVER_SOFTWARE'], 'nginx') !== false) {
516
            // nginx
517
        }
518
    }
519
520
    protected function createConnection(array $params)
521
    {
522
        if (strpos($params['url'], 'mysql') !== false) {
523
            $params['charset'] = 'utf8';
524
            $params['defaultTableOptions'] = [
525
                'collate' => 'utf8_general_ci'
526
            ];
527
        }
528
529
        Type::overrideType('datetime', UTCDateTimeType::class);
530
        Type::overrideType('datetimetz', UTCDateTimeTzType::class);
531
532
        $conn = DriverManager::getConnection($params);
533
        $conn->ping();
534
535
        $platform = $conn->getDatabasePlatform();
536
        $platform->markDoctrineTypeCommented('datetime');
537
        $platform->markDoctrineTypeCommented('datetimetz');
538
539
        return $conn;
540
    }
541
542
    protected function createEntityManager(Connection $conn)
543
    {
544
        $paths = [
545
            $this->getParameter('kernel.project_dir').'/src/Eccube/Entity',
546
            $this->getParameter('kernel.project_dir').'/app/Customize/Entity',
547
        ];
548
        $config = Setup::createConfiguration(true);
549
        $driver = new AnnotationDriver(new CachedReader(new AnnotationReader(), new ArrayCache()), $paths);
550
        $driver->setTraitProxiesDirectory($this->getParameter('kernel.project_dir').'/app/proxy/entity');
551
        $config->setMetadataDriverImpl($driver);
552
553
        $em = EntityManager::create($conn, $config);
554
555
        return $em;
556
    }
557
558
    /**
559
     * @param array $params
560
     *
561
     * @return string
562
     */
563
    public function createDatabaseUrl(array $params)
564
    {
565
        if (!isset($params['database'])) {
566
            return null;
567
        }
568
569
        $url = '';
570
        switch ($params['database']) {
571
            case 'pdo_sqlite':
572
                $url = 'sqlite://'.$params['database_name'];
573
                break;
574
575
            case 'pdo_mysql':
576
            case 'pdo_pgsql':
577
                $url = str_replace('pdo_', '', $params['database']);
578
                $url .= '://';
579 View Code Duplication
                if (isset($params['database_user'])) {
580
                    $url .= $params['database_user'];
581
                    if (isset($params['database_password'])) {
582
                        $url .= ':'.$params['database_password'];
583
                    }
584
                    $url .= '@';
585
                }
586 View Code Duplication
                if (isset($params['database_host'])) {
587
                    $url .= $params['database_host'];
588
                    if (isset($params['database_port'])) {
589
                        $url .= ':'.$params['database_port'];
590
                    }
591
                    $url .= '/';
592
                }
593
                $url .= $params['database_name'];
594
                break;
595
        }
596
597
        return $url;
598
    }
599
600
    /**
601
     * @param string $url
602
     *
603
     * @return array
604
     */
605
    public function extractDatabaseUrl($url)
606
    {
607
        if (preg_match('|^sqlite://(.*)$|', $url, $matches)) {
608
            return [
609
                'database' => 'pdo_sqlite',
610
                'database_name' => $matches[1],
611
            ];
612
        }
613
614
        $parsed = parse_url($url);
615
616
        if ($parsed === false) {
617
            throw new \Exception('Malformed parameter "url".');
618
        }
619
620
        return [
621
            'database' => 'pdo_'.$parsed['scheme'],
622
            'database_name' => ltrim($parsed['path'], '/'),
623
            'database_host' => $parsed['host'],
624
            'database_port' => isset($parsed['port']) ? $parsed['port'] : null,
625
            'database_user' => isset($parsed['user']) ? $parsed['user'] : null,
626
            'database_password' => isset($parsed['pass']) ? $parsed['pass'] : null,
627
        ];
628
    }
629
630
    /**
631
     * @param array $params
632
     *
633
     * @return string
634
     *
635
     * @see https://github.com/symfony/swiftmailer-bundle/blob/9728097df87e76e2db71fc41fd7d211c06daea3e/DependencyInjection/SwiftmailerTransportFactory.php#L80-L142
636
     */
637
    public function createMailerUrl(array $params)
638
    {
639
        $url = '';
0 ignored issues
show
Unused Code introduced by
$url is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
640
        if (isset($params['transport'])) {
641
            $url = $params['transport'].'://';
642
        } else {
643
            $url = 'smtp://';
644
        }
645 View Code Duplication
        if (isset($params['smtp_username'])) {
646
            $url .= $params['smtp_username'];
647
            if (isset($params['smtp_password'])) {
648
                $url .= ':'.$params['smtp_password'];
649
            }
650
            $url .= '@';
651
        }
652
653
        $queryStrings = [];
654
        if (isset($params['encryption'])) {
655
            $queryStrings['encryption'] = $params['encryption'];
656
            if ($params['encryption'] === 'ssl' && !isset($params['smtp_port'])) {
657
                $params['smtp_port'] = 465;
658
            }
659
        }
660
        if (isset($params['auth_mode'])) {
661
            $queryStrings['auth_mode'] = $params['auth_mode'];
662
        } else {
663
            if (isset($params['smtp_username'])) {
664
                $queryStrings['auth_mode'] = 'plain';
665
            }
666
        }
667
        ksort($queryStrings, SORT_STRING);
668
669 View Code Duplication
        if (isset($params['smtp_host'])) {
670
            $url .= $params['smtp_host'];
671
            if (isset($params['smtp_port'])) {
672
                $url .= ':'.$params['smtp_port'];
673
            }
674
        }
675
676
        if (isset($params['smtp_username']) || array_values($queryStrings)) {
677
            $url .= '?';
678
            $i = count($queryStrings);
679
            foreach ($queryStrings as $key => $value) {
680
                $url .= $key.'='.$value;
681
                if ($i > 1) {
682
                    $url .= '&';
683
                }
684
                $i--;
685
            }
686
        }
687
688
        return $url;
689
    }
690
691
    /**
692
     * @param string $url
693
     *
694
     * @return array
695
     */
696
    public function extractMailerUrl($url)
697
    {
698
        $options = [
699
            'transport' => null,
700
            'smtp_username' => null,
701
            'smtp_password' => null,
702
            'smtp_host' => null,
703
            'smtp_port' => null,
704
            'encryption' => null,
705
            'auth_mode' => null,
706
        ];
707
708
        if ($url) {
709
            $parts = parse_url($url);
710
            if (isset($parts['scheme'])) {
711
                $options['transport'] = $parts['scheme'];
712
            }
713
            if (isset($parts['user'])) {
714
                $options['smtp_username'] = $parts['user'];
715
            }
716
            if (isset($parts['pass'])) {
717
                $options['smtp_password'] = $parts['pass'];
718
            }
719
            if (isset($parts['host'])) {
720
                $options['smtp_host'] = $parts['host'];
721
            }
722
            if (isset($parts['port'])) {
723
                $options['smtp_port'] = $parts['port'];
724
            }
725
            if (isset($parts['query'])) {
726
                parse_str($parts['query'], $query);
727
                foreach (array_keys($options) as $key) {
728
                    if (isset($query[$key]) && $query[$key] != '') {
729
                        $options[$key] = $query[$key];
730
                    }
731
                }
732
            }
733
        }
734
        if (!isset($options['transport'])) {
735
            $options['transport'] = 'smtp';
736
        } elseif ('gmail' === $options['transport']) {
737
            $options['encryption'] = 'ssl';
738
            $options['auth_mode'] = 'login';
739
            $options['smtp_host'] = 'smtp.gmail.com';
740
            $options['transport'] = 'smtp';
741
        }
742
        if (!isset($options['smtp_port'])) {
743
            $options['smtp_port'] = 'ssl' === $options['encryption'] ? 465 : 25;
744
        }
745
        if (isset($options['smtp_username']) && !isset($options['auth_mode'])) {
746
            $options['auth_mode'] = 'plain';
747
        }
748
        ksort($options, SORT_STRING);
749
750
        return $options;
751
    }
752
753
    protected function createMigration(Connection $conn)
754
    {
755
        $config = new Configuration($conn);
756
        $config->setMigrationsNamespace('DoctrineMigrations');
757
        $migrationDir = $this->getParameter('kernel.project_dir').'/src/Eccube/Resource/doctrine/migration';
758
        $config->setMigrationsDirectory($migrationDir);
759
        $config->registerMigrationsFromDirectory($migrationDir);
760
761
        $migration = new Migration($config);
762
        $migration->setNoMigrationException(true);
763
764
        return $migration;
765
    }
766
767
    protected function dropTables(EntityManager $em)
768
    {
769
        $metadatas = $em->getMetadataFactory()->getAllMetadata();
770
        $schemaTool = new SchemaTool($em);
771
        $schemaTool->dropSchema($metadatas);
772
        $em->getConnection()->executeQuery('DROP TABLE IF EXISTS doctrine_migration_versions');
773
    }
774
775
    protected function createTables(EntityManager $em)
776
    {
777
        $metadatas = $em->getMetadataFactory()->getAllMetadata();
778
        $schemaTool = new SchemaTool($em);
779
        $schemaTool->createSchema($metadatas);
780
    }
781
782
    protected function importCsv(EntityManager $em)
783
    {
784
        $loader = new \Eccube\Doctrine\Common\CsvDataFixtures\Loader();
785
        $loader->loadFromDirectory($this->getParameter('kernel.project_dir').'/src/Eccube/Resource/doctrine/import_csv');
786
        $executer = new \Eccube\Doctrine\Common\CsvDataFixtures\Executor\DbalExecutor($em);
787
        $fixtures = $loader->getFixtures();
788
        $executer->execute($fixtures);
789
    }
790
791
    protected function insert(Connection $conn, array $data)
792
    {
793
        $conn->beginTransaction();
794
        try {
795
            $salt = StringUtil::random(32);
796
            $this->encoder->setAuthMagic($data['auth_magic']);
797
            $password = $this->encoder->encodePassword($data['login_pass'], $salt);
798
799
            $id = ('postgresql' === $conn->getDatabasePlatform()->getName())
800
                ? $conn->fetchColumn("select nextval('dtb_base_info_id_seq')")
801
                : null;
802
803
            $conn->insert('dtb_base_info', [
804
                'id' => $id,
805
                'shop_name' => $data['shop_name'],
806
                'email01' => $data['email'],
807
                'email02' => $data['email'],
808
                'email03' => $data['email'],
809
                'email04' => $data['email'],
810
                'update_date' => new \DateTime(),
811
                'discriminator_type' => 'baseinfo',
812
            ], [
813
                'update_date' => \Doctrine\DBAL\Types\Type::DATETIME,
814
            ]);
815
816
            $member_id = ('postgresql' === $conn->getDatabasePlatform()->getName())
817
                ? $conn->fetchColumn("select nextval('dtb_member_id_seq')")
818
                : null;
819
820
            $conn->insert('dtb_member', [
821
                'id' => $member_id,
822
                'login_id' => $data['login_id'],
823
                'password' => $password,
824
                'salt' => $salt,
825
                'work_id' => 1,
826
                'authority_id' => 0,
827
                'creator_id' => 1,
828
                'sort_no' => 1,
829
                'update_date' => new \DateTime(),
830
                'create_date' => new \DateTime(),
831
                'name' => trans('install.member_name'),
832
                'department' => $data['shop_name'],
833
                'discriminator_type' => 'member',
834
            ], [
835
                'update_date' => Type::DATETIME,
836
                'create_date' => Type::DATETIME,
837
            ]);
838
            $conn->commit();
839
        } catch (\Exception $e) {
840
            $conn->rollback();
841
            throw $e;
842
        }
843
    }
844
845
    protected function update(Connection $conn, array $data)
846
    {
847
        $conn->beginTransaction();
848
        try {
849
            $salt = StringUtil::random(32);
850
            $stmt = $conn->prepare('SELECT id FROM dtb_member WHERE login_id = :login_id;');
851
            $stmt->execute([':login_id' => $data['login_id']]);
852
            $row = $stmt->fetch();
853
            $this->encoder->setAuthMagic($data['auth_magic']);
854
            $password = $this->encoder->encodePassword($data['login_pass'], $salt);
855
            if ($row) {
856
                // 同一の管理者IDであればパスワードのみ更新
857
                $sth = $conn->prepare('UPDATE dtb_member set password = :password, salt = :salt, update_date = current_timestamp WHERE login_id = :login_id;');
858
                $sth->execute([
859
                    ':password' => $password,
860
                    ':salt' => $salt,
861
                    ':login_id' => $data['login_id'],
862
                ]);
863
            } else {
864
                // 新しい管理者IDが入力されたらinsert
865
                $sth = $conn->prepare("INSERT INTO dtb_member (login_id, password, salt, work_id, authority_id, creator_id, sort_no, update_date, create_date,name,department,discriminator_type) VALUES (:login_id, :password , :salt , '1', '0', '1', '1', current_timestamp, current_timestamp,'管理者','EC-CUBE SHOP', 'member');");
866
                $sth->execute([
867
                    ':login_id' => $data['login_id'],
868
                    ':password' => $password,
869
                    ':salt' => $salt,
870
                ]);
871
            }
872
            $stmt = $conn->prepare('UPDATE dtb_base_info set
873
                shop_name = :shop_name,
874
                email01 = :admin_mail,
875
                email02 = :admin_mail,
876
                email03 = :admin_mail,
877
                email04 = :admin_mail,
878
                update_date = current_timestamp
879
            WHERE id = 1;');
880
            $stmt->execute([
881
                ':shop_name' => $data['shop_name'],
882
                ':admin_mail' => $data['email'],
883
            ]);
884
            $conn->commit();
885
        } catch (\Exception $e) {
886
            $conn->rollback();
887
            throw $e;
888
        }
889
    }
890
891
    public function migrate(Migration $migration)
892
    {
893
        try {
894
            // nullを渡すと最新バージョンまでマイグレートする
895
            $migration->migrate(null, false);
896
        } catch (MigrationException $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
897
        }
898
    }
899
900
    /**
901
     * @param array $params
902
     * @param EntityManager $em
903
     *
904
     * @return array
905
     */
906
    public function createAppData($params, EntityManager $em)
907
    {
908
        $platform = $em->getConnection()->getDatabasePlatform()->getName();
909
        $version = $this->getDatabaseVersion($em);
910
        $data = [
911
            'site_url' => $params['http_url'],
912
            'shop_name' => $params['shop_name'],
913
            'cube_ver' => Constant::VERSION,
914
            'php_ver' => phpversion(),
915
            'db_ver' => $platform.' '.$version,
916
            'os_type' => php_uname(),
917
        ];
918
919
        return $data;
920
    }
921
922
    /**
923
     * @param array $params
924
     * @param EntityManager $em
925
     */
926
    protected function sendAppData($params, EntityManager $em)
927
    {
928
        try {
929
            $query = http_build_query($this->createAppData($params, $em));
930
            $header = [
931
                'Content-Type: application/x-www-form-urlencoded',
932
                'Content-Length: '.strlen($query),
933
            ];
934
            $context = stream_context_create(
935
                [
936
                    'http' => [
937
                        'method' => 'POST',
938
                        'header' => $header,
939
                        'content' => $query,
940
                    ],
941
                ]
942
            );
943
            file_get_contents('https://www.ec-cube.net/mall/use_site.php', false, $context);
944
        } catch (\Exception $e) {
945
            // 送信に失敗してもインストールは継続できるようにする
946
            log_error($e->getMessage());
947
        }
948
949
        return $this;
950
    }
951
952
    /**
953
     * @param EntityManager $em
954
     *
955
     * @return string
956
     */
957
    public function getDatabaseVersion(EntityManager $em)
958
    {
959
        $rsm = new \Doctrine\ORM\Query\ResultSetMapping();
960
        $rsm->addScalarResult('server_version', 'server_version');
961
962
        $platform = $em->getConnection()->getDatabasePlatform()->getName();
963
        switch ($platform) {
964
            case 'sqlite':
965
                $sql = 'SELECT sqlite_version() AS server_version';
966
                break;
967
968
            case 'mysql':
969
                $sql = 'SELECT version() AS server_version';
970
                break;
971
972
            case 'pgsql':
973
            default:
974
                $sql = 'SHOW server_version';
975
        }
976
977
        $version = $em->createNativeQuery($sql, $rsm)
978
            ->getSingleScalarResult();
979
980
        return $version;
981
    }
982
983
    /**
984
     * @param string
985
     *
986
     * @return string
987
     */
988
    public function convertAdminAllowHosts($adminAllowHosts)
989
    {
990
        if (empty($adminAllowHosts)) {
991
            return '[]';
992
        }
993
994
        $adminAllowHosts = \json_encode(
995
            \explode("\n", StringUtil::convertLineFeed($adminAllowHosts))
996
        );
997
998
        return "'$adminAllowHosts'";
999
    }
1000
1001
    /**
1002
     * @return bool
1003
     */
1004
    protected function isInstalled()
1005
    {
1006
        return self::DEFAULT_AUTH_MAGIC !== $this->getParameter('eccube_auth_magic');
1007
    }
1008
1009
    /**
1010
     * @return bool
1011
     */
1012
    protected function isInstallEnv()
1013
    {
1014
        $env = $this->getParameter('kernel.environment');
1015
1016
        if ($env === 'install' || $env === 'test') {
1017
            return true;
1018
        }
1019
1020
        return false;
1021
    }
1022
}
1023