Completed
Push — develop ( 5b6026...8cfa8a )
by Jaap
16:32 queued 07:30
created

UpdateCommand::execute()   B

Complexity

Conditions 8
Paths 38

Size

Total Lines 56
Code Lines 37

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 8
eloc 37
c 2
b 0
f 0
nc 38
nop 2
dl 0
loc 56
rs 7.3333

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
 * phpDocumentor
4
 *
5
 * PHP Version 5.3
6
 *
7
 * @copyright 2010-2014 Mike van Riel / Naenius (http://www.naenius.com)
8
 * @license   http://www.opensource.org/licenses/mit-license.php MIT
9
 * @link      http://phpdoc.org
10
 */
11
12
namespace phpDocumentor\Command\Phar;
13
14
use \Exception;
15
use Humbug\SelfUpdate\Strategy\GithubStrategy;
16
use Humbug\SelfUpdate\Updater;
17
use phpDocumentor\Application;
18
use Symfony\Component\Console\Command\Command;
19
use Symfony\Component\Console\Input\InputArgument;
20
use Symfony\Component\Console\Input\InputInterface;
21
use Symfony\Component\Console\Input\InputOption;
22
use Symfony\Component\Console\Output\OutputInterface;
23
24
/**
25
 * Updates phpDocumentor.phar to the latest version.
26
 *
27
 * ```
28
 * $ php phpDocumentor.phar phar:update [-m|--major] [-p|--pre] [version]
29
 * ```
30
 */
31
class UpdateCommand extends Command
32
{
33
    const PHAR_URL = 'https://github.com/phpDocumentor/phpDocumentor2/releases/latest';
34
35
    /**
36
     * Initializes this command and sets the name, description, options and arguments.
37
     *
38
     * @return void
39
     */
40
    protected function configure()
41
    {
42
        $this->setName('phar:update')
43
            ->setAliases(array('selfupdate', 'self-update'))
44
            ->setDescription('Updates the binary with the latest version.')
45
            ->addOption(
46
                'rollback',
47
                null,
48
                InputOption::VALUE_NONE,
49
                'Rollsback the updated binary to the last version.'
50
            )
51
            ->addOption('pre', 'p', InputOption::VALUE_NONE, 'Allow pre-release version update');
52
    }
53
54
    /**
55
     * Executes the business logic involved with this command.
56
     *
57
     * @param \Symfony\Component\Console\Input\InputInterface $input
58
     * @param \Symfony\Component\Console\Output\OutputInterface $output
59
     *
60
     * @return int
61
     */
62
    protected function execute(InputInterface $input, OutputInterface $output)
63
    {
64
        $output->writeln('Looking for updates...');
65
66
67
        $allowPreRelease = $input->getOption('pre');
68
69
        if (PHP_VERSION_ID < 50600) {
70
            $message = 'Self updating is not available in PHP versions under 5.6.' . "\n";
71
            $message .= 'The latest version can be found at ' . self::PHAR_URL;
72
            $output->writeln(sprintf('<error>%s</error>', $message));
73
            return 1;
74
        } elseif (Application::VERSION === ('@package_version@')) {
75
            $output->writeln('<error>Self updating has been disabled in source version.</error>');
76
            return 1;
77
        }
78
79
        $exitCode = 1;
80
81
        $updater = new Updater();
82
        $updater->setStrategy(Updater::STRATEGY_GITHUB);
83
        $updater->getStrategy()->setPackageName('phpdocumentor/phpDocumentor2');
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Humbug\SelfUpdate\Strategy\StrategyInterface as the method setPackageName() does only exist in the following implementations of said interface: Humbug\SelfUpdate\Strategy\GithubStrategy, Humbug\Test\SelfUpdate\GithubTestStrategy.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
84
        $updater->getStrategy()->setPharName('phpDocumentor.phar');
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Humbug\SelfUpdate\Strategy\StrategyInterface as the method setPharName() does only exist in the following implementations of said interface: Humbug\SelfUpdate\Strategy\GithubStrategy, Humbug\Test\SelfUpdate\GithubTestStrategy.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
85
        $updater->getStrategy()->getCurrentLocalVersion(Application::$VERSION);
0 ignored issues
show
Documentation introduced by
\phpDocumentor\Application::$VERSION is of type string, but the function expects a object<Humbug\SelfUpdate\Updater>.

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...
86
87
        if ($allowPreRelease) {
88
            $updater->getStrategy()->setStability(GithubStrategy::ANY);
0 ignored issues
show
Bug introduced by
It seems like you code against a concrete implementation and not the interface Humbug\SelfUpdate\Strategy\StrategyInterface as the method setStability() does only exist in the following implementations of said interface: Humbug\SelfUpdate\Strategy\GithubStrategy, Humbug\Test\SelfUpdate\GithubTestStrategy.

Let’s take a look at an example:

interface User
{
    /** @return string */
    public function getPassword();
}

class MyUser implements User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the interface:

    interface User
    {
        /** @return string */
        public function getPassword();
    
        /** @return string */
        public function getDisplayName();
    }
    
Loading history...
89
        }
90
91
        try {
92
            if ($input->getOption('rollback')) {
93
                $output->writeln('Rolling back to previous version...');
94
                $result = $updater->rollback();
95
            } else {
96
                if (!$updater->hasUpdate()) {
97
                    $output->writeln('No new version available.');
98
                    return 0;
99
                }
100
101
                $output->writeln('Updating to newer version...');
102
                $result = $updater->update();
103
            }
104
105
            if ($result) {
106
                $new = $updater->getNewVersion();
107
                $old = $updater->getOldVersion();
108
109
                $output->writeln(sprintf('Updated from %s to %s', $old, $new));
110
                $exitCode = 0;
111
            }
112
        } catch (Exception $e) {
113
            $output->writeln(sprintf('<error>%s</error>', $e->getMessage()));
114
        }
115
116
        return $exitCode;
117
    }
118
}
119