Completed
Push — develop ( 21139f...eaa140 )
by Tom
12s
created

SelfUpdateCommand::execute()   D

Complexity

Conditions 14
Paths 212

Size

Total Lines 97
Code Lines 59

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 1 Features 0
Metric Value
c 2
b 1
f 0
dl 0
loc 97
rs 4.4181
cc 14
eloc 59
nc 212
nop 2

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;
4
5
use Composer\Downloader\FilesystemException;
6
use Composer\IO\ConsoleIO;
7
use Composer\Util\RemoteFilesystem;
8
use Exception;
9
use N98\Magento\Command\AbstractMagentoCommand;
10
use Symfony\Component\Console\Input\InputInterface;
11
use Symfony\Component\Console\Input\InputOption;
12
use Symfony\Component\Console\Output\OutputInterface;
13
14
/**
15
 * @codeCoverageIgnore
16
 * @author Igor Wiedler <[email protected]>
17
 * @author Christian Münch <[email protected]>
18
 */
19
class SelfUpdateCommand extends AbstractMagentoCommand
20
{
21
    protected function configure()
22
    {
23
        $this
24
            ->setName('self-update')
25
            ->setAliases(array('selfupdate'))
26
            ->addOption('unstable', null, InputOption::VALUE_NONE, 'Load unstable version from develop branch')
27
            ->setDescription('Updates n98-magerun.phar to the latest version.')
28
            ->setHelp(<<<EOT
29
The <info>self-update</info> command checks github for newer
30
versions of n98-magerun and if found, installs the latest.
31
32
<info>php n98-magerun.phar self-update</info>
33
34
EOT
35
            )
36
        ;
37
    }
38
39
    /**
40
     * @return bool
41
     */
42
    public function isEnabled()
43
    {
44
        return $this->getApplication()->isPharMode();
45
    }
46
47
    /**
48
     * @param InputInterface  $input
49
     * @param OutputInterface $output
50
     *
51
     * @throws FilesystemException
52
     */
53
    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...
54
    {
55
        $localFilename = realpath($_SERVER['argv'][0]) ?: $_SERVER['argv'][0];
56
        $tempFilename = dirname($localFilename) . '/' . basename($localFilename, '.phar') . '-temp.phar';
57
58
        // check for permissions in local filesystem before start connection process
59
        if (!is_writable($tempDirectory = dirname($tempFilename))) {
60
            throw new FilesystemException(
61
                'n98-magerun update failed: the "' . $tempDirectory .
62
                '" directory used to download the temp file could not be written'
63
            );
64
        }
65
66
        if (!is_writable($localFilename)) {
67
            throw new FilesystemException(
68
                'n98-magerun update failed: the "' . $localFilename . '" file could not be written'
69
            );
70
        }
71
72
        $io = new ConsoleIO($input, $output, $this->getHelperSet());
0 ignored issues
show
Bug introduced by
It seems like $this->getHelperSet() can be null; however, __construct() does not accept null, maybe add an additional type check?

Unless you are absolutely sure that the expression can never be null because of other conditions, we strongly recommend to add an additional type check to your code:

/** @return stdClass|null */
function mayReturnNull() { }

function doesNotAcceptNull(stdClass $x) { }

// With potential error.
function withoutCheck() {
    $x = mayReturnNull();
    doesNotAcceptNull($x); // Potential error here.
}

// Safe - Alternative 1
function withCheck1() {
    $x = mayReturnNull();
    if ( ! $x instanceof stdClass) {
        throw new \LogicException('$x must be defined.');
    }
    doesNotAcceptNull($x);
}

// Safe - Alternative 2
function withCheck2() {
    $x = mayReturnNull();
    if ($x instanceof stdClass) {
        doesNotAcceptNull($x);
    }
}
Loading history...
73
        $rfs = new RemoteFilesystem($io);
74
75
        $loadUnstable = $input->getOption('unstable');
76
        if ($loadUnstable) {
77
            $versionTxtUrl = 'https://raw.githubusercontent.com/netz98/n98-magerun/develop/version.txt';
78
            $remoteFilename = 'https://files.magerun.net/n98-magerun-dev.phar';
79
        } else {
80
            $versionTxtUrl = 'https://raw.githubusercontent.com/netz98/n98-magerun/master/version.txt';
81
            $remoteFilename = 'https://files.magerun.net/n98-magerun.phar';
82
        }
83
84
        $latest = trim($rfs->getContents('raw.githubusercontent.com', $versionTxtUrl, false));
85
86
        if ($this->getApplication()->getVersion() !== $latest || $loadUnstable) {
87
            $output->writeln(sprintf("Updating to version <info>%s</info>.", $latest));
88
89
            $rfs->copy('raw.github.com', $remoteFilename, $tempFilename);
90
91
            if (!file_exists($tempFilename)) {
92
                $output->writeln('<error>The download of the new n98-magerun version failed for an unexpected reason');
93
94
                return 1;
95
            }
96
97
            try {
98
                \error_reporting(E_ALL); // supress notices
99
100
                @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...
101
                // test the phar validity
102
                $phar = new \Phar($tempFilename);
103
                // free the variable to unlock the file
104
                unset($phar);
105
                @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...
106
                $output->writeln('<info>Successfully updated n98-magerun</info>');
107
108
                if ($loadUnstable) {
109
                    $changeLogContent = $rfs->getContents(
110
                        'raw.github.com',
111
                        'https://raw.github.com/netz98/n98-magerun/develop/CHANGELOG.md',
112
                        false
113
                    );
114
                } else {
115
                    $changeLogContent = $rfs->getContents(
116
                        'raw.github.com',
117
                        'https://raw.github.com/netz98/n98-magerun/master/CHANGELOG.md',
118
                        false
119
                    );
120
                }
121
122
                if ($changeLogContent) {
123
                    $output->writeln($changeLogContent);
0 ignored issues
show
Bug introduced by
It seems like $changeLogContent can also be of type boolean; however, Symfony\Component\Consol...putInterface::writeln() does only seem to accept string|array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
124
                }
125
126
                if ($loadUnstable) {
127
                    $unstableFooterMessage = <<<UNSTABLE_FOOTER
128
<comment>
129
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
130
!! DEVELOPMENT VERSION. DO NOT USE IN PRODUCTION !!
131
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
132
</comment>
133
UNSTABLE_FOOTER;
134
                    $output->writeln($unstableFooterMessage);
135
                }
136
137
                $this->_exit();
138
            } catch (Exception $e) {
139
                @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...
140
                if (!$e instanceof \UnexpectedValueException && !$e instanceof \PharException) {
141
                    throw $e;
142
                }
143
                $output->writeln('<error>The download is corrupted (' . $e->getMessage() . ').</error>');
144
                $output->writeln('<error>Please re-run the self-update command to try again.</error>');
145
            }
146
        } else {
147
            $output->writeln("<info>You are using the latest n98-magerun version.</info>");
148
        }
149
    }
150
151
    /**
152
     * Stop execution
153
     *
154
     * This is a workaround to prevent warning of dispatcher after replacing
155
     * the phar file.
156
     *
157
     * @return void
158
     */
159
    protected function _exit()
160
    {
161
        exit;
0 ignored issues
show
Coding Style Compatibility introduced by
The method _exit() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
162
    }
163
}
164