Failed Conditions
Pull Request — experimental/3.1 (#2550)
by chihiro
139:43 queued 128:07
created

eccube_install.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
if (php_sapi_name() !== 'cli') {
4
    exit(1);
5
}
6
7
set_time_limit(0);
8
ini_set('display_errors', 1);
9
10
define('COMPOSER_FILE', 'composer.phar');
11
define('COMPOSER_SETUP_FILE', 'composer-setup.php');
12
13
setUseAnsi($argv);
14
15
$argv = is_array($argv) ? $argv : array();
16
17
$argv[1] = isset($argv[1]) ? $argv[1] : null;
18
$argv[2] = isset($argv[2]) ? $argv[2] : null;
19
20
if (in_array('--help', $argv) || empty($argv[1])) {
21
    displayHelp($argv);
22
    exit(0);
23
}
24
25
if (in_array('-v', $argv) || in_array('--version', $argv)) {
26
    require __DIR__.'/src/Eccube/Common/Constant.php';
27
    echo 'EC-CUBE '.Eccube\Common\Constant::VERSION.PHP_EOL;
28
    exit(0);
29
}
30
31
out('EC-CUBE3 installer use database driver of ', null, false);
32
33
switch ($argv[1]) {
34
    case 'mysql':
35
        $database = 'mysql';
36
        break;
37
    case 'pgsql':
38
    case 'postgres':
39
    case 'postgresql':
40
        $database = 'pgsql';
41
        break;
42
    case 'sqlite':
43
    case 'sqlite3':
44
    default:
45
        $database = 'sqlite';
46
}
47
out($database);
48
49
if ($argv[2] != 'none') {
50
    composerSetup();
51
    composerInstall();
52
}
53
54
$loader = require __DIR__.'/autoload.php';
55
56
initializeDefaultVariables($database);
57
58
if (in_array('-V', $argv) || in_array('--verbose', $argv)) {
59
    displayEnvironmentVariables();
60
}
61
62
out('update permissions...');
63
updatePermissions($argv);
64
65
if (!in_array('--skip-createdb', $argv)) {
66
    $params = getDatabaseConfig();
67
    if ($params['driver'] === 'pdo_sqlite') {
68
        $dbname = $params['path'];
69
    } else {
70
        $dbname = $params['dbname'];
71
    }
72
    $conn = createConnection($params, true);
73
    createDatabase($conn, $dbname);
74
}
75
76
out('Created database connection...', 'info');
77
78
$conn = createConnection(getDatabaseConfig());
79
80
if (!in_array('--skip-initdb', $argv)) {
81
    $em = createEntityManager($conn);
82
    initializeDatabase($em);
83
}
84
85
copyConfigFiles();
86
replaceConfigFiles();
87
88
out('EC-CUBE3 install finished successfully!', 'success');
89
$root_urlpath = env('ECCUBE_ROOT_URLPATH');
90
if (PHP_VERSION_ID >= 50400 && empty($root_urlpath)) {
91
    out('PHP built-in web server to run applications, `php -S localhost:8080`', 'info');
92
    out('Open your browser and access the http://localhost:8080/', 'info');
93
}
94
exit(0);
95
96
function displayHelp($argv)
97
{
98
    echo <<<EOF
99
EC-CUBE3 Installer
100
------------------
101
Usage:
102
${argv[0]} [mysql|pgsql|sqlite3] [none] [options]
103
104
Arguments[1]:
105
Specify database types
106
107
Arguments[2]:
108
Specifying the "none" to skip the installation of Composer
109
110
Options:
111
-v, --version        print ec-cube version
112
-V, --verbose        enable verbose output
113
--skip-createdb      skip to create database
114
--skip-initdb        skip to initialize database
115
--help               this help
116
--ansi               force ANSI color output
117
--no-ansi            disable ANSI color output
118
119
Environment variables:
120
121
EOF;
122
    foreach (getExampleVariables() as $name => $value) {
123
        echo $name.'='.$value.PHP_EOL;
124
    }
125
}
126
127
function initializeDefaultVariables($database)
128
{
129
    // heroku用定義
130
    $database_url = env('DATABASE_URL');
131
    if ($database_url) {
132
        $url = parse_url($database_url);
133
        putenv('ECCUBE_DB_DEFAULT='.$url['scheme']);
134
        putenv('ECCUBE_DB_HOST='.$url['host']);
135
        putenv('ECCUBE_DB_DATABASE='.substr($url['path'], 1));
136
        putenv('ECCUBE_DB_USERNAME='.$url['user']);
137
        putenv('ECCUBE_DB_PORT='.$url['port']);
138
        putenv('ECCUBE_DB_PASSWORD='.$url['pass']);
139
    }
140
141
    switch ($database) {
142
        case 'pgsql':
143
            putenv('ECCUBE_ROOTUSER='.env('ECCUBE_ROOTUSER', env('ECCUBE_DB_USERNAME', 'postgres')));
144
            putenv('ECCUBE_ROOTPASS='.env('ECCUBE_ROOTPASS', env('ECCUBE_DB_PASSWORD', 'password')));
145
            break;
146
        case 'mysql':
147
            putenv('ECCUBE_ROOTUSER='.env('ROOTUSER', env('ECCUBE_DB_USERNAME', 'root')));
148
            putenv('ECCUBE_ROOTPASS='.env('ROOTPASS', env('ECCUBE_DB_PASSWORD', 'password')));
149
            break;
150
        case 'sqlite':
151
            putenv('ECCUBE_DB_DATABASE='.__DIR__.'/app/config/eccube/eccube.db');
152
            break;
153
        default:
154
    }
155
    putenv('ECCUBE_DB_DEFAULT='.$database);
156
    putenv('ECCUBE_AUTH_MAGIC='.env('ECCUBE_AUTH_MAGIC', \Eccube\Util\Str::random(32)));
157
    putenv('ECCUBE_ADMIN_USER='.env('ECCUBE_ADMIN_USER', 'admin'));
158
    putenv('ECCUBE_ADMIN_PASS='.env('ECCUBE_ADMIN_PASS', 'password'));
159
    putenv('ECCUBE_ADMIN_MAIL='.env('ECCUBE_ADMIN_MAIL', '[email protected]'));
160
    putenv('ECCUBE_SHOP_NAME='.env('ECCUBE_SHOP_NAME', 'EC-CUBE SHOP'));
161
}
162
163
function getExampleVariables()
164
{
165
    return [
166
        'ECCUBE_ADMIN_USER' => 'admin',
167
        'ECCUBE_ADMIN_MAIL' => '[email protected]',
168
        'ECCUBE_SHOP_NAME' => 'EC-CUBE SHOP',
169
        'ECCUBE_ROOTUSER' => 'root|postgres',
170
        'ECCUBE_ROOTPASS' => 'password',
171
        'ECCUBE_AUTH_MAGIC' => '<auth magic>',
172
        'ECCUBE_FORCE_SSL' => 'false',
173
        'ECCUBE_ADMIN_ALLOW_HOSTS' => '[]',
174
        'ECCUBE_COOKIE_LIFETIME' => '0',
175
        'ECCUBE_COOKIE_NAME' => 'eccube',
176
        'ECCUBE_LOCALE' => 'ja',
177
        'ECCUBE_TIMEZONE' => 'Asia/Tokyo',
178
        'ECCUBE_CURRENCY' => 'JPY',
179
        'ECCUBE_ROOT_URLPATH' => '<eccube root url>',
180
        'ECCUBE_TEMPLATE_CODE' => 'default',
181
        'ECCUBE_ADMIN_ROUTE' => 'admin',
182
        'ECCUBE_USER_DATA_ROUTE' => 'user_data',
183
        'ECCUBE_TRUSTED_PROXIES_CONNECTION_ONLY' => 'false',
184
        'ECCUBE_TRUSTED_PROXIES' => '["127.0.0.1/8", "::1"]',
185
        'ECCUBE_DB_DEFAULT' => 'mysql',
186
        'ECCUBE_DB_HOST' => '127.0.0.1',
187
        'ECCUBE_DB_PORT' => '<database port>',
188
        'ECCUBE_DB_DATABASE' => 'eccube_db',
189
        'ECCUBE_DB_USERNAME' => 'eccube_db_user',
190
        'ECCUBE_DB_PASSWORD' => 'password',
191
        'ECCUBE_DB_CHARASET' => 'utf8',
192
        'ECCUBE_DB_COLLATE' => 'utf8_general_ci',
193
        'ECCUBE_MAIL_TRANSPORT' => 'smtp',
194
        'ECCUBE_MAIL_HOST' => 'localhost',
195
        'ECCUBE_MAIL_PORT' => '1025',
196
        'ECCUBE_MAIL_USERNAME' => '<SMTP AUTH user>',
197
        'ECCUBE_MAIL_PASSWORD' => '<SMTP AUTH password>',
198
        'ECCUBE_MAIL_ENCRYPTION' => null,
199
        'ECCUBE_MAIL_AUTH_MODE' => null,
200
        'ECCUBE_MAIL_CHARSET_ISO_2022_JP' => 'false',
201
        'ECCUBE_MAIL_SPOOL' => 'false',
202
    ];
203
}
204
205
function displayEnvironmentVariables()
206
{
207
    echo 'Environment variables:'.PHP_EOL;
208
    foreach (array_keys(getExampleVariables()) as $name) {
209
        echo $name.'='.env($name).PHP_EOL;
210
    }
211
}
212
213
function composerSetup()
214
{
215
    if (!file_exists(__DIR__.'/'.COMPOSER_FILE)) {
216
        if (!file_exists(__DIR__.'/'.COMPOSER_SETUP_FILE)) {
217
            copy('https://getcomposer.org/installer', COMPOSER_SETUP_FILE);
218
        }
219
220
        $sha = hash_file('SHA384', COMPOSER_SETUP_FILE).PHP_EOL;
221
        out(COMPOSER_SETUP_FILE.': '.$sha);
222
223
        $command = 'php '.COMPOSER_SETUP_FILE;
224
        out("execute: $command", 'info');
225
        passthru($command);
226
        unlink(COMPOSER_SETUP_FILE);
227
    } else {
228
        $command = 'php '.COMPOSER_FILE.' self-update';
229
        passthru($command);
230
    }
231
}
232
233
function composerInstall()
234
{
235
    $command = 'php '.COMPOSER_FILE.' install --dev --no-interaction';
236
    passthru($command);
237
}
238
239
function getDatabaseConfig()
240
{
241
    $config = require __DIR__.'/src/Eccube/Resource/config/database.php';
242
    $default = $config['database']['default'];
243
244
    return $config['database'][$default];
245
}
246
247
function createDatabase(\Doctrine\DBAL\Connection $conn, $dbname)
248
{
249
    $sm = $conn->getSchemaManager();
250
251
    if ($conn->getDatabasePlatform()->getName() === 'sqlite') {
252
        out('unlink database to '.$dbname, 'info');
253
        if (file_exists($dbname)) {
254
            unlink($dbname);
255
        }
256
    } else {
257
        $databases = $sm->listDatabases();
258
        if (in_array($dbname, $databases)) {
259
            out('database exists '.$dbname, 'info');
260
            out('drop database to '.$dbname, 'info');
261
            $sm->dropDatabase($dbname);
262
        }
263
    }
264
    out('create database to '.$dbname, 'info');
265
    $sm->createDatabase($dbname);
266
}
267
268
function createConnection(array $params, $noDb = false)
269
{
270
    if ($noDb) {
271
        unset($params['dbname']);
272
    }
273
    return \Doctrine\DBAL\DriverManager::getConnection($params);
274
}
275
276
function createEntityManager(\Doctrine\DBAL\Connection $conn)
277
{
278
    $paths = [
279
        __DIR__.'/src/Eccube/Entity',
280
        __DIR__.'/app/Acme/Entity',
281
    ];
282
    // todo プロキシ, プラグインの対応
283
    $config = \Doctrine\ORM\Tools\Setup::createAnnotationMetadataConfiguration($paths, true, null, null, false);
284
285
    return \Doctrine\ORM\EntityManager::create($conn, $config);
286
}
287
288 View Code Duplication
function createMigration(\Doctrine\DBAL\Connection $conn)
289
{
290
    $config = new \Doctrine\DBAL\Migrations\Configuration\Configuration($conn);
291
    $config->setMigrationsNamespace('DoctrineMigrations');
292
    $migrationDir = __DIR__.'/src/Eccube/Resource/doctrine/migration';
293
    $config->setMigrationsDirectory($migrationDir);
294
    $config->registerMigrationsFromDirectory($migrationDir);
295
296
    $migration = new \Doctrine\DBAL\Migrations\Migration($config);
297
    $migration->setNoMigrationException(true);
298
299
    return $migration;
300
}
301
302
function initializeDatabase(\Doctrine\ORM\EntityManager $em)
303
{
304
    // Clear Doctrine to be safe
305
    $em->getConnection()->getConfiguration()->setSQLLogger(null);
306
    $em->clear();
307
    gc_collect_cycles();
308
309
    // Schema Tool to process our entities
310
    $tool = new \Doctrine\ORM\Tools\SchemaTool($em);
311
    $classes = $em->getMetaDataFactory()->getAllMetaData();
312
313
    // Drop all classes and re-build them for each test case
314
    out('Dropping database schema...', 'info');
315
    $tool->dropSchema($classes);
316
    out('Creating database schema...', 'info');
317
    $tool->createSchema($classes);
318
    out('Database schema created successfully!', 'success');
319
320
    $loader = new \Eccube\Doctrine\Common\CsvDataFixtures\Loader();
321
    $loader->loadFromDirectory(__DIR__.'/src/Eccube/Resource/doctrine/import_csv');
322
    $executer = new \Eccube\Doctrine\Common\CsvDataFixtures\Executor\DbalExecutor($em);
323
    $fixtures = $loader->getFixtures();
324
    $executer->execute($fixtures);
325
326
    out('Migrating database schema...', 'info');
327
    $migration = createMigration($em->getConnection());
328
    $migration->migrate();
329
    out('Database migration successfully!', 'success');
330
331
    out('Creating admin accounts...', 'info');
332
    $login_id = env('ECCUBE_ADMIN_USER');
333
    $login_password = env('ECCUBE_ADMIN_PASS');
334
335
    $encoder = new \Eccube\Security\Core\Encoder\PasswordEncoder([
336
        'auth_type' => '',
337
        'auth_magic' => env('ECCUBE_AUTH_MAGIC'),
338
        'password_hash_algos' => 'sha256',
339
    ]);
340
    $salt = \Eccube\Util\Str::random(32);
341
    $password = $encoder->encodePassword($login_password, $salt);
342
343
    $conn = $em->getConnection();
344
    $member_id = ('postgresql' === $conn->getDatabasePlatform()->getName())
345
        ? $conn->fetchColumn("select nextval('dtb_member_member_id_seq')")
346
        : null;
347
348
    $conn->insert('dtb_member', [
349
        'member_id' => $member_id,
350
        'login_id' => $login_id,
351
        'password' => $password,
352
        'salt' => $salt,
353
        'work' => 1,
354
        'authority' => 0,
355
        'creator_id' => 1,
356
        'rank' => 1,
357
        'update_date' => new \DateTime(),
358
        'create_date' => new \DateTime(),
359
        'name' => '管理者',
360
        'department' => 'EC-CUBE SHOP',
361
        'discriminator_type' => 'member',
362
    ], [
363
        'update_date' => Doctrine\DBAL\Types\Type::DATETIME,
364
        'create_date' => Doctrine\DBAL\Types\Type::DATETIME,
365
    ]);
366
367
    $shop_name = env('ECCUBE_SHOP_NAME');
368
    $admin_mail = env('ECCUBE_ADMIN_MAIL');
369
370
    $id = ('postgresql' === $conn->getDatabasePlatform()->getName())
371
        ? $conn->fetchColumn("select nextval('dtb_base_info_id_seq')")
372
        : null;
373
374
    $conn->insert('dtb_base_info', [
375
        'id' => $id,
376
        'shop_name' => $shop_name,
377
        'email01' => $admin_mail,
378
        'email02' => $admin_mail,
379
        'email03' => $admin_mail,
380
        'email04' => $admin_mail,
381
        'update_date' => new \DateTime(),
382
        'discriminator_type' => 'baseinfo',
383
    ], [
384
        'update_date' => \Doctrine\DBAL\Types\Type::DATETIME,
385
    ]);
386
}
387
388
function updatePermissions($argv)
389
{
390
    $finder = \Symfony\Component\Finder\Finder::create();
391
    $finder
392
        ->in('html')->notName('.htaccess')
393
        ->in('app')->notName('console');
394
395
    $verbose = false;
396
    if (in_array('-V', $argv) || in_array('--verbose', $argv)) {
397
        $verbose = true;
398
    }
399
    foreach ($finder as $content) {
400
        $permission = $content->getPerms();
401
        // see also http://www.php.net/fileperms
402
        if (!($permission & 0x0010) || !($permission & 0x0002)) {
403
            $realPath = $content->getRealPath();
404
            if ($verbose) {
405
                out(sprintf('%s %s to ', $realPath, substr(sprintf('%o', $permission), -4)), 'info', false);
406
            }
407
            $permission = !($permission & 0x0020) ? $permission += 040 : $permission; // g+r
408
            $permission = !($permission & 0x0010) ? $permission += 020 : $permission; // g+w
409
            $permission = !($permission & 0x0004) ? $permission += 04 : $permission;  // o+r
410
            $permission = !($permission & 0x0002) ? $permission += 02 : $permission;  // o+w
411
            $result = chmod($realPath, $permission);
412
            if ($verbose) {
413
                if ($result) {
414
                    out(substr(sprintf('%o', $permission), -4), 'info');
415
                } else {
416
                    out('failure', 'error');
417
                }
418
            }
419
        }
420
    }
421
}
422
423
function copyConfigFiles()
424
{
425
    $src = __DIR__.'/src/Eccube/Resource/config';
426
    $dist = __DIR__.'/app/config/eccube';
427
    $fs = new \Symfony\Component\Filesystem\Filesystem();
428
    $fs->mirror($src, $dist, null, ['override' => true]);
429
}
430
431
function replaceConfig($keys, $content)
432
{
433
    $patternFormat = "/(env\('%s'.*?\),)/s";
434
    $replacementFormat = "env('%s', %s),";
435
436
    foreach ($keys as $key) {
437
        // 環境変数が未定義の場合はスキップ.
438
        $value = getenv($key);
439
        if ($value === false) {
440
            continue;
441
        }
442
        // インストール時のみ必要な環境はスキップ.
443
        $installOnly = [
444
            'ECCUBE_ADMIN_USER',
445
            'ECCUBE_ADMIN_MAIL',
446
            'ECCUBE_SHOP_NAME',
447
        ];
448
        if (in_array($key, $installOnly)) {
449
            continue;
450
        }
451
452
        $value = env($key);
453
454 View Code Duplication
        if (is_bool($value)
455
            || is_null($value)
456
            || is_array($value)
457
            || is_numeric($value)
458
        ) {
459
            $value = var_export($value, true);
460
        } else {
461
            $value = "'".$value."'";
462
        }
463
464
        $pattern = sprintf($patternFormat, $key);
465
        $replacement = sprintf($replacementFormat, $key, $value);
466
467
        $content = preg_replace($pattern, $replacement, $content);
468
        if (is_null($content)) {
469
            out('config replace failed.', 'error');
470
            out("-> $key : $value", 'error');
471
            exit(1);
0 ignored issues
show
Coding Style Compatibility introduced by
The function replaceConfig() 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...
472
        }
473
    }
474
475
    return $content;
476
}
477
478
function replaceConfigFiles()
479
{
480
    $dir = __DIR__.'/app/config/eccube';
481
    $files = [
482
        $dir.'/config.php',
483
        $dir.'/database.php',
484
        $dir.'/mail.php',
485
        $dir.'/path.php',
486
    ];
487
    $keys = array_keys(getExampleVariables());
488
489
    putenv('ECCUBE_INSTALL=1');
490
    $keys[] = 'ECCUBE_INSTALL';
491
492
    foreach ($files as $file) {
493
        $content = file_get_contents($file);
494
        $replaced = replaceConfig($keys, $content);
495
        if ($content !== $replaced) {
496
            file_put_contents($file, $replaced);
497
        }
498
    }
499
}
500
/**
501
 * @link https://github.com/composer/windows-setup/blob/master/src/php/installer.php
502
 */
503
function setUseAnsi($argv)
504
{
505
    // --no-ansi wins over --ansi
506
    if (in_array('--no-ansi', $argv)) {
507
        define('USE_ANSI', false);
508
    } elseif (in_array('--ansi', $argv)) {
509
        define('USE_ANSI', true);
510
    } else {
511
        // On Windows, default to no ANSI, except in ANSICON and ConEmu.
512
        // Everywhere else, default to ANSI if stdout is a terminal.
513
        define(
514
            'USE_ANSI',
515
            (DIRECTORY_SEPARATOR == '\\')
516
                ? (false !== getenv('ANSICON') || 'ON' === getenv('ConEmuANSI'))
517
                : (function_exists('posix_isatty') && posix_isatty(1))
518
        );
519
    }
520
}
521
522
/**
523
 * @link https://github.com/composer/windows-setup/blob/master/src/php/installer.php
524
 */
525
function out($text, $color = null, $newLine = true)
526
{
527
    $styles = array(
528
        'success' => "\033[0;32m%s\033[0m",
529
        'error' => "\033[31;31m%s\033[0m",
530
        'info' => "\033[33;33m%s\033[0m",
531
    );
532
    $format = '%s';
533
    if (isset($styles[$color]) && USE_ANSI) {
534
        $format = $styles[$color];
535
    }
536
    if ($newLine) {
537
        $format .= PHP_EOL;
538
    }
539
    printf($format, $text);
540
}
541