Completed
Push — dev ( 6d8737...fe3822 )
by Zach
02:19
created

Command::option()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 4
nc 2
nop 1
dl 0
loc 8
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
namespace Yarak\Console;
4
5
use Yarak\Console\Output\SymfonyOutput;
6
use Symfony\Component\Console\Input\InputInterface;
7
use Symfony\Component\Console\Output\OutputInterface;
8
use Symfony\Component\Console\Command\Command as SymfonyCommand;
9
10
abstract class Command extends SymfonyCommand
11
{
12
    /**
13
     * Symfony console output.
14
     *
15
     * @var SymfonyOutput
16
     */
17
    protected $output;
18
19
    /**
20
     * Symfony input implementation.
21
     *
22
     * @var InputInterface
23
     */
24
    protected $input;
25
26
    /**
27
     * Execute the command.
28
     *
29
     * @param InputInterface  $input
30
     * @param OutputInterface $output
31
     */
32
    protected function execute(InputInterface $input, OutputInterface $output)
33
    {
34
        $this->output = new SymfonyOutput($output);
35
36
        $this->input = $input;
37
38
        if (method_exists($this, 'handle')) {
39
            $this->handle();
1 ignored issue
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class Yarak\Console\Command as the method handle() does only exist in the following sub-classes of Yarak\Console\Command: DoSomething, Yarak\Commands\DBGenerate, Yarak\Commands\DBSeed, Yarak\Commands\MakeCommand, Yarak\Commands\MakeMigration, Yarak\Commands\MakeSeeder, Yarak\Commands\Migrate, Yarak\Commands\MigrateRefresh, Yarak\Commands\MigrateReset, Yarak\Commands\MigrateRollback. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

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

class MyUser extends 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 sub-classes 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 parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
40
        }
41
    }
42
43
    /**
44
     * Return the output implementation.
45
     *
46
     * @return SymfonyOutput
47
     */
48
    protected function getOutput()
49
    {
50
        return $this->output;
51
    }
52
53
    /**
54
     * Get the value of a command argument.
55
     *
56
     * @param string $key
57
     *
58
     * @return string|array
59
     */
60
    protected function argument($key = null)
61
    {
62
        if (is_null($key)) {
63
            return $this->input->getArguments();
64
        }
65
66
        return $this->input->getArgument($key);
67
    }
68
69
    /**
70
     * Determine if the given argument is present.
71
     *
72
     * @param string|int $name
73
     *
74
     * @return bool
75
     */
76
    protected function hasArgument($name)
77
    {
78
        return $this->input->hasArgument($name);
79
    }
80
81
    /**
82
     * Get the value of a command option.
83
     *
84
     * @param string $key
85
     *
86
     * @return string|array
87
     */
88
    protected function option($key = null)
89
    {
90
        if (is_null($key)) {
91
            return $this->input->getOptions();
92
        }
93
94
        return $this->input->getOption($key);
95
    }
96
97
    /**
98
     * Determine if the given option is present.
99
     *
100
     * @param string $name
101
     *
102
     * @return bool
103
     */
104
    protected function hasOption($name)
105
    {
106
        return $this->input->hasOption($name);
107
    }
108
}
109