Completed
Pull Request — master (#615)
by
unknown
05:05
created

SelfUpdateCommand::execute()   B

Complexity

Conditions 8
Paths 48

Size

Total Lines 54
Code Lines 31

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 54
rs 7.4119
c 0
b 0
f 0
cc 8
eloc 31
nc 48
nop 2

How to fix   Long Method   

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
/*
4
 * This file is part of the Symfony package.
5
 *
6
 * (c) Fabien Potencier <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
namespace Robo;
13
14
use Symfony\Component\Console\Command\Command;
15
use Symfony\Component\Console\Input\InputInterface;
16
use Symfony\Component\Console\Output\OutputInterface;
17
use Symfony\Component\Filesystem\Filesystem as sfFilesystem;
18
19
/**
20
 * Update the robo.phar from the latest github release
21
 *
22
 * @author Alexander Menk <[email protected]>
23
 */
24
class SelfUpdateCommand extends Command
25
{
26
    private $command;
0 ignored issues
show
Unused Code introduced by
The property $command is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
27
28
    /**
29
     * {@inheritdoc}
30
     */
31
    protected function configure()
32
    {
33
	    $this
34
		    ->setName('self-update')
35
		    ->setAliases(array('selfupdate'))
36
		    ->setDescription('Updates the robo.phar to the latest version.')
37
		    ->setHelp(
38
			    <<<EOT
39
The <info>self-update</info> command checks github for newer
40
versions of robo and if found, installs the latest.
41
EOT
42
		    )
43
	    ;
44
    }
45
46
    protected function getLatestReleaseFromGithub($repository)
47
    {
48
	    $opts = [
49
		    'http' => [
50
			    'method' => 'GET',
51
			    'header' => [
52
				    'User-Agent: PHP'
53
			    ]
54
		    ]
55
	    ];
56
57
	    $context = stream_context_create($opts);
58
59
	    $releases = file_get_contents('https://api.github.com/repos/' . $repository . '/releases', false, $context);
60
	    $releases = json_decode($releases);
61
62
	    if (!isset($releases[0])) {
63
	        throw new \Exception('API error - no release found at GitHub repository ' . $repository);
64
        }
65
66
	    $version = $releases[0]->tag_name;
67
	    $url = $releases[0]->assets[0]->browser_download_url;
68
69
	    return [$version, $url];
70
    }
71
72
    /**
73
     * {@inheritdoc}
74
     */
75
    protected function execute(InputInterface $input, OutputInterface $output)
0 ignored issues
show
Coding Style introduced by
execute 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...
76
    {
77
	    $localFilename = realpath($_SERVER['argv'][0]) ?: $_SERVER['argv'][0];
78
	    $programName = basename($localFilename);
79
	    $tempFilename = dirname($localFilename) . '/' . basename($localFilename, '.phar') . '-temp.phar';
80
81
	    // check for permissions in local filesystem before start connection process
82
	    if (!is_writable($tempDirectory = dirname($tempFilename))) {
83
		    throw new \Exception(
84
			    $programName . ' update failed: the "' . $tempDirectory .
85
			    '" directory used to download the temp file could not be written'
86
		    );
87
	    }
88
89
	    if (!is_writable($localFilename)) {
90
		    throw new \Exception(
91
			    $programName . ' update failed: the "' . $localFilename . '" file could not be written'
92
		    );
93
	    }
94
95
	    list($latest, $downloadUrl) = $this->getLatestReleaseFromGithub('consolidation/robo');
96
97
98
	    if (Robo::VERSION == $latest) {
99
	    	$output->writeln('No update available');
100
	    }
101
102
	    $fs = new sfFilesystem();
103
104
	    $output->writeln('Downloading ' . Robo::APPLICATION_NAME . ' ' . $latest);
105
106
	    $fs->copy($downloadUrl, $tempFilename);
107
108
	    $output->writeln('Download finished');
109
110
	    try {
111
		    \error_reporting(E_ALL); // supress notices
112
113
		    @chmod($tempFilename, 0777 & ~umask());
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
114
		    // test the phar validity
115
		    $phar = new \Phar($tempFilename);
116
		    // free the variable to unlock the file
117
		    unset($phar);
118
		    @rename($tempFilename, $localFilename);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
119
		    $output->writeln('<info>Successfully updated ' . $programName . '</info>');
120
	    } catch (\Exception $e) {
121
		    @unlink($tempFilename);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
122
		    if (!$e instanceof \UnexpectedValueException && !$e instanceof \PharException) {
123
			    throw $e;
124
		    }
125
		    $output->writeln('<error>The download is corrupted (' . $e->getMessage() . ').</error>');
126
		    $output->writeln('<error>Please re-run the self-update command to try again.</error>');
127
	    }
128
    }
129
}
130