InstallController   F
last analyzed

Complexity

Total Complexity 88

Size/Duplication

Total Lines 872
Duplicated Lines 2.98 %

Coupling/Cohesion

Components 1
Dependencies 22
Metric Value
wmc 88
lcom 1
cbo 22
dl 26
loc 872
rs 1.263

30 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 1
A isValid() 0 16 4
A getSessionData() 0 4 1
A index() 0 6 1
A step1() 0 18 2
A step2() 0 20 2
B step3() 0 62 6
B step4() 0 41 5
B step5() 0 59 5
A complete() 0 14 1
A resetNatTimer() 0 7 1
F checkModules() 0 40 18
A setPDO() 0 16 2
A dropTables() 14 14 1
B getEntityManager() 0 28 1
A createTables() 12 12 1
A insert() 0 59 2
A update() 0 62 3
A getMigration() 0 17 1
A doMigrate() 0 18 3
A getProtectedDirs() 0 23 3
B createConfigYamlFile() 0 45 5
A addInstallStatus() 0 10 1
B createDatabaseYamlFile() 0 54 7
B createMailYamlFile() 0 26 2
B createPathYamlFile() 0 27 2
A sendAppData() 0 47 3
A migration() 0 4 1
A migration_plugin() 0 18 2
A migration_end() 0 11 1

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complex Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like InstallController often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use InstallController, and based on these observations, apply Extract Interface, too.

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
25
namespace Eccube\Controller\Install;
26
27
use Doctrine\DBAL\Migrations\Configuration\Configuration;
28
use Doctrine\DBAL\Migrations\Migration;
29
use Doctrine\DBAL\Migrations\MigrationException;
30
use Doctrine\ORM\EntityManager;
31
use Doctrine\ORM\Tools\SchemaTool;
32
use Eccube\Common\Constant;
33
use Eccube\InstallApplication;
34
use Eccube\Util\Str;
35
use Symfony\Component\Filesystem\Filesystem;
36
use Symfony\Component\Finder\Finder;
37
use Symfony\Component\Form\Form;
38
use Symfony\Component\HttpFoundation\Request;
39
use Symfony\Component\Yaml\Yaml;
40
41
class InstallController
0 ignored issues
show
introduced by
Missing class doc comment
Loading history...
42
{
43
    private $app;
44
45
    private $PDO;
46
47
    private $config_path;
48
49
    private $dist_path;
50
51
    private $cache_path;
52
53
    private $session_data;
54
55
    private $required_modules = array('pdo', 'phar', 'mbstring', 'zlib', 'ctype', 'session', 'JSON', 'xml', 'libxml', 'OpenSSL', 'zip', 'cURL', 'fileinfo');
56
57
    private $recommended_module = array('hash', 'mcrypt');
58
59
    const SESSION_KEY = 'eccube.session.install';
60
61
    public function __construct()
0 ignored issues
show
introduced by
Missing function doc comment
Loading history...
62
    {
63
        $this->config_path = __DIR__ . '/../../../../app/config/eccube';
0 ignored issues
show
Coding Style introduced by
Concat operator must not be surrounded by spaces
Loading history...
64
        $this->dist_path = __DIR__ . '/../../Resource/config';
0 ignored issues
show
Coding Style introduced by
Concat operator must not be surrounded by spaces
Loading history...
65
        $this->cache_path = __DIR__ . '/../../../../app/cache';
0 ignored issues
show
Coding Style introduced by
Concat operator must not be surrounded by spaces
Loading history...
66
    }
67
68
    private function isValid(Request $request, Form $form)
69
    {
70
        $session = $request->getSession();
71
        if ('POST' === $request->getMethod()) {
72
            $form->handleRequest($request);
73
            if ($form->isValid()) {
74
                $sessionData = $session->get(self::SESSION_KEY) ?: array();
75
                $formData = array_replace_recursive($sessionData, $form->getData());
76
                $session->set(self::SESSION_KEY, $formData);
77
78
                return true;
79
            }
80
        }
81
82
        return false;
83
    }
84
85
    private function getSessionData(Request $request)
86
    {
87
        return $this->session_data = $request->getSession()->get(self::SESSION_KEY);
88
    }
89
90
    // 最初からやり直す場合、SESSION情報をクリア
91
    public function index(InstallApplication $app, Request $request)
0 ignored issues
show
introduced by
Declare public methods first, then protected ones and finally private ones
Loading history...
introduced by
You must use "/**" style comments for a function comment
Loading history...
92
    {
93
        $request->getSession()->remove(self::SESSION_KEY);
94
95
        return $app->redirect($app->url('install_step1'));
96
    }
97
98
    // ようこそ
99
    public function step1(InstallApplication $app, Request $request)
0 ignored issues
show
introduced by
You must use "/**" style comments for a function comment
Loading history...
100
    {
101
        $form = $app['form.factory']
102
            ->createBuilder('install_step1')
103
            ->getForm();
104
        $sessionData = $this->getSessionData($request);
105
        $form->setData($sessionData);
106
107
        if ($this->isValid($request, $form)) {
108
            return $app->redirect($app->url('install_step2'));
109
        }
110
111
        $this->checkModules($app);
112
113
        return $app['twig']->render('step1.twig', array(
114
            'form' => $form->createView(),
115
        ));
116
    }
117
118
    // 権限チェック
119
    public function step2(InstallApplication $app, Request $request)
0 ignored issues
show
introduced by
You must use "/**" style comments for a function comment
Loading history...
120
    {
121
        $this->getSessionData($request);
122
123
        $protectedDirs = $this->getProtectedDirs();
124
125
        // 権限がある場合, キャッシュディレクトリをクリア
126
        if (empty($protectedDirs)) {
127
            $finder = Finder::create()
128
                ->in($this->cache_path)
129
                ->directories()
130
                ->depth(0);
131
            $fs = new Filesystem();
132
            $fs->remove($finder);
133
        }
134
135
        return $app['twig']->render('step2.twig', array(
136
            'protectedDirs' => $protectedDirs,
137
        ));
138
    }
139
140
    //    サイトの設定
141
    public function step3(InstallApplication $app, Request $request)
0 ignored issues
show
introduced by
You must use "/**" style comments for a function comment
Loading history...
142
    {
143
        $form = $app['form.factory']
144
            ->createBuilder('install_step3')
145
            ->getForm();
146
        $sessionData = $this->getSessionData($request);
147
148
        if (empty($sessionData['shop_name'])) {
0 ignored issues
show
Coding Style introduced by
Blank line found at start of control structure
Loading history...
149
150
            $config_file = $this->config_path . '/config.yml';
0 ignored issues
show
Coding Style introduced by
Concat operator must not be surrounded by spaces
Loading history...
151
            $fs = new Filesystem();
152
153
            if ($fs->exists($config_file)) {
154
                // すでに登録されていた場合、登録データを表示
155
                $this->setPDO();
156
                $stmt = $this->PDO->query("SELECT shop_name, email01 FROM dtb_base_info WHERE id = 1;");
157
158
                foreach ($stmt as $row) {
159
                    $sessionData['shop_name'] = $row['shop_name'];
160
                    $sessionData['email'] = $row['email01'];
161
                }
162
163
                // セキュリティの設定
164
                $config_file = $this->config_path . '/path.yml';
0 ignored issues
show
Coding Style introduced by
Concat operator must not be surrounded by spaces
Loading history...
165
                $config = Yaml::parse(file_get_contents($config_file));
166
                $sessionData['admin_dir'] = $config['admin_route'];
167
168
                $config_file = $this->config_path . '/config.yml';
0 ignored issues
show
Coding Style introduced by
Concat operator must not be surrounded by spaces
Loading history...
169
                $config = Yaml::parse(file_get_contents($config_file));
170
171
                $allowHost = $config['admin_allow_host'];
172
                if (count($allowHost) > 0) {
173
                    $sessionData['admin_allow_hosts'] = Str::convertLineFeed(implode("\n", $allowHost));
174
                }
175
                $sessionData['admin_force_ssl'] = (bool)$config['force_ssl'];
0 ignored issues
show
Coding Style introduced by
As per coding-style, a cast statement should be followed by a single space.
Loading history...
176
177
                // メール設定
178
                $config_file = $this->config_path . '/mail.yml';
0 ignored issues
show
Coding Style introduced by
Concat operator must not be surrounded by spaces
Loading history...
179
                $config = Yaml::parse(file_get_contents($config_file));
180
                $mail = $config['mail'];
181
                $sessionData['mail_backend'] = $mail['transport'];
182
                $sessionData['smtp_host'] = $mail['host'];
183
                $sessionData['smtp_port'] = $mail['port'];
184
                $sessionData['smtp_username'] = $mail['username'];
185
                $sessionData['smtp_password'] = $mail['password'];
186
            } else {
187
                // 初期値にmailを設定
188
                $sessionData['mail_backend'] = 'mail';
189
            }
190
        }
191
192
        $form->setData($sessionData);
193
        if ($this->isValid($request, $form)) {
194
            $data = $form->getData();
0 ignored issues
show
Unused Code introduced by
$data 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...
195
196
            return $app->redirect($app->url('install_step4'));
197
        }
198
199
        return $app['twig']->render('step3.twig', array(
200
            'form' => $form->createView(),
201
        ));
202
    }
203
204
    //    データベースの設定
205
    public function step4(InstallApplication $app, Request $request)
0 ignored issues
show
introduced by
You must use "/**" style comments for a function comment
Loading history...
206
    {
207
        $form = $app['form.factory']
208
            ->createBuilder('install_step4')
209
            ->getForm();
210
211
        $sessionData = $this->getSessionData($request);
212
213
        if (empty($sessionData['database'])) {
0 ignored issues
show
Coding Style introduced by
Blank line found at start of control structure
Loading history...
214
215
            $config_file = $this->config_path.'/database.yml';
216
            $fs = new Filesystem();
217
218
            if ($fs->exists($config_file)) {
219
                // すでに登録されていた場合、登録データを表示
220
221
                // データベース設定
222
                $config = Yaml::parse(file_get_contents($config_file));
223
                $database = $config['database'];
224
                $sessionData['database'] = $database['driver'];
225
                if ($database['driver'] != 'pdo_sqlite') {
226
                    $sessionData['database_host'] = $database['host'];
227
                    $sessionData['database_port'] = $database['port'];
228
                    $sessionData['database_name'] = $database['dbname'];
229
                    $sessionData['database_user'] = $database['user'];
230
                    $sessionData['database_password'] = $database['password'];
231
                }
232
            }
233
        }
234
235
        $form->setData($sessionData);
236
237
        if ($this->isValid($request, $form)) {
0 ignored issues
show
Coding Style introduced by
Blank line found at start of control structure
Loading history...
238
239
            return $app->redirect($app->url('install_step5'));
240
        }
241
242
        return $app['twig']->render('step4.twig', array(
243
            'form' => $form->createView(),
244
        ));
245
    }
246
247
    //    データベースの初期化
248
    public function step5(InstallApplication $app, Request $request)
0 ignored issues
show
introduced by
You must use "/**" style comments for a function comment
Loading history...
249
    {
250
        set_time_limit(0);
251
        $this->app = $app;
252
        $form = $app['form.factory']
253
            ->createBuilder('install_step5')
254
            ->getForm();
255
        $sessionData = $this->getSessionData($request);
256
        $form->setData($sessionData);
257
258
        if ($this->isValid($request, $form)) {
0 ignored issues
show
Coding Style introduced by
Blank line found at start of control structure
Loading history...
259
260
            $this
261
                ->createDatabaseYamlFile($sessionData)
262
                ->createMailYamlFile($sessionData)
263
                ->createPathYamlFile($sessionData, $request);
264
265
            if (!$form['no_update']->getData()) {
266
                set_time_limit(0);
267
                $this->createConfigYamlFile($sessionData);
268
269
                $this
270
                    ->setPDO()
271
                    ->dropTables()
272
                    ->createTables()
273
                    ->doMigrate()
274
                    ->insert();
275
            } else {
276
                // データベースを初期化しない場合、auth_magicは初期化しない
277
                $this->createConfigYamlFile($sessionData, false);
278
279
                $this
280
                    ->setPDO()
281
                    ->update();
282
0 ignored issues
show
Coding Style introduced by
Blank line found at end of control structure
Loading history...
283
            }
284
285
286
            if (isset($sessionData['agree']) && $sessionData['agree'] == '1') {
287
                $host = $request->getSchemeAndHttpHost();
288
                $basePath = $request->getBasePath();
289
                $params = array(
290
                    'http_url' => $host . $basePath,
0 ignored issues
show
Coding Style introduced by
Concat operator must not be surrounded by spaces
Loading history...
291
                    'shop_name' => $sessionData['shop_name'],
292
                );
293
294
                $this->sendAppData($params);
295
            }
296
            $this->addInstallStatus();
297
298
            $request->getSession()->remove(self::SESSION_KEY);
299
300
            return $app->redirect($app->url('install_complete'));
301
        }
302
303
        return $app['twig']->render('step5.twig', array(
304
            'form' => $form->createView(),
305
        ));
306
    }
307
308
    //    インストール完了
309
    public function complete(InstallApplication $app, Request $request)
0 ignored issues
show
introduced by
You must use "/**" style comments for a function comment
Loading history...
310
    {
311
        $config_file = $this->config_path . '/path.yml';
0 ignored issues
show
Coding Style introduced by
Concat operator must not be surrounded by spaces
Loading history...
312
        $config = Yaml::parse(file_get_contents($config_file));
313
314
        $host = $request->getSchemeAndHttpHost();
315
        $basePath = $request->getBasePath();
316
317
        $adminUrl = $host . $basePath . '/' . $config['admin_dir'];
0 ignored issues
show
Coding Style introduced by
Concat operator must not be surrounded by spaces
Loading history...
318
319
        return $app['twig']->render('complete.twig', array(
320
            'admin_url' => $adminUrl,
321
        ));
322
    }
323
324
    private function resetNatTimer()
325
    {
326
        // NATの無通信タイマ対策(仮)
327
        echo str_repeat(' ', 4 * 1024);
328
        ob_flush();
329
        flush();
330
    }
331
332
333
    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...
334
    {
335
        foreach ($this->required_modules as $module) {
336
            if (!extension_loaded($module)) {
337
                $app->addDanger('[必須] ' . $module . ' 拡張モジュールが有効になっていません。', 'install');
0 ignored issues
show
Coding Style introduced by
Concat operator must not be surrounded by spaces
Loading history...
338
            }
339
        }
340
341
        if (!extension_loaded('pdo_mysql') && !extension_loaded('pdo_pgsql')) {
342
            $app->addDanger('[必須] ' . 'pdo_pgsql又はpdo_mysql 拡張モジュールを有効にしてください。', 'install');
0 ignored issues
show
Coding Style introduced by
Concat operator must not be surrounded by spaces
Loading history...
343
        }
344
345
        foreach ($this->recommended_module as $module) {
346
            if (!extension_loaded($module)) {
347
                $app->addWarning('[推奨] ' . $module . ' 拡張モジュールが有効になっていません。', 'install');
0 ignored issues
show
Coding Style introduced by
Concat operator must not be surrounded by spaces
Loading history...
348
            }
349
        }
350
351
        if ('\\' === DIRECTORY_SEPARATOR) { // for Windows
352
            if (!extension_loaded('wincache')) {
353
                $app->addWarning('[推奨] WinCache 拡張モジュールが有効になっていません。', 'install');
354
            }
355
        } else {
356
            if (!extension_loaded('apc')) {
357
                $app->addWarning('[推奨] APC 拡張モジュールが有効になっていません。', 'install');
358
            }
359
        }
360
361
        if (isset($_SERVER['SERVER_SOFTWARE']) && strpos('Apache', $_SERVER['SERVER_SOFTWARE']) !== false) {
362
            if (!function_exists('apache_get_modules')) {
363
                $app->addWarning('mod_rewrite が有効になっているか不明です。', 'install');
364
            } elseif (!in_array('mod_rewrite', apache_get_modules())) {
365
                $app->addDanger('[必須] ' . 'mod_rewriteを有効にしてください。', 'install');
0 ignored issues
show
Coding Style introduced by
Concat operator must not be surrounded by spaces
Loading history...
366
            }
367
        } elseif (isset($_SERVER['SERVER_SOFTWARE']) && strpos('Microsoft-IIS', $_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...
368
            // iis
369
        } 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...
370
            // nginx
371
        }
372
    }
373
374
    private function setPDO()
375
    {
376
        $config_file = $this->config_path . '/database.yml';
0 ignored issues
show
Coding Style introduced by
Concat operator must not be surrounded by spaces
Loading history...
377
        $config = Yaml::parse(file_get_contents($config_file));
378
379
        try {
380
            $this->PDO = \Doctrine\DBAL\DriverManager::getConnection($config['database'], new \Doctrine\DBAL\Configuration());
381
            $this->PDO->connect();
382
0 ignored issues
show
Coding Style introduced by
Blank line found at end of control structure
Loading history...
383
        } catch (\Exception $e) {
384
            $this->PDO->close();
385
            throw $e;
386
        }
387
388
        return $this;
389
    }
390
391 View Code Duplication
    private function dropTables()
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...
392
    {
393
        $this->resetNatTimer();
394
395
        $em = $this->getEntityManager();
396
        $metadatas = $em->getMetadataFactory()->getAllMetadata();
397
        $schemaTool = new SchemaTool($em);
398
399
        $schemaTool->dropSchema($metadatas);
400
401
        $em->getConnection()->executeQuery('DROP TABLE IF EXISTS doctrine_migration_versions');
402
403
        return $this;
404
    }
405
406
    /**
407
     * @return EntityManager
408
     */
409
    private function getEntityManager()
410
    {
411
        $config_file = $this->config_path . '/database.yml';
0 ignored issues
show
Coding Style introduced by
Concat operator must not be surrounded by spaces
Loading history...
412
        $database = Yaml::parse(file_get_contents($config_file));
413
414
        $this->app->register(new \Silex\Provider\DoctrineServiceProvider(), array(
0 ignored issues
show
introduced by
Add a comma after each item in a multi-line array
Loading history...
415
            'db.options' => $database['database']
416
        ));
417
418
        $this->app->register(new \Dflydev\Silex\Provider\DoctrineOrm\DoctrineOrmServiceProvider(), array(
0 ignored issues
show
introduced by
Add a comma after each item in a multi-line array
Loading history...
419
            'orm.proxies_dir' => __DIR__ . '/../../app/cache/doctrine',
0 ignored issues
show
Coding Style introduced by
Concat operator must not be surrounded by spaces
Loading history...
420
            'orm.em.options' => array(
421
                'mappings' => array(
422
                    array(
423
                        'type' => 'yml',
424
                        'namespace' => 'Eccube\Entity',
425
                        'path' => array(
426
                            __DIR__ . '/../../Resource/doctrine',
0 ignored issues
show
Coding Style introduced by
Concat operator must not be surrounded by spaces
Loading history...
427
                            __DIR__ . '/../../Resource/doctrine/master',
0 ignored issues
show
Coding Style introduced by
Concat operator must not be surrounded by spaces
Loading history...
428
                        ),
429
                    ),
430
431
                ),
432
            )
433
        ));
434
435
        return $em = $this->app['orm.em'];
0 ignored issues
show
Unused Code introduced by
$em 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...
436
    }
437
438 View Code Duplication
    private function createTables()
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...
439
    {
440
        $this->resetNatTimer();
441
442
        $em = $this->getEntityManager();
443
        $metadatas = $em->getMetadataFactory()->getAllMetadata();
444
        $schemaTool = new SchemaTool($em);
445
446
        $schemaTool->createSchema($metadatas);
447
448
        return $this;
449
    }
450
451
    private function insert()
452
    {
453
        $this->resetNatTimer();
454
455
        $config_file = $this->config_path . '/database.yml';
0 ignored issues
show
Coding Style introduced by
Concat operator must not be surrounded by spaces
Loading history...
456
        $database = Yaml::parse(file_get_contents($config_file));
457
        $config['database'] = $database['database'];
0 ignored issues
show
Coding Style Comprehensibility introduced by
$config was never initialized. Although not strictly required by PHP, it is generally a good practice to add $config = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
458
459
        $config_file = $this->config_path . '/config.yml';
0 ignored issues
show
Coding Style introduced by
Concat operator must not be surrounded by spaces
Loading history...
460
        $baseConfig = Yaml::parse(file_get_contents($config_file));
461
        $config['config'] = $baseConfig;
462
463
        $this->PDO->beginTransaction();
464
465
        try {
0 ignored issues
show
Coding Style introduced by
Blank line found at start of control structure
Loading history...
466
467
            $config = array(
468
                'auth_type' => '',
469
                'auth_magic' => $config['config']['auth_magic'],
470
                'password_hash_algos' => 'sha256',
471
            );
472
            $passwordEncoder = new \Eccube\Security\Core\Encoder\PasswordEncoder($config);
473
            $salt = \Eccube\Util\Str::random(32);
474
475
            $encodedPassword = $passwordEncoder->encodePassword($this->session_data['login_pass'], $salt);
476
            $sth = $this->PDO->prepare('INSERT INTO dtb_base_info (
477
                id,
478
                shop_name,
479
                email01,
480
                email02,
481
                email03,
482
                email04,
483
                update_date,
484
                option_product_tax_rule
485
            ) VALUES (
486
                1,
487
                :shop_name,
488
                :admin_mail,
489
                :admin_mail,
490
                :admin_mail,
491
                :admin_mail,
492
                current_timestamp,
493
                0);');
494
            $sth->execute(array(
0 ignored issues
show
introduced by
Add a comma after each item in a multi-line array
Loading history...
495
                ':shop_name' => $this->session_data['shop_name'],
496
                ':admin_mail' => $this->session_data['email']
497
            ));
498
499
            $sth = $this->PDO->prepare("INSERT INTO dtb_member (member_id, login_id, password, salt, work, del_flg, authority, creator_id, rank, update_date, create_date,name,department) VALUES (2, :login_id, :admin_pass , :salt , '1', '0', '0', '1', '1', current_timestamp, current_timestamp,'管理者','EC-CUBE SHOP');");
500
            $sth->execute(array(':login_id' => $this->session_data['login_id'], ':admin_pass' => $encodedPassword, ':salt' => $salt));
501
502
            $this->PDO->commit();
503
        } catch (\Exception $e) {
504
            $this->PDO->rollback();
505
            throw $e;
506
        }
507
508
        return $this;
509
    }
510
511
    private function update()
512
    {
513
        $this->resetNatTimer();
514
515
        $config_file = $this->config_path . '/database.yml';
0 ignored issues
show
Coding Style introduced by
Concat operator must not be surrounded by spaces
Loading history...
516
        $database = Yaml::parse(file_get_contents($config_file));
517
        $config['database'] = $database['database'];
0 ignored issues
show
Coding Style Comprehensibility introduced by
$config was never initialized. Although not strictly required by PHP, it is generally a good practice to add $config = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
518
519
        $config_file = $this->config_path . '/config.yml';
0 ignored issues
show
Coding Style introduced by
Concat operator must not be surrounded by spaces
Loading history...
520
        $baseConfig = Yaml::parse(file_get_contents($config_file));
521
        $config['config'] = $baseConfig;
522
523
        $this->PDO->beginTransaction();
524
525
        try {
0 ignored issues
show
Coding Style introduced by
Blank line found at start of control structure
Loading history...
526
527
            $config = array(
528
                'auth_type' => '',
529
                'auth_magic' => $config['config']['auth_magic'],
530
                'password_hash_algos' => 'sha256',
531
            );
532
            $passwordEncoder = new \Eccube\Security\Core\Encoder\PasswordEncoder($config);
533
            $salt = \Eccube\Util\Str::random(32);
534
535
            $stmt = $this->PDO->prepare("SELECT member_id FROM dtb_member WHERE login_id = :login_id;");
536
            $stmt->execute(array(':login_id' => $this->session_data['login_id']));
537
            $rs = $stmt->fetch();
538
539
            $encodedPassword = $passwordEncoder->encodePassword($this->session_data['login_pass'], $salt);
540
541
            if ($rs) {
542
                // 同一の管理者IDであればパスワードのみ更新
543
                $sth = $this->PDO->prepare("UPDATE dtb_member set password = :admin_pass, salt = :salt, update_date = current_timestamp WHERE login_id = :login_id;");
544
                $sth->execute(array(':admin_pass' => $encodedPassword, ':salt' => $salt, ':login_id' => $this->session_data['login_id']));
545
0 ignored issues
show
Coding Style introduced by
Blank line found at end of control structure
Loading history...
546
            } else {
547
                // 新しい管理者IDが入力されたらinsert
548
                $sth = $this->PDO->prepare("INSERT INTO dtb_member (login_id, password, salt, work, del_flg, authority, creator_id, rank, update_date, create_date,name,department) VALUES (:login_id, :admin_pass , :salt , '1', '0', '0', '1', '1', current_timestamp, current_timestamp,'管理者','EC-CUBE SHOP');");
549
                $sth->execute(array(':login_id' => $this->session_data['login_id'], ':admin_pass' => $encodedPassword, ':salt' => $salt));
550
            }
551
552
            $sth = $this->PDO->prepare('UPDATE dtb_base_info set
553
                shop_name = :shop_name,
554
                email01 = :admin_mail,
555
                email02 = :admin_mail,
556
                email03 = :admin_mail,
557
                email04 = :admin_mail,
558
                update_date = current_timestamp
559
            WHERE id = 1;');
560
            $sth->execute(array(
0 ignored issues
show
introduced by
Add a comma after each item in a multi-line array
Loading history...
561
                ':shop_name' => $this->session_data['shop_name'],
562
                ':admin_mail' => $this->session_data['email']
563
            ));
564
565
            $this->PDO->commit();
566
        } catch (\Exception $e) {
567
            $this->PDO->rollback();
568
            throw $e;
569
        }
570
571
        return $this;
572
    }
573
574
575
    private function getMigration()
576
    {
577
        $app = \Eccube\Application::getInstance();
578
        $app->initialize();
579
        $app->boot();
580
581
        $config = new Configuration($app['db']);
582
        $config->setMigrationsNamespace('DoctrineMigrations');
583
584
        $migrationDir = __DIR__ . '/../../Resource/doctrine/migration';
0 ignored issues
show
Coding Style introduced by
Concat operator must not be surrounded by spaces
Loading history...
585
        $config->setMigrationsDirectory($migrationDir);
586
        $config->registerMigrationsFromDirectory($migrationDir);
587
588
        $migration = new Migration($config);
589
590
        return $migration;
591
    }
592
593
    private function doMigrate()
594
    {
595
        try {
596
            $migration = $this->getMigration();
597
598
            // DBとのコネクションを維持するためpingさせる
599
            if (is_null($this->PDO)) {
600
                $this->setPDO();
601
            }
602
            $this->PDO->ping();
603
604
            // nullを渡すと最新バージョンまでマイグレートする
605
            $migration->migrate(null, false);
606
        } catch (MigrationException $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
607
        }
608
609
        return $this;
610
    }
611
612
    private function getProtectedDirs()
613
    {
614
        $protectedDirs = array();
615
        $base = __DIR__ . '/../../../..';
0 ignored issues
show
Coding Style introduced by
Concat operator must not be surrounded by spaces
Loading history...
616
        $dirs = array(
617
            '/html',
618
            '/app',
619
            '/app/template',
620
            '/app/cache',
621
            '/app/config',
622
            '/app/config/eccube',
623
            '/app/log',
624
            '/app/Plugin',
625
        );
626
627
        foreach ($dirs as $dir) {
628
            if (!is_writable($base . $dir)) {
0 ignored issues
show
Coding Style introduced by
Concat operator must not be surrounded by spaces
Loading history...
629
                $protectedDirs[] = $dir;
630
            }
631
        }
632
633
        return $protectedDirs;
634
    }
635
636
    private function createConfigYamlFile($data, $auth = true)
637
    {
638
        $fs = new Filesystem();
639
        $config_file = $this->config_path . '/config.yml';
0 ignored issues
show
Coding Style introduced by
Concat operator must not be surrounded by spaces
Loading history...
640
641
        if ($fs->exists($config_file)) {
642
            $config = Yaml::parse(file_get_contents($config_file));
643
            $fs->remove($config_file);
644
        }
645
646
        if ($auth) {
647
            $auth_magic = Str::random(32);
648
        } else {
649
            if (isset($config['auth_magic'])) {
650
                $auth_magic = $config['auth_magic'];
651
            } else {
652
                $auth_magic = Str::random(32);
653
            }
654
        }
655
656
        $allowHost = Str::convertLineFeed($data['admin_allow_hosts']);
657
        if (empty($allowHost)) {
658
            $adminAllowHosts = array();
659
        } else {
660
            $adminAllowHosts = explode("\n", $allowHost);
661
        }
662
663
        $target = array('${AUTH_MAGIC}', '${SHOP_NAME}', '${ECCUBE_INSTALL}', '${FORCE_SSL}');
664
        $replace = array($auth_magic, $data['shop_name'], '0', $data['admin_force_ssl']);
665
666
        $fs = new Filesystem();
667
        $content = str_replace(
668
            $target,
669
            $replace,
670
            file_get_contents($this->dist_path . '/config.yml.dist')
0 ignored issues
show
Coding Style introduced by
Concat operator must not be surrounded by spaces
Loading history...
671
        );
672
        $fs->dumpFile($config_file, $content);
673
674
        $config = Yaml::parse(file_get_contents($config_file));
675
        $config['admin_allow_host'] = $adminAllowHosts;
676
        $yml = Yaml::dump($config);
677
        file_put_contents($config_file, $yml);
678
679
        return $this;
680
    }
681
682
    private function addInstallStatus()
683
    {
684
        $config_file = $this->config_path . '/config.yml';
0 ignored issues
show
Coding Style introduced by
Concat operator must not be surrounded by spaces
Loading history...
685
        $config = Yaml::parse(file_get_contents($config_file));
686
        $config['eccube_install'] = 1;
687
        $yml = Yaml::dump($config);
688
        file_put_contents($config_file, $yml);
689
690
        return $this;
691
    }
692
693
    private function createDatabaseYamlFile($data)
694
    {
695
        $fs = new Filesystem();
696
        $config_file = $this->config_path . '/database.yml';
0 ignored issues
show
Coding Style introduced by
Concat operator must not be surrounded by spaces
Loading history...
697
        if ($fs->exists($config_file)) {
698
            $fs->remove($config_file);
699
        }
700
701
        if ($data['database'] != 'pdo_sqlite') {
702
            switch ($data['database']) {
703
                case 'pdo_pgsql':
704
                    if (empty($data['db_port'])) {
705
                        $data['db_port'] = '5432';
706
                    }
707
                    $data['db_driver'] = 'pdo_pgsql';
708
                    break;
709
                case 'pdo_mysql':
710
                    if (empty($data['db_port'])) {
711
                        $data['db_port'] = '3306';
712
                    }
713
                    $data['db_driver'] = 'pdo_mysql';
714
                    break;
715
            }
716
            $target = array('${DBDRIVER}', '${DBSERVER}', '${DBNAME}', '${DBPORT}', '${DBUSER}', '${DBPASS}');
717
            $replace = array(
0 ignored issues
show
introduced by
Add a comma after each item in a multi-line array
Loading history...
718
                $data['db_driver'],
719
                $data['database_host'],
720
                $data['database_name'],
721
                $data['database_port'],
722
                $data['database_user'],
723
                $data['database_password']
724
            );
725
726
            $fs = new Filesystem();
727
            $content = str_replace(
728
                $target,
729
                $replace,
730
                file_get_contents($this->dist_path . '/database.yml.dist')
0 ignored issues
show
Coding Style introduced by
Concat operator must not be surrounded by spaces
Loading history...
731
            );
732
0 ignored issues
show
Coding Style introduced by
Blank line found at end of control structure
Loading history...
733
        } else {
734
            $content = Yaml::dump(
735
                array(
0 ignored issues
show
introduced by
Add a comma after each item in a multi-line array
Loading history...
736
                    'database' => array(
0 ignored issues
show
introduced by
Add a comma after each item in a multi-line array
Loading history...
737
                        'driver' => 'pdo_sqlite',
738
                        'path' => realpath($this->config_path.'/eccube.db')
739
                    )
740
                )
741
            );
742
        }
743
        $fs->dumpFile($config_file, $content);
744
745
        return $this;
746
    }
747
748
    private function createMailYamlFile($data)
749
    {
750
        $fs = new Filesystem();
751
        $config_file = $this->config_path . '/mail.yml';
0 ignored issues
show
Coding Style introduced by
Concat operator must not be surrounded by spaces
Loading history...
752
        if ($fs->exists($config_file)) {
753
            $fs->remove($config_file);
754
        }
755
        $target = array('${MAIL_BACKEND}', '${MAIL_HOST}', '${MAIL_PORT}', '${MAIL_USER}', '${MAIL_PASS}');
756
        $replace = array(
0 ignored issues
show
introduced by
Add a comma after each item in a multi-line array
Loading history...
757
            $data['mail_backend'],
758
            $data['smtp_host'],
759
            $data['smtp_port'],
760
            $data['smtp_username'],
761
            $data['smtp_password']
762
        );
763
764
        $fs = new Filesystem();
765
        $content = str_replace(
766
            $target,
767
            $replace,
768
            file_get_contents($this->dist_path . '/mail.yml.dist')
0 ignored issues
show
Coding Style introduced by
Concat operator must not be surrounded by spaces
Loading history...
769
        );
770
        $fs->dumpFile($config_file, $content);
771
772
        return $this;
773
    }
774
775
    private function createPathYamlFile($data, Request $request)
776
    {
777
        $fs = new Filesystem();
778
        $config_file = $this->config_path . '/path.yml';
0 ignored issues
show
Coding Style introduced by
Concat operator must not be surrounded by spaces
Loading history...
779
        if ($fs->exists($config_file)) {
780
            $fs->remove($config_file);
781
        }
782
783
        $ADMIN_ROUTE = $data['admin_dir'];
784
        $TEMPLATE_CODE = 'default';
785
        $USER_DATA_ROUTE = 'user_data';
786
        $ROOT_DIR = realpath(__DIR__ . '/../../../../');
0 ignored issues
show
Coding Style introduced by
Concat operator must not be surrounded by spaces
Loading history...
787
        $ROOT_URLPATH = $request->getBasePath();
788
789
        $target = array('${ADMIN_ROUTE}', '${TEMPLATE_CODE}', '${USER_DATA_ROUTE}', '${ROOT_DIR}', '${ROOT_URLPATH}');
790
        $replace = array($ADMIN_ROUTE, $TEMPLATE_CODE, $USER_DATA_ROUTE, $ROOT_DIR, $ROOT_URLPATH);
791
792
        $fs = new Filesystem();
793
        $content = str_replace(
794
            $target,
795
            $replace,
796
            file_get_contents($this->dist_path . '/path.yml.dist')
0 ignored issues
show
Coding Style introduced by
Concat operator must not be surrounded by spaces
Loading history...
797
        );
798
        $fs->dumpFile($config_file, $content);
799
800
        return $this;
801
    }
802
803
    private function sendAppData($params)
804
    {
805
        $config_file = $this->config_path . '/database.yml';
0 ignored issues
show
Coding Style introduced by
Concat operator must not be surrounded by spaces
Loading history...
806
        $db_config = Yaml::parse(file_get_contents($config_file));
807
808
        $this->setPDO();
809
        $stmt = $this->PDO->query('select version() as v');
810
811
        $version = '';
812
        foreach ($stmt as $row) {
813
            $version = $row['v'];
814
        }
815
816
        if ($db_config['database']['driver'] === 'pdo_mysql') {
817
            $db_ver = 'MySQL:' . $version;
0 ignored issues
show
Coding Style introduced by
Concat operator must not be surrounded by spaces
Loading history...
818
        } else {
819
            $db_ver = $version;
820
        }
821
822
        $data = http_build_query(
823
            array(
824
                'site_url' => $params['http_url'],
825
                'shop_name' => $params['shop_name'],
826
                'cube_ver' => Constant::VERSION,
827
                'php_ver' => phpversion(),
828
                'db_ver' => $db_ver,
829
                'os_type' => php_uname(),
830
            )
831
        );
832
833
        $header = array(
834
            'Content-Type: application/x-www-form-urlencoded',
835
            'Content-Length: ' . strlen($data),
0 ignored issues
show
Coding Style introduced by
Concat operator must not be surrounded by spaces
Loading history...
836
        );
837
        $context = stream_context_create(
838
            array(
0 ignored issues
show
introduced by
Add a comma after each item in a multi-line array
Loading history...
839
                'http' => array(
840
                    'method' => 'POST',
841
                    'header' => $header,
842
                    'content' => $data,
843
                )
844
            )
845
        );
846
        file_get_contents('http://www.ec-cube.net/mall/use_site.php', false, $context);
847
848
        return $this;
849
    }
850
851
852
    /**
853
     * マイグレーション画面を表示する.
854
     *
855
     * @param InstallApplication $app
856
     * @param Request $request
0 ignored issues
show
introduced by
Expected 12 spaces after parameter type; 1 found
Loading history...
857
     *
858
     * @return \Symfony\Component\HttpFoundation\Response
859
     */
860
    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...
861
    {
862
        return $app['twig']->render('migration.twig');
863
    }
864
865
    /**
866
     * インストール済プラグインの一覧を表示する.
867
     * プラグインがインストールされていない場合は, マイグレーション実行画面へリダイレクトする.
868
     *
869
     * @param InstallApplication $app
870
     * @param Request $request
0 ignored issues
show
introduced by
Expected 12 spaces after parameter type; 1 found
Loading history...
871
     *
872
     * @return \Symfony\Component\HttpFoundation\Response
873
     */
874
    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...
875
    {
876
        $eccube = \Eccube\Application::getInstance();
877
        $eccube->initialize();
878
        $eccube->boot();
879
880
        $pluginRepository = $eccube['orm.em']->getRepository('Eccube\Entity\Plugin');
881
        $Plugins = $pluginRepository->findBy(array('del_flg' => Constant::DISABLED));
882
883
        if (empty($Plugins)) {
884
            // インストール済プラグインがない場合はマイグレーション実行画面へリダイレクト.
885
            return $app->redirect($app->url('migration_end'));
886
        } else {
887
            return $app['twig']->render('migration_plugin.twig', array(
0 ignored issues
show
introduced by
Add a comma after each item in a multi-line array
Loading history...
888
                'Plugins' => $Plugins,
889
                'version' => Constant::VERSION));
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...
890
        }
891
    }
892
893
    /**
894
     * マイグレーションを実行し, 完了画面を表示させる
895
     *
896
     * @param InstallApplication $app
897
     * @param Request $request
0 ignored issues
show
introduced by
Expected 12 spaces after parameter type; 1 found
Loading history...
898
     *
899
     * @return \Symfony\Component\HttpFoundation\Response
900
     */
901
    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...
902
    {
903
        $this->doMigrate();
904
905
        $config_app = new \Eccube\Application(); // install用のappだとconfigが取れないので
906
        $config_app->initialize();
907
        $config_app->boot();
908
        \Eccube\Util\Cache::clear($config_app, true);
0 ignored issues
show
Documentation introduced by
$config_app is of type object<Eccube\Application>, but the function expects a object<Eccube\Util\Application>.

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

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

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

function acceptsInteger($int) { }

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

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
909
910
        return $app['twig']->render('migration_end.twig');
911
    }
912
}
913