GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

FetchCommand::doExecute()   F
last analyzed

Complexity

Conditions 15
Paths 440

Size

Total Lines 137
Code Lines 97

Duplication

Lines 0
Ratio 0 %

Importance

Changes 10
Bugs 5 Features 1
Metric Value
c 10
b 5
f 1
dl 0
loc 137
rs 3.5163
cc 15
eloc 97
nc 440
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 Kunstmaan\Skylab\Command;
4
5
use Symfony\Component\Console\Input\InputArgument;
6
use Symfony\Component\Console\Input\InputOption;
7
8
class FetchCommand extends AbstractCommand
9
{
10
11
    const TYPE_JAVA = "java";
12
    const TYPE_PHP = "php";
13
14
    /**
15
     * Configures the current command.
16
     */
17
    protected function configure()
18
    {
19
        $this
20
            ->addDefaults()
21
            ->setName('fetch')
22
            ->setDescription('Fetches a project from a production server')
23
            ->addArgument('project', InputArgument::OPTIONAL, 'The name of the Skylab project')
24
            ->addArgument('host', InputArgument::OPTIONAL, 'The hostname of the server to fetch from')
25
            ->addOption('location', 'l', InputOption::VALUE_OPTIONAL, 'Override the target location')
26
            ->addOption('no-database', null, InputOption::VALUE_NONE, 'Don\'t delete the local database')
27
            ->setHelp(<<<EOT
28
The <info>fetch</info> command fetches a Skylab project from a server and puts it in the right locations on your computer. It
29
will also drop the databases, so be very careful if you want to use this on a production server to do a migration.
30
31
<info>php skylab.phar fetch</info>                         # Will ask for a project and server to fetch it from
32
<info>php skylab.phar fetch testproject server1</info>     # Will fetch the testproject from server1
33
34
EOT
35
            );
36
    }
37
38
    /**
39
     * @throws \RuntimeException
40
     */
41
    protected function doExecute()
42
    {
43
44
        $location = $this->input->getOption("location");
45
        if ($location){
46
            $config = $this->app["config"];
47
            $projects = $config["projects"];
48
            $projects["path"] = $location;
49
            $config["projects"] = $projects;
50
            $this->app["config"]= $config;
51
        }
52
53
        $projectname = $this->dialogProvider->askFor("Please enter the name of the project", 'project');
54
        $hostname = $this->dialogProvider->askFor("Please enter the hostname of the server", 'host');
55
56
        $this->dialogProvider->logStep("Checking preconditions");
57
        $this->dialogProvider->logTask("Checking the server");
58
        $exists = $this->isRemoteProjectAvailable($projectname, $hostname);
59
        if (!$exists) {
60
            $this->dialogProvider->logError("The project " . $projectname . " does not exist on " . $hostname, false);
61
        }
62
        $this->dialogProvider->logTask("Detecting the project type");
63
        $type = $this->detectProjectType($projectname, $hostname);
64
65
        $excludes = array(
66
            ".composer",
67
            "apachelogs/*",
68
            "resizedcache/*",
69
            "nobackup/*",
70
            "tmp/*",
71
            ".viminfo",
72
            ".ssh",
73
            ".bash_history",
74
            ".config",
75
            ".cache",
76
            ".mysql_history",
77
            "data/current/app/logs/*",
78
            "data/current/var/logs/*",
79
            "data/current/app/cache/*",
80
            "data/current/var/cache/*",
81
        );
82
83
        if (!$this->fileSystemProvider->projectExists($projectname)) {
84
            $this->dialogProvider->logStep("Running the full rsync commands since " . $projectname . " is not on this computer");
85
            $fullExcludes = $excludes;
86
            $fullExcludes[] = "data/shared";
87
            $fullExcludes[] = "data/builds";
88
            $fullExcludes[] = "data/releases";
89
            if ($type !== self::TYPE_JAVA) {
90
                $fullExcludes[] = "data/" . $projectname;
91
            }
92
            $this->fetchFolder(
93
                $this->app["config"]["projects"]["path"] . '/',
94
                $hostname,
95
                $this->app["config"]["remote_projects"]["path"]. "/" . $projectname,
96
                $fullExcludes,
97
                true
98
            );
99
100
            if ($type !== self::TYPE_JAVA) {
101
                $mvCommand = "mv " . $this->fileSystemProvider->getProjectDirectory($projectname) . "/data/current " . $this->fileSystemProvider->getProjectDirectory($projectname) . "/data/" . $projectname;
102
                $this->processProvider->executeCommand($mvCommand);
103
            }
104
            if (file_exists($this->fileSystemProvider->getProjectDirectory($projectname) . "/data/" . $projectname)) {
105
                $this->dialogProvider->logStep("Getting git repo data and try resetting to the master branch");
106
                $this->processProvider->executeCommand("cd ".$this->fileSystemProvider->getProjectDirectory($projectname) . "/data/" . $projectname. "; git pull 2>/dev/null; git fetch origin && git reset --hard && git clean -f -d && git checkout master", true);
107
            }
108
        } else {
109
            $this->dialogProvider->logStep("Running the update rsync commands since " . $projectname . " already is on this computer");
110
            $updateExcludes = $excludes;
111
            $updateExcludes[] = "data/*";
112
113
            $this->fetchFolderIfExists(
114
                $this->fileSystemProvider->getProjectDirectory($projectname). '/',
115
                $hostname,
116
                "/home/projects/" . $projectname . '/*',
117
                $updateExcludes
118
            );
119
120
            $this->fetchFolderIfExists(
121
                $this->fileSystemProvider->getProjectDirectory($projectname) . "/data/" . $projectname . "/web/uploads/",
122
                $hostname,
123
                "/home/projects/" . $projectname . "/data/current/web/uploads/*",
124
                $updateExcludes
125
            );
126
127
            $this->fetchFolderIfExists(
128
                $this->fileSystemProvider->getProjectDirectory($projectname) . "/data/" . $projectname . "/sites/default/files/",
129
                $hostname,
130
                "/home/projects/" . $projectname . "/data/current/sites/default/files/*",
131
                $updateExcludes
132
            );
133
            if (file_exists($this->fileSystemProvider->getProjectDirectory($projectname) . "/data/" . $projectname) && $this->processProvider->executeCommand("cd ".$this->fileSystemProvider->getProjectDirectory($projectname) . "/data/" . $projectname. "; git status", true)===false) {
134
                if($this->dialogProvider->askConfirmation("It looks like your source repo is broken, can I try reset this to master? [Y,n]")){
135
                    $this->processProvider->executeCommand("cd ".$this->fileSystemProvider->getProjectDirectory($projectname) . "/data/" . $projectname. "; git pull 2>/dev/null; git fetch origin && git branch master origin/master && git reset --hard && git clean -f -d && git checkout master", true);
136
                }
137
            }
138
        }
139
140
        if (file_exists($this->fileSystemProvider->getProjectDirectory($projectname) . "/data/" . $projectname . '/.skylab/conf') && is_link($this->fileSystemProvider->getProjectDirectory($projectname) . '/conf')) {
141
        	$this->processProvider->executeSudoCommand("ln -sf " . $this->fileSystemProvider->getProjectDirectory($projectname) . "/data/" . $projectname . '/.skylab/conf ' . $this->fileSystemProvider->getProjectDirectory($projectname).'/conf');
142
        }
143
        
144
        $project = $this->projectConfigProvider->loadProjectConfig($projectname);
145
        $project['dir'] = $this->app["config"]["projects"]["path"] . $projectname;
146
        $this->projectConfigProvider->writeProjectConfig($project);
147
148
        if (!$this->input->getOption('no-database')) {
149
150
            $this->dialogProvider->logStep("Dropping the databases");
151
152
            if( in_array('mysql', $this->skeletonProvider->getSkeletons() ) )
153
            {
154
                $this->dialogProvider->logTask("Dropping the MySQL database");
155
                $dbh = new \PDO('mysql:host=localhost;', $this->app["config"]["mysql"]["user"], $this->app["config"]["mysql"]["password"]);
156
                $dbh->query("DROP DATABASE IF EXISTS " . $projectname);
157
            }
158
159
            if( in_array('postgres', $this->skeletonProvider->getSkeletons() ) )
160
            {
161
                $this->dialogProvider->logTask("Dropping the PostgreSQL database");
162
                $dbh = new \PDO(
163
                    $this->dialogProvider->logQuery(
164
                        'pgsql:host=localhost;dbname=template1',
165
                        array(
166
                            "user" => $this->app["config"]["postgresql"]["user"],
167
                            "password" => $this->app["config"]["postgresql"]["password"]
168
                        )
169
                    ),
170
                    $this->app["config"]["postgresql"]["user"],
171
                    $this->app["config"]["postgresql"]["password"]
172
                );
173
                $dbh->query("DROP DATABASE IF EXISTS " . $projectname);
174
            }
175
176
        }
177
    }
178
179
    /**
180
     * Tries to detect if the remote project is a Java project.
181
     *
182
     * @param string $projectname
183
     * @param string $hostname
184
     * @return string
185
     */
186
    private function detectProjectType($projectname, $hostname)
187
    {
188
        $command = "ssh " . $hostname . " 'test -d /home/projects/" . $projectname . "/data/" . $projectname . "/src/be/smartlounge && echo found'";
189
        $this->dialogProvider->logCommand($command);
190
        $found = $this->processProvider->executeCommand($command, true);
191
        if ($found) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $found of type string|false is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
192
            return self::TYPE_JAVA;
193
        }
194
195
        return self::TYPE_PHP;
196
    }
