Completed
Push — develop ( 34b62e...8dc176 )
by Tom
03:57
created

CreateDatabase::validateDatabaseSettings()   B

Complexity

Conditions 6
Paths 16

Size

Total Lines 40
Code Lines 24

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 40
rs 8.439
c 0
b 0
f 0
cc 6
eloc 24
nc 16
nop 2
1
<?php
2
3
namespace N98\Magento\Command\Installer\SubCommand;
4
5
use N98\Magento\Command\SubCommand\AbstractSubCommand;
6
use N98\Util\BinaryString;
7
use Symfony\Component\Console\Helper\DialogHelper;
8
use Symfony\Component\Console\Input\InputInterface;
9
use Symfony\Component\Console\Output\OutputInterface;
10
11
class CreateDatabase extends AbstractSubCommand
12
{
13
    /**
14
     * @var array
15
     */
16
    private $argv;
17
18
    /**
19
     * @var \Closure
20
     */
21
    protected $notEmptyCallback;
22
23
    /**
24
     * @return void
25
     */
26
    public function execute()
27
    {
28
        $this->notEmptyCallback = function ($input) {
29
            if (empty($input)) {
30
                throw new \InvalidArgumentException('Please enter a value');
31
            }
32
            return $input;
33
        };
34
35
        $dbOptions = array('--dbHost', '--dbUser', '--dbPass', '--dbName');
36
        $dbOptionsFound = 0;
37
        foreach ($dbOptions as $dbOption) {
38
            foreach ($this->getCliArguments() as $definedCliOption) {
39
                if (BinaryString::startsWith($definedCliOption, $dbOption)) {
40
                    $dbOptionsFound++;
41
                }
42
            }
43
        }
44
45
        $hasAllOptions = $dbOptionsFound == 4;
46
47
        // if all database options were passed in at cmd line
48
        if ($hasAllOptions) {
49
            $this->config->setString('db_host', $this->input->getOption('dbHost'));
50
            $this->config->setString('db_user', $this->input->getOption('dbUser'));
51
            $this->config->setString('db_pass', $this->input->getOption('dbPass'));
52
            $this->config->setString('db_name', $this->input->getOption('dbName'));
53
            $this->config->setInt('db_port', intval($this->input->getOption('dbPort')));
0 ignored issues
show
Documentation introduced by
intval($this->input->getOption('dbPort')) is of type integer, but the function expects a boolean.

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...
54
            $db = $this->validateDatabaseSettings($this->input, $this->output);
55
56
            if ($db === false) {
57
                throw new \InvalidArgumentException("Database configuration is invalid", null);
58
            }
59
        } else {
60
            /** @var DialogHelper $dialog */
61
            $dialog = $this->getCommand()->getHelperSet()->get('dialog');
62
            do {
63
                // Host
64
                $dbHostDefault = $this->input->getOption('dbHost') ?
65
                    $this->input->getOption('dbHost') : $this->commandConfig['installation']['db']['host'];
66
                $this->config->setString(
67
                    'db_host',
68
                    $dialog->askAndValidate(
0 ignored issues
show
Documentation introduced by
$dialog->askAndValidate(... false, $dbHostDefault) is of type string, but the function expects a boolean.

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...
69
                        $this->output,
70
                        '<question>Please enter the database host</question> <comment>[' .
71
                        $dbHostDefault . ']</comment>: ',
72
                        $this->notEmptyCallback,
73
                        false,
74
                        $dbHostDefault
75
                    )
76
                );
77
78
                // Port
79
                $dbPortDefault = $this->input->getOption('dbPort') ?
80
                    $this->input->getOption('dbPort') : $this->commandConfig['installation']['db']['port'];
81
                $this->config->setInt(
82
                    'db_port',
83
                    intval($dialog->askAndValidate(
0 ignored issues
show
Documentation introduced by
intval($dialog->askAndVa...false, $dbPortDefault)) is of type integer, but the function expects a boolean.

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...
84
                        $this->output,
85
                        '<question>Please enter the database port </question> <comment>[' .
86
                        $dbPortDefault . ']</comment>: ',
87
                        $this->notEmptyCallback,
88
                        false,
89
                        $dbPortDefault
90
                    ))
91
                );
92
93
                // User
94
                $dbUserDefault = $this->input->getOption('dbUser') ?
95
                    $this->input->getOption('dbUser') : $this->commandConfig['installation']['db']['user'];
96
                $this->config->setString(
97
                    'db_user',
98
                    $dialog->askAndValidate(
0 ignored issues
show
Documentation introduced by
$dialog->askAndValidate(... false, $dbUserDefault) is of type string, but the function expects a boolean.

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...
99
                        $this->output,
100
                        '<question>Please enter the database username</question> <comment>[' .
101
                        $dbUserDefault . ']</comment>: ',
102
                        $this->notEmptyCallback,
103
                        false,
104
                        $dbUserDefault
105
                    )
106
                );
107
108
                // Password
109
                $dbPassDefault = $this->input->getOption('dbPass') ?
110
                    $this->input->getOption('dbPass') : $this->commandConfig['installation']['db']['pass'];
111
                $this->config->setString(
112
                    'db_pass',
113
                    $dialog->ask(
0 ignored issues
show
Documentation introduced by
$dialog->ask($this->outp...nt>: ', $dbPassDefault) is of type string, but the function expects a boolean.

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...
114
                        $this->output,
115
                        '<question>Please enter the database password</question> <comment>[' .
116
                        $dbPassDefault . ']</comment>: ',
117
                        $dbPassDefault
118
                    )
119
                );
120
121
                // DB-Name
122
                $dbNameDefault = $this->input->getOption('dbName') ?
123
                    $this->input->getOption('dbName') : $this->commandConfig['installation']['db']['name'];
124
                $this->config->setString(
125
                    'db_name',
126
                    $dialog->askAndValidate(
0 ignored issues
show
Documentation introduced by
$dialog->askAndValidate(... false, $dbNameDefault) is of type string, but the function expects a boolean.

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...
127
                        $this->output,
128
                        '<question>Please enter the database name</question> <comment>[' .
129
                        $dbNameDefault . ']</comment>: ',
130
                        $this->notEmptyCallback,
131
                        false,
132
                        $dbNameDefault
133
                    )
134
                );
135
136
                $db = $this->validateDatabaseSettings($this->input, $this->output);
137
            } while ($db === false);
138
        }
139
140
        $this->config->setObject('db', $db);
141
    }
142
143
    /**
144
     * @param InputInterface $input
145
     * @param OutputInterface $output
146
     * @return bool|\PDO
147
     */
148
    protected function validateDatabaseSettings(InputInterface $input, OutputInterface $output)
149
    {
150
        try {
151
            $dsn = sprintf(
152
                "mysql:host=%s;port=%s",
153
                $this->config->getString('db_host'),
154
                $this->config->getString('db_port')
155
            );
156
157
            $db = new \PDO($dsn, $this->config->getString('db_user'), $this->config->getString('db_pass'));
158
159
            $dbName = $this->config->getString('db_name');
160
            if (!$db->query('USE `' . $dbName . '`')) {
161
                $db->query("CREATE DATABASE `" . $dbName . "`");
162
                $output->writeln('<info>Created database ' . $dbName . '</info>');
163
                $db->query('USE `' . $dbName . '`');
164
165
                // Check DB version
166
                $statement = $db->query('SELECT VERSION()');
167
                $mysqlVersion = $statement->fetchColumn(0);
168
                if (version_compare($mysqlVersion, '5.6.0', '<')) {
169
                    throw new \Exception('MySQL Version must be >= 5.6.0');
170
                }
171
172
                return $db;
173
            }
174
175
            if ($input->getOption('noDownload') && !$input->getOption('forceUseDb')) {
176
                $output->writeln("<error>Database {$this->config->getString('db_name')} already exists.</error>");
177
178
                return false;
179
            }
180
181
            return $db;
182
        } catch (\Exception $e) {
183
            $output->writeln('<error>' . $e->getMessage() . '</error>');
184
        }
185
186
        return false;
187
    }
188
189
    /**
190
     * @return array
191
     */
192
    private function getCliArguments()
0 ignored issues
show
Coding Style introduced by
getCliArguments 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...
193
    {
194
        if ($this->argv === null) {
195
            $this->argv = $_SERVER['argv'];
196
        }
197
198
        return $this->argv;
199
    }
200
}
201