PublishInstall::handle()   F
last analyzed

Complexity

Conditions 14
Paths 0

Size

Total Lines 82
Code Lines 50

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 14
eloc 50
nc 0
nop 0
dl 0
loc 82
rs 2.0021
c 0
b 0
f 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 Acacha\ForgePublish\Commands;
4
5
use Acacha\ForgePublish\Commands\Traits\ChecksEnv;
6
use Acacha\ForgePublish\Commands\Traits\ChecksSSHConnection;
7
use GuzzleHttp\Client;
8
use Illuminate\Console\Command;
9
use Illuminate\Support\Facades\File;
10
use josegonzalez\Dotenv\Loader;
11
12
/**
13
 * Class PublishInstall.
14
 *
15
 * @package Acacha\ForgePublish\Commands
16
 */
17
class PublishInstall extends Command
18
{
19
    use ChecksEnv,ChecksSSHConnection;
20
21
    /**
22
     * Server name
23
     *
24
     * @var String
25
     */
26
    protected $server;
27
28
    /**
29
     * Domain
30
     *
31
     * @var String
32
     */
33
    protected $domain;
34
35
    /**
36
     * The name and signature of the console command.
37
     *
38
     * @var string
39
     */
40
    protected $signature = 'publish:install {--server=} {--domain=}';
41
42
    /**
43
     * The console command description.
44
     *
45
     * @var string
46
     */
47
    protected $description = 'Install project into production Laravel Forge server';
48
49
    /**
50
     * Is mysq database already configured.
51
     *
52
     * @var boolean
53
     */
54
    protected $databaseAlreadyConfigured = false;
55
56
    /**
57
     * Guzzle http client.
58
     *
59
     * @var Client
60
     */
61
    protected $http;
62
63
    /**
64
     * Create a new command instance.
65
     *
66
     */
67
    public function __construct(Client $http)
68
    {
69
        parent::__construct();
70
        $this->http = $http;
71
    }
72
73
    /**
74
     * Execute the console command.
75
     *
76
     */
77
    public function handle()
78
    {
79
        $this->abortCommandExecution();
80
        $this->info("I'm going to install this project to production...");
81
82
        if ($this->confirm('Do you have ignored local files you want to add to production?')) {
83
            $this->call('publish:ignored');
84
        }
85
86
        if ($this->confirm('Do you have ignored local Github projects that do you want to add to production?')) {
87
            $this->call('publish:git_dependencies');
88
        }
89
90
        $this->call('publish:composer', [
91
            'composer_command' => 'install'
92
        ]);
93
94
        $this->call('publish:npm', [
95
            'npm_command' => 'install',
96
        ]);
97
98
        $this->call('publish:key_generate');
99
100
        check_env_production:
101
102
        if (! File::exists($productionEnv = base_path('.env.production'))) {
103
            $this->error("File $productionEnv not found!");
104
            $this->line("Be careful! Without $productionEnv file the default Laravel Forge .env will be applied.");
105
            $this->line("For example default database forge will be used. This could affect other apps in production using the same database");
106
            if ($this->confirm('Do you want to create the File? please choose yes once you have been created the file!')) {
107
                goto check_env_production;
108
            }
109
        } else {
110
            if (! File::exists($gitIgnore = base_path('.gitignore'))) {
111
                $this->error("Be careful! File $gitIgnore doesn't exists and you have a $productionEnv file. Be sure you are not publishing sensible data to your repo!");
112
            } else {
113
                if (strpos(file_get_contents($gitIgnore), ".env.production") === false) {
114
                    $this->error("Be careful! File $gitIgnore doesn't have $productionEnv file. Be sure you are not publishing sensible data to your repo!");
115
                }
116
            }
117
118
            if ($this->confirm('Do you wish to install .env.production file and overwrite .env in production?')) {
119
                $this->call('publish:env-production');
120
            }
121
122
            $mysql_data = $this->obtainMySQLDatabaseInfoFromEnv(base_path('.env.production'));
123
124
            if (! $mysql_data) {
125
                $this->error('Not all MYSQL info (DB_CONNECTION=mysql,DB_DATABASE,DB_USER,DB_PASSWORD,) found in .env production');
126
            } else {
127
                $this->info("We have found a MYSQL database and user configuration in your .env.production file.");
128
                $this->line("Database type: MySQL");
129
                $this->line("Database name: " . $mysql_data['name']);
130
                $this->line("Database user: " . $mysql_data['user']);
131
                if ($this->confirm('Do you want to create this database and user in production?')) {
132
                    $this->call('publish:mysql', array_merge($mysql_data, ['--wait' => true]));
133
                }
134
                $this->databaseAlreadyConfigured = true;
135
            }
136
        }
137
138
        if (! $this->databaseAlreadyConfigured) {
139
            if ($this->confirm('Do you want to create a database in production?')) {
140
                $mysql_data['name'] = $this->ask('Database?');
0 ignored issues
show
Bug introduced by
The variable $mysql_data does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
141
                $mysql_data['user'] = $this->ask('User?');
142
                $mysql_data['password'] = $this->secret('Password?');
143
                $this->call('publish:mysql', $mysql_data);
144
            }
145
        }
146
147
        if ($this->confirm('Do you wish run migrations on production?')) {
148
            $this->call('publish:artisan', [
149
                'artisan_command' => 'migrate --force',
150
            ]);
151
        }
152
153
        if ($this->confirm('Do you want to seed database on production?')) {
154
            $this->call('publish:artisan', [
155
                'artisan_command' => 'db:seed --force',
156
            ]);
157
        }
158
    }
159
160
    /**
161
     * Obtain MySQL Database Info From env file.
162
     *
163
     * @param $file
164
     * @return array
165
     */
166
    protected function obtainMySQLDatabaseInfoFromEnv($file)
167
    {
168
        $env = (new Loader($file))->parse()->toArray();
169
170
        if (! array_key_exists('DB_CONNECTION', $env)  || $env['DB_CONNECTION'] != 'mysql') {
171
            return null;
172
        }
173
174
        if (! array_key_exists('DB_DATABASE', $env) ||
175
             ! array_key_exists('DB_USERNAME', $env) ||
176
             ! array_key_exists('DB_PASSWORD', $env)) {
177
            return null;
178
        }
179
180
        return [
181
          'name' => $env['DB_DATABASE'],
182
          'user' => $env['DB_USERNAME'],
183
          'password' => $env['DB_PASSWORD'],
184
        ];
185
    }
186
187
    /**
188
     * Abort command execution?
189
     */
190
    protected function abortCommandExecution()
191
    {
192
        $this->server = $this->checkEnv('server', 'ACACHA_FORGE_SERVER');
193
        $this->domain = $this->checkEnv('domain', 'ACACHA_FORGE_DOMAIN');
194
195
        $this->abortIfNoSSHConnection();
196
    }
197
}
198