197
198
    /**
199
     * Tries to detect if the remote project exists
200
     *
201
     * @param string $projectname
202
     * @param string $hostname
203
     * @return bool
204
     */
205
    private function isRemoteProjectAvailable($projectname, $hostname)
206
    {
207
        $command = "ssh " . $hostname . " 'test -d /home/projects/" . $projectname . " && echo found'";
208
        $this->dialogProvider->logCommand($command);
209
        $found = $this->processProvider->executeCommand($command, true);
210
        return (bool) $found;
211
    }
212
213
    /**
214
     * @param string   $folder
215
     * @param string   $hostname
216
     * @param string   $remoteFolder
217
     * @param string[] $excludes
218
     * @param bool     $links
219
     */
220
    private function fetchFolderIfExists($folder, $hostname, $remoteFolder, $excludes, $links = false)
221
    {
222
        if (file_exists($folder)) {
223
            $this->fetchFolder($folder, $hostname, $remoteFolder, $excludes, $links);
224
        }
225
    }
226
227
    /**
228
     * @param string   $folder
229
     * @param string   $hostname
230
     * @param string   $remoteFolder
231
     * @param string[] $excludes
232
     * @param bool     $links
233
     */
234
    private function fetchFolder($folder, $hostname, $remoteFolder, $excludes, $links = false)
235
    {
236
        $rsyncCommand = "rsync --no-acls -r" . ($links ? "L" : "l") . "Dhz --info=progress2 --delete --size-only";
237
        foreach ($excludes as $exclude) {
238
            $rsyncCommand .= " --exclude=" . $exclude;
239
        }
240
        $rsyncCommand .= " " . $hostname . ":" . $remoteFolder;
241
        $rsyncCommand .= " " . $folder;
242
        $this->processProvider->executeCommand($rsyncCommand, false, function ($type, $buffer) {
243
            strlen($type); // just to get rid of the scrutinizer error... sigh
244
            echo $buffer;
245
        });
246
    }
247
}
248