CreateDatabase::execute()   D
last analyzed

Complexity

Conditions 13
Paths 136

Size

Total Lines 111
Code Lines 75

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 2 Features 0
Metric Value
c 2
b 2
f 0
dl 0
loc 111
rs 4.6605
cc 13
eloc 75
nc 136
nop 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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\Input\InputInterface;
8
use Symfony\Component\Console\Output\OutputInterface;
9
10
class CreateDatabase extends AbstractSubCommand
11
{
12
    /**
13
     * @var array
14
     */
15
    protected $_argv;
16
17
    /**
18
     * @var \Closure
19
     */
20
    protected $notEmptyCallback;
21
22
    /**
23
     * @return void
24
     */
25
    public function execute()
26
    {
27
        $this->notEmptyCallback = function ($input) {
28
            if (empty($input)) {
29
                throw new \InvalidArgumentException('Please enter a value');
30
            }
31
            return $input;
32
        };
33
34
        $dbOptions = array('--dbHost', '--dbUser', '--dbPass', '--dbName');
35
        $dbOptionsFound = 0;
36
        foreach ($dbOptions as $dbOption) {
37
            foreach ($this->getCliArguments() as $definedCliOption) {
38
                if (BinaryString::startsWith($definedCliOption, $dbOption)) {
39
                    $dbOptionsFound++;
40
                }
41
            }
42
        }
43
44
        $hasAllOptions = $dbOptionsFound == 4;
45
46
        // if all database options were passed in at cmd line
47
        if ($hasAllOptions) {
48
            $this->config->setString('db_host', $this->input->getOption('dbHost'));
49
            $this->config->setString('db_user', $this->input->getOption('dbUser'));
50
            $this->config->setString('db_pass', $this->input->getOption('dbPass'));
51
            $this->config->setString('db_name', $this->input->getOption('dbName'));
52
            $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...
53
            $db = $this->validateDatabaseSettings($this->input, $this->output);
54
55
            if ($db === false) {
56
                throw new \InvalidArgumentException("Database configuration is invalid", null);
57
            }
58
        } else {
59
            $dialog = $this->getCommand()->getHelperSet()->get('dialog');
60
            do {
61
62
                // Host
63
                $dbHostDefault = $this->input->getOption('dbHost') ? $this->input->getOption('dbHost') : 'localhost';
64
                $this->config->setString(
65
                    'db_host',
66
                    $dialog->askAndValidate(
67
                        $this->output,
68
                        '<question>Please enter the database host</question> <comment>[' .
69
                        $dbHostDefault . ']</comment>: ',
70
                        $this->notEmptyCallback,
71
                        false,
72
                        $dbHostDefault
73
                    )
74
                );
75
76
                // Port
77
                $dbPortDefault = $this->input->getOption('dbPort') ? $this->input->getOption('dbPort') : 3306;
78
                $this->config->setInt(
79
                    'db_port',
80
                    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...
81
                        $this->output,
82
                        '<question>Please enter the database port </question> <comment>[' .
83
                        $dbPortDefault . ']</comment>: ',
84
                        $this->notEmptyCallback,
85
                        false,
86
                        $dbPortDefault
87
                    ))
88
                );
89
90
                // User
91
                $dbUserDefault = $this->input->getOption('dbUser') ? $this->input->getOption('dbUser') : 'root';
92
                $this->config->setString(
93
                    'db_user',
94
                    $dialog->askAndValidate(
95
                        $this->output,
96
                        '<question>Please enter the database username</question> <comment>[' .
97
                        $dbUserDefault . ']</comment>: ',
98
                        $this->notEmptyCallback,
99
                        false,
100
                        $dbUserDefault
101
                    )
102
                );
103
104
                // Password
105
                $dbPassDefault = $this->input->getOption('dbPass') ? $this->input->getOption('dbPass') : '';
106
                $this->config->setString(
107
                    'db_pass',
108
                    $dialog->ask(
109
                        $this->output,
110
                        '<question>Please enter the database password</question> <comment>[' .
111
                        $dbPassDefault . ']</comment>: ',
112
                        $dbPassDefault
113
                    )
114
                );
115
116
                // DB-Name
117
                $dbNameDefault = $this->input->getOption('dbName') ? $this->input->getOption('dbName') : 'magento';
118
                $this->config->setString(
119
                    'db_name',
120
                    $dialog->askAndValidate(
121
                        $this->output,
122
                        '<question>Please enter the database name</question> <comment>[' .
123
                        $dbNameDefault . ']</comment>: ',
124
                        $this->notEmptyCallback,
125
                        false,
126
                        $dbNameDefault
127
                    )
128
                );
129
130
                $db = $this->validateDatabaseSettings($this->input, $this->output);
131
            } while ($db === false);
132
        }
133
134
        $this->config->setObject('db', $db);
135
    }
136
137
    /**
138
     * @param InputInterface $input
139
     * @param OutputInterface $output
140
     * @return bool|\PDO
141
     */
142
    protected function validateDatabaseSettings(InputInterface $input, OutputInterface $output)
143
    {
144
        try {
145
            $dsn = sprintf(
146
                "mysql:host=%s;port=%s",
147
                $this->config->getString('db_host'),
148
                $this->config->getString('db_port')
149
            );
150
151
            $db = new \PDO($dsn, $this->config->getString('db_user'), $this->config->getString('db_pass'));
152
153
            $dbName = $this->config->getString('db_name');
154
            if (!$db->query('USE `' . $dbName . '`')) {
155
                $db->query("CREATE DATABASE `" . $dbName . "`");
156
                $output->writeln('<info>Created database ' . $dbName . '</info>');
157
                $db->query('USE `' . $dbName . '`');
158
159
                // Check DB version
160
                $statement = $db->query('SELECT VERSION()');
161
                $mysqlVersion = $statement->fetchColumn(0);
162
                if (version_compare($mysqlVersion, '5.6.0', '<')) {
163
                    throw new \Exception('MySQL Version must be >= 5.6.0');
164
                }
165
166
                return $db;
167
            }
168
169
            if ($input->getOption('noDownload') && !$input->getOption('forceUseDb')) {
170
                $output->writeln("<error>Database {$this->config->getString('db_name')} already exists.</error>");
171
172
                return false;
173
            }
174
175
            return $db;
176
        } catch (\Exception $e) {
177
            $output->writeln('<error>' . $e->getMessage() . '</error>');
178
        } catch (\PDOException $e) {
179
            $output->writeln('<error>' . $e->getMessage() . '</error>');
180
        }
181
182
        return false;
183
    }
184
185
    /**
186
     * @return array
187
     */
188
    public 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...
189
    {
190
        if ($this->_argv === null) {
191
            $this->_argv = $_SERVER['argv'];
192
        }
193
194
        return $this->_argv;
195
    }
196
}
197